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