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