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