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