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