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