xref: /freebsd/contrib/ntp/ntpd/refclock_parse.c (revision aa0a1e58)
1 /*
2  * /src/NTP/REPOSITORY/ntp4-dev/ntpd/refclock_parse.c,v 4.80 2007/08/11 12:06:29 kardel Exp
3  *
4  * refclock_parse.c,v 4.80 2007/08/11 12:06:29 kardel Exp
5  *
6  * generic reference clock driver for several DCF/GPS/MSF/... receivers
7  *
8  * PPS notes:
9  *   On systems that support PPSAPI (RFC2783) PPSAPI is the
10  *   preferred interface.
11  *
12  *   Optionally make use of a STREAMS module for input processing where
13  *   available and configured. This STREAMS module reduces the time
14  *   stamp latency for serial and PPS events.
15  *   Currently the STREAMS module is only available for Suns running
16  *   SunOS 4.x and SunOS5.x.
17  *
18  * Copyright (c) 1995-2007 by Frank Kardel <kardel <AT> ntp.org>
19  * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universit�t Erlangen-N�rnberg, Germany
20  *
21  * Redistribution and use in source and binary forms, with or without
22  * modification, are permitted provided that the following conditions
23  * are met:
24  * 1. Redistributions of source code must retain the above copyright
25  *    notice, this list of conditions and the following disclaimer.
26  * 2. Redistributions in binary form must reproduce the above copyright
27  *    notice, this list of conditions and the following disclaimer in the
28  *    documentation and/or other materials provided with the distribution.
29  * 3. Neither the name of the author nor the names of its contributors
30  *    may be used to endorse or promote products derived from this software
31  *    without specific prior written permission.
32  *
33  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
34  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
35  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
37  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43  * SUCH DAMAGE.
44  *
45  */
46 
47 #ifdef HAVE_CONFIG_H
48 # include "config.h"
49 #endif
50 
51 #if defined(REFCLOCK) && defined(CLOCK_PARSE)
52 
53 /*
54  * This driver currently provides the support for
55  *   - Meinberg receiver DCF77 PZF 535 (TCXO version)       (DCF)
56  *   - Meinberg receiver DCF77 PZF 535 (OCXO version)       (DCF)
57  *   - Meinberg receiver DCF77 PZF 509                      (DCF)
58  *   - Meinberg receiver DCF77 AM receivers (e.g. C51)      (DCF)
59  *   - IGEL CLOCK                                           (DCF)
60  *   - ELV DCF7000                                          (DCF)
61  *   - Schmid clock                                         (DCF)
62  *   - Conrad DCF77 receiver module                         (DCF)
63  *   - FAU DCF77 NTP receiver (TimeBrick)                   (DCF)
64  *   - WHARTON 400A Series clock			    (DCF)
65  *
66  *   - Meinberg GPS166/GPS167                               (GPS)
67  *   - Trimble (TSIP and TAIP protocol)                     (GPS)
68  *
69  *   - RCC8000 MSF Receiver                                 (MSF)
70  *   - VARITEXT clock					    (MSF)
71  */
72 
73 /*
74  * Meinberg receivers are usually connected via a
75  * 9600 baud serial line
76  *
77  * The Meinberg GPS receivers also have a special NTP time stamp
78  * format. The firmware release is Uni-Erlangen.
79  *
80  * Meinberg generic receiver setup:
81  *	output time code every second
82  *	Baud rate 9600 7E2S
83  *
84  * Meinberg GPS16x setup:
85  *      output time code every second
86  *      Baudrate 19200 8N1
87  *
88  * This software supports the standard data formats used
89  * in Meinberg receivers.
90  *
91  * Special software versions are only sensible for the
92  * GPS 16x family of receivers.
93  *
94  * Meinberg can be reached via: http://www.meinberg.de/
95  */
96 
97 #include "ntpd.h"
98 #include "ntp_refclock.h"
99 #include "ntp_unixtime.h"	/* includes <sys/time.h> */
100 #include "ntp_control.h"
101 #include "ntp_string.h"
102 
103 #include <stdio.h>
104 #include <ctype.h>
105 #ifndef TM_IN_SYS_TIME
106 # include <time.h>
107 #endif
108 
109 #ifdef HAVE_UNISTD_H
110 # include <unistd.h>
111 #endif
112 
113 #if !defined(STREAM) && !defined(HAVE_SYSV_TTYS) && !defined(HAVE_BSD_TTYS) && !defined(HAVE_TERMIOS)
114 # include "Bletch:  Define one of {STREAM,HAVE_SYSV_TTYS,HAVE_TERMIOS}"
115 #endif
116 
117 #ifdef STREAM
118 # include <sys/stream.h>
119 # include <sys/stropts.h>
120 #endif
121 
122 #ifdef HAVE_TERMIOS
123 # define TTY_GETATTR(_FD_, _ARG_) tcgetattr((_FD_), (_ARG_))
124 # define TTY_SETATTR(_FD_, _ARG_) tcsetattr((_FD_), TCSANOW, (_ARG_))
125 # undef HAVE_SYSV_TTYS
126 #endif
127 
128 #ifdef HAVE_SYSV_TTYS
129 # define TTY_GETATTR(_FD_, _ARG_) ioctl((_FD_), TCGETA, (_ARG_))
130 # define TTY_SETATTR(_FD_, _ARG_) ioctl((_FD_), TCSETAW, (_ARG_))
131 #endif
132 
133 #ifdef HAVE_BSD_TTYS
134 /* #error CURRENTLY NO BSD TTY SUPPORT */
135 # include "Bletch: BSD TTY not currently supported"
136 #endif
137 
138 #ifdef HAVE_SYS_IOCTL_H
139 # include <sys/ioctl.h>
140 #endif
141 
142 #ifdef HAVE_PPSAPI
143 # include "ppsapi_timepps.h"
144 #endif
145 
146 #ifdef PPS
147 # ifdef HAVE_SYS_PPSCLOCK_H
148 #  include <sys/ppsclock.h>
149 # endif
150 # ifdef HAVE_TIO_SERIAL_STUFF
151 #  include <linux/serial.h>
152 # endif
153 #endif
154 
155 #define BUFFER_SIZE(_BUF, _PTR) ((_BUF) + sizeof(_BUF) - (_PTR))
156 #define BUFFER_SIZES(_BUF, _PTR, _SZ) ((_BUF) + (_SZ) - (_PTR))
157 
158 /*
159  * document type of PPS interfacing - copy of ifdef mechanism in local_input()
160  */
161 #undef PPS_METHOD
162 
163 #ifdef HAVE_PPSAPI
164 #define PPS_METHOD "PPS API"
165 #else
166 #ifdef TIOCDCDTIMESTAMP
167 #define PPS_METHOD "TIOCDCDTIMESTAMP"
168 #else /* TIOCDCDTIMESTAMP */
169 #if defined(HAVE_STRUCT_PPSCLOCKEV) && (defined(HAVE_CIOGETEV) || defined(HAVE_TIOCGPPSEV))
170 #ifdef HAVE_CIOGETEV
171 #define PPS_METHOD "CIOGETEV"
172 #endif
173 #ifdef HAVE_TIOCGPPSEV
174 #define PPS_METHOD "TIOCGPPSEV"
175 #endif
176 #endif
177 #endif /* TIOCDCDTIMESTAMP */
178 #endif /* HAVE_PPSAPI */
179 
180 #include "ntp_io.h"
181 #include "ntp_stdlib.h"
182 
183 #include "parse.h"
184 #include "mbg_gps166.h"
185 #include "trimble.h"
186 #include "binio.h"
187 #include "ascii.h"
188 #include "ieee754io.h"
189 #include "recvbuff.h"
190 
191 static char rcsid[] = "refclock_parse.c,v 4.80 2007/08/11 12:06:29 kardel Exp";
192 
193 /**===========================================================================
194  ** external interface to ntp mechanism
195  **/
196 
197 static	int	parse_start	P((int, struct peer *));
198 static	void	parse_shutdown	P((int, struct peer *));
199 static	void	parse_poll	P((int, struct peer *));
200 static	void	parse_control	P((int, struct refclockstat *, struct refclockstat *, struct peer *));
201 
202 struct	refclock refclock_parse = {
203 	parse_start,
204 	parse_shutdown,
205 	parse_poll,
206 	parse_control,
207 	noentry,
208 	noentry,
209 	NOFLAGS
210 };
211 
212 /*
213  * Definitions
214  */
215 #define	MAXUNITS	4	/* maximum number of "PARSE" units permitted */
216 #define PARSEDEVICE	"/dev/refclock-%d" /* device to open %d is unit number */
217 #define PARSEPPSDEVICE	"/dev/refclockpps-%d" /* optional pps device to open %d is unit number */
218 
219 #undef ABS
220 #define ABS(_X_) (((_X_) < 0) ? -(_X_) : (_X_))
221 
222 #define PARSE_HARDPPS_DISABLE 0
223 #define PARSE_HARDPPS_ENABLE  1
224 
225 /**===========================================================================
226  ** function vector for dynamically binding io handling mechanism
227  **/
228 
229 struct parseunit;		/* to keep inquiring minds happy */
230 
231 typedef struct bind
232 {
233   const char *bd_description;	                                /* name of type of binding */
234   int	(*bd_init)     P((struct parseunit *));			/* initialize */
235   void	(*bd_end)      P((struct parseunit *));			/* end */
236   int   (*bd_setcs)    P((struct parseunit *, parsectl_t *));	/* set character size */
237   int	(*bd_disable)  P((struct parseunit *));			/* disable */
238   int	(*bd_enable)   P((struct parseunit *));			/* enable */
239   int	(*bd_getfmt)   P((struct parseunit *, parsectl_t *));	/* get format */
240   int	(*bd_setfmt)   P((struct parseunit *, parsectl_t *));	/* setfmt */
241   int	(*bd_timecode) P((struct parseunit *, parsectl_t *));	/* get time code */
242   void	(*bd_receive)  P((struct recvbuf *));			/* receive operation */
243   int	(*bd_io_input) P((struct recvbuf *));			/* input operation */
244 } bind_t;
245 
246 #define PARSE_END(_X_)			(*(_X_)->binding->bd_end)(_X_)
247 #define PARSE_SETCS(_X_, _CS_)		(*(_X_)->binding->bd_setcs)(_X_, _CS_)
248 #define PARSE_ENABLE(_X_)		(*(_X_)->binding->bd_enable)(_X_)
249 #define PARSE_DISABLE(_X_)		(*(_X_)->binding->bd_disable)(_X_)
250 #define PARSE_GETFMT(_X_, _DCT_)	(*(_X_)->binding->bd_getfmt)(_X_, _DCT_)
251 #define PARSE_SETFMT(_X_, _DCT_)	(*(_X_)->binding->bd_setfmt)(_X_, _DCT_)
252 #define PARSE_GETTIMECODE(_X_, _DCT_)	(*(_X_)->binding->bd_timecode)(_X_, _DCT_)
253 
254 /*
255  * io modes
256  */
257 #define PARSE_F_PPSPPS		0x0001 /* use loopfilter PPS code (CIOGETEV) */
258 #define PARSE_F_PPSONSECOND	0x0002 /* PPS pulses are on second */
259 
260 
261 /**===========================================================================
262  ** error message regression handling
263  **
264  ** there are quite a few errors that can occur in rapid succession such as
265  ** noisy input data or no data at all. in order to reduce the amount of
266  ** syslog messages in such case, we are using a backoff algorithm. We limit
267  ** the number of error messages of a certain class to 1 per time unit. if a
268  ** configurable number of messages is displayed that way, we move on to the
269  ** next time unit / count for that class. a count of messages that have been
270  ** suppressed is held and displayed whenever a corresponding message is
271  ** displayed. the time units for a message class will also be displayed.
272  ** whenever an error condition clears we reset the error message state,
273  ** thus we would still generate much output on pathological conditions
274  ** where the system oscillates between OK and NOT OK states. coping
275  ** with that condition is currently considered too complicated.
276  **/
277 
278 #define ERR_ALL	        (unsigned)~0	/* "all" errors */
279 #define ERR_BADDATA	(unsigned)0	/* unusable input data/conversion errors */
280 #define ERR_NODATA	(unsigned)1	/* no input data */
281 #define ERR_BADIO	(unsigned)2	/* read/write/select errors */
282 #define ERR_BADSTATUS	(unsigned)3	/* unsync states */
283 #define ERR_BADEVENT	(unsigned)4	/* non nominal events */
284 #define ERR_INTERNAL	(unsigned)5	/* internal error */
285 #define ERR_CNT		(unsigned)(ERR_INTERNAL+1)
286 
287 #define ERR(_X_)	if (list_err(parse, (_X_)))
288 
289 struct errorregression
290 {
291 	u_long err_count;	/* number of repititions per class */
292 	u_long err_delay;	/* minimum delay between messages */
293 };
294 
295 static struct errorregression
296 err_baddata[] =			/* error messages for bad input data */
297 {
298 	{ 1,       0 },		/* output first message immediately */
299 	{ 5,      60 },		/* output next five messages in 60 second intervals */
300 	{ 3,    3600 },		/* output next 3 messages in hour intervals */
301 	{ 0, 12*3600 }		/* repeat messages only every 12 hours */
302 };
303 
304 static struct errorregression
305 err_nodata[] =			/* error messages for missing input data */
306 {
307 	{ 1,       0 },		/* output first message immediately */
308 	{ 5,      60 },		/* output next five messages in 60 second intervals */
309 	{ 3,    3600 },		/* output next 3 messages in hour intervals */
310 	{ 0, 12*3600 }		/* repeat messages only every 12 hours */
311 };
312 
313 static struct errorregression
314 err_badstatus[] =		/* unsynchronized state messages */
315 {
316 	{ 1,       0 },		/* output first message immediately */
317 	{ 5,      60 },		/* output next five messages in 60 second intervals */
318 	{ 3,    3600 },		/* output next 3 messages in hour intervals */
319 	{ 0, 12*3600 }		/* repeat messages only every 12 hours */
320 };
321 
322 static struct errorregression
323 err_badio[] =			/* io failures (bad reads, selects, ...) */
324 {
325 	{ 1,       0 },		/* output first message immediately */
326 	{ 5,      60 },		/* output next five messages in 60 second intervals */
327 	{ 5,    3600 },		/* output next 3 messages in hour intervals */
328 	{ 0, 12*3600 }		/* repeat messages only every 12 hours */
329 };
330 
331 static struct errorregression
332 err_badevent[] =		/* non nominal events */
333 {
334 	{ 20,      0 },		/* output first message immediately */
335 	{ 6,      60 },		/* output next five messages in 60 second intervals */
336 	{ 5,    3600 },		/* output next 3 messages in hour intervals */
337 	{ 0, 12*3600 }		/* repeat messages only every 12 hours */
338 };
339 
340 static struct errorregression
341 err_internal[] =		/* really bad things - basically coding/OS errors */
342 {
343 	{ 0,       0 },		/* output all messages immediately */
344 };
345 
346 static struct errorregression *
347 err_tbl[] =
348 {
349 	err_baddata,
350 	err_nodata,
351 	err_badio,
352 	err_badstatus,
353 	err_badevent,
354 	err_internal
355 };
356 
357 struct errorinfo
358 {
359 	u_long err_started;	/* begin time (ntp) of error condition */
360 	u_long err_last;	/* last time (ntp) error occurred */
361 	u_long err_cnt;	/* number of error repititions */
362 	u_long err_suppressed;	/* number of suppressed messages */
363 	struct errorregression *err_stage; /* current error stage */
364 };
365 
366 /**===========================================================================
367  ** refclock instance data
368  **/
369 
370 struct parseunit
371 {
372 	/*
373 	 * NTP management
374 	 */
375 	struct peer         *peer;		/* backlink to peer structure - refclock inactive if 0  */
376 	struct refclockproc *generic;		/* backlink to refclockproc structure */
377 
378 	/*
379 	 * PARSE io
380 	 */
381 	bind_t	     *binding;	        /* io handling binding */
382 
383 	/*
384 	 * parse state
385 	 */
386 	parse_t	      parseio;	        /* io handling structure (user level parsing) */
387 
388 	/*
389 	 * type specific parameters
390 	 */
391 	struct parse_clockinfo   *parse_type;	        /* link to clock description */
392 
393 	/*
394 	 * clock state handling/reporting
395 	 */
396 	u_char	      flags;	        /* flags (leap_control) */
397 	u_long	      lastchange;       /* time (ntp) when last state change accured */
398 	u_long	      statetime[CEVNT_MAX+1]; /* accumulated time of clock states */
399 	u_long        pollneeddata; 	/* current_time(!=0) for receive sample expected in PPS mode */
400 	u_short	      lastformat;       /* last format used */
401 	u_long        lastsync;		/* time (ntp) when clock was last seen fully synchronized */
402         u_long        maxunsync;        /* max time in seconds a receiver is trusted after loosing synchronisation */
403         double        ppsphaseadjust;   /* phase adjustment of PPS time stamp */
404         u_long        lastmissed;       /* time (ntp) when poll didn't get data (powerup heuristic) */
405 	u_long        ppsserial;        /* magic cookie for ppsclock serials (avoids stale ppsclock data) */
406 	int	      ppsfd;	        /* fd to ise for PPS io */
407 #ifdef HAVE_PPSAPI
408         pps_handle_t  ppshandle;        /* store PPSAPI handle */
409         pps_params_t  ppsparams;        /* current PPS parameters */
410         int           hardppsstate;     /* current hard pps state */
411 #endif
412 	parsetime_t   timedata;		/* last (parse module) data */
413 	void         *localdata;        /* optional local, receiver-specific data */
414         unsigned long localstate;       /* private local state */
415 	struct errorinfo errors[ERR_CNT];  /* error state table for suppressing excessive error messages */
416 	struct ctl_var *kv;	        /* additional pseudo variables */
417 	u_long        laststatistic;    /* time when staticstics where output */
418 };
419 
420 
421 /**===========================================================================
422  ** Clockinfo section all parameter for specific clock types
423  ** includes NTP parameters, TTY parameters and IO handling parameters
424  **/
425 
426 static	void	poll_dpoll	P((struct parseunit *));
427 static	void	poll_poll	P((struct peer *));
428 static	int	poll_init	P((struct parseunit *));
429 
430 typedef struct poll_info
431 {
432 	u_long      rate;		/* poll rate - once every "rate" seconds - 0 off */
433 	const char *string;		/* string to send for polling */
434 	u_long      count;		/* number of characters in string */
435 } poll_info_t;
436 
437 #define NO_CL_FLAGS	0
438 #define NO_POLL		0
439 #define NO_INIT		0
440 #define NO_END		0
441 #define NO_EVENT	0
442 #define NO_LCLDATA	0
443 #define NO_MESSAGE	0
444 #define NO_PPSDELAY     0
445 
446 #define DCF_ID		"DCF"	/* generic DCF */
447 #define DCF_A_ID	"DCFa"	/* AM demodulation */
448 #define DCF_P_ID	"DCFp"	/* psuedo random phase shift */
449 #define GPS_ID		"GPS"	/* GPS receiver */
450 
451 #define	NOCLOCK_ROOTDELAY	0.0
452 #define	NOCLOCK_BASEDELAY	0.0
453 #define	NOCLOCK_DESCRIPTION	0
454 #define NOCLOCK_MAXUNSYNC       0
455 #define NOCLOCK_CFLAG           0
456 #define NOCLOCK_IFLAG           0
457 #define NOCLOCK_OFLAG           0
458 #define NOCLOCK_LFLAG           0
459 #define NOCLOCK_ID		"TILT"
460 #define NOCLOCK_POLL		NO_POLL
461 #define NOCLOCK_INIT		NO_INIT
462 #define NOCLOCK_END		NO_END
463 #define NOCLOCK_DATA		NO_LCLDATA
464 #define NOCLOCK_FORMAT		""
465 #define NOCLOCK_TYPE		CTL_SST_TS_UNSPEC
466 #define NOCLOCK_SAMPLES		0
467 #define NOCLOCK_KEEP		0
468 
469 #define DCF_TYPE		CTL_SST_TS_LF
470 #define GPS_TYPE		CTL_SST_TS_UHF
471 
472 /*
473  * receiver specific constants
474  */
475 #define MBG_SPEED		(B9600)
476 #define MBG_CFLAG		(CS7|PARENB|CREAD|CLOCAL|HUPCL|CSTOPB)
477 #define MBG_IFLAG		(IGNBRK|IGNPAR|ISTRIP)
478 #define MBG_OFLAG		0
479 #define MBG_LFLAG		0
480 #define MBG_FLAGS               PARSE_F_PPSONSECOND
481 
482 /*
483  * Meinberg DCF77 receivers
484  */
485 #define	DCFUA31_ROOTDELAY	0.0  /* 0 */
486 #define	DCFUA31_BASEDELAY	0.010  /* 10.7421875ms: 10 ms (+/- 3 ms) */
487 #define	DCFUA31_DESCRIPTION	"Meinberg DCF77 C51 or compatible"
488 #define DCFUA31_MAXUNSYNC       60*30       /* only trust clock for 1/2 hour */
489 #define DCFUA31_SPEED		MBG_SPEED
490 #define DCFUA31_CFLAG           MBG_CFLAG
491 #define DCFUA31_IFLAG           MBG_IFLAG
492 #define DCFUA31_OFLAG           MBG_OFLAG
493 #define DCFUA31_LFLAG           MBG_LFLAG
494 #define DCFUA31_SAMPLES		5
495 #define DCFUA31_KEEP		3
496 #define DCFUA31_FORMAT		"Meinberg Standard"
497 
498 /*
499  * Meinberg DCF PZF535/TCXO (FM/PZF) receiver
500  */
501 #define	DCFPZF535_ROOTDELAY	0.0
502 #define	DCFPZF535_BASEDELAY	0.001968  /* 1.968ms +- 104us (oscilloscope) - relative to start (end of STX) */
503 #define	DCFPZF535_DESCRIPTION	"Meinberg DCF PZF 535/509 / TCXO"
504 #define DCFPZF535_MAXUNSYNC     60*60*12           /* only trust clock for 12 hours
505 						    * @ 5e-8df/f we have accumulated
506 						    * at most 2.16 ms (thus we move to
507 						    * NTP synchronisation */
508 #define DCFPZF535_SPEED		MBG_SPEED
509 #define DCFPZF535_CFLAG         MBG_CFLAG
510 #define DCFPZF535_IFLAG         MBG_IFLAG
511 #define DCFPZF535_OFLAG         MBG_OFLAG
512 #define DCFPZF535_LFLAG         MBG_LFLAG
513 #define DCFPZF535_SAMPLES	       5
514 #define DCFPZF535_KEEP		       3
515 #define DCFPZF535_FORMAT	"Meinberg Standard"
516 
517 /*
518  * Meinberg DCF PZF535/OCXO receiver
519  */
520 #define	DCFPZF535OCXO_ROOTDELAY	0.0
521 #define	DCFPZF535OCXO_BASEDELAY	0.001968 /* 1.968ms +- 104us (oscilloscope) - relative to start (end of STX) */
522 #define	DCFPZF535OCXO_DESCRIPTION "Meinberg DCF PZF 535/509 / OCXO"
523 #define DCFPZF535OCXO_MAXUNSYNC     60*60*96       /* only trust clock for 4 days
524 						    * @ 5e-9df/f we have accumulated
525 						    * at most an error of 1.73 ms
526 						    * (thus we move to NTP synchronisation) */
527 #define DCFPZF535OCXO_SPEED	    MBG_SPEED
528 #define DCFPZF535OCXO_CFLAG         MBG_CFLAG
529 #define DCFPZF535OCXO_IFLAG         MBG_IFLAG
530 #define DCFPZF535OCXO_OFLAG         MBG_OFLAG
531 #define DCFPZF535OCXO_LFLAG         MBG_LFLAG
532 #define DCFPZF535OCXO_SAMPLES		   5
533 #define DCFPZF535OCXO_KEEP	           3
534 #define DCFPZF535OCXO_FORMAT	    "Meinberg Standard"
535 
536 /*
537  * Meinberg GPS16X receiver
538  */
539 static	void	gps16x_message	 P((struct parseunit *, parsetime_t *));
540 static  int     gps16x_poll_init P((struct parseunit *));
541 
542 #define	GPS16X_ROOTDELAY	0.0         /* nothing here */
543 #define	GPS16X_BASEDELAY	0.001968         /* XXX to be fixed ! 1.968ms +- 104us (oscilloscope) - relative to start (end of STX) */
544 #define	GPS16X_DESCRIPTION      "Meinberg GPS16x receiver"
545 #define GPS16X_MAXUNSYNC        60*60*96       /* only trust clock for 4 days
546 						* @ 5e-9df/f we have accumulated
547 						* at most an error of 1.73 ms
548 						* (thus we move to NTP synchronisation) */
549 #define GPS16X_SPEED		B19200
550 #define GPS16X_CFLAG            (CS8|CREAD|CLOCAL|HUPCL)
551 #define GPS16X_IFLAG            (IGNBRK|IGNPAR)
552 #define GPS16X_OFLAG            MBG_OFLAG
553 #define GPS16X_LFLAG            MBG_LFLAG
554 #define GPS16X_POLLRATE	6
555 #define GPS16X_POLLCMD	""
556 #define GPS16X_CMDSIZE	0
557 
558 static poll_info_t gps16x_pollinfo = { GPS16X_POLLRATE, GPS16X_POLLCMD, GPS16X_CMDSIZE };
559 
560 #define GPS16X_INIT		gps16x_poll_init
561 #define GPS16X_POLL	        0
562 #define GPS16X_END		0
563 #define GPS16X_DATA		((void *)(&gps16x_pollinfo))
564 #define GPS16X_MESSAGE		gps16x_message
565 #define GPS16X_ID		GPS_ID
566 #define GPS16X_FORMAT		"Meinberg GPS Extended"
567 #define GPS16X_SAMPLES		5
568 #define GPS16X_KEEP		3
569 
570 /*
571  * ELV DCF7000 Wallclock-Receiver/Switching Clock (Kit)
572  *
573  * This is really not the hottest clock - but before you have nothing ...
574  */
575 #define DCF7000_ROOTDELAY	0.0 /* 0 */
576 #define DCF7000_BASEDELAY	0.405 /* slow blow */
577 #define DCF7000_DESCRIPTION	"ELV DCF7000"
578 #define DCF7000_MAXUNSYNC	(60*5) /* sorry - but it just was not build as a clock */
579 #define DCF7000_SPEED		(B9600)
580 #define DCF7000_CFLAG           (CS8|CREAD|PARENB|PARODD|CLOCAL|HUPCL)
581 #define DCF7000_IFLAG		(IGNBRK)
582 #define DCF7000_OFLAG		0
583 #define DCF7000_LFLAG		0
584 #define DCF7000_SAMPLES		5
585 #define DCF7000_KEEP		3
586 #define DCF7000_FORMAT		"ELV DCF7000"
587 
588 /*
589  * Schmid DCF Receiver Kit
590  *
591  * When the WSDCF clock is operating optimally we want the primary clock
592  * distance to come out at 300 ms.  Thus, peer.distance in the WSDCF peer
593  * structure is set to 290 ms and we compute delays which are at least
594  * 10 ms long.  The following are 290 ms and 10 ms expressed in u_fp format
595  */
596 #define WS_POLLRATE	1	/* every second - watch interdependency with poll routine */
597 #define WS_POLLCMD	"\163"
598 #define WS_CMDSIZE	1
599 
600 static poll_info_t wsdcf_pollinfo = { WS_POLLRATE, WS_POLLCMD, WS_CMDSIZE };
601 
602 #define WSDCF_INIT		poll_init
603 #define WSDCF_POLL		poll_dpoll
604 #define WSDCF_END		0
605 #define WSDCF_DATA		((void *)(&wsdcf_pollinfo))
606 #define	WSDCF_ROOTDELAY		0.0	/* 0 */
607 #define	WSDCF_BASEDELAY	 	0.010	/*  ~  10ms */
608 #define WSDCF_DESCRIPTION	"WS/DCF Receiver"
609 #define WSDCF_FORMAT		"Schmid"
610 #define WSDCF_MAXUNSYNC		(60*60)	/* assume this beast hold at 1 h better than 2 ms XXX-must verify */
611 #define WSDCF_SPEED		(B1200)
612 #define WSDCF_CFLAG		(CS8|CREAD|CLOCAL)
613 #define WSDCF_IFLAG		0
614 #define WSDCF_OFLAG		0
615 #define WSDCF_LFLAG		0
616 #define WSDCF_SAMPLES		5
617 #define WSDCF_KEEP		3
618 
619 /*
620  * RAW DCF77 - input of DCF marks via RS232 - many variants
621  */
622 #define RAWDCF_FLAGS		0
623 #define RAWDCF_ROOTDELAY	0.0 /* 0 */
624 #define RAWDCF_BASEDELAY	0.258
625 #define RAWDCF_FORMAT		"RAW DCF77 Timecode"
626 #define RAWDCF_MAXUNSYNC	(0) /* sorry - its a true receiver - no signal - no time */
627 #define RAWDCF_SPEED		(B50)
628 #ifdef NO_PARENB_IGNPAR /* Was: defined(SYS_IRIX4) || defined(SYS_IRIX5) */
629 /* somehow doesn't grok PARENB & IGNPAR (mj) */
630 # define RAWDCF_CFLAG            (CS8|CREAD|CLOCAL)
631 #else
632 # define RAWDCF_CFLAG            (CS8|CREAD|CLOCAL|PARENB)
633 #endif
634 #ifdef RAWDCF_NO_IGNPAR /* Was: defined(SYS_LINUX) && defined(CLOCK_RAWDCF) */
635 # define RAWDCF_IFLAG		0
636 #else
637 # define RAWDCF_IFLAG		(IGNPAR)
638 #endif
639 #define RAWDCF_OFLAG		0
640 #define RAWDCF_LFLAG		0
641 #define RAWDCF_SAMPLES		20
642 #define RAWDCF_KEEP		12
643 #define RAWDCF_INIT		0
644 
645 /*
646  * RAW DCF variants
647  */
648 /*
649  * Conrad receiver
650  *
651  * simplest (cheapest) DCF clock - e. g. DCF77 receiver by Conrad
652  * (~40DM - roughly $30 ) followed by a level converter for RS232
653  */
654 #define CONRAD_BASEDELAY	0.292 /* Conrad receiver @ 50 Baud on a Sun */
655 #define CONRAD_DESCRIPTION	"RAW DCF77 CODE (Conrad DCF77 receiver module)"
656 
657 /* Gude Analog- und Digitalsystem GmbH 'Expert mouseCLOCK USB v2.0' */
658 #define GUDE_EMC_USB_V20_SPEED            (B4800)
659 #define GUDE_EMC_USB_V20_BASEDELAY        0.425 /* USB serial<->USB converter FTDI232R */
660 #define GUDE_EMC_USB_V20_DESCRIPTION      "RAW DCF77 CODE (Expert mouseCLOCK USB v2.0)"
661 
662 /*
663  * TimeBrick receiver
664  */
665 #define TIMEBRICK_BASEDELAY	0.210 /* TimeBrick @ 50 Baud on a Sun */
666 #define TIMEBRICK_DESCRIPTION	"RAW DCF77 CODE (TimeBrick)"
667 
668 /*
669  * IGEL:clock receiver
670  */
671 #define IGELCLOCK_BASEDELAY	0.258 /* IGEL:clock receiver */
672 #define IGELCLOCK_DESCRIPTION	"RAW DCF77 CODE (IGEL:clock)"
673 #define IGELCLOCK_SPEED		(B1200)
674 #define IGELCLOCK_CFLAG		(CS8|CREAD|HUPCL|CLOCAL)
675 
676 /*
677  * RAWDCF receivers that need to be powered from DTR
678  * (like Expert mouse clock)
679  */
680 static	int	rawdcf_init_1	P((struct parseunit *));
681 #define RAWDCFDTRSET_DESCRIPTION	"RAW DCF77 CODE (DTR SET/RTS CLR)"
682 #define RAWDCFDTRSET_INIT 		rawdcf_init_1
683 
684 /*
685  * RAWDCF receivers that need to be powered from
686  * DTR CLR and RTS SET
687  */
688 static	int	rawdcf_init_2	P((struct parseunit *));
689 #define RAWDCFDTRCLRRTSSET_DESCRIPTION	"RAW DCF77 CODE (DTR CLR/RTS SET)"
690 #define RAWDCFDTRCLRRTSSET_INIT	rawdcf_init_2
691 
692 /*
693  * Trimble GPS receivers (TAIP and TSIP protocols)
694  */
695 #ifndef TRIM_POLLRATE
696 #define TRIM_POLLRATE	0	/* only true direct polling */
697 #endif
698 
699 #define TRIM_TAIPPOLLCMD	">SRM;FR_FLAG=F;EC_FLAG=F<>QTM<"
700 #define TRIM_TAIPCMDSIZE	(sizeof(TRIM_TAIPPOLLCMD)-1)
701 
702 static poll_info_t trimbletaip_pollinfo = { TRIM_POLLRATE, TRIM_TAIPPOLLCMD, TRIM_TAIPCMDSIZE };
703 static	int	trimbletaip_init	P((struct parseunit *));
704 static	void	trimbletaip_event	P((struct parseunit *, int));
705 
706 /* query time & UTC correction data */
707 static char tsipquery[] = { DLE, 0x21, DLE, ETX, DLE, 0x2F, DLE, ETX };
708 
709 static poll_info_t trimbletsip_pollinfo = { TRIM_POLLRATE, tsipquery, sizeof(tsipquery) };
710 static	int	trimbletsip_init	P((struct parseunit *));
711 static	void	trimbletsip_end   	P((struct parseunit *));
712 static	void	trimbletsip_message	P((struct parseunit *, parsetime_t *));
713 static	void	trimbletsip_event	P((struct parseunit *, int));
714 
715 #define TRIMBLETSIP_IDLE_TIME	    (300) /* 5 minutes silence at most */
716 #define TRIMBLE_RESET_HOLDOFF       TRIMBLETSIP_IDLE_TIME
717 
718 #define TRIMBLETAIP_SPEED	    (B4800)
719 #define TRIMBLETAIP_CFLAG           (CS8|CREAD|CLOCAL)
720 #define TRIMBLETAIP_IFLAG           (BRKINT|IGNPAR|ISTRIP|ICRNL|IXON)
721 #define TRIMBLETAIP_OFLAG           (OPOST|ONLCR)
722 #define TRIMBLETAIP_LFLAG           (0)
723 
724 #define TRIMBLETSIP_SPEED	    (B9600)
725 #define TRIMBLETSIP_CFLAG           (CS8|CLOCAL|CREAD|PARENB|PARODD)
726 #define TRIMBLETSIP_IFLAG           (IGNBRK)
727 #define TRIMBLETSIP_OFLAG           (0)
728 #define TRIMBLETSIP_LFLAG           (ICANON)
729 
730 #define TRIMBLETSIP_SAMPLES	    5
731 #define TRIMBLETSIP_KEEP	    3
732 #define TRIMBLETAIP_SAMPLES	    5
733 #define TRIMBLETAIP_KEEP	    3
734 
735 #define TRIMBLETAIP_FLAGS	    (PARSE_F_PPSONSECOND)
736 #define TRIMBLETSIP_FLAGS	    (TRIMBLETAIP_FLAGS)
737 
738 #define TRIMBLETAIP_POLL	    poll_dpoll
739 #define TRIMBLETSIP_POLL	    poll_dpoll
740 
741 #define TRIMBLETAIP_INIT	    trimbletaip_init
742 #define TRIMBLETSIP_INIT	    trimbletsip_init
743 
744 #define TRIMBLETAIP_EVENT	    trimbletaip_event
745 
746 #define TRIMBLETSIP_EVENT	    trimbletsip_event
747 #define TRIMBLETSIP_MESSAGE	    trimbletsip_message
748 
749 #define TRIMBLETAIP_END		    0
750 #define TRIMBLETSIP_END		    trimbletsip_end
751 
752 #define TRIMBLETAIP_DATA	    ((void *)(&trimbletaip_pollinfo))
753 #define TRIMBLETSIP_DATA	    ((void *)(&trimbletsip_pollinfo))
754 
755 #define TRIMBLETAIP_ID		    GPS_ID
756 #define TRIMBLETSIP_ID		    GPS_ID
757 
758 #define TRIMBLETAIP_FORMAT	    "Trimble TAIP"
759 #define TRIMBLETSIP_FORMAT	    "Trimble TSIP"
760 
761 #define TRIMBLETAIP_ROOTDELAY        0x0
762 #define TRIMBLETSIP_ROOTDELAY        0x0
763 
764 #define TRIMBLETAIP_BASEDELAY        0.0
765 #define TRIMBLETSIP_BASEDELAY        0.020	/* GPS time message latency */
766 
767 #define TRIMBLETAIP_DESCRIPTION      "Trimble GPS (TAIP) receiver"
768 #define TRIMBLETSIP_DESCRIPTION      "Trimble GPS (TSIP) receiver"
769 
770 #define TRIMBLETAIP_MAXUNSYNC        0
771 #define TRIMBLETSIP_MAXUNSYNC        0
772 
773 #define TRIMBLETAIP_EOL		    '<'
774 
775 /*
776  * RadioCode Clocks RCC 800 receiver
777  */
778 #define RCC_POLLRATE   0       /* only true direct polling */
779 #define RCC_POLLCMD    "\r"
780 #define RCC_CMDSIZE    1
781 
782 static poll_info_t rcc8000_pollinfo = { RCC_POLLRATE, RCC_POLLCMD, RCC_CMDSIZE };
783 #define RCC8000_FLAGS		0
784 #define RCC8000_POLL            poll_dpoll
785 #define RCC8000_INIT            poll_init
786 #define RCC8000_END             0
787 #define RCC8000_DATA            ((void *)(&rcc8000_pollinfo))
788 #define RCC8000_ROOTDELAY       0.0
789 #define RCC8000_BASEDELAY       0.0
790 #define RCC8000_ID              "MSF"
791 #define RCC8000_DESCRIPTION     "RCC 8000 MSF Receiver"
792 #define RCC8000_FORMAT          "Radiocode RCC8000"
793 #define RCC8000_MAXUNSYNC       (60*60) /* should be ok for an hour */
794 #define RCC8000_SPEED		(B2400)
795 #define RCC8000_CFLAG           (CS8|CREAD|CLOCAL)
796 #define RCC8000_IFLAG           (IGNBRK|IGNPAR)
797 #define RCC8000_OFLAG           0
798 #define RCC8000_LFLAG           0
799 #define RCC8000_SAMPLES         5
800 #define RCC8000_KEEP	        3
801 
802 /*
803  * Hopf Radio clock 6021 Format
804  *
805  */
806 #define HOPF6021_ROOTDELAY	0.0
807 #define HOPF6021_BASEDELAY	0.0
808 #define HOPF6021_DESCRIPTION	"HOPF 6021"
809 #define HOPF6021_FORMAT         "hopf Funkuhr 6021"
810 #define HOPF6021_MAXUNSYNC	(60*60)  /* should be ok for an hour */
811 #define HOPF6021_SPEED         (B9600)
812 #define HOPF6021_CFLAG          (CS8|CREAD|CLOCAL)
813 #define HOPF6021_IFLAG		(IGNBRK|ISTRIP)
814 #define HOPF6021_OFLAG		0
815 #define HOPF6021_LFLAG		0
816 #define HOPF6021_FLAGS          0
817 #define HOPF6021_SAMPLES        5
818 #define HOPF6021_KEEP	        3
819 
820 /*
821  * Diem's Computime Radio Clock Receiver
822  */
823 #define COMPUTIME_FLAGS       0
824 #define COMPUTIME_ROOTDELAY   0.0
825 #define COMPUTIME_BASEDELAY   0.0
826 #define COMPUTIME_ID          DCF_ID
827 #define COMPUTIME_DESCRIPTION "Diem's Computime receiver"
828 #define COMPUTIME_FORMAT      "Diem's Computime Radio Clock"
829 #define COMPUTIME_TYPE        DCF_TYPE
830 #define COMPUTIME_MAXUNSYNC   (60*60)       /* only trust clock for 1 hour */
831 #define COMPUTIME_SPEED       (B9600)
832 #define COMPUTIME_CFLAG       (CSTOPB|CS7|CREAD|CLOCAL)
833 #define COMPUTIME_IFLAG       (IGNBRK|IGNPAR|ISTRIP)
834 #define COMPUTIME_OFLAG       0
835 #define COMPUTIME_LFLAG       0
836 #define COMPUTIME_SAMPLES     5
837 #define COMPUTIME_KEEP        3
838 
839 /*
840  * Varitext Radio Clock Receiver
841  */
842 #define VARITEXT_FLAGS       0
843 #define VARITEXT_ROOTDELAY   0.0
844 #define VARITEXT_BASEDELAY   0.0
845 #define VARITEXT_ID          "MSF"
846 #define VARITEXT_DESCRIPTION "Varitext receiver"
847 #define VARITEXT_FORMAT      "Varitext Radio Clock"
848 #define VARITEXT_TYPE        DCF_TYPE
849 #define VARITEXT_MAXUNSYNC   (60*60)       /* only trust clock for 1 hour */
850 #define VARITEXT_SPEED       (B9600)
851 #define VARITEXT_CFLAG       (CS7|CREAD|CLOCAL|PARENB|PARODD)
852 #define VARITEXT_IFLAG       (IGNPAR|IGNBRK|INPCK) /*|ISTRIP)*/
853 #define VARITEXT_OFLAG       0
854 #define VARITEXT_LFLAG       0
855 #define VARITEXT_SAMPLES     32
856 #define VARITEXT_KEEP        20
857 
858 static struct parse_clockinfo
859 {
860 	u_long  cl_flags;		/* operation flags (io modes) */
861   void  (*cl_poll)    P((struct parseunit *));			/* active poll routine */
862   int   (*cl_init)    P((struct parseunit *));			/* active poll init routine */
863   void  (*cl_event)   P((struct parseunit *, int));		/* special event handling (e.g. reset clock) */
864   void  (*cl_end)     P((struct parseunit *));			/* active poll end routine */
865   void  (*cl_message) P((struct parseunit *, parsetime_t *));	/* process a lower layer message */
866 	void   *cl_data;		/* local data area for "poll" mechanism */
867 	double    cl_rootdelay;		/* rootdelay */
868 	double    cl_basedelay;		/* current offset by which the RS232
869 				time code is delayed from the actual time */
870 	const char *cl_id;		/* ID code */
871 	const char *cl_description;		/* device name */
872 	const char *cl_format;		/* fixed format */
873 	u_char  cl_type;		/* clock type (ntp control) */
874 	u_long  cl_maxunsync;		/* time to trust oscillator after losing synch */
875 	u_long  cl_speed;		/* terminal input & output baudrate */
876 	u_long  cl_cflag;             /* terminal control flags */
877 	u_long  cl_iflag;             /* terminal input flags */
878 	u_long  cl_oflag;             /* terminal output flags */
879 	u_long  cl_lflag;             /* terminal local flags */
880 	u_long  cl_samples;	      /* samples for median filter */
881 	u_long  cl_keep;              /* samples for median filter to keep */
882 } parse_clockinfo[] =
883 {
884 	{				/* mode 0 */
885 		MBG_FLAGS,
886 		NO_POLL,
887 		NO_INIT,
888 		NO_EVENT,
889 		NO_END,
890 		NO_MESSAGE,
891 		NO_LCLDATA,
892 		DCFPZF535_ROOTDELAY,
893 		DCFPZF535_BASEDELAY,
894 		DCF_P_ID,
895 		DCFPZF535_DESCRIPTION,
896 		DCFPZF535_FORMAT,
897 		DCF_TYPE,
898 		DCFPZF535_MAXUNSYNC,
899 		DCFPZF535_SPEED,
900 		DCFPZF535_CFLAG,
901 		DCFPZF535_IFLAG,
902 		DCFPZF535_OFLAG,
903 		DCFPZF535_LFLAG,
904 		DCFPZF535_SAMPLES,
905 		DCFPZF535_KEEP
906 	},
907 	{				/* mode 1 */
908 		MBG_FLAGS,
909 		NO_POLL,
910 		NO_INIT,
911 		NO_EVENT,
912 		NO_END,
913 		NO_MESSAGE,
914 		NO_LCLDATA,
915 		DCFPZF535OCXO_ROOTDELAY,
916 		DCFPZF535OCXO_BASEDELAY,
917 		DCF_P_ID,
918 		DCFPZF535OCXO_DESCRIPTION,
919 		DCFPZF535OCXO_FORMAT,
920 		DCF_TYPE,
921 		DCFPZF535OCXO_MAXUNSYNC,
922 		DCFPZF535OCXO_SPEED,
923 		DCFPZF535OCXO_CFLAG,
924 		DCFPZF535OCXO_IFLAG,
925 		DCFPZF535OCXO_OFLAG,
926 		DCFPZF535OCXO_LFLAG,
927 		DCFPZF535OCXO_SAMPLES,
928 		DCFPZF535OCXO_KEEP
929 	},
930 	{				/* mode 2 */
931 		MBG_FLAGS,
932 		NO_POLL,
933 		NO_INIT,
934 		NO_EVENT,
935 		NO_END,
936 		NO_MESSAGE,
937 		NO_LCLDATA,
938 		DCFUA31_ROOTDELAY,
939 		DCFUA31_BASEDELAY,
940 		DCF_A_ID,
941 		DCFUA31_DESCRIPTION,
942 		DCFUA31_FORMAT,
943 		DCF_TYPE,
944 		DCFUA31_MAXUNSYNC,
945 		DCFUA31_SPEED,
946 		DCFUA31_CFLAG,
947 		DCFUA31_IFLAG,
948 		DCFUA31_OFLAG,
949 		DCFUA31_LFLAG,
950 		DCFUA31_SAMPLES,
951 		DCFUA31_KEEP
952 	},
953 	{				/* mode 3 */
954 		MBG_FLAGS,
955 		NO_POLL,
956 		NO_INIT,
957 		NO_EVENT,
958 		NO_END,
959 		NO_MESSAGE,
960 		NO_LCLDATA,
961 		DCF7000_ROOTDELAY,
962 		DCF7000_BASEDELAY,
963 		DCF_A_ID,
964 		DCF7000_DESCRIPTION,
965 		DCF7000_FORMAT,
966 		DCF_TYPE,
967 		DCF7000_MAXUNSYNC,
968 		DCF7000_SPEED,
969 		DCF7000_CFLAG,
970 		DCF7000_IFLAG,
971 		DCF7000_OFLAG,
972 		DCF7000_LFLAG,
973 		DCF7000_SAMPLES,
974 		DCF7000_KEEP
975 	},
976 	{				/* mode 4 */
977 		NO_CL_FLAGS,
978 		WSDCF_POLL,
979 		WSDCF_INIT,
980 		NO_EVENT,
981 		WSDCF_END,
982 		NO_MESSAGE,
983 		WSDCF_DATA,
984 		WSDCF_ROOTDELAY,
985 		WSDCF_BASEDELAY,
986 		DCF_A_ID,
987 		WSDCF_DESCRIPTION,
988 		WSDCF_FORMAT,
989 		DCF_TYPE,
990 		WSDCF_MAXUNSYNC,
991 		WSDCF_SPEED,
992 		WSDCF_CFLAG,
993 		WSDCF_IFLAG,
994 		WSDCF_OFLAG,
995 		WSDCF_LFLAG,
996 		WSDCF_SAMPLES,
997 		WSDCF_KEEP
998 	},
999 	{				/* mode 5 */
1000 		RAWDCF_FLAGS,
1001 		NO_POLL,
1002 		RAWDCF_INIT,
1003 		NO_EVENT,
1004 		NO_END,
1005 		NO_MESSAGE,
1006 		NO_LCLDATA,
1007 		RAWDCF_ROOTDELAY,
1008 		CONRAD_BASEDELAY,
1009 		DCF_A_ID,
1010 		CONRAD_DESCRIPTION,
1011 		RAWDCF_FORMAT,
1012 		DCF_TYPE,
1013 		RAWDCF_MAXUNSYNC,
1014 		RAWDCF_SPEED,
1015 		RAWDCF_CFLAG,
1016 		RAWDCF_IFLAG,
1017 		RAWDCF_OFLAG,
1018 		RAWDCF_LFLAG,
1019 		RAWDCF_SAMPLES,
1020 		RAWDCF_KEEP
1021 	},
1022 	{				/* mode 6 */
1023 		RAWDCF_FLAGS,
1024 		NO_POLL,
1025 		RAWDCF_INIT,
1026 		NO_EVENT,
1027 		NO_END,
1028 		NO_MESSAGE,
1029 		NO_LCLDATA,
1030 		RAWDCF_ROOTDELAY,
1031 		TIMEBRICK_BASEDELAY,
1032 		DCF_A_ID,
1033 		TIMEBRICK_DESCRIPTION,
1034 		RAWDCF_FORMAT,
1035 		DCF_TYPE,
1036 		RAWDCF_MAXUNSYNC,
1037 		RAWDCF_SPEED,
1038 		RAWDCF_CFLAG,
1039 		RAWDCF_IFLAG,
1040 		RAWDCF_OFLAG,
1041 		RAWDCF_LFLAG,
1042 		RAWDCF_SAMPLES,
1043 		RAWDCF_KEEP
1044 	},
1045 	{				/* mode 7 */
1046 		MBG_FLAGS,
1047 		GPS16X_POLL,
1048 		GPS16X_INIT,
1049 		NO_EVENT,
1050 		GPS16X_END,
1051 		GPS16X_MESSAGE,
1052 		GPS16X_DATA,
1053 		GPS16X_ROOTDELAY,
1054 		GPS16X_BASEDELAY,
1055 		GPS16X_ID,
1056 		GPS16X_DESCRIPTION,
1057 		GPS16X_FORMAT,
1058 		GPS_TYPE,
1059 		GPS16X_MAXUNSYNC,
1060 		GPS16X_SPEED,
1061 		GPS16X_CFLAG,
1062 		GPS16X_IFLAG,
1063 		GPS16X_OFLAG,
1064 		GPS16X_LFLAG,
1065 		GPS16X_SAMPLES,
1066 		GPS16X_KEEP
1067 	},
1068 	{				/* mode 8 */
1069 		RAWDCF_FLAGS,
1070 		NO_POLL,
1071 		NO_INIT,
1072 		NO_EVENT,
1073 		NO_END,
1074 		NO_MESSAGE,
1075 		NO_LCLDATA,
1076 		RAWDCF_ROOTDELAY,
1077 		IGELCLOCK_BASEDELAY,
1078 		DCF_A_ID,
1079 		IGELCLOCK_DESCRIPTION,
1080 		RAWDCF_FORMAT,
1081 		DCF_TYPE,
1082 		RAWDCF_MAXUNSYNC,
1083 		IGELCLOCK_SPEED,
1084 		IGELCLOCK_CFLAG,
1085 		RAWDCF_IFLAG,
1086 		RAWDCF_OFLAG,
1087 		RAWDCF_LFLAG,
1088 		RAWDCF_SAMPLES,
1089 		RAWDCF_KEEP
1090 	},
1091 	{				/* mode 9 */
1092 		TRIMBLETAIP_FLAGS,
1093 #if TRIM_POLLRATE		/* DHD940515: Allow user config */
1094 		NO_POLL,
1095 #else
1096 		TRIMBLETAIP_POLL,
1097 #endif
1098 		TRIMBLETAIP_INIT,
1099 		TRIMBLETAIP_EVENT,
1100 		TRIMBLETAIP_END,
1101 		NO_MESSAGE,
1102 		TRIMBLETAIP_DATA,
1103 		TRIMBLETAIP_ROOTDELAY,
1104 		TRIMBLETAIP_BASEDELAY,
1105 		TRIMBLETAIP_ID,
1106 		TRIMBLETAIP_DESCRIPTION,
1107 		TRIMBLETAIP_FORMAT,
1108 		GPS_TYPE,
1109 		TRIMBLETAIP_MAXUNSYNC,
1110 		TRIMBLETAIP_SPEED,
1111 		TRIMBLETAIP_CFLAG,
1112 		TRIMBLETAIP_IFLAG,
1113 		TRIMBLETAIP_OFLAG,
1114 		TRIMBLETAIP_LFLAG,
1115 		TRIMBLETAIP_SAMPLES,
1116 		TRIMBLETAIP_KEEP
1117 	},
1118 	{				/* mode 10 */
1119 		TRIMBLETSIP_FLAGS,
1120 #if TRIM_POLLRATE		/* DHD940515: Allow user config */
1121 		NO_POLL,
1122 #else
1123 		TRIMBLETSIP_POLL,
1124 #endif
1125 		TRIMBLETSIP_INIT,
1126 		TRIMBLETSIP_EVENT,
1127 		TRIMBLETSIP_END,
1128 		TRIMBLETSIP_MESSAGE,
1129 		TRIMBLETSIP_DATA,
1130 		TRIMBLETSIP_ROOTDELAY,
1131 		TRIMBLETSIP_BASEDELAY,
1132 		TRIMBLETSIP_ID,
1133 		TRIMBLETSIP_DESCRIPTION,
1134 		TRIMBLETSIP_FORMAT,
1135 		GPS_TYPE,
1136 		TRIMBLETSIP_MAXUNSYNC,
1137 		TRIMBLETSIP_SPEED,
1138 		TRIMBLETSIP_CFLAG,
1139 		TRIMBLETSIP_IFLAG,
1140 		TRIMBLETSIP_OFLAG,
1141 		TRIMBLETSIP_LFLAG,
1142 		TRIMBLETSIP_SAMPLES,
1143 		TRIMBLETSIP_KEEP
1144 	},
1145 	{                             /* mode 11 */
1146 		NO_CL_FLAGS,
1147 		RCC8000_POLL,
1148 		RCC8000_INIT,
1149 		NO_EVENT,
1150 		RCC8000_END,
1151 		NO_MESSAGE,
1152 		RCC8000_DATA,
1153 		RCC8000_ROOTDELAY,
1154 		RCC8000_BASEDELAY,
1155 		RCC8000_ID,
1156 		RCC8000_DESCRIPTION,
1157 		RCC8000_FORMAT,
1158 		DCF_TYPE,
1159 		RCC8000_MAXUNSYNC,
1160 		RCC8000_SPEED,
1161 		RCC8000_CFLAG,
1162 		RCC8000_IFLAG,
1163 		RCC8000_OFLAG,
1164 		RCC8000_LFLAG,
1165 		RCC8000_SAMPLES,
1166 		RCC8000_KEEP
1167 	},
1168 	{                             /* mode 12 */
1169 		HOPF6021_FLAGS,
1170 		NO_POLL,
1171 		NO_INIT,
1172 		NO_EVENT,
1173 		NO_END,
1174 		NO_MESSAGE,
1175 		NO_LCLDATA,
1176 		HOPF6021_ROOTDELAY,
1177 		HOPF6021_BASEDELAY,
1178 		DCF_ID,
1179 		HOPF6021_DESCRIPTION,
1180 		HOPF6021_FORMAT,
1181 		DCF_TYPE,
1182 		HOPF6021_MAXUNSYNC,
1183 		HOPF6021_SPEED,
1184 		HOPF6021_CFLAG,
1185 		HOPF6021_IFLAG,
1186 		HOPF6021_OFLAG,
1187 		HOPF6021_LFLAG,
1188 		HOPF6021_SAMPLES,
1189 		HOPF6021_KEEP
1190 	},
1191 	{                            /* mode 13 */
1192 		COMPUTIME_FLAGS,
1193 		NO_POLL,
1194 		NO_INIT,
1195 		NO_EVENT,
1196 		NO_END,
1197 		NO_MESSAGE,
1198 		NO_LCLDATA,
1199 		COMPUTIME_ROOTDELAY,
1200 		COMPUTIME_BASEDELAY,
1201 		COMPUTIME_ID,
1202 		COMPUTIME_DESCRIPTION,
1203 		COMPUTIME_FORMAT,
1204 		COMPUTIME_TYPE,
1205 		COMPUTIME_MAXUNSYNC,
1206 		COMPUTIME_SPEED,
1207 		COMPUTIME_CFLAG,
1208 		COMPUTIME_IFLAG,
1209 		COMPUTIME_OFLAG,
1210 		COMPUTIME_LFLAG,
1211 		COMPUTIME_SAMPLES,
1212 		COMPUTIME_KEEP
1213 	},
1214 	{				/* mode 14 */
1215 		RAWDCF_FLAGS,
1216 		NO_POLL,
1217 		RAWDCFDTRSET_INIT,
1218 		NO_EVENT,
1219 		NO_END,
1220 		NO_MESSAGE,
1221 		NO_LCLDATA,
1222 		RAWDCF_ROOTDELAY,
1223 		RAWDCF_BASEDELAY,
1224 		DCF_A_ID,
1225 		RAWDCFDTRSET_DESCRIPTION,
1226 		RAWDCF_FORMAT,
1227 		DCF_TYPE,
1228 		RAWDCF_MAXUNSYNC,
1229 		RAWDCF_SPEED,
1230 		RAWDCF_CFLAG,
1231 		RAWDCF_IFLAG,
1232 		RAWDCF_OFLAG,
1233 		RAWDCF_LFLAG,
1234 		RAWDCF_SAMPLES,
1235 		RAWDCF_KEEP
1236 	},
1237 	{				/* mode 15 */
1238 		0,				/* operation flags (io modes) */
1239   		NO_POLL,			/* active poll routine */
1240 		NO_INIT,			/* active poll init routine */
1241   		NO_EVENT,		        /* special event handling (e.g. reset clock) */
1242   		NO_END,				/* active poll end routine */
1243   		NO_MESSAGE,			/* process a lower layer message */
1244 		NO_LCLDATA,			/* local data area for "poll" mechanism */
1245 		0,				/* rootdelay */
1246 		11.0 /* bits */ / 9600,		/* current offset by which the RS232
1247 				           	time code is delayed from the actual time */
1248 		DCF_ID,				/* ID code */
1249 		"WHARTON 400A Series clock",	/* device name */
1250 		"WHARTON 400A Series clock Output Format 1",	/* fixed format */
1251 			/* Must match a format-name in a libparse/clk_xxx.c file */
1252 		DCF_TYPE,			/* clock type (ntp control) */
1253 		(1*60*60),		        /* time to trust oscillator after losing synch */
1254 		B9600,				/* terminal input & output baudrate */
1255 		(CS8|CREAD|PARENB|CLOCAL|HUPCL),/* terminal control flags */
1256 		0,				/* terminal input flags */
1257 		0,				/* terminal output flags */
1258 		0,				/* terminal local flags */
1259 		5,				/* samples for median filter */
1260 		3,				/* samples for median filter to keep */
1261 	},
1262 	{				/* mode 16 - RAWDCF RTS set, DTR clr */
1263 		RAWDCF_FLAGS,
1264 		NO_POLL,
1265 		RAWDCFDTRCLRRTSSET_INIT,
1266 		NO_EVENT,
1267 		NO_END,
1268 		NO_MESSAGE,
1269 		NO_LCLDATA,
1270 		RAWDCF_ROOTDELAY,
1271 		RAWDCF_BASEDELAY,
1272 		DCF_A_ID,
1273 		RAWDCFDTRCLRRTSSET_DESCRIPTION,
1274 		RAWDCF_FORMAT,
1275 		DCF_TYPE,
1276 		RAWDCF_MAXUNSYNC,
1277 		RAWDCF_SPEED,
1278 		RAWDCF_CFLAG,
1279 		RAWDCF_IFLAG,
1280 		RAWDCF_OFLAG,
1281 		RAWDCF_LFLAG,
1282 		RAWDCF_SAMPLES,
1283 		RAWDCF_KEEP
1284 	},
1285         {                            /* mode 17 */
1286                 VARITEXT_FLAGS,
1287                 NO_POLL,
1288                 NO_INIT,
1289                 NO_EVENT,
1290                 NO_END,
1291                 NO_MESSAGE,
1292                 NO_LCLDATA,
1293                 VARITEXT_ROOTDELAY,
1294                 VARITEXT_BASEDELAY,
1295                 VARITEXT_ID,
1296                 VARITEXT_DESCRIPTION,
1297                 VARITEXT_FORMAT,
1298                 VARITEXT_TYPE,
1299                 VARITEXT_MAXUNSYNC,
1300                 VARITEXT_SPEED,
1301                 VARITEXT_CFLAG,
1302                 VARITEXT_IFLAG,
1303                 VARITEXT_OFLAG,
1304                 VARITEXT_LFLAG,
1305                 VARITEXT_SAMPLES,
1306                 VARITEXT_KEEP
1307         },
1308 	{				/* mode 18 */
1309 		MBG_FLAGS,
1310 		NO_POLL,
1311 		NO_INIT,
1312 		NO_EVENT,
1313 		GPS16X_END,
1314 		GPS16X_MESSAGE,
1315 		GPS16X_DATA,
1316 		GPS16X_ROOTDELAY,
1317 		GPS16X_BASEDELAY,
1318 		GPS16X_ID,
1319 		GPS16X_DESCRIPTION,
1320 		GPS16X_FORMAT,
1321 		GPS_TYPE,
1322 		GPS16X_MAXUNSYNC,
1323 		GPS16X_SPEED,
1324 		GPS16X_CFLAG,
1325 		GPS16X_IFLAG,
1326 		GPS16X_OFLAG,
1327 		GPS16X_LFLAG,
1328 		GPS16X_SAMPLES,
1329 		GPS16X_KEEP
1330 	},
1331 	{				/* mode 19 */
1332 		RAWDCF_FLAGS,
1333 		NO_POLL,
1334 		RAWDCF_INIT,
1335 		NO_EVENT,
1336 		NO_END,
1337 		NO_MESSAGE,
1338 		NO_LCLDATA,
1339 		RAWDCF_ROOTDELAY,
1340 		GUDE_EMC_USB_V20_BASEDELAY,
1341 		DCF_A_ID,
1342 		GUDE_EMC_USB_V20_DESCRIPTION,
1343 		RAWDCF_FORMAT,
1344 		DCF_TYPE,
1345 		RAWDCF_MAXUNSYNC,
1346 		GUDE_EMC_USB_V20_SPEED,
1347 		RAWDCF_CFLAG,
1348 		RAWDCF_IFLAG,
1349 		RAWDCF_OFLAG,
1350 		RAWDCF_LFLAG,
1351 		RAWDCF_SAMPLES,
1352 		RAWDCF_KEEP
1353 	},
1354 };
1355 
1356 static int ncltypes = sizeof(parse_clockinfo) / sizeof(struct parse_clockinfo);
1357 
1358 #define CLK_REALTYPE(x) ((int)(((x)->ttl) & 0x7F))
1359 #define CLK_TYPE(x)	((CLK_REALTYPE(x) >= ncltypes) ? ~0 : CLK_REALTYPE(x))
1360 #define CLK_UNIT(x)	((int)REFCLOCKUNIT(&(x)->srcadr))
1361 #define CLK_PPS(x)	(((x)->ttl) & 0x80)
1362 
1363 /*
1364  * Other constant stuff
1365  */
1366 #define	PARSEHSREFID	0x7f7f08ff	/* 127.127.8.255 refid for hi strata */
1367 
1368 #define PARSESTATISTICS   (60*60)	        /* output state statistics every hour */
1369 
1370 static int notice = 0;
1371 
1372 #define PARSE_STATETIME(parse, i) ((parse->generic->currentstatus == i) ? parse->statetime[i] + current_time - parse->lastchange : parse->statetime[i])
1373 
1374 static void parse_event   P((struct parseunit *, int));
1375 static void parse_process P((struct parseunit *, parsetime_t *));
1376 static void clear_err     P((struct parseunit *, u_long));
1377 static int  list_err      P((struct parseunit *, u_long));
1378 static char * l_mktime    P((u_long));
1379 
1380 /**===========================================================================
1381  ** implementation error message regression module
1382  **/
1383 static void
1384 clear_err(
1385 	struct parseunit *parse,
1386 	u_long            lstate
1387 	)
1388 {
1389 	if (lstate == ERR_ALL)
1390 	{
1391 		int i;
1392 
1393 		for (i = 0; i < ERR_CNT; i++)
1394 		{
1395 			parse->errors[i].err_stage   = err_tbl[i];
1396 			parse->errors[i].err_cnt     = 0;
1397 			parse->errors[i].err_last    = 0;
1398 			parse->errors[i].err_started = 0;
1399 			parse->errors[i].err_suppressed = 0;
1400 		}
1401 	}
1402 	else
1403 	{
1404 		parse->errors[lstate].err_stage   = err_tbl[lstate];
1405 		parse->errors[lstate].err_cnt     = 0;
1406 		parse->errors[lstate].err_last    = 0;
1407 		parse->errors[lstate].err_started = 0;
1408 		parse->errors[lstate].err_suppressed = 0;
1409 	}
1410 }
1411 
1412 static int
1413 list_err(
1414 	struct parseunit *parse,
1415 	u_long            lstate
1416 	)
1417 {
1418 	int do_it;
1419 	struct errorinfo *err = &parse->errors[lstate];
1420 
1421 	if (err->err_started == 0)
1422 	{
1423 		err->err_started = current_time;
1424 	}
1425 
1426 	do_it = (current_time - err->err_last) >= err->err_stage->err_delay;
1427 
1428 	if (do_it)
1429 	    err->err_cnt++;
1430 
1431 	if (err->err_stage->err_count &&
1432 	    (err->err_cnt >= err->err_stage->err_count))
1433 	{
1434 		err->err_stage++;
1435 		err->err_cnt = 0;
1436 	}
1437 
1438 	if (!err->err_cnt && do_it)
1439 	    msyslog(LOG_INFO, "PARSE receiver #%d: interval for following error message class is at least %s",
1440 		    CLK_UNIT(parse->peer), l_mktime(err->err_stage->err_delay));
1441 
1442 	if (!do_it)
1443 	    err->err_suppressed++;
1444 	else
1445 	    err->err_last = current_time;
1446 
1447 	if (do_it && err->err_suppressed)
1448 	{
1449 		msyslog(LOG_INFO, "PARSE receiver #%d: %ld message%s suppressed, error condition class persists for %s",
1450 			CLK_UNIT(parse->peer), err->err_suppressed, (err->err_suppressed == 1) ? " was" : "s where",
1451 			l_mktime(current_time - err->err_started));
1452 		err->err_suppressed = 0;
1453 	}
1454 
1455 	return do_it;
1456 }
1457 
1458 /*--------------------------------------------------
1459  * mkreadable - make a printable ascii string (without
1460  * embedded quotes so that the ntpq protocol isn't
1461  * fooled
1462  */
1463 #ifndef isprint
1464 #define isprint(_X_) (((_X_) > 0x1F) && ((_X_) < 0x7F))
1465 #endif
1466 
1467 static char *
1468 mkreadable(
1469 	char  *buffer,
1470 	long  blen,
1471 	const char  *src,
1472 	u_long  srclen,
1473 	int hex
1474 	)
1475 {
1476 	char *b    = buffer;
1477 	char *endb = (char *)0;
1478 
1479 	if (blen < 4)
1480 		return (char *)0;		/* don't bother with mini buffers */
1481 
1482 	endb = buffer + blen - 4;
1483 
1484 	blen--;			/* account for '\0' */
1485 
1486 	while (blen && srclen--)
1487 	{
1488 		if (!hex &&             /* no binary only */
1489 		    (*src != '\\') &&   /* no plain \ */
1490 		    (*src != '"') &&    /* no " */
1491 		    isprint((int)*src))	/* only printables */
1492 		{			/* they are easy... */
1493 			*buffer++ = *src++;
1494 			blen--;
1495 		}
1496 		else
1497 		{
1498 			if (blen < 4)
1499 			{
1500 				while (blen--)
1501 				{
1502 					*buffer++ = '.';
1503 				}
1504 				*buffer = '\0';
1505 				return b;
1506 			}
1507 			else
1508 			{
1509 				if (*src == '\\')
1510 				{
1511 					strcpy(buffer,"\\\\");
1512 					buffer += 2;
1513 					blen   -= 2;
1514 					src++;
1515 				}
1516 				else
1517 				{
1518 					sprintf(buffer, "\\x%02x", *src++);
1519 					blen   -= 4;
1520 					buffer += 4;
1521 				}
1522 			}
1523 		}
1524 		if (srclen && !blen && endb) /* overflow - set last chars to ... */
1525 			strcpy(endb, "...");
1526 	}
1527 
1528 	*buffer = '\0';
1529 	return b;
1530 }
1531 
1532 
1533 /*--------------------------------------------------
1534  * mkascii - make a printable ascii string
1535  * assumes (unless defined better) 7-bit ASCII
1536  */
1537 static char *
1538 mkascii(
1539 	char  *buffer,
1540 	long  blen,
1541 	const char  *src,
1542 	u_long  srclen
1543 	)
1544 {
1545 	return mkreadable(buffer, blen, src, srclen, 0);
1546 }
1547 
1548 /**===========================================================================
1549  ** implementation of i/o handling methods
1550  ** (all STREAM, partial STREAM, user level)
1551  **/
1552 
1553 /*
1554  * define possible io handling methods
1555  */
1556 #ifdef STREAM
1557 static int  ppsclock_init   P((struct parseunit *));
1558 static int  stream_init     P((struct parseunit *));
1559 static void stream_end      P((struct parseunit *));
1560 static int  stream_enable   P((struct parseunit *));
1561 static int  stream_disable  P((struct parseunit *));
1562 static int  stream_setcs    P((struct parseunit *, parsectl_t *));
1563 static int  stream_getfmt   P((struct parseunit *, parsectl_t *));
1564 static int  stream_setfmt   P((struct parseunit *, parsectl_t *));
1565 static int  stream_timecode P((struct parseunit *, parsectl_t *));
1566 static void stream_receive  P((struct recvbuf *));
1567 #endif
1568 
1569 static int  local_init     P((struct parseunit *));
1570 static void local_end      P((struct parseunit *));
1571 static int  local_nop      P((struct parseunit *));
1572 static int  local_setcs    P((struct parseunit *, parsectl_t *));
1573 static int  local_getfmt   P((struct parseunit *, parsectl_t *));
1574 static int  local_setfmt   P((struct parseunit *, parsectl_t *));
1575 static int  local_timecode P((struct parseunit *, parsectl_t *));
1576 static void local_receive  P((struct recvbuf *));
1577 static int  local_input    P((struct recvbuf *));
1578 
1579 static bind_t io_bindings[] =
1580 {
1581 #ifdef STREAM
1582 	{
1583 		"parse STREAM",
1584 		stream_init,
1585 		stream_end,
1586 		stream_setcs,
1587 		stream_disable,
1588 		stream_enable,
1589 		stream_getfmt,
1590 		stream_setfmt,
1591 		stream_timecode,
1592 		stream_receive,
1593 		0,
1594 	},
1595 	{
1596 		"ppsclock STREAM",
1597 		ppsclock_init,
1598 		local_end,
1599 		local_setcs,
1600 		local_nop,
1601 		local_nop,
1602 		local_getfmt,
1603 		local_setfmt,
1604 		local_timecode,
1605 		local_receive,
1606 		local_input,
1607 	},
1608 #endif
1609 	{
1610 		"normal",
1611 		local_init,
1612 		local_end,
1613 		local_setcs,
1614 		local_nop,
1615 		local_nop,
1616 		local_getfmt,
1617 		local_setfmt,
1618 		local_timecode,
1619 		local_receive,
1620 		local_input,
1621 	},
1622 	{
1623 		(char *)0,
1624 	}
1625 };
1626 
1627 #ifdef STREAM
1628 
1629 #define fix_ts(_X_) \
1630                         if ((&(_X_))->tv.tv_usec >= 1000000)                \
1631                           {                                                 \
1632 			    (&(_X_))->tv.tv_usec -= 1000000;                \
1633 			    (&(_X_))->tv.tv_sec  += 1;                      \
1634 			  }
1635 
1636 #define cvt_ts(_X_, _Y_) \
1637                         {                                                   \
1638 			  l_fp ts;				            \
1639 			  fix_ts((_X_));                                    \
1640 			  if (!buftvtots((const char *)&(&(_X_))->tv, &ts)) \
1641 			    {                                               \
1642                               ERR(ERR_BADDATA)	 		            \
1643                                 msyslog(LOG_ERR,"parse: stream_receive: timestamp conversion error (buftvtots) (%s) (%ld.%06ld) ", (_Y_), (long)(&(_X_))->tv.tv_sec, (long)(&(_X_))->tv.tv_usec);\
1644 			      return;                                       \
1645 			    }                                               \
1646 			  else                                              \
1647 			    {                                               \
1648 			      (&(_X_))->fp = ts;                            \
1649 			    }                                               \
1650 		        }
1651 
1652 /*--------------------------------------------------
1653  * ppsclock STREAM init
1654  */
1655 static int
1656 ppsclock_init(
1657 	struct parseunit *parse
1658 	)
1659 {
1660         static char m1[] = "ppsclocd";
1661 	static char m2[] = "ppsclock";
1662 
1663 	/*
1664 	 * now push the parse streams module
1665 	 * it will ensure exclusive access to the device
1666 	 */
1667 	if (ioctl(parse->ppsfd, I_PUSH, (caddr_t)m1) == -1 &&
1668 	    ioctl(parse->ppsfd, I_PUSH, (caddr_t)m2) == -1)
1669 	{
1670 		if (errno != EINVAL)
1671 		{
1672 			msyslog(LOG_ERR, "PARSE receiver #%d: ppsclock_init: ioctl(fd, I_PUSH, \"ppsclock\"): %m",
1673 				CLK_UNIT(parse->peer));
1674 		}
1675 		return 0;
1676 	}
1677 	if (!local_init(parse))
1678 	{
1679 		(void)ioctl(parse->ppsfd, I_POP, (caddr_t)0);
1680 		return 0;
1681 	}
1682 
1683 	parse->flags |= PARSE_PPSCLOCK;
1684 	return 1;
1685 }
1686 
1687 /*--------------------------------------------------
1688  * parse STREAM init
1689  */
1690 static int
1691 stream_init(
1692 	struct parseunit *parse
1693 	)
1694 {
1695 	static char m1[] = "parse";
1696 	/*
1697 	 * now push the parse streams module
1698 	 * to test whether it is there (neat interface 8-( )
1699 	 */
1700 	if (ioctl(parse->generic->io.fd, I_PUSH, (caddr_t)m1) == -1)
1701 	{
1702 		if (errno != EINVAL) /* accept non-existence */
1703 		{
1704 			msyslog(LOG_ERR, "PARSE receiver #%d: stream_init: ioctl(fd, I_PUSH, \"parse\"): %m", CLK_UNIT(parse->peer));
1705 		}
1706 		return 0;
1707 	}
1708 	else
1709 	{
1710 		while(ioctl(parse->generic->io.fd, I_POP, (caddr_t)0) == 0)
1711 		    /* empty loop */;
1712 
1713 		/*
1714 		 * now push it a second time after we have removed all
1715 		 * module garbage
1716 		 */
1717 		if (ioctl(parse->generic->io.fd, I_PUSH, (caddr_t)m1) == -1)
1718 		{
1719 			msyslog(LOG_ERR, "PARSE receiver #%d: stream_init: ioctl(fd, I_PUSH, \"parse\"): %m", CLK_UNIT(parse->peer));
1720 			return 0;
1721 		}
1722 		else
1723 		{
1724 			return 1;
1725 		}
1726 	}
1727 }
1728 
1729 /*--------------------------------------------------
1730  * parse STREAM end
1731  */
1732 static void
1733 stream_end(
1734 	struct parseunit *parse
1735 	)
1736 {
1737 	while(ioctl(parse->generic->io.fd, I_POP, (caddr_t)0) == 0)
1738 	    /* empty loop */;
1739 }
1740 
1741 /*--------------------------------------------------
1742  * STREAM setcs
1743  */
1744 static int
1745 stream_setcs(
1746 	struct parseunit *parse,
1747 	parsectl_t  *tcl
1748 	)
1749 {
1750 	struct strioctl strioc;
1751 
1752 	strioc.ic_cmd     = PARSEIOC_SETCS;
1753 	strioc.ic_timout  = 0;
1754 	strioc.ic_dp      = (char *)tcl;
1755 	strioc.ic_len     = sizeof (*tcl);
1756 
1757 	if (ioctl(parse->generic->io.fd, I_STR, (caddr_t)&strioc) == -1)
1758 	{
1759 		msyslog(LOG_ERR, "PARSE receiver #%d: stream_setcs: ioctl(fd, I_STR, PARSEIOC_SETCS): %m", CLK_UNIT(parse->peer));
1760 		return 0;
1761 	}
1762 	return 1;
1763 }
1764 
1765 /*--------------------------------------------------
1766  * STREAM enable
1767  */
1768 static int
1769 stream_enable(
1770 	struct parseunit *parse
1771 	)
1772 {
1773 	struct strioctl strioc;
1774 
1775 	strioc.ic_cmd     = PARSEIOC_ENABLE;
1776 	strioc.ic_timout  = 0;
1777 	strioc.ic_dp      = (char *)0;
1778 	strioc.ic_len     = 0;
1779 
1780 	if (ioctl(parse->generic->io.fd, I_STR, (caddr_t)&strioc) == -1)
1781 	{
1782 		msyslog(LOG_ERR, "PARSE receiver #%d: stream_enable: ioctl(fd, I_STR, PARSEIOC_ENABLE): %m", CLK_UNIT(parse->peer));
1783 		return 0;
1784 	}
1785 	parse->generic->io.clock_recv = stream_receive; /* ok - parse input in kernel */
1786 	return 1;
1787 }
1788 
1789 /*--------------------------------------------------
1790  * STREAM disable
1791  */
1792 static int
1793 stream_disable(
1794 	struct parseunit *parse
1795 	)
1796 {
1797 	struct strioctl strioc;
1798 
1799 	strioc.ic_cmd     = PARSEIOC_DISABLE;
1800 	strioc.ic_timout  = 0;
1801 	strioc.ic_dp      = (char *)0;
1802 	strioc.ic_len     = 0;
1803 
1804 	if (ioctl(parse->generic->io.fd, I_STR, (caddr_t)&strioc) == -1)
1805 	{
1806 		msyslog(LOG_ERR, "PARSE receiver #%d: stream_disable: ioctl(fd, I_STR, PARSEIOC_DISABLE): %m", CLK_UNIT(parse->peer));
1807 		return 0;
1808 	}
1809 	parse->generic->io.clock_recv = local_receive; /* ok - parse input in daemon */
1810 	return 1;
1811 }
1812 
1813 /*--------------------------------------------------
1814  * STREAM getfmt
1815  */
1816 static int
1817 stream_getfmt(
1818 	struct parseunit *parse,
1819 	parsectl_t  *tcl
1820 	)
1821 {
1822 	struct strioctl strioc;
1823 
1824 	strioc.ic_cmd     = PARSEIOC_GETFMT;
1825 	strioc.ic_timout  = 0;
1826 	strioc.ic_dp      = (char *)tcl;
1827 	strioc.ic_len     = sizeof (*tcl);
1828 	if (ioctl(parse->generic->io.fd, I_STR, (caddr_t)&strioc) == -1)
1829 	{
1830 		msyslog(LOG_ERR, "PARSE receiver #%d: ioctl(fd, I_STR, PARSEIOC_GETFMT): %m", CLK_UNIT(parse->peer));
1831 		return 0;
1832 	}
1833 	return 1;
1834 }
1835 
1836 /*--------------------------------------------------
1837  * STREAM setfmt
1838  */
1839 static int
1840 stream_setfmt(
1841 	struct parseunit *parse,
1842 	parsectl_t  *tcl
1843 	)
1844 {
1845 	struct strioctl strioc;
1846 
1847 	strioc.ic_cmd     = PARSEIOC_SETFMT;
1848 	strioc.ic_timout  = 0;
1849 	strioc.ic_dp      = (char *)tcl;
1850 	strioc.ic_len     = sizeof (*tcl);
1851 
1852 	if (ioctl(parse->generic->io.fd, I_STR, (caddr_t)&strioc) == -1)
1853 	{
1854 		msyslog(LOG_ERR, "PARSE receiver #%d: stream_setfmt: ioctl(fd, I_STR, PARSEIOC_SETFMT): %m", CLK_UNIT(parse->peer));
1855 		return 0;
1856 	}
1857 	return 1;
1858 }
1859 
1860 
1861 /*--------------------------------------------------
1862  * STREAM timecode
1863  */
1864 static int
1865 stream_timecode(
1866 	struct parseunit *parse,
1867 	parsectl_t  *tcl
1868 	)
1869 {
1870 	struct strioctl strioc;
1871 
1872 	strioc.ic_cmd     = PARSEIOC_TIMECODE;
1873 	strioc.ic_timout  = 0;
1874 	strioc.ic_dp      = (char *)tcl;
1875 	strioc.ic_len     = sizeof (*tcl);
1876 
1877 	if (ioctl(parse->generic->io.fd, I_STR, (caddr_t)&strioc) == -1)
1878 	{
1879 		ERR(ERR_INTERNAL)
1880 			msyslog(LOG_ERR, "PARSE receiver #%d: stream_timecode: ioctl(fd, I_STR, PARSEIOC_TIMECODE): %m", CLK_UNIT(parse->peer));
1881 		return 0;
1882 	}
1883 	clear_err(parse, ERR_INTERNAL);
1884 	return 1;
1885 }
1886 
1887 /*--------------------------------------------------
1888  * STREAM receive
1889  */
1890 static void
1891 stream_receive(
1892 	struct recvbuf *rbufp
1893 	)
1894 {
1895 	struct parseunit *parse = (struct parseunit *)((void *)rbufp->recv_srcclock);
1896 	parsetime_t parsetime;
1897 
1898 	if (!parse->peer)
1899 	    return;
1900 
1901 	if (rbufp->recv_length != sizeof(parsetime_t))
1902 	{
1903 		ERR(ERR_BADIO)
1904 			msyslog(LOG_ERR,"PARSE receiver #%d: stream_receive: bad size (got %d expected %d)",
1905 				CLK_UNIT(parse->peer), rbufp->recv_length, (int)sizeof(parsetime_t));
1906 		parse_event(parse, CEVNT_BADREPLY);
1907 		return;
1908 	}
1909 	clear_err(parse, ERR_BADIO);
1910 
1911 	memmove((caddr_t)&parsetime,
1912 		(caddr_t)rbufp->recv_buffer,
1913 		sizeof(parsetime_t));
1914 
1915 #ifdef DEBUG
1916 	if (debug > 3)
1917 	  {
1918 	    printf("PARSE receiver #%d: status %06x, state %08x, time %lx.%08lx, stime %lx.%08lx, ptime %lx.%08lx\n",
1919 		   CLK_UNIT(parse->peer),
1920 		   (unsigned int)parsetime.parse_status,
1921 		   (unsigned int)parsetime.parse_state,
1922 		   (unsigned long)parsetime.parse_time.tv.tv_sec,
1923 		   (unsigned long)parsetime.parse_time.tv.tv_usec,
1924 		   (unsigned long)parsetime.parse_stime.tv.tv_sec,
1925 		   (unsigned long)parsetime.parse_stime.tv.tv_usec,
1926 		   (unsigned long)parsetime.parse_ptime.tv.tv_sec,
1927 		   (unsigned long)parsetime.parse_ptime.tv.tv_usec);
1928 	  }
1929 #endif
1930 
1931 	/*
1932 	 * switch time stamp world - be sure to normalize small usec field
1933 	 * errors.
1934 	 */
1935 
1936 	cvt_ts(parsetime.parse_stime, "parse_stime");
1937 
1938 	if (PARSE_TIMECODE(parsetime.parse_state))
1939 	{
1940 	    cvt_ts(parsetime.parse_time, "parse_time");
1941 	}
1942 
1943 	if (PARSE_PPS(parsetime.parse_state))
1944 	    cvt_ts(parsetime.parse_ptime, "parse_ptime");
1945 
1946 	parse_process(parse, &parsetime);
1947 }
1948 #endif
1949 
1950 /*--------------------------------------------------
1951  * local init
1952  */
1953 static int
1954 local_init(
1955 	struct parseunit *parse
1956 	)
1957 {
1958 	return parse_ioinit(&parse->parseio);
1959 }
1960 
1961 /*--------------------------------------------------
1962  * local end
1963  */
1964 static void
1965 local_end(
1966 	struct parseunit *parse
1967 	)
1968 {
1969 	parse_ioend(&parse->parseio);
1970 }
1971 
1972 
1973 /*--------------------------------------------------
1974  * local nop
1975  */
1976 static int
1977 local_nop(
1978 	struct parseunit *parse
1979 	)
1980 {
1981 	return 1;
1982 }
1983 
1984 /*--------------------------------------------------
1985  * local setcs
1986  */
1987 static int
1988 local_setcs(
1989 	struct parseunit *parse,
1990 	parsectl_t  *tcl
1991 	)
1992 {
1993 	return parse_setcs(tcl, &parse->parseio);
1994 }
1995 
1996 /*--------------------------------------------------
1997  * local getfmt
1998  */
1999 static int
2000 local_getfmt(
2001 	struct parseunit *parse,
2002 	parsectl_t  *tcl
2003 	)
2004 {
2005 	return parse_getfmt(tcl, &parse->parseio);
2006 }
2007 
2008 /*--------------------------------------------------
2009  * local setfmt
2010  */
2011 static int
2012 local_setfmt(
2013 	struct parseunit *parse,
2014 	parsectl_t  *tcl
2015 	)
2016 {
2017 	return parse_setfmt(tcl, &parse->parseio);
2018 }
2019 
2020 /*--------------------------------------------------
2021  * local timecode
2022  */
2023 static int
2024 local_timecode(
2025 	struct parseunit *parse,
2026 	parsectl_t  *tcl
2027 	)
2028 {
2029 	return parse_timecode(tcl, &parse->parseio);
2030 }
2031 
2032 
2033 /*--------------------------------------------------
2034  * local input
2035  */
2036 static int
2037 local_input(
2038 	struct recvbuf *rbufp
2039 	)
2040 {
2041 	struct parseunit *parse = (struct parseunit *)((void *)rbufp->recv_srcclock);
2042 	int count;
2043 	unsigned char *s;
2044 	timestamp_t ts;
2045 
2046 	if (!parse->peer)
2047 		return 0;
2048 
2049 	/*
2050 	 * eat all characters, parsing then and feeding complete samples
2051 	 */
2052 	count = rbufp->recv_length;
2053 	s = (unsigned char *)rbufp->recv_buffer;
2054 	ts.fp = rbufp->recv_time;
2055 
2056 	while (count--)
2057 	{
2058 		if (parse_ioread(&parse->parseio, (unsigned int)(*s++), &ts))
2059 		{
2060 			struct recvbuf *buf;
2061 
2062 			/*
2063 			 * got something good to eat
2064 			 */
2065 			if (!PARSE_PPS(parse->parseio.parse_dtime.parse_state))
2066 			{
2067 #ifdef HAVE_PPSAPI
2068 				if (parse->flags & PARSE_PPSCLOCK)
2069 				{
2070 					struct timespec pps_timeout;
2071 					pps_info_t      pps_info;
2072 
2073 					pps_timeout.tv_sec  = 0;
2074 					pps_timeout.tv_nsec = 0;
2075 
2076 					if (time_pps_fetch(parse->ppshandle, PPS_TSFMT_TSPEC, &pps_info,
2077 							   &pps_timeout) == 0)
2078 					{
2079 						if (pps_info.assert_sequence + pps_info.clear_sequence != parse->ppsserial)
2080 						{
2081 							double dtemp;
2082 
2083 						        struct timespec pts;
2084 							/*
2085 							 * add PPS time stamp if available via ppsclock module
2086 							 * and not supplied already.
2087 							 */
2088 							if (parse->flags & PARSE_CLEAR)
2089 							  pts = pps_info.clear_timestamp;
2090 							else
2091 							  pts = pps_info.assert_timestamp;
2092 
2093 							parse->parseio.parse_dtime.parse_ptime.fp.l_ui = pts.tv_sec + JAN_1970;
2094 
2095 							dtemp = pts.tv_nsec / 1e9;
2096 							if (dtemp < 0.) {
2097 								dtemp += 1;
2098 								parse->parseio.parse_dtime.parse_ptime.fp.l_ui--;
2099 							}
2100 							if (dtemp > 1.) {
2101 								dtemp -= 1;
2102 								parse->parseio.parse_dtime.parse_ptime.fp.l_ui++;
2103 							}
2104 							parse->parseio.parse_dtime.parse_ptime.fp.l_uf = dtemp * FRAC;
2105 
2106 						        parse->parseio.parse_dtime.parse_state |= PARSEB_PPS|PARSEB_S_PPS;
2107 #ifdef DEBUG
2108 							if (debug > 3)
2109 							{
2110 								printf(
2111 								       "parse: local_receive: fd %d PPSAPI seq %ld - PPS %s\n",
2112 								       rbufp->fd,
2113 								       (long)pps_info.assert_sequence + (long)pps_info.clear_sequence,
2114 								       lfptoa(&parse->parseio.parse_dtime.parse_ptime.fp, 6));
2115 							}
2116 #endif
2117 						}
2118 #ifdef DEBUG
2119 						else
2120 						{
2121 							if (debug > 3)
2122 							{
2123 								printf(
2124 								       "parse: local_receive: fd %d PPSAPI seq assert %ld, seq clear %ld - NO PPS event\n",
2125 								       rbufp->fd,
2126 								       (long)pps_info.assert_sequence, (long)pps_info.clear_sequence);
2127 							}
2128 						}
2129 #endif
2130 						parse->ppsserial = pps_info.assert_sequence + pps_info.clear_sequence;
2131 					}
2132 #ifdef DEBUG
2133 					else
2134 					{
2135 						if (debug > 3)
2136 						{
2137 							printf(
2138 							       "parse: local_receive: fd %d PPSAPI time_pps_fetch errno = %d\n",
2139 							       rbufp->fd,
2140 							       errno);
2141 						}
2142 					}
2143 #endif
2144 				}
2145 #else
2146 #ifdef TIOCDCDTIMESTAMP
2147 				struct timeval dcd_time;
2148 
2149 				if (ioctl(parse->ppsfd, TIOCDCDTIMESTAMP, &dcd_time) != -1)
2150 				{
2151 					l_fp tstmp;
2152 
2153 					TVTOTS(&dcd_time, &tstmp);
2154 					tstmp.l_ui += JAN_1970;
2155 					L_SUB(&ts.fp, &tstmp);
2156 					if (ts.fp.l_ui == 0)
2157 					{
2158 #ifdef DEBUG
2159 						if (debug)
2160 						{
2161 							printf(
2162 							       "parse: local_receive: fd %d DCDTIMESTAMP %s\n",
2163 							       parse->ppsfd,
2164 							       lfptoa(&tstmp, 6));
2165 							printf(" sigio %s\n",
2166 							       lfptoa(&ts.fp, 6));
2167 						}
2168 #endif
2169 						parse->parseio.parse_dtime.parse_ptime.fp = tstmp;
2170 						parse->parseio.parse_dtime.parse_state |= PARSEB_PPS|PARSEB_S_PPS;
2171 					}
2172 				}
2173 #else /* TIOCDCDTIMESTAMP */
2174 #if defined(HAVE_STRUCT_PPSCLOCKEV) && (defined(HAVE_CIOGETEV) || defined(HAVE_TIOCGPPSEV))
2175 				if (parse->flags & PARSE_PPSCLOCK)
2176 				  {
2177 				    l_fp tts;
2178 				    struct ppsclockev ev;
2179 
2180 #ifdef HAVE_CIOGETEV
2181 				    if (ioctl(parse->ppsfd, CIOGETEV, (caddr_t)&ev) == 0)
2182 #endif
2183 #ifdef HAVE_TIOCGPPSEV
2184 				    if (ioctl(parse->ppsfd, TIOCGPPSEV, (caddr_t)&ev) == 0)
2185 #endif
2186 					{
2187 					  if (ev.serial != parse->ppsserial)
2188 					    {
2189 					      /*
2190 					       * add PPS time stamp if available via ppsclock module
2191 					       * and not supplied already.
2192 					       */
2193 					      if (!buftvtots((const char *)&ev.tv, &tts))
2194 						{
2195 						  ERR(ERR_BADDATA)
2196 						    msyslog(LOG_ERR,"parse: local_receive: timestamp conversion error (buftvtots) (ppsclockev.tv)");
2197 						}
2198 					      else
2199 						{
2200 						  parse->parseio.parse_dtime.parse_ptime.fp = tts;
2201 						  parse->parseio.parse_dtime.parse_state |= PARSEB_PPS|PARSEB_S_PPS;
2202 						}
2203 					    }
2204 					  parse->ppsserial = ev.serial;
2205 					}
2206 				  }
2207 #endif
2208 #endif /* TIOCDCDTIMESTAMP */
2209 #endif /* !HAVE_PPSAPI */
2210 			}
2211 			if (count)
2212 			{	/* simulate receive */
2213 				buf = get_free_recv_buffer();
2214 				if (buf != NULL) {
2215 					memmove((caddr_t)buf->recv_buffer,
2216 						(caddr_t)&parse->parseio.parse_dtime,
2217 						sizeof(parsetime_t));
2218 					buf->recv_length  = sizeof(parsetime_t);
2219 					buf->recv_time    = rbufp->recv_time;
2220 					buf->srcadr       = rbufp->srcadr;
2221 					buf->dstadr       = rbufp->dstadr;
2222 					buf->receiver     = rbufp->receiver;
2223 					buf->fd           = rbufp->fd;
2224 					buf->X_from_where = rbufp->X_from_where;
2225 					add_full_recv_buffer(buf);
2226 				}
2227 				parse_iodone(&parse->parseio);
2228 			}
2229 			else
2230 			{
2231 				memmove((caddr_t)rbufp->recv_buffer,
2232 					(caddr_t)&parse->parseio.parse_dtime,
2233 					sizeof(parsetime_t));
2234 				parse_iodone(&parse->parseio);
2235 				rbufp->recv_length = sizeof(parsetime_t);
2236 				return 1; /* got something & in place return */
2237 			}
2238 		}
2239 	}
2240 	return 0;		/* nothing to pass up */
2241 }
2242 
2243 /*--------------------------------------------------
2244  * local receive
2245  */
2246 static void
2247 local_receive(
2248 	struct recvbuf *rbufp
2249 	)
2250 {
2251 	struct parseunit *parse = (struct parseunit *)((void *)rbufp->recv_srcclock);
2252 	parsetime_t parsetime;
2253 
2254 	if (!parse->peer)
2255 	    return;
2256 
2257 	if (rbufp->recv_length != sizeof(parsetime_t))
2258 	{
2259 		ERR(ERR_BADIO)
2260 			msyslog(LOG_ERR,"PARSE receiver #%d: local_receive: bad size (got %d expected %d)",
2261 				CLK_UNIT(parse->peer), rbufp->recv_length, (int)sizeof(parsetime_t));
2262 		parse_event(parse, CEVNT_BADREPLY);
2263 		return;
2264 	}
2265 	clear_err(parse, ERR_BADIO);
2266 
2267 	memmove((caddr_t)&parsetime,
2268 		(caddr_t)rbufp->recv_buffer,
2269 		sizeof(parsetime_t));
2270 
2271 #ifdef DEBUG
2272 	if (debug > 3)
2273 	  {
2274 	    printf("PARSE receiver #%d: status %06x, state %08x, time(fp) %lx.%08lx, stime(fp) %lx.%08lx, ptime(fp) %lx.%08lx\n",
2275 		   CLK_UNIT(parse->peer),
2276 		   (unsigned int)parsetime.parse_status,
2277 		   (unsigned int)parsetime.parse_state,
2278 		   (unsigned long)parsetime.parse_time.fp.l_ui,
2279 		   (unsigned long)parsetime.parse_time.fp.l_uf,
2280 		   (unsigned long)parsetime.parse_stime.fp.l_ui,
2281 		   (unsigned long)parsetime.parse_stime.fp.l_uf,
2282 		   (unsigned long)parsetime.parse_ptime.fp.l_ui,
2283 		   (unsigned long)parsetime.parse_ptime.fp.l_uf);
2284 	  }
2285 #endif
2286 
2287 	parse_process(parse, &parsetime);
2288 }
2289 
2290 /*--------------------------------------------------
2291  * init_iobinding - find and initialize lower layers
2292  */
2293 static bind_t *
2294 init_iobinding(
2295 	struct parseunit *parse
2296 	)
2297 {
2298   bind_t *b = io_bindings;
2299 
2300 	while (b->bd_description != (char *)0)
2301 	{
2302 		if ((*b->bd_init)(parse))
2303 		{
2304 			return b;
2305 		}
2306 		b++;
2307 	}
2308 	return (bind_t *)0;
2309 }
2310 
2311 /**===========================================================================
2312  ** support routines
2313  **/
2314 
2315 /*--------------------------------------------------
2316  * convert a flag field to a string
2317  */
2318 static char *
2319 parsestate(
2320 	u_long lstate,
2321 	char *buffer,
2322 	int size
2323 	)
2324 {
2325 	static struct bits
2326 	{
2327 		u_long      bit;
2328 		const char *name;
2329 	} flagstrings[] =
2330 	  {
2331 		  { PARSEB_ANNOUNCE,   "DST SWITCH WARNING" },
2332 		  { PARSEB_POWERUP,    "NOT SYNCHRONIZED" },
2333 		  { PARSEB_NOSYNC,     "TIME CODE NOT CONFIRMED" },
2334 		  { PARSEB_DST,        "DST" },
2335 		  { PARSEB_UTC,        "UTC DISPLAY" },
2336 		  { PARSEB_LEAPADD,    "LEAP ADD WARNING" },
2337 		  { PARSEB_LEAPDEL,    "LEAP DELETE WARNING" },
2338 		  { PARSEB_LEAPSECOND, "LEAP SECOND" },
2339 		  { PARSEB_ALTERNATE,  "ALTERNATE ANTENNA" },
2340 		  { PARSEB_TIMECODE,   "TIME CODE" },
2341 		  { PARSEB_PPS,        "PPS" },
2342 		  { PARSEB_POSITION,   "POSITION" },
2343 		  { 0 }
2344 	  };
2345 
2346 	static struct sbits
2347 	{
2348 		u_long      bit;
2349 		const char *name;
2350 	} sflagstrings[] =
2351 	  {
2352 		  { PARSEB_S_LEAP,     "LEAP INDICATION" },
2353 		  { PARSEB_S_PPS,      "PPS SIGNAL" },
2354 		  { PARSEB_S_ANTENNA,  "ANTENNA" },
2355 		  { PARSEB_S_POSITION, "POSITION" },
2356 		  { 0 }
2357 	  };
2358 	int i;
2359 	char *s, *t;
2360 
2361 
2362 	*buffer = '\0';
2363 	s = t = buffer;
2364 
2365 	i = 0;
2366 	while (flagstrings[i].bit)
2367 	{
2368 		if (flagstrings[i].bit & lstate)
2369 		{
2370 			if (s != t)
2371 				strncpy(t, "; ", BUFFER_SIZES(buffer, t, size));
2372 			strncat(t, flagstrings[i].name, BUFFER_SIZES(buffer, t, size));
2373 			t += strlen(t);
2374 		}
2375 		i++;
2376 	}
2377 
2378 	if (lstate & (PARSEB_S_LEAP|PARSEB_S_ANTENNA|PARSEB_S_PPS|PARSEB_S_POSITION))
2379 	{
2380 		if (s != t)
2381 			strncpy(t, "; ", BUFFER_SIZES(buffer, t, size));
2382 
2383 		t += strlen(t);
2384 
2385 		strncpy(t, "(", BUFFER_SIZES(buffer, t, size));
2386 
2387 		s = t = t + strlen(t);
2388 
2389 		i = 0;
2390 		while (sflagstrings[i].bit)
2391 		{
2392 			if (sflagstrings[i].bit & lstate)
2393 			{
2394 				if (t != s)
2395 				{
2396 					strncpy(t, "; ", BUFFER_SIZES(buffer, t, size));
2397 					t += 2;
2398 				}
2399 
2400 				strncpy(t, sflagstrings[i].name, BUFFER_SIZES(buffer, t, size));
2401 				t += strlen(t);
2402 			}
2403 			i++;
2404 		}
2405 		strncpy(t, ")", BUFFER_SIZES(buffer, t, size));
2406 	}
2407 	return buffer;
2408 }
2409 
2410 /*--------------------------------------------------
2411  * convert a status flag field to a string
2412  */
2413 static char *
2414 parsestatus(
2415 	u_long lstate,
2416 	char *buffer,
2417 	int size
2418 	)
2419 {
2420 	static struct bits
2421 	{
2422 		u_long      bit;
2423 		const char *name;
2424 	} flagstrings[] =
2425 	  {
2426 		  { CVT_OK,      "CONVERSION SUCCESSFUL" },
2427 		  { CVT_NONE,    "NO CONVERSION" },
2428 		  { CVT_FAIL,    "CONVERSION FAILED" },
2429 		  { CVT_BADFMT,  "ILLEGAL FORMAT" },
2430 		  { CVT_BADDATE, "DATE ILLEGAL" },
2431 		  { CVT_BADTIME, "TIME ILLEGAL" },
2432 		  { CVT_ADDITIONAL, "ADDITIONAL DATA" },
2433 		  { 0 }
2434 	  };
2435 	int i;
2436 
2437 	*buffer = '\0';
2438 
2439 	i = 0;
2440 	while (flagstrings[i].bit)
2441 	{
2442 		if (flagstrings[i].bit & lstate)
2443 		{
2444 			if (buffer[0])
2445 				strncat(buffer, "; ", size);
2446 			strncat(buffer, flagstrings[i].name, size);
2447 		}
2448 		i++;
2449 	}
2450 
2451 	return buffer;
2452 }
2453 
2454 /*--------------------------------------------------
2455  * convert a clock status flag field to a string
2456  */
2457 static const char *
2458 clockstatus(
2459 	u_long lstate
2460 	)
2461 {
2462 	static char buffer[20];
2463 	static struct status
2464 	{
2465 		u_long      value;
2466 		const char *name;
2467 	} flagstrings[] =
2468 	  {
2469 		  { CEVNT_NOMINAL, "NOMINAL" },
2470 		  { CEVNT_TIMEOUT, "NO RESPONSE" },
2471 		  { CEVNT_BADREPLY,"BAD FORMAT" },
2472 		  { CEVNT_FAULT,   "FAULT" },
2473 		  { CEVNT_PROP,    "PROPAGATION DELAY" },
2474 		  { CEVNT_BADDATE, "ILLEGAL DATE" },
2475 		  { CEVNT_BADTIME, "ILLEGAL TIME" },
2476 		  { (unsigned)~0L }
2477 	  };
2478 	int i;
2479 
2480 	i = 0;
2481 	while (flagstrings[i].value != ~0)
2482 	{
2483 		if (flagstrings[i].value == lstate)
2484 		{
2485 			return flagstrings[i].name;
2486 		}
2487 		i++;
2488 	}
2489 
2490 	snprintf(buffer, sizeof(buffer), "unknown #%ld", (u_long)lstate);
2491 
2492 	return buffer;
2493 }
2494 
2495 
2496 /*--------------------------------------------------
2497  * l_mktime - make representation of a relative time
2498  */
2499 static char *
2500 l_mktime(
2501 	u_long delta
2502 	)
2503 {
2504 	u_long tmp, m, s;
2505 	static char buffer[40];
2506 	char *t;
2507 
2508 	buffer[0] = '\0';
2509 
2510 	if ((tmp = delta / (60*60*24)) != 0)
2511 	{
2512 		snprintf(buffer, BUFFER_SIZE(buffer, buffer), "%ldd+", (u_long)tmp);
2513 		delta -= tmp * 60*60*24;
2514 	}
2515 
2516 	s = delta % 60;
2517 	delta /= 60;
2518 	m = delta % 60;
2519 	delta /= 60;
2520 
2521 	t = buffer + strlen(buffer);
2522 
2523 	snprintf(t, BUFFER_SIZE(buffer, t), "%02d:%02d:%02d",
2524 		 (int)delta, (int)m, (int)s);
2525 
2526 	return buffer;
2527 }
2528 
2529 
2530 /*--------------------------------------------------
2531  * parse_statistics - list summary of clock states
2532  */
2533 static void
2534 parse_statistics(
2535 	struct parseunit *parse
2536 	)
2537 {
2538 	int i;
2539 
2540 	NLOG(NLOG_CLOCKSTATIST) /* conditional if clause for conditional syslog */
2541 		{
2542 			msyslog(LOG_INFO, "PARSE receiver #%d: running time: %s",
2543 				CLK_UNIT(parse->peer),
2544 				l_mktime(current_time - parse->generic->timestarted));
2545 
2546 			msyslog(LOG_INFO, "PARSE receiver #%d: current status: %s",
2547 				CLK_UNIT(parse->peer),
2548 				clockstatus(parse->generic->currentstatus));
2549 
2550 			for (i = 0; i <= CEVNT_MAX; i++)
2551 			{
2552 				u_long s_time;
2553 				u_long percent, d = current_time - parse->generic->timestarted;
2554 
2555 				percent = s_time = PARSE_STATETIME(parse, i);
2556 
2557 				while (((u_long)(~0) / 10000) < percent)
2558 				{
2559 					percent /= 10;
2560 					d       /= 10;
2561 				}
2562 
2563 				if (d)
2564 				    percent = (percent * 10000) / d;
2565 				else
2566 				    percent = 10000;
2567 
2568 				if (s_time)
2569 				    msyslog(LOG_INFO, "PARSE receiver #%d: state %18s: %13s (%3ld.%02ld%%)",
2570 					    CLK_UNIT(parse->peer),
2571 					    clockstatus((unsigned int)i),
2572 					    l_mktime(s_time),
2573 					    percent / 100, percent % 100);
2574 			}
2575 		}
2576 }
2577 
2578 /*--------------------------------------------------
2579  * cparse_statistics - wrapper for statistics call
2580  */
2581 static void
2582 cparse_statistics(
2583         struct parseunit *parse
2584 	)
2585 {
2586 	if (parse->laststatistic + PARSESTATISTICS < current_time)
2587 		parse_statistics(parse);
2588 	parse->laststatistic = current_time;
2589 }
2590 
2591 /**===========================================================================
2592  ** ntp interface routines
2593  **/
2594 
2595 /*--------------------------------------------------
2596  * parse_shutdown - shut down a PARSE clock
2597  */
2598 static void
2599 parse_shutdown(
2600 	int unit,
2601 	struct peer *peer
2602 	)
2603 {
2604 	struct parseunit *parse = (struct parseunit *)0;
2605 
2606 	if (peer && peer->procptr)
2607 		parse = (struct parseunit *)peer->procptr->unitptr;
2608 
2609 	if (!parse)
2610 	{
2611 		/* nothing to clean up */
2612 		return;
2613 	}
2614 
2615         if (!parse->peer)
2616 	{
2617 		msyslog(LOG_INFO, "PARSE receiver #%d: INTERNAL ERROR - unit already inactive - shutdown ignored", unit);
2618 		return;
2619 	}
2620 
2621 #ifdef HAVE_PPSAPI
2622 	if (parse->flags & PARSE_PPSCLOCK)
2623 	{
2624 		(void)time_pps_destroy(parse->ppshandle);
2625 	}
2626 #endif
2627 	if (parse->generic->io.fd != parse->ppsfd && parse->ppsfd != -1)
2628 		(void)close(parse->ppsfd);  /* close separate PPS source */
2629 
2630 	/*
2631 	 * print statistics a last time and
2632 	 * stop statistics machine
2633 	 */
2634 	parse_statistics(parse);
2635 
2636 	if (parse->parse_type->cl_end)
2637 	{
2638 		parse->parse_type->cl_end(parse);
2639 	}
2640 
2641 	/*
2642 	 * cleanup before leaving this world
2643 	 */
2644 	if (parse->binding)
2645 	    PARSE_END(parse);
2646 
2647 	/*
2648 	 * Tell the I/O module to turn us off.  We're history.
2649 	 */
2650 	io_closeclock(&parse->generic->io);
2651 
2652 	free_varlist(parse->kv);
2653 
2654 	NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
2655 		msyslog(LOG_INFO, "PARSE receiver #%d: reference clock \"%s\" removed",
2656 			CLK_UNIT(parse->peer), parse->parse_type->cl_description);
2657 
2658 	parse->peer = (struct peer *)0; /* unused now */
2659 	peer->procptr->unitptr = (caddr_t)0;
2660 	free(parse);
2661 }
2662 
2663 #ifdef HAVE_PPSAPI
2664 /*----------------------------------------
2665  * set up HARDPPS via PPSAPI
2666  */
2667 static void
2668 parse_hardpps(
2669 	      struct parseunit *parse,
2670 	      int mode
2671 	      )
2672 {
2673         if (parse->hardppsstate == mode)
2674 	        return;
2675 
2676 	if (CLK_PPS(parse->peer) && (parse->flags & PARSE_PPSKERNEL)) {
2677 		int	i = 0;
2678 
2679 		if (mode == PARSE_HARDPPS_ENABLE)
2680 		        {
2681 			        if (parse->flags & PARSE_CLEAR)
2682 				        i = PPS_CAPTURECLEAR;
2683 				else
2684 				        i = PPS_CAPTUREASSERT;
2685 			}
2686 
2687 		if (time_pps_kcbind(parse->ppshandle, PPS_KC_HARDPPS, i,
2688 		    PPS_TSFMT_TSPEC) < 0) {
2689 		        msyslog(LOG_ERR, "PARSE receiver #%d: time_pps_kcbind failed: %m",
2690 				CLK_UNIT(parse->peer));
2691 		} else {
2692 		        NLOG(NLOG_CLOCKINFO)
2693 		                msyslog(LOG_INFO, "PARSE receiver #%d: kernel PPS synchronisation %sabled",
2694 					CLK_UNIT(parse->peer), (mode == PARSE_HARDPPS_ENABLE) ? "en" : "dis");
2695 			/*
2696 			 * tell the rest, that we have a kernel PPS source, iff we ever enable HARDPPS
2697 			 */
2698 			if (mode == PARSE_HARDPPS_ENABLE)
2699 			        pps_enable = 1;
2700 		}
2701 	}
2702 
2703 	parse->hardppsstate = mode;
2704 }
2705 
2706 /*----------------------------------------
2707  * set up PPS via PPSAPI
2708  */
2709 static int
2710 parse_ppsapi(
2711 	     struct parseunit *parse
2712 	)
2713 {
2714 	int cap, mode, mode1;
2715 	char *cp;
2716 
2717 	parse->flags &= ~PARSE_PPSCLOCK;
2718 
2719 	if (time_pps_getcap(parse->ppshandle, &cap) < 0) {
2720 		msyslog(LOG_ERR, "PARSE receiver #%d: parse_ppsapi: time_pps_getcap failed: %m",
2721 			CLK_UNIT(parse->peer));
2722 
2723 		return 0;
2724 	}
2725 
2726 	if (time_pps_getparams(parse->ppshandle, &parse->ppsparams) < 0) {
2727 		msyslog(LOG_ERR, "PARSE receiver #%d: parse_ppsapi: time_pps_getparams failed: %m",
2728 			CLK_UNIT(parse->peer));
2729 		return 0;
2730 	}
2731 
2732 	/* nb. only turn things on, if someone else has turned something
2733 	 *	on before we get here, leave it alone!
2734 	 */
2735 
2736 	if (parse->flags & PARSE_CLEAR) {
2737 		cp = "CLEAR";
2738 		mode = PPS_CAPTURECLEAR;
2739 		mode1 = PPS_OFFSETCLEAR;
2740 	} else {
2741 		cp = "ASSERT";
2742 		mode = PPS_CAPTUREASSERT;
2743 		mode1 = PPS_OFFSETASSERT;
2744 	}
2745 
2746 	msyslog(LOG_INFO, "PARSE receiver #%d: initializing PPS to %s",
2747 		CLK_UNIT(parse->peer), cp);
2748 
2749 	if (!(mode & cap)) {
2750 	  msyslog(LOG_ERR, "PARSE receiver #%d: FAILED to initialize PPS to %s (PPS API capabilities=0x%x)",
2751 		  CLK_UNIT(parse->peer), cp, cap);
2752 
2753 		return 0;
2754 	}
2755 
2756 	if (!(mode1 & cap)) {
2757 	  msyslog(LOG_WARNING, "PARSE receiver #%d: Cannot set PPS_%sCLEAR, this will increase jitter (PPS API capabilities=0x%x)",
2758 		  CLK_UNIT(parse->peer), cp, cap);
2759 		mode1 = 0;
2760 	} else {
2761 	        if (mode1 == PPS_OFFSETCLEAR)
2762 		        {
2763 			        parse->ppsparams.clear_offset.tv_sec = -parse->ppsphaseadjust;
2764 			        parse->ppsparams.clear_offset.tv_nsec = -1e9*(parse->ppsphaseadjust - (long)parse->ppsphaseadjust);
2765 			}
2766 
2767 		if (mode1 == PPS_OFFSETASSERT)
2768 	                {
2769 		                parse->ppsparams.assert_offset.tv_sec = -parse->ppsphaseadjust;
2770 				parse->ppsparams.assert_offset.tv_nsec = -1e9*(parse->ppsphaseadjust - (long)parse->ppsphaseadjust);
2771 			}
2772 	}
2773 
2774 	/* only set what is legal */
2775 
2776 	parse->ppsparams.mode = (mode | mode1 | PPS_TSFMT_TSPEC) & cap;
2777 
2778 	if (time_pps_setparams(parse->ppshandle, &parse->ppsparams) < 0) {
2779 	  msyslog(LOG_ERR, "PARSE receiver #%d: FAILED set PPS parameters: %m",
2780 		  CLK_UNIT(parse->peer));
2781 		return 0;
2782 	}
2783 
2784 	parse->flags |= PARSE_PPSCLOCK;
2785 	return 1;
2786 }
2787 #else
2788 #define parse_hardpps(_PARSE_, _MODE_) /* empty */
2789 #endif
2790 
2791 /*--------------------------------------------------
2792  * parse_start - open the PARSE devices and initialize data for processing
2793  */
2794 static int
2795 parse_start(
2796 	int sysunit,
2797 	struct peer *peer
2798 	)
2799 {
2800 	u_int unit;
2801 	int fd232;
2802 #ifdef HAVE_TERMIOS
2803 	struct termios tio;		/* NEEDED FOR A LONG TIME ! */
2804 #endif
2805 #ifdef HAVE_SYSV_TTYS
2806 	struct termio tio;		/* NEEDED FOR A LONG TIME ! */
2807 #endif
2808 	struct parseunit * parse;
2809 	char parsedev[sizeof(PARSEDEVICE)+20];
2810 	char parseppsdev[sizeof(PARSEPPSDEVICE)+20];
2811 	parsectl_t tmp_ctl;
2812 	u_int type;
2813 
2814 	/*
2815 	 * get out Copyright information once
2816 	 */
2817 	if (!notice)
2818         {
2819 		NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
2820 			msyslog(LOG_INFO, "NTP PARSE support: Copyright (c) 1989-2006, Frank Kardel");
2821 		notice = 1;
2822 	}
2823 
2824 	type = CLK_TYPE(peer);
2825 	unit = CLK_UNIT(peer);
2826 
2827 	if ((type == ~0) || (parse_clockinfo[type].cl_description == (char *)0))
2828 	{
2829 		msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: unsupported clock type %d (max %d)",
2830 			unit, CLK_REALTYPE(peer), ncltypes-1);
2831 		return 0;
2832 	}
2833 
2834 	/*
2835 	 * Unit okay, attempt to open the device.
2836 	 */
2837 	(void) snprintf(parsedev, sizeof(parsedev), PARSEDEVICE, unit);
2838 	(void) snprintf(parseppsdev, sizeof(parsedev), PARSEPPSDEVICE, unit);
2839 
2840 #ifndef O_NOCTTY
2841 #define O_NOCTTY 0
2842 #endif
2843 
2844 	fd232 = open(parsedev, O_RDWR | O_NOCTTY
2845 #ifdef O_NONBLOCK
2846 		     | O_NONBLOCK
2847 #endif
2848 		     , 0777);
2849 
2850 	if (fd232 == -1)
2851 	{
2852 		msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: open of %s failed: %m", unit, parsedev);
2853 		return 0;
2854 	}
2855 
2856 	parse = (struct parseunit *)emalloc(sizeof(struct parseunit));
2857 
2858 	memset((char *)parse, 0, sizeof(struct parseunit));
2859 
2860 	parse->generic = peer->procptr;	 /* link up */
2861 	parse->generic->unitptr = (caddr_t)parse; /* link down */
2862 
2863 	/*
2864 	 * Set up the structures
2865 	 */
2866 	parse->generic->timestarted    = current_time;
2867 	parse->lastchange     = current_time;
2868 
2869 	parse->flags          = 0;
2870 	parse->pollneeddata   = 0;
2871 	parse->laststatistic  = current_time;
2872 	parse->lastformat     = (unsigned short)~0;	/* assume no format known */
2873 	parse->timedata.parse_status = (unsigned short)~0;	/* be sure to mark initial status change */
2874 	parse->lastmissed     = 0;	/* assume got everything */
2875 	parse->ppsserial      = 0;
2876 	parse->ppsfd	      = -1;
2877 	parse->localdata      = (void *)0;
2878 	parse->localstate     = 0;
2879 	parse->kv             = (struct ctl_var *)0;
2880 
2881 	clear_err(parse, ERR_ALL);
2882 
2883 	parse->parse_type     = &parse_clockinfo[type];
2884 
2885 	parse->maxunsync      = parse->parse_type->cl_maxunsync;
2886 
2887 	parse->generic->fudgetime1 = parse->parse_type->cl_basedelay;
2888 
2889 	parse->generic->fudgetime2 = 0.0;
2890 	parse->ppsphaseadjust = parse->generic->fudgetime2;
2891 
2892 	parse->generic->clockdesc  = parse->parse_type->cl_description;
2893 
2894 	peer->rootdelay       = parse->parse_type->cl_rootdelay;
2895 	peer->sstclktype      = parse->parse_type->cl_type;
2896 	peer->precision       = sys_precision;
2897 
2898 	peer->stratum         = STRATUM_REFCLOCK;
2899 
2900 	if (peer->stratum <= 1)
2901 	    memmove((char *)&parse->generic->refid, parse->parse_type->cl_id, 4);
2902 	else
2903 	    parse->generic->refid = htonl(PARSEHSREFID);
2904 
2905 	parse->generic->io.fd = fd232;
2906 
2907 	parse->peer = peer;		/* marks it also as busy */
2908 
2909 	/*
2910 	 * configure terminal line
2911 	 */
2912 	if (TTY_GETATTR(fd232, &tio) == -1)
2913 	{
2914 		msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: tcgetattr(%d, &tio): %m", unit, fd232);
2915 		parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
2916 		return 0;
2917 	}
2918 	else
2919 	{
2920 #ifndef _PC_VDISABLE
2921 		memset((char *)tio.c_cc, 0, sizeof(tio.c_cc));
2922 #else
2923 		int disablec;
2924 		errno = 0;		/* pathconf can deliver -1 without changing errno ! */
2925 
2926 		disablec = fpathconf(parse->generic->io.fd, _PC_VDISABLE);
2927 		if (disablec == -1 && errno)
2928 		{
2929 			msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: fpathconf(fd, _PC_VDISABLE): %m", CLK_UNIT(parse->peer));
2930 			memset((char *)tio.c_cc, 0, sizeof(tio.c_cc)); /* best guess */
2931 		}
2932 		else
2933 		    if (disablec != -1)
2934 			memset((char *)tio.c_cc, disablec, sizeof(tio.c_cc));
2935 #endif
2936 
2937 #if defined (VMIN) || defined(VTIME)
2938 		if ((parse_clockinfo[type].cl_lflag & ICANON) == 0)
2939 		{
2940 #ifdef VMIN
2941 			tio.c_cc[VMIN]   = 1;
2942 #endif
2943 #ifdef VTIME
2944 			tio.c_cc[VTIME]  = 0;
2945 #endif
2946 		}
2947 #endif
2948 
2949 		tio.c_cflag = parse_clockinfo[type].cl_cflag;
2950 		tio.c_iflag = parse_clockinfo[type].cl_iflag;
2951 		tio.c_oflag = parse_clockinfo[type].cl_oflag;
2952 		tio.c_lflag = parse_clockinfo[type].cl_lflag;
2953 
2954 
2955 #ifdef HAVE_TERMIOS
2956 		if ((cfsetospeed(&tio, parse_clockinfo[type].cl_speed) == -1) ||
2957 		    (cfsetispeed(&tio, parse_clockinfo[type].cl_speed) == -1))
2958 		{
2959 			msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: tcset{i,o}speed(&tio, speed): %m", unit);
2960 			parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
2961 			return 0;
2962 		}
2963 #else
2964 		tio.c_cflag     |= parse_clockinfo[type].cl_speed;
2965 #endif
2966 
2967 		/*
2968 		 * set up pps device
2969 		 * if the PARSEPPSDEVICE can be opened that will be used
2970 		 * for PPS else PARSEDEVICE will be used
2971 		 */
2972 		parse->ppsfd = open(parseppsdev, O_RDWR | O_NOCTTY
2973 #ifdef O_NONBLOCK
2974 				    | O_NONBLOCK
2975 #endif
2976 				    , 0777);
2977 
2978 		if (parse->ppsfd == -1)
2979 		{
2980 			parse->ppsfd = fd232;
2981 		}
2982 
2983 /*
2984  * Linux PPS - the old way
2985  */
2986 #if defined(HAVE_TIO_SERIAL_STUFF)		/* Linux hack: define PPS interface */
2987 		{
2988 			struct serial_struct	ss;
2989 			if (ioctl(parse->ppsfd, TIOCGSERIAL, &ss) < 0 ||
2990 			    (
2991 #ifdef ASYNC_LOW_LATENCY
2992 			     ss.flags |= ASYNC_LOW_LATENCY,
2993 #endif
2994 #ifndef HAVE_PPSAPI
2995 #ifdef ASYNC_PPS_CD_NEG
2996 			     ss.flags |= ASYNC_PPS_CD_NEG,
2997 #endif
2998 #endif
2999 			     ioctl(parse->ppsfd, TIOCSSERIAL, &ss)) < 0) {
3000 				msyslog(LOG_NOTICE, "refclock_parse: TIOCSSERIAL fd %d, %m", parse->ppsfd);
3001 				msyslog(LOG_NOTICE,
3002 					"refclock_parse: optional PPS processing not available");
3003 			} else {
3004 				parse->flags    |= PARSE_PPSCLOCK;
3005 #ifdef ASYNC_PPS_CD_NEG
3006 				NLOG(NLOG_CLOCKINFO)
3007 				  msyslog(LOG_INFO,
3008 					  "refclock_parse: PPS detection on");
3009 #endif
3010 			}
3011 		}
3012 #endif
3013 
3014 /*
3015  * SUN the Solaris way
3016  */
3017 #ifdef HAVE_TIOCSPPS			/* SUN PPS support */
3018 		if (CLK_PPS(parse->peer))
3019 		    {
3020 			int i = 1;
3021 
3022 			if (ioctl(parse->ppsfd, TIOCSPPS, (caddr_t)&i) == 0)
3023 			    {
3024 				parse->flags |= PARSE_PPSCLOCK;
3025 			    }
3026 		    }
3027 #endif
3028 
3029 /*
3030  * PPS via PPSAPI
3031  */
3032 #if defined(HAVE_PPSAPI)
3033 		parse->hardppsstate = PARSE_HARDPPS_DISABLE;
3034 		if (CLK_PPS(parse->peer))
3035 		{
3036 		  if (time_pps_create(parse->ppsfd, &parse->ppshandle) < 0)
3037 		    {
3038 		      msyslog(LOG_NOTICE, "PARSE receiver #%d: parse_start: could not set up PPS: %m", CLK_UNIT(parse->peer));
3039 		    }
3040 		  else
3041 		    {
3042 		      parse_ppsapi(parse);
3043 		    }
3044 		}
3045 #endif
3046 
3047 		if (TTY_SETATTR(fd232, &tio) == -1)
3048 		{
3049 			msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: tcsetattr(%d, &tio): %m", unit, fd232);
3050 			parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
3051 			return 0;
3052 		}
3053 	}
3054 
3055 	/*
3056 	 * pick correct input machine
3057 	 */
3058 	parse->generic->io.srcclock = (caddr_t)parse;
3059 	parse->generic->io.datalen = 0;
3060 
3061 	parse->binding = init_iobinding(parse);
3062 
3063 	if (parse->binding == (bind_t *)0)
3064 		{
3065 			msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: io sub system initialisation failed.", CLK_UNIT(parse->peer));
3066 			parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
3067 			return 0;			/* well, ok - special initialisation broke */
3068 		}
3069 
3070 	parse->generic->io.clock_recv = parse->binding->bd_receive; /* pick correct receive routine */
3071 	parse->generic->io.io_input   = parse->binding->bd_io_input; /* pick correct input routine */
3072 
3073 	/*
3074 	 * as we always(?) get 8 bit chars we want to be
3075 	 * sure, that the upper bits are zero for less
3076 	 * than 8 bit I/O - so we pass that information on.
3077 	 * note that there can be only one bit count format
3078 	 * per file descriptor
3079 	 */
3080 
3081 	switch (tio.c_cflag & CSIZE)
3082 	{
3083 	    case CS5:
3084 		tmp_ctl.parsesetcs.parse_cs = PARSE_IO_CS5;
3085 		break;
3086 
3087 	    case CS6:
3088 		tmp_ctl.parsesetcs.parse_cs = PARSE_IO_CS6;
3089 		break;
3090 
3091 	    case CS7:
3092 		tmp_ctl.parsesetcs.parse_cs = PARSE_IO_CS7;
3093 		break;
3094 
3095 	    case CS8:
3096 		tmp_ctl.parsesetcs.parse_cs = PARSE_IO_CS8;
3097 		break;
3098 	}
3099 
3100 	if (!PARSE_SETCS(parse, &tmp_ctl))
3101 	{
3102 		msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: parse_setcs() FAILED.", unit);
3103 		parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
3104 		return 0;			/* well, ok - special initialisation broke */
3105 	}
3106 
3107 	strncpy(tmp_ctl.parseformat.parse_buffer, parse->parse_type->cl_format, sizeof(tmp_ctl.parseformat.parse_buffer));
3108 	tmp_ctl.parseformat.parse_count = strlen(tmp_ctl.parseformat.parse_buffer);
3109 
3110 	if (!PARSE_SETFMT(parse, &tmp_ctl))
3111 	{
3112 		msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: parse_setfmt() FAILED.", unit);
3113 		parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
3114 		return 0;			/* well, ok - special initialisation broke */
3115 	}
3116 
3117 	/*
3118 	 * get rid of all IO accumulated so far
3119 	 */
3120 #ifdef HAVE_TERMIOS
3121 	(void) tcflush(parse->generic->io.fd, TCIOFLUSH);
3122 #else
3123 #if defined(TCFLSH) && defined(TCIOFLUSH)
3124 	{
3125 		int flshcmd = TCIOFLUSH;
3126 
3127 		(void) ioctl(parse->generic->io.fd, TCFLSH, (caddr_t)&flshcmd);
3128 	}
3129 #endif
3130 #endif
3131 
3132 	/*
3133 	 * try to do any special initializations
3134 	 */
3135 	if (parse->parse_type->cl_init)
3136 		{
3137 			if (parse->parse_type->cl_init(parse))
3138 				{
3139 					parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
3140 					return 0;		/* well, ok - special initialisation broke */
3141 				}
3142 		}
3143 
3144 	/*
3145 	 * Insert in async io device list.
3146 	 */
3147 	if (!io_addclock(&parse->generic->io))
3148         {
3149 		msyslog(LOG_ERR,
3150 			"PARSE receiver #%d: parse_start: addclock %s fails (ABORT - clock type requires async io)", CLK_UNIT(parse->peer), parsedev);
3151 		parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
3152 		return 0;
3153 	}
3154 
3155 	/*
3156 	 * print out configuration
3157 	 */
3158 	NLOG(NLOG_CLOCKINFO)
3159 		{
3160 			/* conditional if clause for conditional syslog */
3161 			msyslog(LOG_INFO, "PARSE receiver #%d: reference clock \"%s\" (I/O device %s, PPS device %s) added",
3162 				CLK_UNIT(parse->peer),
3163 				parse->parse_type->cl_description, parsedev,
3164 				(parse->ppsfd != parse->generic->io.fd) ? parseppsdev : parsedev);
3165 
3166 			msyslog(LOG_INFO, "PARSE receiver #%d: Stratum %d, trust time %s, precision %d",
3167 				CLK_UNIT(parse->peer),
3168 				parse->peer->stratum,
3169 				l_mktime(parse->maxunsync), parse->peer->precision);
3170 
3171 			msyslog(LOG_INFO, "PARSE receiver #%d: rootdelay %.6f s, phase adjustment %.6f s, PPS phase adjustment %.6f s, %s IO handling",
3172 				CLK_UNIT(parse->peer),
3173 				parse->parse_type->cl_rootdelay,
3174 				parse->generic->fudgetime1,
3175 				parse->ppsphaseadjust,
3176                                 parse->binding->bd_description);
3177 
3178 			msyslog(LOG_INFO, "PARSE receiver #%d: Format recognition: %s", CLK_UNIT(parse->peer),
3179 				parse->parse_type->cl_format);
3180                         msyslog(LOG_INFO, "PARSE receiver #%d: %sPPS support%s", CLK_UNIT(parse->peer),
3181 				CLK_PPS(parse->peer) ? "" : "NO ",
3182 				CLK_PPS(parse->peer) ?
3183 #ifdef PPS_METHOD
3184 				" (implementation " PPS_METHOD ")"
3185 #else
3186 				""
3187 #endif
3188 				: ""
3189 				);
3190 		}
3191 
3192 	return 1;
3193 }
3194 
3195 /*--------------------------------------------------
3196  * parse_ctl - process changes on flags/time values
3197  */
3198 static void
3199 parse_ctl(
3200 	    struct parseunit *parse,
3201 	    struct refclockstat *in
3202 	    )
3203 {
3204         if (in)
3205 	{
3206 		if (in->haveflags & (CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4))
3207 		{
3208 		  parse->flags = (parse->flags & ~(CLK_FLAG1|CLK_FLAG2|CLK_FLAG3|CLK_FLAG4)) |
3209 		    (in->flags & (CLK_FLAG1|CLK_FLAG2|CLK_FLAG3|CLK_FLAG4));
3210 #if defined(HAVE_PPSAPI)
3211 		  if (CLK_PPS(parse->peer))
3212 		    {
3213 		      parse_ppsapi(parse);
3214 		    }
3215 #endif
3216 		}
3217 
3218 		if (in->haveflags & CLK_HAVETIME1)
3219                 {
3220 		  parse->generic->fudgetime1 = in->fudgetime1;
3221 		  msyslog(LOG_INFO, "PARSE receiver #%d: new phase adjustment %.6f s",
3222 			  CLK_UNIT(parse->peer),
3223 			  parse->generic->fudgetime1);
3224 		}
3225 
3226 		if (in->haveflags & CLK_HAVETIME2)
3227                 {
3228 		  parse->generic->fudgetime2 = in->fudgetime2;
3229 		  if (parse->flags & PARSE_TRUSTTIME)
3230 		    {
3231 		      parse->maxunsync = (u_long)ABS(in->fudgetime2);
3232 		      msyslog(LOG_INFO, "PARSE receiver #%d: new trust time %s",
3233 			      CLK_UNIT(parse->peer),
3234 			      l_mktime(parse->maxunsync));
3235 		    }
3236 		  else
3237 		    {
3238 		      parse->ppsphaseadjust = in->fudgetime2;
3239 		      msyslog(LOG_INFO, "PARSE receiver #%d: new PPS phase adjustment %.6f s",
3240 			  CLK_UNIT(parse->peer),
3241 			      parse->ppsphaseadjust);
3242 #if defined(HAVE_PPSAPI)
3243 		      if (CLK_PPS(parse->peer))
3244 		      {
3245 			      parse_ppsapi(parse);
3246 		      }
3247 #endif
3248 		    }
3249 		}
3250 	}
3251 }
3252 
3253 /*--------------------------------------------------
3254  * parse_poll - called by the transmit procedure
3255  */
3256 static void
3257 parse_poll(
3258 	int unit,
3259 	struct peer *peer
3260 	)
3261 {
3262 	struct parseunit *parse = (struct parseunit *)peer->procptr->unitptr;
3263 
3264 	if (peer != parse->peer)
3265 	{
3266 		msyslog(LOG_ERR,
3267 			"PARSE receiver #%d: poll: INTERNAL: peer incorrect",
3268 			unit);
3269 		return;
3270 	}
3271 
3272 	/*
3273 	 * Update clock stat counters
3274 	 */
3275 	parse->generic->polls++;
3276 
3277 	if (parse->pollneeddata &&
3278 	    ((current_time - parse->pollneeddata) > (1<<(max(min(parse->peer->hpoll, parse->peer->ppoll), parse->peer->minpoll)))))
3279 	{
3280 		/*
3281 		 * start worrying when exceeding a poll inteval
3282 		 * bad news - didn't get a response last time
3283 		 */
3284 		parse->lastmissed = current_time;
3285 		parse_event(parse, CEVNT_TIMEOUT);
3286 
3287 		ERR(ERR_NODATA)
3288 			msyslog(LOG_WARNING, "PARSE receiver #%d: no data from device within poll interval (check receiver / wiring)", CLK_UNIT(parse->peer));
3289 	}
3290 
3291 	/*
3292 	 * we just mark that we want the next sample for the clock filter
3293 	 */
3294 	parse->pollneeddata = current_time;
3295 
3296 	if (parse->parse_type->cl_poll)
3297 	{
3298 		parse->parse_type->cl_poll(parse);
3299 	}
3300 
3301 	cparse_statistics(parse);
3302 
3303 	return;
3304 }
3305 
3306 #define LEN_STATES 300		/* length of state string */
3307 
3308 /*--------------------------------------------------
3309  * parse_control - set fudge factors, return statistics
3310  */
3311 static void
3312 parse_control(
3313 	int unit,
3314 	struct refclockstat *in,
3315 	struct refclockstat *out,
3316 	struct peer *peer
3317 	)
3318 {
3319         struct parseunit *parse = (struct parseunit *)peer->procptr->unitptr;
3320 	parsectl_t tmpctl;
3321 
3322 	static char outstatus[400];	/* status output buffer */
3323 
3324 	if (out)
3325 	{
3326 		out->lencode       = 0;
3327 		out->p_lastcode    = 0;
3328 		out->kv_list       = (struct ctl_var *)0;
3329 	}
3330 
3331 	if (!parse || !parse->peer)
3332 	{
3333 		msyslog(LOG_ERR, "PARSE receiver #%d: parse_control: unit invalid (UNIT INACTIVE)",
3334 			unit);
3335 		return;
3336 	}
3337 
3338 	unit = CLK_UNIT(parse->peer);
3339 
3340 	/*
3341 	 * handle changes
3342 	 */
3343 	parse_ctl(parse, in);
3344 
3345 	/*
3346 	 * supply data
3347 	 */
3348 	if (out)
3349 	{
3350 		u_long sum = 0;
3351 		char *tt, *start;
3352 		int i;
3353 
3354 		outstatus[0] = '\0';
3355 
3356 		out->type       = REFCLK_PARSE;
3357 
3358 		/*
3359 		 * keep fudgetime2 in sync with TRUSTTIME/MAXUNSYNC flag1
3360 		 */
3361 		parse->generic->fudgetime2 = (parse->flags & PARSE_TRUSTTIME) ? (double)parse->maxunsync : parse->ppsphaseadjust;
3362 
3363 		/*
3364 		 * figure out skew between PPS and RS232 - just for informational
3365 		 * purposes
3366 		 */
3367 		if (PARSE_SYNC(parse->timedata.parse_state))
3368 		{
3369 			if (PARSE_PPS(parse->timedata.parse_state) && PARSE_TIMECODE(parse->timedata.parse_state))
3370 			{
3371 				l_fp off;
3372 
3373 				/*
3374 				 * we have a PPS and RS232 signal - calculate the skew
3375 				 * WARNING: assumes on TIMECODE == PULSE (timecode after pulse)
3376 				 */
3377 				off = parse->timedata.parse_stime.fp;
3378 				L_SUB(&off, &parse->timedata.parse_ptime.fp); /* true offset */
3379 				tt = add_var(&out->kv_list, 80, RO);
3380 				snprintf(tt, 80, "refclock_ppsskew=%s", lfptoms(&off, 6));
3381 			}
3382 		}
3383 
3384 		if (PARSE_PPS(parse->timedata.parse_state))
3385 		{
3386 			tt = add_var(&out->kv_list, 80, RO|DEF);
3387 			snprintf(tt, 80, "refclock_ppstime=\"%s\"", gmprettydate(&parse->timedata.parse_ptime.fp));
3388 		}
3389 
3390 		start = tt = add_var(&out->kv_list, 128, RO|DEF);
3391 		snprintf(tt, 128, "refclock_time=\"");
3392 		tt += strlen(tt);
3393 
3394 		if (parse->timedata.parse_time.fp.l_ui == 0)
3395 		{
3396 			strncpy(tt, "<UNDEFINED>\"", BUFFER_SIZES(start, tt, 128));
3397 		}
3398 		else
3399 		{
3400 			snprintf(tt, 128, "%s\"", gmprettydate(&parse->timedata.parse_time.fp));
3401 		}
3402 
3403 		if (!PARSE_GETTIMECODE(parse, &tmpctl))
3404 		{
3405 			ERR(ERR_INTERNAL)
3406 				msyslog(LOG_ERR, "PARSE receiver #%d: parse_control: parse_timecode() FAILED", unit);
3407 		}
3408 		else
3409 		{
3410 			start = tt = add_var(&out->kv_list, 512, RO|DEF);
3411 			snprintf(tt, 512, "refclock_status=\"");
3412 			tt += strlen(tt);
3413 
3414 			/*
3415 			 * copy PPS flags from last read transaction (informational only)
3416 			 */
3417 			tmpctl.parsegettc.parse_state |= parse->timedata.parse_state &
3418 				(PARSEB_PPS|PARSEB_S_PPS);
3419 
3420 			(void) parsestate(tmpctl.parsegettc.parse_state, tt, BUFFER_SIZES(start, tt, 512));
3421 
3422 			strncat(tt, "\"", BUFFER_SIZES(start, tt, 512));
3423 
3424 			if (tmpctl.parsegettc.parse_count)
3425 			    mkascii(outstatus+strlen(outstatus), (int)(sizeof(outstatus)- strlen(outstatus) - 1),
3426 				    tmpctl.parsegettc.parse_buffer, (unsigned)(tmpctl.parsegettc.parse_count));
3427 
3428 		}
3429 
3430 		tmpctl.parseformat.parse_format = tmpctl.parsegettc.parse_format;
3431 
3432 		if (!PARSE_GETFMT(parse, &tmpctl))
3433 		{
3434 			ERR(ERR_INTERNAL)
3435 				msyslog(LOG_ERR, "PARSE receiver #%d: parse_control: parse_getfmt() FAILED", unit);
3436 		}
3437 		else
3438 		{
3439 			tt = add_var(&out->kv_list, 80, RO|DEF);
3440 			snprintf(tt, 80, "refclock_format=\"");
3441 
3442 			strncat(tt, tmpctl.parseformat.parse_buffer, tmpctl.parseformat.parse_count);
3443 			strncat(tt,"\"", 80);
3444 		}
3445 
3446 		/*
3447 		 * gather state statistics
3448 		 */
3449 
3450 		start = tt = add_var(&out->kv_list, LEN_STATES, RO|DEF);
3451 		strncpy(tt, "refclock_states=\"", LEN_STATES);
3452 		tt += strlen(tt);
3453 
3454 		for (i = 0; i <= CEVNT_MAX; i++)
3455 		{
3456 			u_long s_time;
3457 			u_long d = current_time - parse->generic->timestarted;
3458 			u_long percent;
3459 
3460 			percent = s_time = PARSE_STATETIME(parse, i);
3461 
3462 			while (((u_long)(~0) / 10000) < percent)
3463 			{
3464 				percent /= 10;
3465 				d       /= 10;
3466 			}
3467 
3468 			if (d)
3469 			    percent = (percent * 10000) / d;
3470 			else
3471 			    percent = 10000;
3472 
3473 			if (s_time)
3474 			{
3475 				char item[80];
3476 				int count;
3477 
3478 				snprintf(item, 80, "%s%s%s: %s (%d.%02d%%)",
3479 					sum ? "; " : "",
3480 					(parse->generic->currentstatus == i) ? "*" : "",
3481 					clockstatus((unsigned int)i),
3482 					l_mktime(s_time),
3483 					(int)(percent / 100), (int)(percent % 100));
3484 				if ((count = strlen(item)) < (LEN_STATES - 40 - (tt - start)))
3485 					{
3486 						strncpy(tt, item, BUFFER_SIZES(start, tt, LEN_STATES));
3487 						tt  += count;
3488 					}
3489 				sum += s_time;
3490 			}
3491 		}
3492 
3493 		snprintf(tt, BUFFER_SIZES(start, tt, LEN_STATES), "; running time: %s\"", l_mktime(sum));
3494 
3495 		tt = add_var(&out->kv_list, 32, RO);
3496 		snprintf(tt, 32,  "refclock_id=\"%s\"", parse->parse_type->cl_id);
3497 
3498 		tt = add_var(&out->kv_list, 80, RO);
3499 		snprintf(tt, 80,  "refclock_iomode=\"%s\"", parse->binding->bd_description);
3500 
3501 		tt = add_var(&out->kv_list, 128, RO);
3502 		snprintf(tt, 128, "refclock_driver_version=\"%s\"", rcsid);
3503 
3504 		{
3505 			struct ctl_var *k;
3506 
3507 			k = parse->kv;
3508 			while (k && !(k->flags & EOV))
3509 			{
3510 				set_var(&out->kv_list, k->text, strlen(k->text)+1, k->flags);
3511 				k++;
3512 			}
3513 		}
3514 
3515 		out->lencode       = strlen(outstatus);
3516 		out->p_lastcode    = outstatus;
3517 	}
3518 }
3519 
3520 /**===========================================================================
3521  ** processing routines
3522  **/
3523 
3524 /*--------------------------------------------------
3525  * event handling - note that nominal events will also be posted
3526  * keep track of state dwelling times
3527  */
3528 static void
3529 parse_event(
3530 	struct parseunit *parse,
3531 	int event
3532 	)
3533 {
3534 	if (parse->generic->currentstatus != (u_char) event)
3535 	{
3536 		parse->statetime[parse->generic->currentstatus] += current_time - parse->lastchange;
3537 		parse->lastchange              = current_time;
3538 
3539 		if (parse->parse_type->cl_event)
3540 		    parse->parse_type->cl_event(parse, event);
3541 
3542 		if (event == CEVNT_NOMINAL)
3543 		{
3544 			NLOG(NLOG_CLOCKSTATUS)
3545 				msyslog(LOG_INFO, "PARSE receiver #%d: SYNCHRONIZED",
3546 					CLK_UNIT(parse->peer));
3547 		}
3548 
3549 		refclock_report(parse->peer, event);
3550 	}
3551 }
3552 
3553 /*--------------------------------------------------
3554  * process a PARSE time sample
3555  */
3556 static void
3557 parse_process(
3558 	struct parseunit *parse,
3559 	parsetime_t      *parsetime
3560 	)
3561 {
3562 	l_fp off, rectime, reftime;
3563 	double fudge;
3564 
3565 	/*
3566 	 * check for changes in conversion status
3567 	 * (only one for each new status !)
3568 	 */
3569 	if (((parsetime->parse_status & CVT_MASK) != CVT_OK) &&
3570 	    ((parsetime->parse_status & CVT_MASK) != CVT_NONE) &&
3571 	    (parse->timedata.parse_status != parsetime->parse_status))
3572 	{
3573 		char buffer[400];
3574 
3575 		NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
3576 			msyslog(LOG_WARNING, "PARSE receiver #%d: conversion status \"%s\"",
3577 				CLK_UNIT(parse->peer), parsestatus(parsetime->parse_status, buffer, sizeof(buffer)));
3578 
3579 		if ((parsetime->parse_status & CVT_MASK) == CVT_FAIL)
3580 		{
3581 			/*
3582 			 * tell more about the story - list time code
3583 			 * there is a slight change for a race condition and
3584 			 * the time code might be overwritten by the next packet
3585 			 */
3586 			parsectl_t tmpctl;
3587 
3588 			if (!PARSE_GETTIMECODE(parse, &tmpctl))
3589 			{
3590 				ERR(ERR_INTERNAL)
3591 					msyslog(LOG_ERR, "PARSE receiver #%d: parse_process: parse_timecode() FAILED", CLK_UNIT(parse->peer));
3592 			}
3593 			else
3594 			{
3595 				ERR(ERR_BADDATA)
3596 					msyslog(LOG_WARNING, "PARSE receiver #%d: FAILED TIMECODE: \"%s\" (check receiver configuration / wiring)",
3597 						CLK_UNIT(parse->peer), mkascii(buffer, sizeof buffer, tmpctl.parsegettc.parse_buffer, (unsigned)(tmpctl.parsegettc.parse_count - 1)));
3598 			}
3599 		}
3600 	}
3601 
3602 	/*
3603 	 * examine status and post appropriate events
3604 	 */
3605 	if ((parsetime->parse_status & CVT_MASK) != CVT_OK)
3606 	{
3607 		/*
3608 		 * got bad data - tell the rest of the system
3609 		 */
3610 		switch (parsetime->parse_status & CVT_MASK)
3611 		{
3612 		case CVT_NONE:
3613 			if ((parsetime->parse_status & CVT_ADDITIONAL) &&
3614 			    parse->parse_type->cl_message)
3615 				parse->parse_type->cl_message(parse, parsetime);
3616 			/*
3617 			 * save PPS information that comes piggyback
3618 			 */
3619 			if (PARSE_PPS(parsetime->parse_state))
3620 			  {
3621 			    parse->timedata.parse_state |= PARSEB_PPS|PARSEB_S_PPS;
3622 			    parse->timedata.parse_ptime  = parsetime->parse_ptime;
3623 			  }
3624 			break; 		/* well, still waiting - timeout is handled at higher levels */
3625 
3626 		case CVT_FAIL:
3627 			if (parsetime->parse_status & CVT_BADFMT)
3628 			{
3629 				parse_event(parse, CEVNT_BADREPLY);
3630 			}
3631 			else
3632 				if (parsetime->parse_status & CVT_BADDATE)
3633 				{
3634 					parse_event(parse, CEVNT_BADDATE);
3635 				}
3636 				else
3637 					if (parsetime->parse_status & CVT_BADTIME)
3638 					{
3639 						parse_event(parse, CEVNT_BADTIME);
3640 					}
3641 					else
3642 					{
3643 						parse_event(parse, CEVNT_BADREPLY); /* for the lack of something better */
3644 					}
3645 		}
3646 		return;			/* skip the rest - useless */
3647 	}
3648 
3649 	/*
3650 	 * check for format changes
3651 	 * (in case somebody has swapped clocks 8-)
3652 	 */
3653 	if (parse->lastformat != parsetime->parse_format)
3654 	{
3655 		parsectl_t tmpctl;
3656 
3657 		tmpctl.parseformat.parse_format = parsetime->parse_format;
3658 
3659 		if (!PARSE_GETFMT(parse, &tmpctl))
3660 		{
3661 			ERR(ERR_INTERNAL)
3662 				msyslog(LOG_ERR, "PARSE receiver #%d: parse_getfmt() FAILED", CLK_UNIT(parse->peer));
3663 		}
3664 		else
3665 		{
3666 			NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
3667 				msyslog(LOG_INFO, "PARSE receiver #%d: packet format \"%s\"",
3668 					CLK_UNIT(parse->peer), tmpctl.parseformat.parse_buffer);
3669 		}
3670 		parse->lastformat = parsetime->parse_format;
3671 	}
3672 
3673 	/*
3674 	 * now, any changes ?
3675 	 */
3676 	if ((parse->timedata.parse_state ^ parsetime->parse_state) &
3677 	    ~(unsigned)(PARSEB_PPS|PARSEB_S_PPS))
3678 	{
3679 		char tmp1[200];
3680 		char tmp2[200];
3681 		/*
3682 		 * something happend - except for PPS events
3683 		 */
3684 
3685 		(void) parsestate(parsetime->parse_state, tmp1, sizeof(tmp1));
3686 		(void) parsestate(parse->timedata.parse_state, tmp2, sizeof(tmp2));
3687 
3688 		NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
3689 			msyslog(LOG_INFO,"PARSE receiver #%d: STATE CHANGE: %s -> %s",
3690 				CLK_UNIT(parse->peer), tmp2, tmp1);
3691 	}
3692 
3693 	/*
3694 	 * carry on PPS information if still usable
3695 	 */
3696 	if (PARSE_PPS(parse->timedata.parse_state) && !PARSE_PPS(parsetime->parse_state))
3697         {
3698 	        parsetime->parse_state |= PARSEB_PPS|PARSEB_S_PPS;
3699 		parsetime->parse_ptime  = parse->timedata.parse_ptime;
3700 	}
3701 
3702 	/*
3703 	 * remember for future
3704 	 */
3705 	parse->timedata = *parsetime;
3706 
3707 	/*
3708 	 * check to see, whether the clock did a complete powerup or lost PZF signal
3709 	 * and post correct events for current condition
3710 	 */
3711 	if (PARSE_POWERUP(parsetime->parse_state))
3712 	{
3713 		/*
3714 		 * this is bad, as we have completely lost synchronisation
3715 		 * well this is a problem with the receiver here
3716 		 * for PARSE Meinberg DCF77 receivers the lost synchronisation
3717 		 * is true as it is the powerup state and the time is taken
3718 		 * from a crude real time clock chip
3719 		 * for the PZF series this is only partly true, as
3720 		 * PARSE_POWERUP only means that the pseudo random
3721 		 * phase shift sequence cannot be found. this is only
3722 		 * bad, if we have never seen the clock in the SYNC
3723 		 * state, where the PHASE and EPOCH are correct.
3724 		 * for reporting events the above business does not
3725 		 * really matter, but we can use the time code
3726 		 * even in the POWERUP state after having seen
3727 		 * the clock in the synchronized state (PZF class
3728 		 * receivers) unless we have had a telegram disruption
3729 		 * after having seen the clock in the SYNC state. we
3730 		 * thus require having seen the clock in SYNC state
3731 		 * *after* having missed telegrams (noresponse) from
3732 		 * the clock. one problem remains: we might use erroneously
3733 		 * POWERUP data if the disruption is shorter than 1 polling
3734 		 * interval. fortunately powerdowns last usually longer than 64
3735 		 * seconds and the receiver is at least 2 minutes in the
3736 		 * POWERUP or NOSYNC state before switching to SYNC
3737 		 */
3738 		parse_event(parse, CEVNT_FAULT);
3739 		NLOG(NLOG_CLOCKSTATUS)
3740 			ERR(ERR_BADSTATUS)
3741 			msyslog(LOG_ERR,"PARSE receiver #%d: NOT SYNCHRONIZED",
3742 				CLK_UNIT(parse->peer));
3743 	}
3744 	else
3745 	{
3746 		/*
3747 		 * we have two states left
3748 		 *
3749 		 * SYNC:
3750 		 *  this state means that the EPOCH (timecode) and PHASE
3751 		 *  information has be read correctly (at least two
3752 		 *  successive PARSE timecodes were received correctly)
3753 		 *  this is the best possible state - full trust
3754 		 *
3755 		 * NOSYNC:
3756 		 *  The clock should be on phase with respect to the second
3757 		 *  signal, but the timecode has not been received correctly within
3758 		 *  at least the last two minutes. this is a sort of half baked state
3759 		 *  for PARSE Meinberg DCF77 clocks this is bad news (clock running
3760 		 *  without timecode confirmation)
3761 		 *  PZF 535 has also no time confirmation, but the phase should be
3762 		 *  very precise as the PZF signal can be decoded
3763 		 */
3764 
3765 		if (PARSE_SYNC(parsetime->parse_state))
3766 		{
3767 			/*
3768 			 * currently completely synchronized - best possible state
3769 			 */
3770 			parse->lastsync = current_time;
3771 			clear_err(parse, ERR_BADSTATUS);
3772 		}
3773 		else
3774 		{
3775 			/*
3776 			 * we have had some problems receiving the time code
3777 			 */
3778 			parse_event(parse, CEVNT_PROP);
3779 			NLOG(NLOG_CLOCKSTATUS)
3780 				ERR(ERR_BADSTATUS)
3781 				msyslog(LOG_ERR,"PARSE receiver #%d: TIMECODE NOT CONFIRMED",
3782 					CLK_UNIT(parse->peer));
3783 		}
3784 	}
3785 
3786 	fudge = parse->generic->fudgetime1; /* standard RS232 Fudgefactor */
3787 
3788 	if (PARSE_TIMECODE(parsetime->parse_state))
3789 	{
3790 		rectime = parsetime->parse_stime.fp;
3791 		off = reftime = parsetime->parse_time.fp;
3792 
3793 		L_SUB(&off, &rectime); /* prepare for PPS adjustments logic */
3794 
3795 #ifdef DEBUG
3796 		if (debug > 3)
3797 			printf("PARSE receiver #%d: Reftime %s, Recvtime %s - initial offset %s\n",
3798 			       CLK_UNIT(parse->peer),
3799 			       prettydate(&reftime),
3800 			       prettydate(&rectime),
3801 			       lfptoa(&off,6));
3802 #endif
3803 	}
3804 
3805 	if (PARSE_PPS(parsetime->parse_state) && CLK_PPS(parse->peer))
3806 	{
3807 		l_fp offset;
3808 		double ppsphaseadjust = parse->ppsphaseadjust;
3809 
3810 #ifdef HAVE_PPSAPI
3811 		/*
3812 		 * set fudge = 0.0 if already included in PPS time stamps
3813 		 */
3814 		if (parse->ppsparams.mode & (PPS_OFFSETCLEAR|PPS_OFFSETASSERT))
3815 		        {
3816 			        ppsphaseadjust = 0.0;
3817 			}
3818 #endif
3819 
3820 		/*
3821 		 * we have a PPS signal - much better than the RS232 stuff (we hope)
3822 		 */
3823 		offset = parsetime->parse_ptime.fp;
3824 
3825 #ifdef DEBUG
3826 		if (debug > 3)
3827 			printf("PARSE receiver #%d: PPStime %s\n",
3828 				CLK_UNIT(parse->peer),
3829 				prettydate(&offset));
3830 #endif
3831 		if (PARSE_TIMECODE(parsetime->parse_state))
3832 		{
3833 			if (M_ISGEQ(off.l_i, off.l_f, -1, 0x80000000) &&
3834 			    M_ISGEQ(0, 0x7fffffff, off.l_i, off.l_f))
3835 			{
3836 				fudge = ppsphaseadjust; /* pick PPS fudge factor */
3837 
3838 				/*
3839 				 * RS232 offsets within [-0.5..0.5[ - take PPS offsets
3840 				 */
3841 
3842 				if (parse->parse_type->cl_flags & PARSE_F_PPSONSECOND)
3843 				{
3844 					reftime = off = offset;
3845 					if (reftime.l_uf & (unsigned)0x80000000)
3846 						reftime.l_ui++;
3847 					reftime.l_uf = 0;
3848 
3849 
3850 					/*
3851 					 * implied on second offset
3852 					 */
3853 					off.l_uf = ~off.l_uf; /* map [0.5..1[ -> [-0.5..0[ */
3854 					off.l_ui = (off.l_f < 0) ? ~0 : 0; /* sign extend */
3855 				}
3856 				else
3857 				{
3858 					/*
3859 					 * time code describes pulse
3860 					 */
3861 					reftime = off = parsetime->parse_time.fp;
3862 
3863 					L_SUB(&off, &offset); /* true offset */
3864 				}
3865 			}
3866 			/*
3867 			 * take RS232 offset when PPS when out of bounds
3868 			 */
3869 		}
3870 		else
3871 		{
3872 			fudge = ppsphaseadjust; /* pick PPS fudge factor */
3873 			/*
3874 			 * Well, no time code to guide us - assume on second pulse
3875 			 * and pray, that we are within [-0.5..0.5[
3876 			 */
3877 			off = offset;
3878 			reftime = offset;
3879 			if (reftime.l_uf & (unsigned)0x80000000)
3880 				reftime.l_ui++;
3881 			reftime.l_uf = 0;
3882 			/*
3883 			 * implied on second offset
3884 			 */
3885 			off.l_uf = ~off.l_uf; /* map [0.5..1[ -> [-0.5..0[ */
3886 			off.l_ui = (off.l_f < 0) ? ~0 : 0; /* sign extend */
3887 		}
3888 	}
3889 	else
3890 	{
3891 		if (!PARSE_TIMECODE(parsetime->parse_state))
3892 		{
3893 			/*
3894 			 * Well, no PPS, no TIMECODE, no more work ...
3895 			 */
3896 			if ((parsetime->parse_status & CVT_ADDITIONAL) &&
3897 			    parse->parse_type->cl_message)
3898 				parse->parse_type->cl_message(parse, parsetime);
3899 			return;
3900 		}
3901 	}
3902 
3903 #ifdef DEBUG
3904 	if (debug > 3)
3905 		printf("PARSE receiver #%d: Reftime %s, Recvtime %s - final offset %s\n",
3906 			CLK_UNIT(parse->peer),
3907 			prettydate(&reftime),
3908 			prettydate(&rectime),
3909 			lfptoa(&off,6));
3910 #endif
3911 
3912 
3913 	rectime = reftime;
3914 	L_SUB(&rectime, &off);	/* just to keep the ntp interface happy */
3915 
3916 #ifdef DEBUG
3917 	if (debug > 3)
3918 		printf("PARSE receiver #%d: calculated Reftime %s, Recvtime %s\n",
3919 			CLK_UNIT(parse->peer),
3920 			prettydate(&reftime),
3921 			prettydate(&rectime));
3922 #endif
3923 
3924 	if ((parsetime->parse_status & CVT_ADDITIONAL) &&
3925 	    parse->parse_type->cl_message)
3926 		parse->parse_type->cl_message(parse, parsetime);
3927 
3928 	if (PARSE_SYNC(parsetime->parse_state))
3929 	{
3930 		/*
3931 		 * log OK status
3932 		 */
3933 		parse_event(parse, CEVNT_NOMINAL);
3934 	}
3935 
3936 	clear_err(parse, ERR_BADIO);
3937 	clear_err(parse, ERR_BADDATA);
3938 	clear_err(parse, ERR_NODATA);
3939 	clear_err(parse, ERR_INTERNAL);
3940 
3941 	/*
3942 	 * and now stick it into the clock machine
3943 	 * samples are only valid iff lastsync is not too old and
3944 	 * we have seen the clock in sync at least once
3945 	 * after the last time we didn't see an expected data telegram
3946 	 * at startup being not in sync is also bad just like
3947 	 * POWERUP state
3948 	 * see the clock states section above for more reasoning
3949 	 */
3950 	if (((current_time - parse->lastsync) > parse->maxunsync) ||
3951 	    (parse->lastsync < parse->lastmissed) ||
3952 	    ((parse->lastsync == 0) && !PARSE_SYNC(parsetime->parse_state)) ||
3953 	    PARSE_POWERUP(parsetime->parse_state))
3954 	{
3955 		parse->generic->leap = LEAP_NOTINSYNC;
3956 		parse->lastsync = 0;	/* wait for full sync again */
3957 	}
3958 	else
3959 	{
3960 		if (PARSE_LEAPADD(parsetime->parse_state))
3961 		{
3962 			/*
3963 			 * we pick this state also for time code that pass leap warnings
3964 			 * without direction information (as earth is currently slowing
3965 			 * down).
3966 			 */
3967 			parse->generic->leap = (parse->flags & PARSE_LEAP_DELETE) ? LEAP_DELSECOND : LEAP_ADDSECOND;
3968 		}
3969 		else
3970 		    if (PARSE_LEAPDEL(parsetime->parse_state))
3971 		    {
3972 			    parse->generic->leap = LEAP_DELSECOND;
3973 		    }
3974 		    else
3975 		    {
3976 			    parse->generic->leap = LEAP_NOWARNING;
3977 		    }
3978 	}
3979 
3980 	if (parse->generic->leap != LEAP_NOTINSYNC)
3981 	{
3982 	        /*
3983 		 * only good/trusted samples are interesting
3984 		 */
3985 #ifdef DEBUG
3986 	        if (debug > 2)
3987 		        {
3988 			        printf("PARSE receiver #%d: refclock_process_offset(reftime=%s, rectime=%s, Fudge=%f)\n",
3989 				       CLK_UNIT(parse->peer),
3990 				       prettydate(&reftime),
3991 				       prettydate(&rectime),
3992 				       fudge);
3993 			}
3994 #endif
3995 		parse->generic->lastref = reftime;
3996 
3997 		refclock_process_offset(parse->generic, reftime, rectime, fudge);
3998 
3999 		/*
4000 		 * pass PPS information on to PPS clock
4001 		 */
4002 		if (PARSE_PPS(parsetime->parse_state) && CLK_PPS(parse->peer))
4003 		        {
4004 			        (void) pps_sample(&parse->timedata.parse_ptime.fp);
4005 				parse_hardpps(parse, PARSE_HARDPPS_ENABLE);
4006 			}
4007 	} else {
4008 	        parse_hardpps(parse, PARSE_HARDPPS_DISABLE);
4009 	}
4010 
4011 	/*
4012 	 * ready, unless the machine wants a sample or
4013 	 * we are in fast startup mode (peer->dist > MAXDISTANCE)
4014 	 */
4015 	if (!parse->pollneeddata && parse->peer->disp <= MAXDISTANCE)
4016 	    return;
4017 
4018 	parse->pollneeddata = 0;
4019 
4020 	parse->timedata.parse_state &= ~(unsigned)(PARSEB_PPS|PARSEB_S_PPS);
4021 
4022 	refclock_receive(parse->peer);
4023 }
4024 
4025 /**===========================================================================
4026  ** special code for special clocks
4027  **/
4028 
4029 static void
4030 mk_utcinfo(
4031 	   char *t,
4032 	   int wnt,
4033 	   int wnlsf,
4034 	   int dn,
4035 	   int dtls,
4036 	   int dtlsf,
4037 	   int size
4038 	   )
4039 {
4040   l_fp leapdate;
4041   char *start = t;
4042 
4043   snprintf(t, size, "current correction %d sec", dtls);
4044   t += strlen(t);
4045 
4046   if (wnlsf < 990)
4047     wnlsf += 1024;
4048 
4049   if (wnt < 990)
4050     wnt += 1024;
4051 
4052   gpstolfp((unsigned short)wnlsf, (unsigned short)dn, 0, &leapdate);
4053 
4054   if ((dtlsf != dtls) &&
4055       ((wnlsf - wnt) < 52))
4056     {
4057 	    snprintf(t, BUFFER_SIZES(start, t, size), ", next correction %d sec on %s, new GPS-UTC offset %d",
4058 	      dtlsf - dtls, gmprettydate(&leapdate), dtlsf);
4059     }
4060   else
4061     {
4062 	    snprintf(t, BUFFER_SIZES(start, t, size), ", last correction on %s",
4063 	      gmprettydate(&leapdate));
4064     }
4065 }
4066 
4067 #ifdef CLOCK_MEINBERG
4068 /**===========================================================================
4069  ** Meinberg GPS166/GPS167 support
4070  **/
4071 
4072 /*------------------------------------------------------------
4073  * gps16x_message - process GPS16x messages
4074  */
4075 static void
4076 gps16x_message(
4077 	       struct parseunit *parse,
4078 	       parsetime_t      *parsetime
4079 	       )
4080 {
4081 	if (parse->timedata.parse_msglen && parsetime->parse_msg[0] == SOH)
4082 	{
4083 		GPS_MSG_HDR header;
4084 		unsigned char *bufp = (unsigned char *)parsetime->parse_msg + 1;
4085 
4086 #ifdef DEBUG
4087 		if (debug > 2)
4088 		{
4089 			char msgbuffer[600];
4090 
4091 			mkreadable(msgbuffer, sizeof(msgbuffer), (char *)parsetime->parse_msg, parsetime->parse_msglen, 1);
4092 			printf("PARSE receiver #%d: received message (%d bytes) >%s<\n",
4093 				CLK_UNIT(parse->peer),
4094 				parsetime->parse_msglen,
4095 				msgbuffer);
4096 		}
4097 #endif
4098 		get_mbg_header(&bufp, &header);
4099 		if (header.gps_hdr_csum == mbg_csum(parsetime->parse_msg + 1, 6) &&
4100 		    (header.gps_len == 0 ||
4101 		     (header.gps_len < sizeof(parsetime->parse_msg) &&
4102 		      header.gps_data_csum == mbg_csum(bufp, header.gps_len))))
4103 		{
4104 			/*
4105 			 * clean message
4106 			 */
4107 			switch (header.gps_cmd)
4108 			{
4109 			case GPS_SW_REV:
4110 				{
4111 					char buffer[64];
4112 					SW_REV gps_sw_rev;
4113 
4114 					get_mbg_sw_rev(&bufp, &gps_sw_rev);
4115 					snprintf(buffer, sizeof(buffer), "meinberg_gps_version=\"%x.%02x%s%s\"",
4116 						(gps_sw_rev.code >> 8) & 0xFF,
4117 						gps_sw_rev.code & 0xFF,
4118 						gps_sw_rev.name[0] ? " " : "",
4119 						gps_sw_rev.name);
4120 					set_var(&parse->kv, buffer, strlen(buffer)+1, RO|DEF);
4121 				}
4122 			break;
4123 
4124 			case GPS_STAT:
4125 				{
4126 					static struct state
4127 					{
4128 						unsigned short flag; /* status flag */
4129 						unsigned const char *string; /* bit name */
4130 					} states[] =
4131 					  {
4132 						  { TM_ANT_DISCONN, (const unsigned char *)"ANTENNA FAULTY" },
4133 						  { TM_SYN_FLAG,    (const unsigned char *)"NO SYNC SIGNAL" },
4134 						  { TM_NO_SYNC,     (const unsigned char *)"NO SYNC POWERUP" },
4135 						  { TM_NO_POS,      (const unsigned char *)"NO POSITION" },
4136 						  { 0, (const unsigned char *)"" }
4137 					  };
4138 					unsigned short status;
4139 					struct state *s = states;
4140 					char buffer[512];
4141 					char *p, *b;
4142 
4143 					status = get_lsb_short(&bufp);
4144 					snprintf(buffer, sizeof(buffer), "meinberg_gps_status=\"[0x%04x] ", status);
4145 
4146 					if (status)
4147 					{
4148 						p = b = buffer + strlen(buffer);
4149 						while (s->flag)
4150 						{
4151 							if (status & s->flag)
4152 							{
4153 								if (p != b)
4154 								{
4155 									*p++ = ',';
4156 									*p++ = ' ';
4157 								}
4158 
4159 								strncat(p, (const char *)s->string, sizeof(buffer));
4160 							}
4161 							s++;
4162 						}
4163 
4164 						*p++ = '"';
4165 						*p   = '\0';
4166 					}
4167 					else
4168 					{
4169 						strncat(buffer, "<OK>\"", sizeof(buffer));
4170 					}
4171 
4172 					set_var(&parse->kv, buffer, strlen(buffer)+1, RO|DEF);
4173 				}
4174 			break;
4175 
4176 			case GPS_POS_XYZ:
4177 				{
4178 					XYZ xyz;
4179 					char buffer[256];
4180 
4181 					get_mbg_xyz(&bufp, xyz);
4182 					snprintf(buffer, sizeof(buffer), "gps_position(XYZ)=\"%s m, %s m, %s m\"",
4183 						mfptoa(xyz[XP].l_ui, xyz[XP].l_uf, 1),
4184 						mfptoa(xyz[YP].l_ui, xyz[YP].l_uf, 1),
4185 						mfptoa(xyz[ZP].l_ui, xyz[ZP].l_uf, 1));
4186 
4187 					set_var(&parse->kv, buffer, sizeof(buffer), RO|DEF);
4188 				}
4189 			break;
4190 
4191 			case GPS_POS_LLA:
4192 				{
4193 					LLA lla;
4194 					char buffer[256];
4195 
4196 					get_mbg_lla(&bufp, lla);
4197 
4198 					snprintf(buffer, sizeof(buffer), "gps_position(LLA)=\"%s deg, %s deg, %s m\"",
4199 						mfptoa(lla[LAT].l_ui, lla[LAT].l_uf, 4),
4200 						mfptoa(lla[LON].l_ui, lla[LON].l_uf, 4),
4201 						mfptoa(lla[ALT].l_ui, lla[ALT].l_uf, 1));
4202 
4203 					set_var(&parse->kv, buffer, sizeof(buffer), RO|DEF);
4204 				}
4205 			break;
4206 
4207 			case GPS_TZDL:
4208 				break;
4209 
4210 			case GPS_PORT_PARM:
4211 				break;
4212 
4213 			case GPS_SYNTH:
4214 				break;
4215 
4216 			case GPS_ANT_INFO:
4217 				{
4218 					ANT_INFO antinfo;
4219 					char buffer[512];
4220 					char *p;
4221 
4222 					get_mbg_antinfo(&bufp, &antinfo);
4223 					snprintf(buffer, sizeof(buffer), "meinberg_antenna_status=\"");
4224 					p = buffer + strlen(buffer);
4225 
4226 					switch (antinfo.status)
4227 					{
4228 					case ANT_INVALID:
4229 						strncat(p, "<OK>", BUFFER_SIZE(buffer, p));
4230 						p += strlen(p);
4231 						break;
4232 
4233 					case ANT_DISCONN:
4234 						strncat(p, "DISCONNECTED since ", BUFFER_SIZE(buffer, p));
4235 						NLOG(NLOG_CLOCKSTATUS)
4236 							ERR(ERR_BADSTATUS)
4237 							msyslog(LOG_ERR,"PARSE receiver #%d: ANTENNA FAILURE: %s",
4238 								CLK_UNIT(parse->peer), p);
4239 
4240 						p += strlen(p);
4241 						mbg_tm_str(&p, &antinfo.tm_disconn, BUFFER_SIZE(buffer, p));
4242 						*p = '\0';
4243 						break;
4244 
4245 					case ANT_RECONN:
4246 						strncat(p, "RECONNECTED on ", BUFFER_SIZE(buffer, p));
4247 						p += strlen(p);
4248 						mbg_tm_str(&p, &antinfo.tm_reconn, BUFFER_SIZE(buffer, p));
4249 						snprintf(p, BUFFER_SIZE(buffer, p), ", reconnect clockoffset %c%ld.%07ld s, disconnect time ",
4250 							(antinfo.delta_t < 0) ? '-' : '+',
4251 							ABS(antinfo.delta_t) / 10000,
4252 							ABS(antinfo.delta_t) % 10000);
4253 						p += strlen(p);
4254 						mbg_tm_str(&p, &antinfo.tm_disconn, BUFFER_SIZE(buffer, p));
4255 						*p = '\0';
4256 						break;
4257 
4258 					default:
4259 						snprintf(p, BUFFER_SIZE(buffer, p), "bad status 0x%04x", antinfo.status);
4260 						p += strlen(p);
4261 						break;
4262 					}
4263 
4264 					strncat(p, "\"", BUFFER_SIZE(buffer, p));
4265 
4266 					set_var(&parse->kv, buffer, strlen(buffer)+1, RO|DEF);
4267 				}
4268 			break;
4269 
4270 			case GPS_UCAP:
4271 				break;
4272 
4273 			case GPS_CFGH:
4274 				{
4275 					CFGH cfgh;
4276 					char buffer[512];
4277 					char *p;
4278 
4279 					get_mbg_cfgh(&bufp, &cfgh);
4280 					if (cfgh.valid)
4281 					{
4282 						int i;
4283 
4284 						p = buffer;
4285 						strncpy(buffer, "gps_tot_51=\"", BUFFER_SIZE(buffer, p));
4286 						p += strlen(p);
4287 						mbg_tgps_str(&p, &cfgh.tot_51, BUFFER_SIZE(buffer, p));
4288 						strncpy(p, "\"", BUFFER_SIZE(buffer, p));
4289 						set_var(&parse->kv, buffer, strlen(buffer)+1, RO);
4290 
4291 						p = buffer;
4292 						strncpy(buffer, "gps_tot_63=\"", BUFFER_SIZE(buffer, p));
4293 						p += strlen(p);
4294 						mbg_tgps_str(&p, &cfgh.tot_63, BUFFER_SIZE(buffer, p));
4295 						strncpy(p, "\"", BUFFER_SIZE(buffer, p));
4296 						set_var(&parse->kv, buffer, strlen(buffer)+1, RO);
4297 
4298 						p = buffer;
4299 						strncpy(buffer, "gps_t0a=\"", BUFFER_SIZE(buffer, p));
4300 						p += strlen(p);
4301 						mbg_tgps_str(&p, &cfgh.t0a, BUFFER_SIZE(buffer, p));
4302 						strncpy(p, "\"", BUFFER_SIZE(buffer, p));
4303 						set_var(&parse->kv, buffer, strlen(buffer)+1, RO);
4304 
4305 						for (i = MIN_SVNO; i < MAX_SVNO; i++)
4306 						{
4307 							p = buffer;
4308 							snprintf(p, BUFFER_SIZE(buffer, p), "gps_cfg[%d]=\"[0x%x] ", i, cfgh.cfg[i]);
4309 							p += strlen(p);
4310 							switch (cfgh.cfg[i] & 0x7)
4311 							{
4312 							case 0:
4313 								strncpy(p, "BLOCK I", BUFFER_SIZE(buffer, p));
4314 								break;
4315 							case 1:
4316 								strncpy(p, "BLOCK II", BUFFER_SIZE(buffer, p));
4317 								break;
4318 							default:
4319 								strncpy(p, "bad CFG", BUFFER_SIZE(buffer, p));
4320 								break;
4321 							}
4322 							strncat(p, "\"", BUFFER_SIZE(buffer, p));
4323 							set_var(&parse->kv, buffer, strlen(buffer)+1, RO);
4324 
4325 							p = buffer;
4326 							snprintf(p, BUFFER_SIZE(buffer, p), "gps_health[%d]=\"[0x%x] ", i, cfgh.health[i]);
4327 							p += strlen(p);
4328 							switch ((cfgh.health[i] >> 5) & 0x7 )
4329 							{
4330 							case 0:
4331 								strncpy(p, "OK;", BUFFER_SIZE(buffer, p));
4332 								break;
4333 							case 1:
4334 								strncpy(p, "PARITY;", BUFFER_SIZE(buffer, p));
4335 								break;
4336 							case 2:
4337 								strncpy(p, "TLM/HOW;", BUFFER_SIZE(buffer, p));
4338 								break;
4339 							case 3:
4340 								strncpy(p, "Z-COUNT;", BUFFER_SIZE(buffer, p));
4341 								break;
4342 							case 4:
4343 								strncpy(p, "SUBFRAME 1,2,3;", BUFFER_SIZE(buffer, p));
4344 								break;
4345 							case 5:
4346 								strncpy(p, "SUBFRAME 4,5;", BUFFER_SIZE(buffer, p));
4347 								break;
4348 							case 6:
4349 								strncpy(p, "UPLOAD BAD;", BUFFER_SIZE(buffer, p));
4350 								break;
4351 							case 7:
4352 								strncpy(p, "DATA BAD;", BUFFER_SIZE(buffer, p));
4353 								break;
4354 							}
4355 
4356 							p += strlen(p);
4357 
4358 							switch (cfgh.health[i] & 0x1F)
4359 							{
4360 							case 0:
4361 								strncpy(p, "SIGNAL OK", BUFFER_SIZE(buffer, p));
4362 								break;
4363 							case 0x1C:
4364 								strncpy(p, "SV TEMP OUT", BUFFER_SIZE(buffer, p));
4365 								break;
4366 							case 0x1D:
4367 								strncpy(p, "SV WILL BE TEMP OUT", BUFFER_SIZE(buffer, p));
4368 								break;
4369 							case 0x1E:
4370 								break;
4371 							case 0x1F:
4372 								strncpy(p, "MULTIPLE ERRS", BUFFER_SIZE(buffer, p));
4373 								break;
4374 							default:
4375 								strncpy(p, "TRANSMISSION PROBLEMS", BUFFER_SIZE(buffer, p));
4376 								break;
4377 							}
4378 
4379 							strncat(p, "\"", sizeof(buffer));
4380 							set_var(&parse->kv, buffer, strlen(buffer)+1, RO);
4381 						}
4382 					}
4383 				}
4384 			break;
4385 
4386 			case GPS_ALM:
4387 				break;
4388 
4389 			case GPS_EPH:
4390 				break;
4391 
4392 			case GPS_UTC:
4393 				{
4394 					UTC utc;
4395 					char buffer[512];
4396 					char *p;
4397 
4398 					p = buffer;
4399 
4400 					get_mbg_utc(&bufp, &utc);
4401 
4402 					if (utc.valid)
4403 					{
4404 						strncpy(p, "gps_utc_correction=\"", sizeof(buffer));
4405 						p += strlen(p);
4406 						mk_utcinfo(p, utc.t0t.wn, utc.WNlsf, utc.DNt, utc.delta_tls, utc.delta_tlsf, BUFFER_SIZE(buffer, p));
4407 						strncat(p, "\"", BUFFER_SIZE(buffer, p));
4408 					}
4409 					else
4410 					{
4411 						strncpy(p, "gps_utc_correction=\"<NO UTC DATA>\"", BUFFER_SIZE(buffer, p));
4412 					}
4413 					set_var(&parse->kv, buffer, strlen(buffer)+1, RO|DEF);
4414 				}
4415 			break;
4416 
4417 			case GPS_IONO:
4418 				break;
4419 
4420 			case GPS_ASCII_MSG:
4421 				{
4422 					ASCII_MSG gps_ascii_msg;
4423 					char buffer[128];
4424 
4425 					get_mbg_ascii_msg(&bufp, &gps_ascii_msg);
4426 
4427 					if (gps_ascii_msg.valid)
4428 						{
4429 							char buffer1[128];
4430 							mkreadable(buffer1, sizeof(buffer1), gps_ascii_msg.s, strlen(gps_ascii_msg.s), (int)0);
4431 
4432 							snprintf(buffer, sizeof(buffer), "gps_message=\"%s\"", buffer1);
4433 						}
4434 					else
4435 						strncpy(buffer, "gps_message=<NONE>", sizeof(buffer));
4436 
4437 					set_var(&parse->kv, buffer, strlen(buffer)+1, RO|DEF);
4438 				}
4439 
4440 			break;
4441 
4442 			default:
4443 				break;
4444 			}
4445 		}
4446 		else
4447 		{
4448 			msyslog(LOG_DEBUG, "PARSE receiver #%d: gps16x_message: message checksum error: hdr_csum = 0x%x (expected 0x%lx), data_len = %d, data_csum = 0x%x (expected 0x%lx)",
4449 				CLK_UNIT(parse->peer),
4450 				header.gps_hdr_csum, mbg_csum(parsetime->parse_msg + 1, 6),
4451 				header.gps_len,
4452 				header.gps_data_csum, mbg_csum(bufp, (unsigned)((header.gps_len < sizeof(parsetime->parse_msg)) ? header.gps_len : 0)));
4453 		}
4454 	}
4455 
4456 	return;
4457 }
4458 
4459 /*------------------------------------------------------------
4460  * gps16x_poll - query the reciver peridically
4461  */
4462 static void
4463 gps16x_poll(
4464 	    struct peer *peer
4465 	    )
4466 {
4467 	struct parseunit *parse = (struct parseunit *)peer->procptr->unitptr;
4468 
4469 	static GPS_MSG_HDR sequence[] =
4470 	{
4471 		{ GPS_SW_REV,          0, 0, 0 },
4472 		{ GPS_STAT,            0, 0, 0 },
4473 		{ GPS_UTC,             0, 0, 0 },
4474 		{ GPS_ASCII_MSG,       0, 0, 0 },
4475 		{ GPS_ANT_INFO,        0, 0, 0 },
4476 		{ GPS_CFGH,            0, 0, 0 },
4477 		{ GPS_POS_XYZ,         0, 0, 0 },
4478 		{ GPS_POS_LLA,         0, 0, 0 },
4479 		{ (unsigned short)~0,  0, 0, 0 }
4480 	};
4481 
4482 	int rtc;
4483 	unsigned char cmd_buffer[64];
4484 	unsigned char *outp = cmd_buffer;
4485 	GPS_MSG_HDR *header;
4486 
4487 	if (((poll_info_t *)parse->parse_type->cl_data)->rate)
4488 	{
4489 		parse->peer->nextaction = current_time + ((poll_info_t *)parse->parse_type->cl_data)->rate;
4490 	}
4491 
4492 	if (sequence[parse->localstate].gps_cmd == (unsigned short)~0)
4493 		parse->localstate = 0;
4494 
4495 	header = sequence + parse->localstate++;
4496 
4497 	*outp++ = SOH;		/* start command */
4498 
4499 	put_mbg_header(&outp, header);
4500 	outp = cmd_buffer + 1;
4501 
4502 	header->gps_hdr_csum = (short)mbg_csum(outp, 6);
4503 	put_mbg_header(&outp, header);
4504 
4505 #ifdef DEBUG
4506 	if (debug > 2)
4507 	{
4508 		char buffer[128];
4509 
4510 		mkreadable(buffer, sizeof(buffer), (char *)cmd_buffer, (unsigned)(outp - cmd_buffer), 1);
4511 		printf("PARSE receiver #%d: transmitted message #%ld (%d bytes) >%s<\n",
4512 		       CLK_UNIT(parse->peer),
4513 		       parse->localstate - 1,
4514 		       (int)(outp - cmd_buffer),
4515 		       buffer);
4516 	}
4517 #endif
4518 
4519 	rtc = write(parse->generic->io.fd, cmd_buffer, (unsigned long)(outp - cmd_buffer));
4520 
4521 	if (rtc < 0)
4522 	{
4523 		ERR(ERR_BADIO)
4524 			msyslog(LOG_ERR, "PARSE receiver #%d: gps16x_poll: failed to send cmd to clock: %m", CLK_UNIT(parse->peer));
4525 	}
4526 	else
4527 	if (rtc != outp - cmd_buffer)
4528 	{
4529 		ERR(ERR_BADIO)
4530 			msyslog(LOG_ERR, "PARSE receiver #%d: gps16x_poll: failed to send cmd incomplete (%d of %d bytes sent)", CLK_UNIT(parse->peer), rtc, (int)(outp - cmd_buffer));
4531 	}
4532 
4533 	clear_err(parse, ERR_BADIO);
4534 	return;
4535 }
4536 
4537 /*--------------------------------------------------
4538  * init routine - setup timer
4539  */
4540 static int
4541 gps16x_poll_init(
4542 	struct parseunit *parse
4543 	)
4544 {
4545 	if (((poll_info_t *)parse->parse_type->cl_data)->rate)
4546 	{
4547 		parse->peer->action = gps16x_poll;
4548 		gps16x_poll(parse->peer);
4549 	}
4550 
4551 	return 0;
4552 }
4553 
4554 #else
4555 static void
4556 gps16x_message(
4557 	       struct parseunit *parse,
4558 	       parsetime_t      *parsetime
4559 	       )
4560 {}
4561 static int
4562 gps16x_poll_init(
4563 	struct parseunit *parse
4564 	)
4565 {
4566 	return 1;
4567 }
4568 #endif /* CLOCK_MEINBERG */
4569 
4570 /**===========================================================================
4571  ** clock polling support
4572  **/
4573 
4574 /*--------------------------------------------------
4575  * direct poll routine
4576  */
4577 static void
4578 poll_dpoll(
4579 	struct parseunit *parse
4580 	)
4581 {
4582 	int rtc;
4583 	const char *ps = ((poll_info_t *)parse->parse_type->cl_data)->string;
4584 	int   ct = ((poll_info_t *)parse->parse_type->cl_data)->count;
4585 
4586 	rtc = write(parse->generic->io.fd, ps, (unsigned long)ct);
4587 	if (rtc < 0)
4588 	{
4589 		ERR(ERR_BADIO)
4590 			msyslog(LOG_ERR, "PARSE receiver #%d: poll_dpoll: failed to send cmd to clock: %m", CLK_UNIT(parse->peer));
4591 	}
4592 	else
4593 	    if (rtc != ct)
4594 	    {
4595 		    ERR(ERR_BADIO)
4596 			    msyslog(LOG_ERR, "PARSE receiver #%d: poll_dpoll: failed to send cmd incomplete (%d of %d bytes sent)", CLK_UNIT(parse->peer), rtc, ct);
4597 	    }
4598 	clear_err(parse, ERR_BADIO);
4599 }
4600 
4601 /*--------------------------------------------------
4602  * periodic poll routine
4603  */
4604 static void
4605 poll_poll(
4606 	struct peer *peer
4607 	)
4608 {
4609 	struct parseunit *parse = (struct parseunit *)peer->procptr->unitptr;
4610 
4611 	if (parse->parse_type->cl_poll)
4612 		parse->parse_type->cl_poll(parse);
4613 
4614 	if (((poll_info_t *)parse->parse_type->cl_data)->rate)
4615 	{
4616 		parse->peer->nextaction = current_time + ((poll_info_t *)parse->parse_type->cl_data)->rate;
4617 	}
4618 }
4619 
4620 /*--------------------------------------------------
4621  * init routine - setup timer
4622  */
4623 static int
4624 poll_init(
4625 	struct parseunit *parse
4626 	)
4627 {
4628 	if (((poll_info_t *)parse->parse_type->cl_data)->rate)
4629 	{
4630 		parse->peer->action = poll_poll;
4631 		poll_poll(parse->peer);
4632 	}
4633 
4634 	return 0;
4635 }
4636 
4637 /**===========================================================================
4638  ** Trimble support
4639  **/
4640 
4641 /*-------------------------------------------------------------
4642  * trimble TAIP init routine - setup EOL and then do poll_init.
4643  */
4644 static int
4645 trimbletaip_init(
4646 	struct parseunit *parse
4647 	)
4648 {
4649 #ifdef HAVE_TERMIOS
4650 	struct termios tio;
4651 #endif
4652 #ifdef HAVE_SYSV_TTYS
4653 	struct termio tio;
4654 #endif
4655 	/*
4656 	 * configure terminal line for trimble receiver
4657 	 */
4658 	if (TTY_GETATTR(parse->generic->io.fd, &tio) == -1)
4659 	{
4660 		msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_init: tcgetattr(fd, &tio): %m", CLK_UNIT(parse->peer));
4661 		return 0;
4662 	}
4663 	else
4664 	{
4665 		tio.c_cc[VEOL] = TRIMBLETAIP_EOL;
4666 
4667 		if (TTY_SETATTR(parse->generic->io.fd, &tio) == -1)
4668 		{
4669 			msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_init: tcsetattr(fd, &tio): %m", CLK_UNIT(parse->peer));
4670 			return 0;
4671 		}
4672 	}
4673 	return poll_init(parse);
4674 }
4675 
4676 /*--------------------------------------------------
4677  * trimble TAIP event routine - reset receiver upon data format trouble
4678  */
4679 static const char *taipinit[] = {
4680 	">FPV00000000<",
4681 	">SRM;ID_FLAG=F;CS_FLAG=T;EC_FLAG=F;FR_FLAG=T;CR_FLAG=F<",
4682 	">FTM00020001<",
4683 	(char *)0
4684 };
4685 
4686 static void
4687 trimbletaip_event(
4688 	struct parseunit *parse,
4689 	int event
4690 	)
4691 {
4692 	switch (event)
4693 	{
4694 	    case CEVNT_BADREPLY:	/* reset on garbled input */
4695 	    case CEVNT_TIMEOUT:		/* reset on no input */
4696 		    {
4697 			    const char **iv;
4698 
4699 			    iv = taipinit;
4700 			    while (*iv)
4701 			    {
4702 				    int rtc = write(parse->generic->io.fd, *iv, strlen(*iv));
4703 				    if (rtc < 0)
4704 				    {
4705 					    msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_event: failed to send cmd to clock: %m", CLK_UNIT(parse->peer));
4706 					    return;
4707 				    }
4708 				    else
4709 				    {
4710 					    if (rtc != strlen(*iv))
4711 					    {
4712 						    msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_event: failed to send cmd incomplete (%d of %d bytes sent)",
4713 							    CLK_UNIT(parse->peer), rtc, (int)strlen(*iv));
4714 						    return;
4715 					    }
4716 				    }
4717 				    iv++;
4718 			    }
4719 
4720 			    NLOG(NLOG_CLOCKINFO)
4721 				    ERR(ERR_BADIO)
4722 				    msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_event: RECEIVER INITIALIZED",
4723 					    CLK_UNIT(parse->peer));
4724 		    }
4725 		    break;
4726 
4727 	    default:			/* ignore */
4728 		break;
4729 	}
4730 }
4731 
4732 /*
4733  * This driver supports the Trimble SVee Six Plus GPS receiver module.
4734  * It should support other Trimble receivers which use the Trimble Standard
4735  * Interface Protocol (see below).
4736  *
4737  * The module has a serial I/O port for command/data and a 1 pulse-per-second
4738  * output, about 1 microsecond wide. The leading edge of the pulse is
4739  * coincident with the change of the GPS second. This is the same as
4740  * the change of the UTC second +/- ~1 microsecond. Some other clocks
4741  * specifically use a feature in the data message as a timing reference, but
4742  * the SVee Six Plus does not do this. In fact there is considerable jitter
4743  * on the timing of the messages, so this driver only supports the use
4744  * of the PPS pulse for accurate timing. Where it is determined that
4745  * the offset is way off, when first starting up ntpd for example,
4746  * the timing of the data stream is used until the offset becomes low enough
4747  * (|offset| < CLOCK_MAX), at which point the pps offset is used.
4748  *
4749  * It can use either option for receiving PPS information - the 'ppsclock'
4750  * stream pushed onto the serial data interface to timestamp the Carrier
4751  * Detect interrupts, where the 1PPS connects to the CD line. This only
4752  * works on SunOS 4.1.x currently. To select this, define PPSPPS in
4753  * Config.local. The other option is to use a pulse-stretcher/level-converter
4754  * to convert the PPS pulse into a RS232 start pulse & feed this into another
4755  * tty port. To use this option, define PPSCLK in Config.local. The pps input,
4756  * by whichever method, is handled in ntp_loopfilter.c
4757  *
4758  * The receiver uses a serial message protocol called Trimble Standard
4759  * Interface Protocol (it can support others but this driver only supports
4760  * TSIP). Messages in this protocol have the following form:
4761  *
4762  * <DLE><id> ... <data> ... <DLE><ETX>
4763  *
4764  * Any bytes within the <data> portion of value 10 hex (<DLE>) are doubled
4765  * on transmission and compressed back to one on reception. Otherwise
4766  * the values of data bytes can be anything. The serial interface is RS-422
4767  * asynchronous using 9600 baud, 8 data bits with odd party (**note** 9 bits
4768  * in total!), and 1 stop bit. The protocol supports byte, integer, single,
4769  * and double datatypes. Integers are two bytes, sent most significant first.
4770  * Singles are IEEE754 single precision floating point numbers (4 byte) sent
4771  * sign & exponent first. Doubles are IEEE754 double precision floating point
4772  * numbers (8 byte) sent sign & exponent first.
4773  * The receiver supports a large set of messages, only a small subset of
4774  * which are used here. From driver to receiver the following are used:
4775  *
4776  *  ID    Description
4777  *
4778  *  21    Request current time
4779  *  22    Mode Select
4780  *  2C    Set/Request operating parameters
4781  *  2F    Request UTC info
4782  *  35    Set/Request I/O options
4783 
4784  * From receiver to driver the following are recognised:
4785  *
4786  *  ID    Description
4787  *
4788  *  41    GPS Time
4789  *  44    Satellite selection, PDOP, mode
4790  *  46    Receiver health
4791  *  4B    Machine code/status
4792  *  4C    Report operating parameters (debug only)
4793  *  4F    UTC correction data (used to get leap second warnings)
4794  *  55    I/O options (debug only)
4795  *
4796  * All others are accepted but ignored.
4797  *
4798  */
4799 
4800 #define PI		3.1415926535898	/* lots of sig figs */
4801 #define D2R		PI/180.0
4802 
4803 /*-------------------------------------------------------------------
4804  * sendcmd, sendbyte, sendetx, sendflt, sendint implement the command
4805  * interface to the receiver.
4806  *
4807  * CAVEAT: the sendflt, sendint routines are byte order dependend and
4808  * float implementation dependend - these must be converted to portable
4809  * versions !
4810  *
4811  * CURRENT LIMITATION: float implementation. This runs only on systems
4812  * with IEEE754 floats as native floats
4813  */
4814 
4815 typedef struct trimble
4816 {
4817 	u_long last_msg;	/* last message received */
4818 	u_long last_reset;	/* last time a reset was issued */
4819 	u_char qtracking;	/* query tracking status */
4820 	u_long ctrack;		/* current tracking set */
4821 	u_long ltrack;		/* last tracking set */
4822 } trimble_t;
4823 
4824 union uval {
4825 	u_char  bd[8];
4826 	int     iv;
4827 	float   fv;
4828 	double  dv;
4829 };
4830 
4831 struct txbuf
4832 {
4833 	short idx;			/* index to first unused byte */
4834 	u_char *txt;			/* pointer to actual data buffer */
4835 };
4836 
4837 void	sendcmd		P((struct txbuf *buf, int c));
4838 void	sendbyte	P((struct txbuf *buf, int b));
4839 void	sendetx		P((struct txbuf *buf, struct parseunit *parse));
4840 void	sendint		P((struct txbuf *buf, int a));
4841 void	sendflt		P((struct txbuf *buf, double a));
4842 
4843 void
4844 sendcmd(
4845 	struct txbuf *buf,
4846 	int c
4847 	)
4848 {
4849 	buf->txt[0] = DLE;
4850 	buf->txt[1] = (u_char)c;
4851 	buf->idx = 2;
4852 }
4853 
4854 void	sendcmd		P((struct txbuf *buf, int c));
4855 void	sendbyte	P((struct txbuf *buf, int b));
4856 void	sendetx		P((struct txbuf *buf, struct parseunit *parse));
4857 void	sendint		P((struct txbuf *buf, int a));
4858 void	sendflt		P((struct txbuf *buf, double a));
4859 
4860 void
4861 sendbyte(
4862 	struct txbuf *buf,
4863 	int b
4864 	)
4865 {
4866 	if (b == DLE)
4867 	    buf->txt[buf->idx++] = DLE;
4868 	buf->txt[buf->idx++] = (u_char)b;
4869 }
4870 
4871 void
4872 sendetx(
4873 	struct txbuf *buf,
4874 	struct parseunit *parse
4875 	)
4876 {
4877 	buf->txt[buf->idx++] = DLE;
4878 	buf->txt[buf->idx++] = ETX;
4879 
4880 	if (write(parse->generic->io.fd, buf->txt, (unsigned long)buf->idx) != buf->idx)
4881 	{
4882 		ERR(ERR_BADIO)
4883 			msyslog(LOG_ERR, "PARSE receiver #%d: sendetx: failed to send cmd to clock: %m", CLK_UNIT(parse->peer));
4884 	}
4885 	else
4886 	{
4887 #ifdef DEBUG
4888 	  if (debug > 2)
4889 	  {
4890 		  char buffer[256];
4891 
4892 		  mkreadable(buffer, sizeof(buffer), (char *)buf->txt, (unsigned)buf->idx, 1);
4893 		  printf("PARSE receiver #%d: transmitted message (%d bytes) >%s<\n",
4894 			 CLK_UNIT(parse->peer),
4895 			 buf->idx, buffer);
4896 	  }
4897 #endif
4898 		clear_err(parse, ERR_BADIO);
4899 	}
4900 }
4901 
4902 void
4903 sendint(
4904 	struct txbuf *buf,
4905 	int a
4906 	)
4907 {
4908 	/* send 16bit int, msbyte first */
4909 	sendbyte(buf, (u_char)((a>>8) & 0xff));
4910 	sendbyte(buf, (u_char)(a & 0xff));
4911 }
4912 
4913 void
4914 sendflt(
4915 	struct txbuf *buf,
4916 	double a
4917 	)
4918 {
4919 	int i;
4920 	union uval uval;
4921 
4922 	uval.fv = a;
4923 #ifdef WORDS_BIGENDIAN
4924 	for (i=0; i<=3; i++)
4925 #else
4926 	    for (i=3; i>=0; i--)
4927 #endif
4928 		sendbyte(buf, uval.bd[i]);
4929 }
4930 
4931 #define TRIM_POS_OPT	0x13	/* output position with high precision */
4932 #define TRIM_TIME_OPT	0x03	/* use UTC time stamps, on second */
4933 
4934 /*--------------------------------------------------
4935  * trimble TSIP setup routine
4936  */
4937 static int
4938 trimbletsip_setup(
4939 		  struct parseunit *parse,
4940 		  const char *reason
4941 		  )
4942 {
4943 	u_char buffer[256];
4944 	struct txbuf buf;
4945 	trimble_t *t = parse->localdata;
4946 
4947 	if (t && t->last_reset &&
4948 	    ((t->last_reset + TRIMBLE_RESET_HOLDOFF) > current_time)) {
4949 		return 1;	/* not yet */
4950 	}
4951 
4952 	if (t)
4953 		t->last_reset = current_time;
4954 
4955 	buf.txt = buffer;
4956 
4957 	sendcmd(&buf, CMD_CVERSION);	/* request software versions */
4958 	sendetx(&buf, parse);
4959 
4960 	sendcmd(&buf, CMD_COPERPARAM);	/* set operating parameters */
4961 	sendbyte(&buf, 4);	/* static */
4962 	sendflt(&buf, 5.0*D2R);	/* elevation angle mask = 10 deg XXX */
4963 	sendflt(&buf, 4.0);	/* s/n ratio mask = 6 XXX */
4964 	sendflt(&buf, 12.0);	/* PDOP mask = 12 */
4965 	sendflt(&buf, 8.0);	/* PDOP switch level = 8 */
4966 	sendetx(&buf, parse);
4967 
4968 	sendcmd(&buf, CMD_CMODESEL);	/* fix mode select */
4969 	sendbyte(&buf, 1);	/* time transfer mode */
4970 	sendetx(&buf, parse);
4971 
4972 	sendcmd(&buf, CMD_CMESSAGE);	/* request system message */
4973 	sendetx(&buf, parse);
4974 
4975 	sendcmd(&buf, CMD_CSUPER);	/* superpacket fix */
4976 	sendbyte(&buf, 0x2);	/* binary mode */
4977 	sendetx(&buf, parse);
4978 
4979 	sendcmd(&buf, CMD_CIOOPTIONS);	/* set I/O options */
4980 	sendbyte(&buf, TRIM_POS_OPT);	/* position output */
4981 	sendbyte(&buf, 0x00);	/* no velocity output */
4982 	sendbyte(&buf, TRIM_TIME_OPT);	/* UTC, compute on seconds */
4983 	sendbyte(&buf, 0x00);	/* no raw measurements */
4984 	sendetx(&buf, parse);
4985 
4986 	sendcmd(&buf, CMD_CUTCPARAM);	/* request UTC correction data */
4987 	sendetx(&buf, parse);
4988 
4989 	NLOG(NLOG_CLOCKINFO)
4990 		ERR(ERR_BADIO)
4991 		msyslog(LOG_ERR, "PARSE receiver #%d: trimbletsip_setup: RECEIVER RE-INITIALIZED (%s)", CLK_UNIT(parse->peer), reason);
4992 
4993 	return 0;
4994 }
4995 
4996 /*--------------------------------------------------
4997  * TRIMBLE TSIP check routine
4998  */
4999 static void
5000 trimble_check(
5001 	      struct peer *peer
5002 	      )
5003 {
5004 	struct parseunit *parse = (struct parseunit *)peer->procptr->unitptr;
5005 	trimble_t *t = parse->localdata;
5006 	u_char buffer[256];
5007 	struct txbuf buf;
5008 	buf.txt = buffer;
5009 
5010 	if (t)
5011 	{
5012 		if (current_time > t->last_msg + TRIMBLETSIP_IDLE_TIME)
5013 			(void)trimbletsip_setup(parse, "message timeout");
5014 	}
5015 
5016 	poll_poll(parse->peer);	/* emit query string and re-arm timer */
5017 
5018 	if (t && t->qtracking)
5019 	{
5020 		u_long oldsats = t->ltrack & ~t->ctrack;
5021 
5022 		t->qtracking = 0;
5023 		t->ltrack = t->ctrack;
5024 
5025 		if (oldsats)
5026 		{
5027 			int i;
5028 
5029 			for (i = 0; oldsats; i++) {
5030 				if (oldsats & (1 << i))
5031 					{
5032 						sendcmd(&buf, CMD_CSTATTRACK);
5033 						sendbyte(&buf, i+1);	/* old sat */
5034 						sendetx(&buf, parse);
5035 					}
5036 				oldsats &= ~(1 << i);
5037 			}
5038 		}
5039 
5040 		sendcmd(&buf, CMD_CSTATTRACK);
5041 		sendbyte(&buf, 0x00);	/* current tracking set */
5042 		sendetx(&buf, parse);
5043 	}
5044 }
5045 
5046 /*--------------------------------------------------
5047  * TRIMBLE TSIP end routine
5048  */
5049 static void
5050 trimbletsip_end(
5051 	      struct parseunit *parse
5052 	      )
5053 {	trimble_t *t = parse->localdata;
5054 
5055 	if (t)
5056 	{
5057 		free(t);
5058 		parse->localdata = (void *)0;
5059 	}
5060 	parse->peer->nextaction = 0;
5061 	parse->peer->action = (void (*) P((struct peer *)))0;
5062 }
5063 
5064 /*--------------------------------------------------
5065  * TRIMBLE TSIP init routine
5066  */
5067 static int
5068 trimbletsip_init(
5069 	struct parseunit *parse
5070 	)
5071 {
5072 #if defined(VEOL) || defined(VEOL2)
5073 #ifdef HAVE_TERMIOS
5074 	struct termios tio;		/* NEEDED FOR A LONG TIME ! */
5075 #endif
5076 #ifdef HAVE_SYSV_TTYS
5077 	struct termio tio;		/* NEEDED FOR A LONG TIME ! */
5078 #endif
5079 	/*
5080 	 * allocate local data area
5081 	 */
5082 	if (!parse->localdata)
5083 	{
5084 		trimble_t *t;
5085 
5086 		t = (trimble_t *)(parse->localdata = emalloc(sizeof(trimble_t)));
5087 
5088 		if (t)
5089 		{
5090 			memset((char *)t, 0, sizeof(trimble_t));
5091 			t->last_msg = current_time;
5092 		}
5093 	}
5094 
5095 	parse->peer->action     = trimble_check;
5096 	parse->peer->nextaction = current_time;
5097 
5098 	/*
5099 	 * configure terminal line for ICANON mode with VEOL characters
5100 	 */
5101 	if (TTY_GETATTR(parse->generic->io.fd, &tio) == -1)
5102 	{
5103 		msyslog(LOG_ERR, "PARSE receiver #%d: trimbletsip_init: tcgetattr(%d, &tio): %m", CLK_UNIT(parse->peer), parse->generic->io.fd);
5104 		return 0;
5105 	}
5106 	else
5107 	{
5108 		if ((parse_clockinfo[CLK_TYPE(parse->peer)].cl_lflag & ICANON))
5109 		{
5110 #ifdef VEOL
5111 			tio.c_cc[VEOL]  = ETX;
5112 #endif
5113 #ifdef VEOL2
5114 			tio.c_cc[VEOL2]  = DLE;
5115 #endif
5116 		}
5117 
5118 		if (TTY_SETATTR(parse->generic->io.fd, &tio) == -1)
5119 		{
5120 			msyslog(LOG_ERR, "PARSE receiver #%d: trimbletsip_init: tcsetattr(%d, &tio): %m", CLK_UNIT(parse->peer), parse->generic->io.fd);
5121 			return 0;
5122 		}
5123 	}
5124 #endif
5125 	return trimbletsip_setup(parse, "initial startup");
5126 }
5127 
5128 /*------------------------------------------------------------
5129  * trimbletsip_event - handle Trimble events
5130  * simple evente handler - attempt to re-initialize receiver
5131  */
5132 static void
5133 trimbletsip_event(
5134 	struct parseunit *parse,
5135 	int event
5136 	)
5137 {
5138 	switch (event)
5139 	{
5140 	    case CEVNT_BADREPLY:	/* reset on garbled input */
5141 	    case CEVNT_TIMEOUT:		/* reset on no input */
5142 		    (void)trimbletsip_setup(parse, "event BAD_REPLY/TIMEOUT");
5143 		    break;
5144 
5145 	    default:			/* ignore */
5146 		break;
5147 	}
5148 }
5149 
5150 /*
5151  * getflt, getint convert fields in the incoming data into the
5152  * appropriate type of item
5153  *
5154  * CAVEAT: these routines are currently definitely byte order dependent
5155  * and assume Representation(float) == IEEE754
5156  * These functions MUST be converted to portable versions (especially
5157  * converting the float representation into ntp_fp formats in order
5158  * to avoid floating point operations at all!
5159  */
5160 
5161 static float
5162 getflt(
5163 	u_char *bp
5164 	)
5165 {
5166 	union uval uval;
5167 
5168 #ifdef WORDS_BIGENDIAN
5169 	uval.bd[0] = *bp++;
5170 	uval.bd[1] = *bp++;
5171 	uval.bd[2] = *bp++;
5172 	uval.bd[3] = *bp;
5173 #else  /* ! WORDS_BIGENDIAN */
5174 	uval.bd[3] = *bp++;
5175 	uval.bd[2] = *bp++;
5176 	uval.bd[1] = *bp++;
5177 	uval.bd[0] = *bp;
5178 #endif /* ! WORDS_BIGENDIAN */
5179 	return uval.fv;
5180 }
5181 
5182 static double
5183 getdbl(
5184 	u_char *bp
5185 	)
5186 {
5187 	union uval uval;
5188 
5189 #ifdef WORDS_BIGENDIAN
5190 	uval.bd[0] = *bp++;
5191 	uval.bd[1] = *bp++;
5192 	uval.bd[2] = *bp++;
5193 	uval.bd[3] = *bp++;
5194 	uval.bd[4] = *bp++;
5195 	uval.bd[5] = *bp++;
5196 	uval.bd[6] = *bp++;
5197 	uval.bd[7] = *bp;
5198 #else  /* ! WORDS_BIGENDIAN */
5199 	uval.bd[7] = *bp++;
5200 	uval.bd[6] = *bp++;
5201 	uval.bd[5] = *bp++;
5202 	uval.bd[4] = *bp++;
5203 	uval.bd[3] = *bp++;
5204 	uval.bd[2] = *bp++;
5205 	uval.bd[1] = *bp++;
5206 	uval.bd[0] = *bp;
5207 #endif /* ! WORDS_BIGENDIAN */
5208 	return uval.dv;
5209 }
5210 
5211 static int
5212 getshort(
5213 	 unsigned char *p
5214 	 )
5215 {
5216 	return get_msb_short(&p);
5217 }
5218 
5219 /*--------------------------------------------------
5220  * trimbletsip_message - process trimble messages
5221  */
5222 #define RTOD (180.0 / 3.1415926535898)
5223 #define mb(_X_) (buffer[2+(_X_)]) /* shortcut for buffer access */
5224 
5225 static void
5226 trimbletsip_message(
5227 		    struct parseunit *parse,
5228 		    parsetime_t      *parsetime
5229 		    )
5230 {
5231 	unsigned char *buffer = parsetime->parse_msg;
5232 	unsigned int   size   = parsetime->parse_msglen;
5233 
5234 	if ((size < 4) ||
5235 	    (buffer[0]      != DLE) ||
5236 	    (buffer[size-1] != ETX) ||
5237 	    (buffer[size-2] != DLE))
5238 	{
5239 #ifdef DEBUG
5240 		if (debug > 2) {
5241 			int i;
5242 
5243 			printf("TRIMBLE BAD packet, size %d:\n	", size);
5244 			for (i = 0; i < size; i++) {
5245 				printf ("%2.2x, ", buffer[i]&0xff);
5246 				if (i%16 == 15) printf("\n\t");
5247 			}
5248 			printf("\n");
5249 		}
5250 #endif
5251 		return;
5252 	}
5253 	else
5254 	{
5255 		int var_flag;
5256 		trimble_t *tr = parse->localdata;
5257 		unsigned int cmd = buffer[1];
5258 		char pbuffer[200];
5259 		char *t = pbuffer;
5260 		cmd_info_t *s;
5261 
5262 #ifdef DEBUG
5263 		if (debug > 3) {
5264 			int i;
5265 
5266 			printf("TRIMBLE packet 0x%02x, size %d:\n	", cmd, size);
5267 			for (i = 0; i < size; i++) {
5268 				printf ("%2.2x, ", buffer[i]&0xff);
5269 				if (i%16 == 15) printf("\n\t");
5270 			}
5271 			printf("\n");
5272 		}
5273 #endif
5274 
5275 		if (tr)
5276 			tr->last_msg = current_time;
5277 
5278 		s = trimble_convert(cmd, trimble_rcmds);
5279 
5280 		if (s)
5281 		{
5282 			snprintf(t, BUFFER_SIZE(pbuffer, t), "%s=\"", s->varname);
5283 		}
5284 		else
5285 		{
5286 			DPRINTF(1, ("TRIMBLE UNKNOWN COMMAND 0x%02x\n", cmd));
5287 			return;
5288 		}
5289 
5290 		var_flag = s->varmode;
5291 
5292 		t += strlen(t);
5293 
5294 		switch(cmd)
5295 		{
5296 		case CMD_RCURTIME:
5297 			snprintf(t, BUFFER_SIZE(pbuffer, t), "%f, %d, %f",
5298 				 getflt((unsigned char *)&mb(0)), getshort((unsigned char *)&mb(4)),
5299 				 getflt((unsigned char *)&mb(6)));
5300 			break;
5301 
5302 		case CMD_RBEST4:
5303 			strncpy(t, "mode: ", BUFFER_SIZE(pbuffer, t));
5304 			t += strlen(t);
5305 			switch (mb(0) & 0xF)
5306 			{
5307 			default:
5308 				snprintf(t, BUFFER_SIZE(pbuffer, t), "0x%x", mb(0) & 0x7);
5309 				break;
5310 
5311 			case 1:
5312 				strncpy(t, "0D", BUFFER_SIZE(pbuffer, t));
5313 				break;
5314 
5315 			case 3:
5316 				strncpy(t, "2D", BUFFER_SIZE(pbuffer, t));
5317 				break;
5318 
5319 			case 4:
5320 				strncpy(t, "3D", BUFFER_SIZE(pbuffer, t));
5321 				break;
5322 			}
5323 			t += strlen(t);
5324 			if (mb(0) & 0x10)
5325 				strncpy(t, "-MANUAL, ", BUFFER_SIZE(pbuffer, t));
5326 			else
5327 				strncpy(t, "-AUTO, ", BUFFER_SIZE(pbuffer, t));
5328 			t += strlen(t);
5329 
5330 			snprintf(t, BUFFER_SIZE(pbuffer, t), "satellites %02d %02d %02d %02d, PDOP %.2f, HDOP %.2f, VDOP %.2f, TDOP %.2f",
5331 				mb(1), mb(2), mb(3), mb(4),
5332 				getflt((unsigned char *)&mb(5)),
5333 				getflt((unsigned char *)&mb(9)),
5334 				getflt((unsigned char *)&mb(13)),
5335 				getflt((unsigned char *)&mb(17)));
5336 
5337 			break;
5338 
5339 		case CMD_RVERSION:
5340 			snprintf(t, BUFFER_SIZE(pbuffer, t), "%d.%d (%d/%d/%d)",
5341 				mb(0)&0xff, mb(1)&0xff, 1900+(mb(4)&0xff), mb(2)&0xff, mb(3)&0xff);
5342 			break;
5343 
5344 		case CMD_RRECVHEALTH:
5345 		{
5346 			static const char *msgs[] =
5347 			{
5348 				"Battery backup failed",
5349 				"Signal processor error",
5350 				"Alignment error, channel or chip 1",
5351 				"Alignment error, channel or chip 2",
5352 				"Antenna feed line fault",
5353 				"Excessive ref freq. error",
5354 				"<BIT 6>",
5355 				"<BIT 7>"
5356 			};
5357 
5358 			int i, bits;
5359 
5360 			switch (mb(0) & 0xFF)
5361 			{
5362 			default:
5363 				snprintf(t, BUFFER_SIZE(pbuffer, t), "illegal value 0x%02x", mb(0) & 0xFF);
5364 				break;
5365 			case 0x00:
5366 				strncpy(t, "doing position fixes", BUFFER_SIZE(pbuffer, t));
5367 				break;
5368 			case 0x01:
5369 				strncpy(t, "no GPS time yet", BUFFER_SIZE(pbuffer, t));
5370 				break;
5371 			case 0x03:
5372 				strncpy(t, "PDOP too high", BUFFER_SIZE(pbuffer, t));
5373 				break;
5374 			case 0x08:
5375 				strncpy(t, "no usable satellites", BUFFER_SIZE(pbuffer, t));
5376 				break;
5377 			case 0x09:
5378 				strncpy(t, "only ONE usable satellite", BUFFER_SIZE(pbuffer, t));
5379 				break;
5380 			case 0x0A:
5381 				strncpy(t, "only TWO usable satellites", BUFFER_SIZE(pbuffer, t));
5382 				break;
5383 			case 0x0B:
5384 				strncpy(t, "only THREE usable satellites", BUFFER_SIZE(pbuffer, t));
5385 				break;
5386 			case 0x0C:
5387 				strncpy(t, "the chosen satellite is unusable", BUFFER_SIZE(pbuffer, t));
5388 				break;
5389 			}
5390 
5391 			t += strlen(t);
5392 
5393 			bits = mb(1) & 0xFF;
5394 
5395 			for (i = 0; i < 8; i++)
5396 				if (bits & (0x1<<i))
5397 				{
5398 					snprintf(t, BUFFER_SIZE(pbuffer, t), ", %s", msgs[i]);
5399 					t += strlen(t);
5400 				}
5401 		}
5402 		break;
5403 
5404 		case CMD_RMESSAGE:
5405 			mkreadable(t, (int)BUFFER_SIZE(pbuffer, t), (char *)&mb(0), (unsigned)(size - 2 - (&mb(0) - buffer)), 0);
5406 			break;
5407 
5408 		case CMD_RMACHSTAT:
5409 		{
5410 			static const char *msgs[] =
5411 			{
5412 				"Synthesizer Fault",
5413 				"Battery Powered Time Clock Fault",
5414 				"A-to-D Converter Fault",
5415 				"The almanac stored in the receiver is not complete and current",
5416 				"<BIT 4>",
5417 				"<BIT 5",
5418 				"<BIT 6>",
5419 				"<BIT 7>"
5420 			};
5421 
5422 			int i, bits;
5423 
5424 			snprintf(t, BUFFER_SIZE(pbuffer, t), "machine id 0x%02x", mb(0) & 0xFF);
5425 			t += strlen(t);
5426 
5427 			bits = mb(1) & 0xFF;
5428 
5429 			for (i = 0; i < 8; i++)
5430 				if (bits & (0x1<<i))
5431 				{
5432 					snprintf(t, BUFFER_SIZE(pbuffer, t), ", %s", msgs[i]);
5433 					t += strlen(t);
5434 				}
5435 
5436 			snprintf(t, BUFFER_SIZE(pbuffer, t), ", Superpackets %ssupported", (mb(2) & 0xFF) ? "" :"un" );
5437 		}
5438 		break;
5439 
5440 		case CMD_ROPERPARAM:
5441 			snprintf(t, BUFFER_SIZE(pbuffer, t), "%2x %.1f %.1f %.1f %.1f",
5442 				mb(0), getflt((unsigned char *)&mb(1)), getflt((unsigned char *)&mb(5)),
5443 				getflt((unsigned char *)&mb(9)), getflt((unsigned char *)&mb(13)));
5444 			break;
5445 
5446 		case CMD_RUTCPARAM:
5447 		{
5448 			float t0t = getflt((unsigned char *)&mb(14));
5449 			short wnt = getshort((unsigned char *)&mb(18));
5450 			short dtls = getshort((unsigned char *)&mb(12));
5451 			short wnlsf = getshort((unsigned char *)&mb(20));
5452 			short dn = getshort((unsigned char *)&mb(22));
5453 			short dtlsf = getshort((unsigned char *)&mb(24));
5454 
5455 			if ((int)t0t != 0)
5456 			  {
5457 				  mk_utcinfo(t, wnt, wnlsf, dn, dtls, dtlsf, BUFFER_SIZE(pbuffer, t));
5458 			  }
5459 			else
5460 			  {
5461 			    strncpy(t, "<NO UTC DATA>", BUFFER_SIZE(pbuffer, t));
5462 			  }
5463 		}
5464 		break;
5465 
5466 		case CMD_RSAT1BIAS:
5467 			snprintf(t, BUFFER_SIZE(pbuffer, t), "%.1fm %.2fm/s at %.1fs",
5468 				getflt(&mb(0)), getflt(&mb(4)), getflt(&mb(8)));
5469 			break;
5470 
5471 		case CMD_RIOOPTIONS:
5472 		{
5473 			snprintf(t, BUFFER_SIZE(pbuffer, t), "%02x %02x %02x %02x",
5474 				mb(0), mb(1), mb(2), mb(3));
5475 			if (mb(0) != TRIM_POS_OPT ||
5476 			    mb(2) != TRIM_TIME_OPT)
5477 			{
5478 				(void)trimbletsip_setup(parse, "bad io options");
5479 			}
5480 		}
5481 		break;
5482 
5483 		case CMD_RSPOSXYZ:
5484 		{
5485 			double x = getflt((unsigned char *)&mb(0));
5486 			double y = getflt((unsigned char *)&mb(4));
5487 			double z = getflt((unsigned char *)&mb(8));
5488 			double f = getflt((unsigned char *)&mb(12));
5489 
5490 			if (f > 0.0)
5491 			  snprintf(t, BUFFER_SIZE(pbuffer, t), "x= %.1fm, y= %.1fm, z= %.1fm, time_of_fix= %f sec",
5492 				  x, y, z,
5493 				  f);
5494 			else
5495 			  return;
5496 		}
5497 		break;
5498 
5499 		case CMD_RSLLAPOS:
5500 		{
5501 			double lat = getflt((unsigned char *)&mb(0));
5502 			double lng = getflt((unsigned char *)&mb(4));
5503 			double f   = getflt((unsigned char *)&mb(12));
5504 
5505 			if (f > 0.0)
5506 			  snprintf(t, BUFFER_SIZE(pbuffer, t), "lat %f %c, long %f %c, alt %.2fm",
5507 				  ((lat < 0.0) ? (-lat) : (lat))*RTOD, (lat < 0.0 ? 'S' : 'N'),
5508 				  ((lng < 0.0) ? (-lng) : (lng))*RTOD, (lng < 0.0 ? 'W' : 'E'),
5509 				  getflt((unsigned char *)&mb(8)));
5510 			else
5511 			  return;
5512 		}
5513 		break;
5514 
5515 		case CMD_RDOUBLEXYZ:
5516 		{
5517 			double x = getdbl((unsigned char *)&mb(0));
5518 			double y = getdbl((unsigned char *)&mb(8));
5519 			double z = getdbl((unsigned char *)&mb(16));
5520 			snprintf(t, BUFFER_SIZE(pbuffer, t), "x= %.1fm, y= %.1fm, z= %.1fm",
5521 				x, y, z);
5522 		}
5523 		break;
5524 
5525 		case CMD_RDOUBLELLA:
5526 		{
5527 			double lat = getdbl((unsigned char *)&mb(0));
5528 			double lng = getdbl((unsigned char *)&mb(8));
5529 			snprintf(t, BUFFER_SIZE(pbuffer, t), "lat %f %c, lon %f %c, alt %.2fm",
5530 				((lat < 0.0) ? (-lat) : (lat))*RTOD, (lat < 0.0 ? 'S' : 'N'),
5531 				((lng < 0.0) ? (-lng) : (lng))*RTOD, (lng < 0.0 ? 'W' : 'E'),
5532 				getdbl((unsigned char *)&mb(16)));
5533 		}
5534 		break;
5535 
5536 		case CMD_RALLINVIEW:
5537 		{
5538 			int i, sats;
5539 
5540 			strncpy(t, "mode: ", BUFFER_SIZE(pbuffer, t));
5541 			t += strlen(t);
5542 			switch (mb(0) & 0x7)
5543 			{
5544 			default:
5545 				snprintf(t, BUFFER_SIZE(pbuffer, t), "0x%x", mb(0) & 0x7);
5546 				break;
5547 
5548 			case 3:
5549 				strncpy(t, "2D", BUFFER_SIZE(pbuffer, t));
5550 				break;
5551 
5552 			case 4:
5553 				strncpy(t, "3D", BUFFER_SIZE(pbuffer, t));
5554 				break;
5555 			}
5556 			t += strlen(t);
5557 			if (mb(0) & 0x8)
5558 				strncpy(t, "-MANUAL, ", BUFFER_SIZE(pbuffer, t));
5559 			else
5560 				strncpy(t, "-AUTO, ", BUFFER_SIZE(pbuffer, t));
5561 			t += strlen(t);
5562 
5563 			sats = (mb(0)>>4) & 0xF;
5564 
5565 			snprintf(t, BUFFER_SIZE(pbuffer, t), "PDOP %.2f, HDOP %.2f, VDOP %.2f, TDOP %.2f, %d satellite%s in view: ",
5566 				getflt((unsigned char *)&mb(1)),
5567 				getflt((unsigned char *)&mb(5)),
5568 				getflt((unsigned char *)&mb(9)),
5569 				getflt((unsigned char *)&mb(13)),
5570 				sats, (sats == 1) ? "" : "s");
5571 			t += strlen(t);
5572 
5573 			for (i=0; i < sats; i++)
5574 			{
5575 				snprintf(t, BUFFER_SIZE(pbuffer, t), "%s%02d", i ? ", " : "", mb(17+i));
5576 				t += strlen(t);
5577 				if (tr)
5578 					tr->ctrack |= (1 << (mb(17+i)-1));
5579 			}
5580 
5581 			if (tr)
5582                         { /* mark for tracking status query */
5583 				tr->qtracking = 1;
5584 			}
5585 		}
5586 		break;
5587 
5588 		case CMD_RSTATTRACK:
5589 		{
5590 			snprintf(t-2, BUFFER_SIZE(pbuffer, t-2), "[%02d]=\"", mb(0)); /* add index to var name */
5591 			t += strlen(t);
5592 
5593 			if (getflt((unsigned char *)&mb(4)) < 0.0)
5594 			{
5595 				strncpy(t, "<NO MEASUREMENTS>", BUFFER_SIZE(pbuffer, t));
5596 				var_flag &= ~DEF;
5597 			}
5598 			else
5599 			{
5600 				snprintf(t, BUFFER_SIZE(pbuffer, t), "ch=%d, acq=%s, eph=%d, signal_level= %5.2f, elevation= %5.2f, azimuth= %6.2f",
5601 					(mb(1) & 0xFF)>>3,
5602 					mb(2) ? ((mb(2) == 1) ? "ACQ" : "SRCH") : "NEVER",
5603 					mb(3),
5604 					getflt((unsigned char *)&mb(4)),
5605 					getflt((unsigned char *)&mb(12)) * RTOD,
5606 					getflt((unsigned char *)&mb(16)) * RTOD);
5607 				t += strlen(t);
5608 				if (mb(20))
5609 				{
5610 					var_flag &= ~DEF;
5611 					strncpy(t, ", OLD", BUFFER_SIZE(pbuffer, t));
5612 				}
5613 				t += strlen(t);
5614 				if (mb(22))
5615 				{
5616 					if (mb(22) == 1)
5617 						strncpy(t, ", BAD PARITY", BUFFER_SIZE(pbuffer, t));
5618 					else
5619 						if (mb(22) == 2)
5620 							strncpy(t, ", BAD EPH HEALTH", BUFFER_SIZE(pbuffer, t));
5621 				}
5622 				t += strlen(t);
5623 				if (mb(23))
5624 					strncpy(t, ", collecting data", BUFFER_SIZE(pbuffer, t));
5625 			}
5626 		}
5627 		break;
5628 
5629 		default:
5630 			strncpy(t, "<UNDECODED>", BUFFER_SIZE(pbuffer, t));
5631 			break;
5632 		}
5633 		t += strlen(t);
5634 
5635 		strncpy(t,"\"", BUFFER_SIZE(pbuffer, t));
5636 		set_var(&parse->kv, pbuffer, sizeof(pbuffer), var_flag);
5637 	}
5638 }
5639 
5640 
5641 /**============================================================
5642  ** RAWDCF support
5643  **/
5644 
5645 /*--------------------------------------------------
5646  * rawdcf_init_1 - set up modem lines for RAWDCF receivers
5647  * SET DTR line
5648  */
5649 #if defined(TIOCMSET) && (defined(TIOCM_DTR) || defined(CIOCM_DTR))
5650 static int
5651 rawdcf_init_1(
5652 	struct parseunit *parse
5653 	)
5654 {
5655 	/* fixed 2000 for using with Linux by Wolfram Pienkoss <wp@bszh.de> */
5656 	/*
5657 	 * You can use the RS232 to supply the power for a DCF77 receiver.
5658 	 * Here a voltage between the DTR and the RTS line is used. Unfortunately
5659 	 * the name has changed from CIOCM_DTR to TIOCM_DTR recently.
5660 	 */
5661 	int sl232;
5662 
5663 	if (ioctl(parse->generic->io.fd, TIOCMGET, (caddr_t)&sl232) == -1)
5664 	{
5665 		msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_1: WARNING: ioctl(fd, TIOCMGET, [C|T]IOCM_DTR): %m", CLK_UNIT(parse->peer));
5666 		return 0;
5667 	}
5668 
5669 #ifdef TIOCM_DTR
5670 	sl232 = (sl232 & ~TIOCM_RTS) | TIOCM_DTR;	/* turn on DTR, clear RTS for power supply */
5671 #else
5672 	sl232 = (sl232 & ~CIOCM_RTS) | CIOCM_DTR;	/* turn on DTR, clear RTS for power supply */
5673 #endif
5674 
5675 	if (ioctl(parse->generic->io.fd, TIOCMSET, (caddr_t)&sl232) == -1)
5676 	{
5677 		msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_1: WARNING: ioctl(fd, TIOCMSET, [C|T]IOCM_DTR): %m", CLK_UNIT(parse->peer));
5678 	}
5679 	return 0;
5680 }
5681 #else
5682 static int
5683 rawdcfdtr_init_1(
5684 	struct parseunit *parse
5685 	)
5686 {
5687 	msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_1: WARNING: OS interface incapable of setting DTR to power DCF modules", CLK_UNIT(parse->peer));
5688 	return 0;
5689 }
5690 #endif  /* DTR initialisation type */
5691 
5692 /*--------------------------------------------------
5693  * rawdcf_init_2 - set up modem lines for RAWDCF receivers
5694  * CLR DTR line, SET RTS line
5695  */
5696 #if defined(TIOCMSET) &&  (defined(TIOCM_RTS) || defined(CIOCM_RTS))
5697 static int
5698 rawdcf_init_2(
5699 	struct parseunit *parse
5700 	)
5701 {
5702 	/* fixed 2000 for using with Linux by Wolfram Pienkoss <wp@bszh.de> */
5703 	/*
5704 	 * You can use the RS232 to supply the power for a DCF77 receiver.
5705 	 * Here a voltage between the DTR and the RTS line is used. Unfortunately
5706 	 * the name has changed from CIOCM_DTR to TIOCM_DTR recently.
5707 	 */
5708 	int sl232;
5709 
5710 	if (ioctl(parse->generic->io.fd, TIOCMGET, (caddr_t)&sl232) == -1)
5711 	{
5712 		msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_2: WARNING: ioctl(fd, TIOCMGET, [C|T]IOCM_RTS): %m", CLK_UNIT(parse->peer));
5713 		return 0;
5714 	}
5715 
5716 #ifdef TIOCM_RTS
5717 	sl232 = (sl232 & ~TIOCM_DTR) | TIOCM_RTS;	/* turn on RTS, clear DTR for power supply */
5718 #else
5719 	sl232 = (sl232 & ~CIOCM_DTR) | CIOCM_RTS;	/* turn on RTS, clear DTR for power supply */
5720 #endif
5721 
5722 	if (ioctl(parse->generic->io.fd, TIOCMSET, (caddr_t)&sl232) == -1)
5723 	{
5724 		msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_2: WARNING: ioctl(fd, TIOCMSET, [C|T]IOCM_RTS): %m", CLK_UNIT(parse->peer));
5725 	}
5726 	return 0;
5727 }
5728 #else
5729 static int
5730 rawdcf_init_2(
5731 	struct parseunit *parse
5732 	)
5733 {
5734 	msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_2: WARNING: OS interface incapable of setting RTS to power DCF modules", CLK_UNIT(parse->peer));
5735 	return 0;
5736 }
5737 #endif  /* DTR initialisation type */
5738 
5739 #else	/* defined(REFCLOCK) && defined(PARSE) */
5740 int refclock_parse_bs;
5741 #endif	/* defined(REFCLOCK) && defined(PARSE) */
5742 
5743 /*
5744  * History:
5745  *
5746  * refclock_parse.c,v
5747  * Revision 4.80  2007/08/11 12:06:29  kardel
5748  * update comments wrt/ to PPS
5749  *
5750  * Revision 4.79  2007/08/11 11:52:23  kardel
5751  * - terminate io bindings before io_closeclock() will close our file descriptor
5752  *
5753  * Revision 4.78  2006/12/22 20:08:27  kardel
5754  * Bug 746 (RFE): add configuration for Expert mouseCLOCK USB v2.0 as mode 19
5755  *
5756  * Revision 4.77  2006/08/05 07:44:49  kardel
5757  * support optionally separate PPS devices via /dev/refclockpps-{0..3}
5758  *
5759  * Revision 4.76  2006/06/22 18:40:47  kardel
5760  * clean up signedness (gcc 4)
5761  *
5762  * Revision 4.75  2006/06/22 16:58:10  kardel
5763  * Bug #632: call parse_ppsapi() in parse_ctl() when updating
5764  * the PPS offset. Fix sign of offset passed to kernel.
5765  *
5766  * Revision 4.74  2006/06/18 21:18:37  kardel
5767  * NetBSD Coverity CID 3796: possible NULL deref
5768  *
5769  * Revision 4.73  2006/05/26 14:23:46  kardel
5770  * cleanup of copyright info
5771  *
5772  * Revision 4.72  2006/05/26 14:19:43  kardel
5773  * cleanup of ioctl cruft
5774  *
5775  * Revision 4.71  2006/05/26 14:15:57  kardel
5776  * delay adding refclock to async refclock io after all initializations
5777  *
5778  * Revision 4.70  2006/05/25 18:20:50  kardel
5779  * bug #619
5780  * terminate parse io engine after de-registering
5781  * from refclock io engine
5782  *
5783  * Revision 4.69  2006/05/25 17:28:02  kardel
5784  * complete refclock io structure initialization *before* inserting it into the
5785  * refclock input machine (avoids null pointer deref) (bug #619)
5786  *
5787  * Revision 4.68  2006/05/01 17:02:51  kardel
5788  * copy receiver method also for newlwy created receive buffers
5789  *
5790  * Revision 4.67  2006/05/01 14:37:29  kardel
5791  * If an input buffer parses into more than one message do insert the
5792  * parsed message in a new input buffer instead of processing it
5793  * directly. This avoids deed complicated processing in signal
5794  * handling.
5795  *
5796  * Revision 4.66  2006/03/18 00:45:30  kardel
5797  * coverity fixes found in NetBSD coverity scan
5798  *
5799  * Revision 4.65  2006/01/26 06:08:33  kardel
5800  * output errno on PPS setup failure
5801  *
5802  * Revision 4.64  2005/11/09 20:44:47  kardel
5803  * utilize full PPS timestamp resolution from PPS API
5804  *
5805  * Revision 4.63  2005/10/07 22:10:25  kardel
5806  * bounded buffer implementation
5807  *
5808  * Revision 4.62.2.2  2005/09/25 10:20:16  kardel
5809  * avoid unexpected buffer overflows due to sprintf("%f") on strange floats:
5810  * replace almost all str* and *printf functions be their buffer bounded
5811  * counterparts
5812  *
5813  * Revision 4.62.2.1  2005/08/27 16:19:27  kardel
5814  * limit re-set rate of trimble clocks
5815  *
5816  * Revision 4.62  2005/08/06 17:40:00  kardel
5817  * cleanup size handling wrt/ to buffer boundaries
5818  *
5819  * Revision 4.61  2005/07/27 21:16:19  kardel
5820  * fix a long (> 11 years) misconfiguration wrt/ Meinberg cflag factory
5821  * default setup. CSTOPB was missing for the 7E2 default data format of
5822  * the DCF77 clocks.
5823  *
5824  * Revision 4.60  2005/07/17 21:14:44  kardel
5825  * change contents of version string to include the RCS/CVS Id
5826  *
5827  * Revision 4.59  2005/07/06 06:56:38  kardel
5828  * syntax error
5829  *
5830  * Revision 4.58  2005/07/04 13:10:40  kardel
5831  * fix bug 455: tripping over NULL pointer on cleanup
5832  * fix shadow storage logic for ppsphaseadjust and trustime wrt/ time2
5833  * fix compiler warnings for some platforms wrt/ printf formatstrings and
5834  *     varying structure element sizes
5835  * reorder assignment in binding to avoid tripping over NULL pointers
5836  *
5837  * Revision 4.57  2005/06/25 09:25:19  kardel
5838  * sort out log output sequence
5839  *
5840  * Revision 4.56  2005/06/14 21:47:27  kardel
5841  * collect samples only if samples are ok (sync or trusted flywheel)
5842  * propagate pps phase adjustment value to kernel via PPSAPI to help HARDPPS
5843  * en- and dis-able HARDPPS in correlation to receiver sync state
5844  *
5845  * Revision 4.55  2005/06/02 21:28:31  kardel
5846  * clarify trust logic
5847  *
5848  * Revision 4.54  2005/06/02 17:06:49  kardel
5849  * change status reporting to use fixed refclock_report()
5850  *
5851  * Revision 4.53  2005/06/02 16:33:31  kardel
5852  * fix acceptance of clocks unsync clocks right at start
5853  *
5854  * Revision 4.52  2005/05/26 21:55:06  kardel
5855  * cleanup status reporting
5856  *
5857  * Revision 4.51  2005/05/26 19:19:14  kardel
5858  * implement fast refclock startup
5859  *
5860  * Revision 4.50  2005/04/16 20:51:35  kardel
5861  * set pps_enable = 1 when binding a kernel PPS source
5862  *
5863  * Revision 4.49  2005/04/16 17:29:26  kardel
5864  * add non polling clock type 18 for just listenning to Meinberg clocks
5865  *
5866  * Revision 4.48  2005/04/16 16:22:27  kardel
5867  * bk sync 20050415 ntp-dev
5868  *
5869  * Revision 4.47  2004/11/29 10:42:48  kardel
5870  * bk sync ntp-dev 20041129
5871  *
5872  * Revision 4.46  2004/11/29 10:26:29  kardel
5873  * keep fudgetime2 in sync with trusttime/ppsphaseadjust depending in flag1
5874  *
5875  * Revision 4.45  2004/11/14 20:53:20  kardel
5876  * clear PPS flags after using them
5877  *
5878  * Revision 4.44  2004/11/14 15:29:41  kardel
5879  * support PPSAPI, upgrade Copyright to Berkeley style
5880  *
5881  * Revision 4.43  2001/05/26 22:53:16  kardel
5882  * 20010526 reconcilation
5883  *
5884  * Revision 4.42  2000/05/14 15:31:51  kardel
5885  * PPSAPI && RAWDCF modemline support
5886  *
5887  * Revision 4.41  2000/04/09 19:50:45  kardel
5888  * fixed rawdcfdtr_init() -> rawdcf_init_1
5889  *
5890  * Revision 4.40  2000/04/09 15:27:55  kardel
5891  * modem line fiddle in rawdcf_init_2
5892  *
5893  * Revision 4.39  2000/03/18 09:16:55  kardel
5894  * PPSAPI integration
5895  *
5896  * Revision 4.38  2000/03/05 20:25:06  kardel
5897  * support PPSAPI
5898  *
5899  * Revision 4.37  2000/03/05 20:11:14  kardel
5900  * 4.0.99g reconcilation
5901  *
5902  * Revision 4.36  1999/11/28 17:18:20  kardel
5903  * disabled burst mode
5904  *
5905  * Revision 4.35  1999/11/28 09:14:14  kardel
5906  * RECON_4_0_98F
5907  *
5908  * Revision 4.34  1999/05/14 06:08:05  kardel
5909  * store current_time in a suitable container (u_long)
5910  *
5911  * Revision 4.33  1999/05/13 21:48:38  kardel
5912  * double the no response timeout interval
5913  *
5914  * Revision 4.32  1999/05/13 20:09:13  kardel
5915  * complain only about missing polls after a full poll interval
5916  *
5917  * Revision 4.31  1999/05/13 19:59:32  kardel
5918  * add clock type 16 for RTS set DTR clr in RAWDCF
5919  *
5920  * Revision 4.30  1999/02/28 20:36:43  kardel
5921  * fixed printf fmt
5922  *
5923  * Revision 4.29  1999/02/28 19:58:23  kardel
5924  * updated copyright information
5925  *
5926  * Revision 4.28  1999/02/28 19:01:50  kardel
5927  * improved debug out on sent Meinberg messages
5928  *
5929  * Revision 4.27  1999/02/28 18:05:55  kardel
5930  * no linux/ppsclock.h stuff
5931  *
5932  * Revision 4.26  1999/02/28 15:27:27  kardel
5933  * wharton clock integration
5934  *
5935  * Revision 4.25  1999/02/28 14:04:46  kardel
5936  * added missing double quotes to UTC information string
5937  *
5938  * Revision 4.24  1999/02/28 12:06:50  kardel
5939  * (parse_control): using gmprettydate instead of prettydate()
5940  * (mk_utcinfo): new function for formatting GPS derived UTC information
5941  * (gps16x_message): changed to use mk_utcinfo()
5942  * (trimbletsip_message): changed to use mk_utcinfo()
5943  * ignoring position information in unsynchronized mode
5944  * (parse_start): augument linux support for optional ASYNC_LOW_LATENCY
5945  *
5946  * Revision 4.23  1999/02/23 19:47:53  kardel
5947  * fixed #endifs
5948  * (stream_receive): fixed formats
5949  *
5950  * Revision 4.22  1999/02/22 06:21:02  kardel
5951  * use new autoconfig symbols
5952  *
5953  * Revision 4.21  1999/02/21 12:18:13  kardel
5954  * 4.91f reconcilation
5955  *
5956  * Revision 4.20  1999/02/21 10:53:36  kardel
5957  * initial Linux PPSkit version
5958  *
5959  * Revision 4.19  1999/02/07 09:10:45  kardel
5960  * clarify STREAMS mitigation rules in comment
5961  *
5962  * Revision 4.18  1998/12/20 23:45:34  kardel
5963  * fix types and warnings
5964  *
5965  * Revision 4.17  1998/11/15 21:24:51  kardel
5966  * cannot access mbg_ routines when CLOCK_MEINBERG
5967  * is not defined
5968  *
5969  * Revision 4.16  1998/11/15 20:28:17  kardel
5970  * Release 4.0.73e13 reconcilation
5971  *
5972  * Revision 4.15  1998/08/22 21:56:08  kardel
5973  * fixed IO handling for non-STREAM IO
5974  *
5975  * Revision 4.14  1998/08/16 19:00:48  kardel
5976  * (gps16x_message): reduced UTC parameter information (dropped A0,A1)
5977  * made uval a local variable (killed one of the last globals)
5978  * (sendetx): added logging of messages when in debug mode
5979  * (trimble_check): added periodic checks to facilitate re-initialization
5980  * (trimbletsip_init): made use of EOL character if in non-kernel operation
5981  * (trimbletsip_message): extended message interpretation
5982  * (getdbl): fixed data conversion
5983  *
5984  * Revision 4.13  1998/08/09 22:29:13  kardel
5985  * Trimble TSIP support
5986  *
5987  * Revision 4.12  1998/07/11 10:05:34  kardel
5988  * Release 4.0.73d reconcilation
5989  *
5990  * Revision 4.11  1998/06/14 21:09:42  kardel
5991  * Sun acc cleanup
5992  *
5993  * Revision 4.10  1998/06/13 12:36:45  kardel
5994  * signed/unsigned, name clashes
5995  *
5996  * Revision 4.9  1998/06/12 15:30:00  kardel
5997  * prototype fixes
5998  *
5999  * Revision 4.8  1998/06/12 11:19:42  kardel
6000  * added direct input processing routine for refclocks in
6001  * order to avaiod that single character io gobbles up all
6002  * receive buffers and drops input data. (Problem started
6003  * with fast machines so a character a buffer was possible
6004  * one of the few cases where faster machines break existing
6005  * allocation algorithms)
6006  *
6007  * Revision 4.7  1998/06/06 18:35:20  kardel
6008  * (parse_start): added BURST mode initialisation
6009  *
6010  * Revision 4.6  1998/05/27 06:12:46  kardel
6011  * RAWDCF_BASEDELAY default added
6012  * old comment removed
6013  * casts for ioctl()
6014  *
6015  * Revision 4.5  1998/05/25 22:05:09  kardel
6016  * RAWDCF_SETDTR option removed
6017  * clock type 14 attempts to set DTR for
6018  * power supply of RAWDCF receivers
6019  *
6020  * Revision 4.4  1998/05/24 16:20:47  kardel
6021  * updated comments referencing Meinberg clocks
6022  * added RAWDCF clock with DTR set option as type 14
6023  *
6024  * Revision 4.3  1998/05/24 10:48:33  kardel
6025  * calibrated CONRAD RAWDCF default fudge factor
6026  *
6027  * Revision 4.2  1998/05/24 09:59:35  kardel
6028  * corrected version information (ntpq support)
6029  *
6030  * Revision 4.1  1998/05/24 09:52:31  kardel
6031  * use fixed format only (new IO model)
6032  * output debug to stdout instead of msyslog()
6033  * don't include >"< in ASCII output in order not to confuse
6034  * ntpq parsing
6035  *
6036  * Revision 4.0  1998/04/10 19:52:11  kardel
6037  * Start 4.0 release version numbering
6038  *
6039  * Revision 1.2  1998/04/10 19:28:04  kardel
6040  * initial NTP VERSION 4 integration of PARSE with GPS166 binary support
6041  * derived from 3.105.1.2 from V3 tree
6042  *
6043  * Revision information 3.1 - 3.105 from log deleted 1998/04/10 kardel
6044  *
6045  */
6046