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