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