Home | History | Annotate | Line # | Download | only in ntpd
refclock_parse.c revision 1.1.1.2
      1 /*	$NetBSD: refclock_parse.c,v 1.1.1.2 2012/01/31 21:25:18 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 		int 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((int)*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 	}
   1721 };
   1722 
   1723 #ifdef STREAM
   1724 
   1725 #define fix_ts(_X_) \
   1726                         if ((&(_X_))->tv.tv_usec >= 1000000)                \
   1727                           {                                                 \
   1728 			    (&(_X_))->tv.tv_usec -= 1000000;                \
   1729 			    (&(_X_))->tv.tv_sec  += 1;                      \
   1730 			  }
   1731 
   1732 #define cvt_ts(_X_, _Y_) \
   1733                         {                                                   \
   1734 			  l_fp ts;				            \
   1735 			  fix_ts((_X_));                                    \
   1736 			  if (!buftvtots((const char *)&(&(_X_))->tv, &ts)) \
   1737 			    {                                               \
   1738                               ERR(ERR_BADDATA)	 		            \
   1739                                 msyslog(LOG_ERR,"parse: stream_receive: timestamp conversion error (buftvtots) (%s) (%ld.%06ld) ", (_Y_), (long)(&(_X_))->tv.tv_sec, (long)(&(_X_))->tv.tv_usec);\
   1740 			      return;                                       \
   1741 			    }                                               \
   1742 			  else                                              \
   1743 			    {                                               \
   1744 			      (&(_X_))->fp = ts;                            \
   1745 			    }                                               \
   1746 		        }
   1747 
   1748 /*--------------------------------------------------
   1749  * ppsclock STREAM init
   1750  */
   1751 static int
   1752 ppsclock_init(
   1753 	struct parseunit *parse
   1754 	)
   1755 {
   1756         static char m1[] = "ppsclocd";
   1757 	static char m2[] = "ppsclock";
   1758 
   1759 	/*
   1760 	 * now push the parse streams module
   1761 	 * it will ensure exclusive access to the device
   1762 	 */
   1763 	if (ioctl(parse->ppsfd, I_PUSH, (caddr_t)m1) == -1 &&
   1764 	    ioctl(parse->ppsfd, I_PUSH, (caddr_t)m2) == -1)
   1765 	{
   1766 		if (errno != EINVAL)
   1767 		{
   1768 			msyslog(LOG_ERR, "PARSE receiver #%d: ppsclock_init: ioctl(fd, I_PUSH, \"ppsclock\"): %m",
   1769 				CLK_UNIT(parse->peer));
   1770 		}
   1771 		return 0;
   1772 	}
   1773 	if (!local_init(parse))
   1774 	{
   1775 		(void)ioctl(parse->ppsfd, I_POP, (caddr_t)0);
   1776 		return 0;
   1777 	}
   1778 
   1779 	parse->flags |= PARSE_PPSCLOCK;
   1780 	return 1;
   1781 }
   1782 
   1783 /*--------------------------------------------------
   1784  * parse STREAM init
   1785  */
   1786 static int
   1787 stream_init(
   1788 	struct parseunit *parse
   1789 	)
   1790 {
   1791 	static char m1[] = "parse";
   1792 	/*
   1793 	 * now push the parse streams module
   1794 	 * to test whether it is there (neat interface 8-( )
   1795 	 */
   1796 	if (ioctl(parse->generic->io.fd, I_PUSH, (caddr_t)m1) == -1)
   1797 	{
   1798 		if (errno != EINVAL) /* accept non-existence */
   1799 		{
   1800 			msyslog(LOG_ERR, "PARSE receiver #%d: stream_init: ioctl(fd, I_PUSH, \"parse\"): %m", CLK_UNIT(parse->peer));
   1801 		}
   1802 		return 0;
   1803 	}
   1804 	else
   1805 	{
   1806 		while(ioctl(parse->generic->io.fd, I_POP, (caddr_t)0) == 0)
   1807 		    /* empty loop */;
   1808 
   1809 		/*
   1810 		 * now push it a second time after we have removed all
   1811 		 * module garbage
   1812 		 */
   1813 		if (ioctl(parse->generic->io.fd, I_PUSH, (caddr_t)m1) == -1)
   1814 		{
   1815 			msyslog(LOG_ERR, "PARSE receiver #%d: stream_init: ioctl(fd, I_PUSH, \"parse\"): %m", CLK_UNIT(parse->peer));
   1816 			return 0;
   1817 		}
   1818 		else
   1819 		{
   1820 			return 1;
   1821 		}
   1822 	}
   1823 }
   1824 
   1825 /*--------------------------------------------------
   1826  * parse STREAM end
   1827  */
   1828 static void
   1829 stream_end(
   1830 	struct parseunit *parse
   1831 	)
   1832 {
   1833 	while(ioctl(parse->generic->io.fd, I_POP, (caddr_t)0) == 0)
   1834 	    /* empty loop */;
   1835 }
   1836 
   1837 /*--------------------------------------------------
   1838  * STREAM setcs
   1839  */
   1840 static int
   1841 stream_setcs(
   1842 	struct parseunit *parse,
   1843 	parsectl_t  *tcl
   1844 	)
   1845 {
   1846 	struct strioctl strioc;
   1847 
   1848 	strioc.ic_cmd     = PARSEIOC_SETCS;
   1849 	strioc.ic_timout  = 0;
   1850 	strioc.ic_dp      = (char *)tcl;
   1851 	strioc.ic_len     = sizeof (*tcl);
   1852 
   1853 	if (ioctl(parse->generic->io.fd, I_STR, (caddr_t)&strioc) == -1)
   1854 	{
   1855 		msyslog(LOG_ERR, "PARSE receiver #%d: stream_setcs: ioctl(fd, I_STR, PARSEIOC_SETCS): %m", CLK_UNIT(parse->peer));
   1856 		return 0;
   1857 	}
   1858 	return 1;
   1859 }
   1860 
   1861 /*--------------------------------------------------
   1862  * STREAM enable
   1863  */
   1864 static int
   1865 stream_enable(
   1866 	struct parseunit *parse
   1867 	)
   1868 {
   1869 	struct strioctl strioc;
   1870 
   1871 	strioc.ic_cmd     = PARSEIOC_ENABLE;
   1872 	strioc.ic_timout  = 0;
   1873 	strioc.ic_dp      = (char *)0;
   1874 	strioc.ic_len     = 0;
   1875 
   1876 	if (ioctl(parse->generic->io.fd, I_STR, (caddr_t)&strioc) == -1)
   1877 	{
   1878 		msyslog(LOG_ERR, "PARSE receiver #%d: stream_enable: ioctl(fd, I_STR, PARSEIOC_ENABLE): %m", CLK_UNIT(parse->peer));
   1879 		return 0;
   1880 	}
   1881 	parse->generic->io.clock_recv = stream_receive; /* ok - parse input in kernel */
   1882 	return 1;
   1883 }
   1884 
   1885 /*--------------------------------------------------
   1886  * STREAM disable
   1887  */
   1888 static int
   1889 stream_disable(
   1890 	struct parseunit *parse
   1891 	)
   1892 {
   1893 	struct strioctl strioc;
   1894 
   1895 	strioc.ic_cmd     = PARSEIOC_DISABLE;
   1896 	strioc.ic_timout  = 0;
   1897 	strioc.ic_dp      = (char *)0;
   1898 	strioc.ic_len     = 0;
   1899 
   1900 	if (ioctl(parse->generic->io.fd, I_STR, (caddr_t)&strioc) == -1)
   1901 	{
   1902 		msyslog(LOG_ERR, "PARSE receiver #%d: stream_disable: ioctl(fd, I_STR, PARSEIOC_DISABLE): %m", CLK_UNIT(parse->peer));
   1903 		return 0;
   1904 	}
   1905 	parse->generic->io.clock_recv = local_receive; /* ok - parse input in daemon */
   1906 	return 1;
   1907 }
   1908 
   1909 /*--------------------------------------------------
   1910  * STREAM getfmt
   1911  */
   1912 static int
   1913 stream_getfmt(
   1914 	struct parseunit *parse,
   1915 	parsectl_t  *tcl
   1916 	)
   1917 {
   1918 	struct strioctl strioc;
   1919 
   1920 	strioc.ic_cmd     = PARSEIOC_GETFMT;
   1921 	strioc.ic_timout  = 0;
   1922 	strioc.ic_dp      = (char *)tcl;
   1923 	strioc.ic_len     = sizeof (*tcl);
   1924 	if (ioctl(parse->generic->io.fd, I_STR, (caddr_t)&strioc) == -1)
   1925 	{
   1926 		msyslog(LOG_ERR, "PARSE receiver #%d: ioctl(fd, I_STR, PARSEIOC_GETFMT): %m", CLK_UNIT(parse->peer));
   1927 		return 0;
   1928 	}
   1929 	return 1;
   1930 }
   1931 
   1932 /*--------------------------------------------------
   1933  * STREAM setfmt
   1934  */
   1935 static int
   1936 stream_setfmt(
   1937 	struct parseunit *parse,
   1938 	parsectl_t  *tcl
   1939 	)
   1940 {
   1941 	struct strioctl strioc;
   1942 
   1943 	strioc.ic_cmd     = PARSEIOC_SETFMT;
   1944 	strioc.ic_timout  = 0;
   1945 	strioc.ic_dp      = (char *)tcl;
   1946 	strioc.ic_len     = sizeof (*tcl);
   1947 
   1948 	if (ioctl(parse->generic->io.fd, I_STR, (caddr_t)&strioc) == -1)
   1949 	{
   1950 		msyslog(LOG_ERR, "PARSE receiver #%d: stream_setfmt: ioctl(fd, I_STR, PARSEIOC_SETFMT): %m", CLK_UNIT(parse->peer));
   1951 		return 0;
   1952 	}
   1953 	return 1;
   1954 }
   1955 
   1956 
   1957 /*--------------------------------------------------
   1958  * STREAM timecode
   1959  */
   1960 static int
   1961 stream_timecode(
   1962 	struct parseunit *parse,
   1963 	parsectl_t  *tcl
   1964 	)
   1965 {
   1966 	struct strioctl strioc;
   1967 
   1968 	strioc.ic_cmd     = PARSEIOC_TIMECODE;
   1969 	strioc.ic_timout  = 0;
   1970 	strioc.ic_dp      = (char *)tcl;
   1971 	strioc.ic_len     = sizeof (*tcl);
   1972 
   1973 	if (ioctl(parse->generic->io.fd, I_STR, (caddr_t)&strioc) == -1)
   1974 	{
   1975 		ERR(ERR_INTERNAL)
   1976 			msyslog(LOG_ERR, "PARSE receiver #%d: stream_timecode: ioctl(fd, I_STR, PARSEIOC_TIMECODE): %m", CLK_UNIT(parse->peer));
   1977 		return 0;
   1978 	}
   1979 	clear_err(parse, ERR_INTERNAL);
   1980 	return 1;
   1981 }
   1982 
   1983 /*--------------------------------------------------
   1984  * STREAM receive
   1985  */
   1986 static void
   1987 stream_receive(
   1988 	struct recvbuf *rbufp
   1989 	)
   1990 {
   1991 	struct parseunit *parse = (struct parseunit *)((void *)rbufp->recv_srcclock);
   1992 	parsetime_t parsetime;
   1993 
   1994 	if (!parse->peer)
   1995 	    return;
   1996 
   1997 	if (rbufp->recv_length != sizeof(parsetime_t))
   1998 	{
   1999 		ERR(ERR_BADIO)
   2000 			msyslog(LOG_ERR,"PARSE receiver #%d: stream_receive: bad size (got %d expected %d)",
   2001 				CLK_UNIT(parse->peer), rbufp->recv_length, (int)sizeof(parsetime_t));
   2002 		parse_event(parse, CEVNT_BADREPLY);
   2003 		return;
   2004 	}
   2005 	clear_err(parse, ERR_BADIO);
   2006 
   2007 	memmove((caddr_t)&parsetime,
   2008 		(caddr_t)rbufp->recv_buffer,
   2009 		sizeof(parsetime_t));
   2010 
   2011 #ifdef DEBUG
   2012 	if (debug > 3)
   2013 	  {
   2014 	    printf("PARSE receiver #%d: status %06x, state %08x, time %lx.%08lx, stime %lx.%08lx, ptime %lx.%08lx\n",
   2015 		   CLK_UNIT(parse->peer),
   2016 		   (unsigned int)parsetime.parse_status,
   2017 		   (unsigned int)parsetime.parse_state,
   2018 		   (unsigned long)parsetime.parse_time.tv.tv_sec,
   2019 		   (unsigned long)parsetime.parse_time.tv.tv_usec,
   2020 		   (unsigned long)parsetime.parse_stime.tv.tv_sec,
   2021 		   (unsigned long)parsetime.parse_stime.tv.tv_usec,
   2022 		   (unsigned long)parsetime.parse_ptime.tv.tv_sec,
   2023 		   (unsigned long)parsetime.parse_ptime.tv.tv_usec);
   2024 	  }
   2025 #endif
   2026 
   2027 	/*
   2028 	 * switch time stamp world - be sure to normalize small usec field
   2029 	 * errors.
   2030 	 */
   2031 
   2032 	cvt_ts(parsetime.parse_stime, "parse_stime");
   2033 
   2034 	if (PARSE_TIMECODE(parsetime.parse_state))
   2035 	{
   2036 	    cvt_ts(parsetime.parse_time, "parse_time");
   2037 	}
   2038 
   2039 	if (PARSE_PPS(parsetime.parse_state))
   2040 	    cvt_ts(parsetime.parse_ptime, "parse_ptime");
   2041 
   2042 	parse_process(parse, &parsetime);
   2043 }
   2044 #endif
   2045 
   2046 /*--------------------------------------------------
   2047  * local init
   2048  */
   2049 static int
   2050 local_init(
   2051 	struct parseunit *parse
   2052 	)
   2053 {
   2054 	return parse_ioinit(&parse->parseio);
   2055 }
   2056 
   2057 /*--------------------------------------------------
   2058  * local end
   2059  */
   2060 static void
   2061 local_end(
   2062 	struct parseunit *parse
   2063 	)
   2064 {
   2065 	parse_ioend(&parse->parseio);
   2066 }
   2067 
   2068 
   2069 /*--------------------------------------------------
   2070  * local nop
   2071  */
   2072 static int
   2073 local_nop(
   2074 	struct parseunit *parse
   2075 	)
   2076 {
   2077 	return 1;
   2078 }
   2079 
   2080 /*--------------------------------------------------
   2081  * local setcs
   2082  */
   2083 static int
   2084 local_setcs(
   2085 	struct parseunit *parse,
   2086 	parsectl_t  *tcl
   2087 	)
   2088 {
   2089 	return parse_setcs(tcl, &parse->parseio);
   2090 }
   2091 
   2092 /*--------------------------------------------------
   2093  * local getfmt
   2094  */
   2095 static int
   2096 local_getfmt(
   2097 	struct parseunit *parse,
   2098 	parsectl_t  *tcl
   2099 	)
   2100 {
   2101 	return parse_getfmt(tcl, &parse->parseio);
   2102 }
   2103 
   2104 /*--------------------------------------------------
   2105  * local setfmt
   2106  */
   2107 static int
   2108 local_setfmt(
   2109 	struct parseunit *parse,
   2110 	parsectl_t  *tcl
   2111 	)
   2112 {
   2113 	return parse_setfmt(tcl, &parse->parseio);
   2114 }
   2115 
   2116 /*--------------------------------------------------
   2117  * local timecode
   2118  */
   2119 static int
   2120 local_timecode(
   2121 	struct parseunit *parse,
   2122 	parsectl_t  *tcl
   2123 	)
   2124 {
   2125 	return parse_timecode(tcl, &parse->parseio);
   2126 }
   2127 
   2128 
   2129 /*--------------------------------------------------
   2130  * local input
   2131  */
   2132 static int
   2133 local_input(
   2134 	struct recvbuf *rbufp
   2135 	)
   2136 {
   2137 	struct parseunit *parse = (struct parseunit *)((void *)rbufp->recv_srcclock);
   2138 	int count;
   2139 	unsigned char *s;
   2140 	timestamp_t ts;
   2141 
   2142 	if (!parse->peer)
   2143 		return 0;
   2144 
   2145 	/*
   2146 	 * eat all characters, parsing then and feeding complete samples
   2147 	 */
   2148 	count = rbufp->recv_length;
   2149 	s = (unsigned char *)rbufp->recv_buffer;
   2150 	ts.fp = rbufp->recv_time;
   2151 
   2152 	while (count--)
   2153 	{
   2154 		if (parse_ioread(&parse->parseio, (unsigned int)(*s++), &ts))
   2155 		{
   2156 			struct recvbuf *buf;
   2157 
   2158 			/*
   2159 			 * got something good to eat
   2160 			 */
   2161 			if (!PARSE_PPS(parse->parseio.parse_dtime.parse_state))
   2162 			{
   2163 #ifdef HAVE_PPSAPI
   2164 				if (parse->flags & PARSE_PPSCLOCK)
   2165 				{
   2166 					struct timespec pps_timeout;
   2167 					pps_info_t      pps_info;
   2168 
   2169 					pps_timeout.tv_sec  = 0;
   2170 					pps_timeout.tv_nsec = 0;
   2171 
   2172 					if (time_pps_fetch(parse->atom.handle, PPS_TSFMT_TSPEC, &pps_info,
   2173 							   &pps_timeout) == 0)
   2174 					{
   2175 						if (pps_info.assert_sequence + pps_info.clear_sequence != parse->ppsserial)
   2176 						{
   2177 							double dtemp;
   2178 
   2179 						        struct timespec pts;
   2180 							/*
   2181 							 * add PPS time stamp if available via ppsclock module
   2182 							 * and not supplied already.
   2183 							 */
   2184 							if (parse->flags & PARSE_CLEAR)
   2185 							  pts = pps_info.clear_timestamp;
   2186 							else
   2187 							  pts = pps_info.assert_timestamp;
   2188 
   2189 							parse->parseio.parse_dtime.parse_ptime.fp.l_ui = pts.tv_sec + JAN_1970;
   2190 
   2191 							dtemp = pts.tv_nsec / 1e9;
   2192 							if (dtemp < 0.) {
   2193 								dtemp += 1;
   2194 								parse->parseio.parse_dtime.parse_ptime.fp.l_ui--;
   2195 							}
   2196 							if (dtemp > 1.) {
   2197 								dtemp -= 1;
   2198 								parse->parseio.parse_dtime.parse_ptime.fp.l_ui++;
   2199 							}
   2200 							parse->parseio.parse_dtime.parse_ptime.fp.l_uf = dtemp * FRAC;
   2201 
   2202 						        parse->parseio.parse_dtime.parse_state |= PARSEB_PPS|PARSEB_S_PPS;
   2203 #ifdef DEBUG
   2204 							if (debug > 3)
   2205 							{
   2206 								printf(
   2207 								       "parse: local_receive: fd %d PPSAPI seq %ld - PPS %s\n",
   2208 								       rbufp->fd,
   2209 								       (long)pps_info.assert_sequence + (long)pps_info.clear_sequence,
   2210 								       lfptoa(&parse->parseio.parse_dtime.parse_ptime.fp, 6));
   2211 							}
   2212 #endif
   2213 						}
   2214 #ifdef DEBUG
   2215 						else
   2216 						{
   2217 							if (debug > 3)
   2218 							{
   2219 								printf(
   2220 								       "parse: local_receive: fd %d PPSAPI seq assert %ld, seq clear %ld - NO PPS event\n",
   2221 								       rbufp->fd,
   2222 								       (long)pps_info.assert_sequence, (long)pps_info.clear_sequence);
   2223 							}
   2224 						}
   2225 #endif
   2226 						parse->ppsserial = pps_info.assert_sequence + pps_info.clear_sequence;
   2227 					}
   2228 #ifdef DEBUG
   2229 					else
   2230 					{
   2231 						if (debug > 3)
   2232 						{
   2233 							printf(
   2234 							       "parse: local_receive: fd %d PPSAPI time_pps_fetch errno = %d\n",
   2235 							       rbufp->fd,
   2236 							       errno);
   2237 						}
   2238 					}
   2239 #endif
   2240 				}
   2241 #else
   2242 #ifdef TIOCDCDTIMESTAMP
   2243 				struct timeval dcd_time;
   2244 
   2245 				if (ioctl(parse->ppsfd, TIOCDCDTIMESTAMP, &dcd_time) != -1)
   2246 				{
   2247 					l_fp tstmp;
   2248 
   2249 					TVTOTS(&dcd_time, &tstmp);
   2250 					tstmp.l_ui += JAN_1970;
   2251 					L_SUB(&ts.fp, &tstmp);
   2252 					if (ts.fp.l_ui == 0)
   2253 					{
   2254 #ifdef DEBUG
   2255 						if (debug)
   2256 						{
   2257 							printf(
   2258 							       "parse: local_receive: fd %d DCDTIMESTAMP %s\n",
   2259 							       parse->ppsfd,
   2260 							       lfptoa(&tstmp, 6));
   2261 							printf(" sigio %s\n",
   2262 							       lfptoa(&ts.fp, 6));
   2263 						}
   2264 #endif
   2265 						parse->parseio.parse_dtime.parse_ptime.fp = tstmp;
   2266 						parse->parseio.parse_dtime.parse_state |= PARSEB_PPS|PARSEB_S_PPS;
   2267 					}
   2268 				}
   2269 #else /* TIOCDCDTIMESTAMP */
   2270 #if defined(HAVE_STRUCT_PPSCLOCKEV) && (defined(HAVE_CIOGETEV) || defined(HAVE_TIOCGPPSEV))
   2271 				if (parse->flags & PARSE_PPSCLOCK)
   2272 				  {
   2273 				    l_fp tts;
   2274 				    struct ppsclockev ev;
   2275 
   2276 #ifdef HAVE_CIOGETEV
   2277 				    if (ioctl(parse->ppsfd, CIOGETEV, (caddr_t)&ev) == 0)
   2278 #endif
   2279 #ifdef HAVE_TIOCGPPSEV
   2280 				    if (ioctl(parse->ppsfd, TIOCGPPSEV, (caddr_t)&ev) == 0)
   2281 #endif
   2282 					{
   2283 					  if (ev.serial != parse->ppsserial)
   2284 					    {
   2285 					      /*
   2286 					       * add PPS time stamp if available via ppsclock module
   2287 					       * and not supplied already.
   2288 					       */
   2289 					      if (!buftvtots((const char *)&ev.tv, &tts))
   2290 						{
   2291 						  ERR(ERR_BADDATA)
   2292 						    msyslog(LOG_ERR,"parse: local_receive: timestamp conversion error (buftvtots) (ppsclockev.tv)");
   2293 						}
   2294 					      else
   2295 						{
   2296 						  parse->parseio.parse_dtime.parse_ptime.fp = tts;
   2297 						  parse->parseio.parse_dtime.parse_state |= PARSEB_PPS|PARSEB_S_PPS;
   2298 						}
   2299 					    }
   2300 					  parse->ppsserial = ev.serial;
   2301 					}
   2302 				  }
   2303 #endif
   2304 #endif /* TIOCDCDTIMESTAMP */
   2305 #endif /* !HAVE_PPSAPI */
   2306 			}
   2307 			if (count)
   2308 			{	/* simulate receive */
   2309 				buf = get_free_recv_buffer();
   2310 				if (buf != NULL) {
   2311 					memmove((caddr_t)buf->recv_buffer,
   2312 						(caddr_t)&parse->parseio.parse_dtime,
   2313 						sizeof(parsetime_t));
   2314 					buf->recv_length  = sizeof(parsetime_t);
   2315 					buf->recv_time    = rbufp->recv_time;
   2316 					buf->srcadr       = rbufp->srcadr;
   2317 					buf->dstadr       = rbufp->dstadr;
   2318 					buf->receiver     = rbufp->receiver;
   2319 					buf->fd           = rbufp->fd;
   2320 					buf->X_from_where = rbufp->X_from_where;
   2321 					add_full_recv_buffer(buf);
   2322 				}
   2323 				parse_iodone(&parse->parseio);
   2324 			}
   2325 			else
   2326 			{
   2327 				memmove((caddr_t)rbufp->recv_buffer,
   2328 					(caddr_t)&parse->parseio.parse_dtime,
   2329 					sizeof(parsetime_t));
   2330 				parse_iodone(&parse->parseio);
   2331 				rbufp->recv_length = sizeof(parsetime_t);
   2332 				return 1; /* got something & in place return */
   2333 			}
   2334 		}
   2335 	}
   2336 	return 0;		/* nothing to pass up */
   2337 }
   2338 
   2339 /*--------------------------------------------------
   2340  * local receive
   2341  */
   2342 static void
   2343 local_receive(
   2344 	struct recvbuf *rbufp
   2345 	)
   2346 {
   2347 	struct parseunit *parse = (struct parseunit *)((void *)rbufp->recv_srcclock);
   2348 	parsetime_t parsetime;
   2349 
   2350 	if (!parse->peer)
   2351 	    return;
   2352 
   2353 	if (rbufp->recv_length != sizeof(parsetime_t))
   2354 	{
   2355 		ERR(ERR_BADIO)
   2356 			msyslog(LOG_ERR,"PARSE receiver #%d: local_receive: bad size (got %d expected %d)",
   2357 				CLK_UNIT(parse->peer), rbufp->recv_length, (int)sizeof(parsetime_t));
   2358 		parse_event(parse, CEVNT_BADREPLY);
   2359 		return;
   2360 	}
   2361 	clear_err(parse, ERR_BADIO);
   2362 
   2363 	memmove((caddr_t)&parsetime,
   2364 		(caddr_t)rbufp->recv_buffer,
   2365 		sizeof(parsetime_t));
   2366 
   2367 #ifdef DEBUG
   2368 	if (debug > 3)
   2369 	  {
   2370 	    printf("PARSE receiver #%d: status %06x, state %08x, time(fp) %lx.%08lx, stime(fp) %lx.%08lx, ptime(fp) %lx.%08lx\n",
   2371 		   CLK_UNIT(parse->peer),
   2372 		   (unsigned int)parsetime.parse_status,
   2373 		   (unsigned int)parsetime.parse_state,
   2374 		   (unsigned long)parsetime.parse_time.fp.l_ui,
   2375 		   (unsigned long)parsetime.parse_time.fp.l_uf,
   2376 		   (unsigned long)parsetime.parse_stime.fp.l_ui,
   2377 		   (unsigned long)parsetime.parse_stime.fp.l_uf,
   2378 		   (unsigned long)parsetime.parse_ptime.fp.l_ui,
   2379 		   (unsigned long)parsetime.parse_ptime.fp.l_uf);
   2380 	  }
   2381 #endif
   2382 
   2383 	parse_process(parse, &parsetime);
   2384 }
   2385 
   2386 /*--------------------------------------------------
   2387  * init_iobinding - find and initialize lower layers
   2388  */
   2389 static bind_t *
   2390 init_iobinding(
   2391 	struct parseunit *parse
   2392 	)
   2393 {
   2394   bind_t *b = io_bindings;
   2395 
   2396 	while (b->bd_description != (char *)0)
   2397 	{
   2398 		if ((*b->bd_init)(parse))
   2399 		{
   2400 			return b;
   2401 		}
   2402 		b++;
   2403 	}
   2404 	return (bind_t *)0;
   2405 }
   2406 
   2407 /**===========================================================================
   2408  ** support routines
   2409  **/
   2410 
   2411 /*--------------------------------------------------
   2412  * convert a flag field to a string
   2413  */
   2414 static char *
   2415 parsestate(
   2416 	u_long lstate,
   2417 	char *buffer,
   2418 	int size
   2419 	)
   2420 {
   2421 	static struct bits
   2422 	{
   2423 		u_long      bit;
   2424 		const char *name;
   2425 	} flagstrings[] =
   2426 	  {
   2427 		  { PARSEB_ANNOUNCE,   "DST SWITCH WARNING" },
   2428 		  { PARSEB_POWERUP,    "NOT SYNCHRONIZED" },
   2429 		  { PARSEB_NOSYNC,     "TIME CODE NOT CONFIRMED" },
   2430 		  { PARSEB_DST,        "DST" },
   2431 		  { PARSEB_UTC,        "UTC DISPLAY" },
   2432 		  { PARSEB_LEAPADD,    "LEAP ADD WARNING" },
   2433 		  { PARSEB_LEAPDEL,    "LEAP DELETE WARNING" },
   2434 		  { PARSEB_LEAPSECOND, "LEAP SECOND" },
   2435 		  { PARSEB_ALTERNATE,  "ALTERNATE ANTENNA" },
   2436 		  { PARSEB_TIMECODE,   "TIME CODE" },
   2437 		  { PARSEB_PPS,        "PPS" },
   2438 		  { PARSEB_POSITION,   "POSITION" },
   2439 		  { 0 }
   2440 	  };
   2441 
   2442 	static struct sbits
   2443 	{
   2444 		u_long      bit;
   2445 		const char *name;
   2446 	} sflagstrings[] =
   2447 	  {
   2448 		  { PARSEB_S_LEAP,     "LEAP INDICATION" },
   2449 		  { PARSEB_S_PPS,      "PPS SIGNAL" },
   2450 		  { PARSEB_S_ANTENNA,  "ANTENNA" },
   2451 		  { PARSEB_S_POSITION, "POSITION" },
   2452 		  { 0 }
   2453 	  };
   2454 	int i;
   2455 	char *s, *t;
   2456 
   2457 
   2458 	*buffer = '\0';
   2459 	s = t = buffer;
   2460 
   2461 	i = 0;
   2462 	while (flagstrings[i].bit)
   2463 	{
   2464 		if (flagstrings[i].bit & lstate)
   2465 		{
   2466 			if (s != t)
   2467 				strncpy(t, "; ", BUFFER_SIZES(buffer, t, size));
   2468 			strncat(t, flagstrings[i].name, BUFFER_SIZES(buffer, t, size));
   2469 			t += strlen(t);
   2470 		}
   2471 		i++;
   2472 	}
   2473 
   2474 	if (lstate & (PARSEB_S_LEAP|PARSEB_S_ANTENNA|PARSEB_S_PPS|PARSEB_S_POSITION))
   2475 	{
   2476 		if (s != t)
   2477 			strncpy(t, "; ", BUFFER_SIZES(buffer, t, size));
   2478 
   2479 		t += strlen(t);
   2480 
   2481 		strncpy(t, "(", BUFFER_SIZES(buffer, t, size));
   2482 
   2483 		s = t = t + strlen(t);
   2484 
   2485 		i = 0;
   2486 		while (sflagstrings[i].bit)
   2487 		{
   2488 			if (sflagstrings[i].bit & lstate)
   2489 			{
   2490 				if (t != s)
   2491 				{
   2492 					strncpy(t, "; ", BUFFER_SIZES(buffer, t, size));
   2493 					t += 2;
   2494 				}
   2495 
   2496 				strncpy(t, sflagstrings[i].name, BUFFER_SIZES(buffer, t, size));
   2497 				t += strlen(t);
   2498 			}
   2499 			i++;
   2500 		}
   2501 		strncpy(t, ")", BUFFER_SIZES(buffer, t, size));
   2502 	}
   2503 	return buffer;
   2504 }
   2505 
   2506 /*--------------------------------------------------
   2507  * convert a status flag field to a string
   2508  */
   2509 static char *
   2510 parsestatus(
   2511 	u_long lstate,
   2512 	char *buffer,
   2513 	int size
   2514 	)
   2515 {
   2516 	static struct bits
   2517 	{
   2518 		u_long      bit;
   2519 		const char *name;
   2520 	} flagstrings[] =
   2521 	  {
   2522 		  { CVT_OK,      "CONVERSION SUCCESSFUL" },
   2523 		  { CVT_NONE,    "NO CONVERSION" },
   2524 		  { CVT_FAIL,    "CONVERSION FAILED" },
   2525 		  { CVT_BADFMT,  "ILLEGAL FORMAT" },
   2526 		  { CVT_BADDATE, "DATE ILLEGAL" },
   2527 		  { CVT_BADTIME, "TIME ILLEGAL" },
   2528 		  { CVT_ADDITIONAL, "ADDITIONAL DATA" },
   2529 		  { 0 }
   2530 	  };
   2531 	int i;
   2532 
   2533 	*buffer = '\0';
   2534 
   2535 	i = 0;
   2536 	while (flagstrings[i].bit)
   2537 	{
   2538 		if (flagstrings[i].bit & lstate)
   2539 		{
   2540 			if (buffer[0])
   2541 				strncat(buffer, "; ", size);
   2542 			strncat(buffer, flagstrings[i].name, size);
   2543 		}
   2544 		i++;
   2545 	}
   2546 
   2547 	return buffer;
   2548 }
   2549 
   2550 /*--------------------------------------------------
   2551  * convert a clock status flag field to a string
   2552  */
   2553 static const char *
   2554 clockstatus(
   2555 	u_long lstate
   2556 	)
   2557 {
   2558 	static char buffer[20];
   2559 	static struct status
   2560 	{
   2561 		u_long      value;
   2562 		const char *name;
   2563 	} flagstrings[] =
   2564 	  {
   2565 		  { CEVNT_NOMINAL, "NOMINAL" },
   2566 		  { CEVNT_TIMEOUT, "NO RESPONSE" },
   2567 		  { CEVNT_BADREPLY,"BAD FORMAT" },
   2568 		  { CEVNT_FAULT,   "FAULT" },
   2569 		  { CEVNT_PROP,    "PROPAGATION DELAY" },
   2570 		  { CEVNT_BADDATE, "ILLEGAL DATE" },
   2571 		  { CEVNT_BADTIME, "ILLEGAL TIME" },
   2572 		  { (unsigned)~0L }
   2573 	  };
   2574 	int i;
   2575 
   2576 	i = 0;
   2577 	while (flagstrings[i].value != ~0)
   2578 	{
   2579 		if (flagstrings[i].value == lstate)
   2580 		{
   2581 			return flagstrings[i].name;
   2582 		}
   2583 		i++;
   2584 	}
   2585 
   2586 	snprintf(buffer, sizeof(buffer), "unknown #%ld", (u_long)lstate);
   2587 
   2588 	return buffer;
   2589 }
   2590 
   2591 
   2592 /*--------------------------------------------------
   2593  * l_mktime - make representation of a relative time
   2594  */
   2595 static char *
   2596 l_mktime(
   2597 	u_long delta
   2598 	)
   2599 {
   2600 	u_long tmp, m, s;
   2601 	static char buffer[40];
   2602 	char *t;
   2603 
   2604 	buffer[0] = '\0';
   2605 
   2606 	if ((tmp = delta / (60*60*24)) != 0)
   2607 	{
   2608 		snprintf(buffer, BUFFER_SIZE(buffer, buffer), "%ldd+", (u_long)tmp);
   2609 		delta -= tmp * 60*60*24;
   2610 	}
   2611 
   2612 	s = delta % 60;
   2613 	delta /= 60;
   2614 	m = delta % 60;
   2615 	delta /= 60;
   2616 
   2617 	t = buffer + strlen(buffer);
   2618 
   2619 	snprintf(t, BUFFER_SIZE(buffer, t), "%02d:%02d:%02d",
   2620 		 (int)delta, (int)m, (int)s);
   2621 
   2622 	return buffer;
   2623 }
   2624 
   2625 
   2626 /*--------------------------------------------------
   2627  * parse_statistics - list summary of clock states
   2628  */
   2629 static void
   2630 parse_statistics(
   2631 	struct parseunit *parse
   2632 	)
   2633 {
   2634 	int i;
   2635 
   2636 	NLOG(NLOG_CLOCKSTATIST) /* conditional if clause for conditional syslog */
   2637 		{
   2638 			msyslog(LOG_INFO, "PARSE receiver #%d: running time: %s",
   2639 				CLK_UNIT(parse->peer),
   2640 				l_mktime(current_time - parse->generic->timestarted));
   2641 
   2642 			msyslog(LOG_INFO, "PARSE receiver #%d: current status: %s",
   2643 				CLK_UNIT(parse->peer),
   2644 				clockstatus(parse->generic->currentstatus));
   2645 
   2646 			for (i = 0; i <= CEVNT_MAX; i++)
   2647 			{
   2648 				u_long s_time;
   2649 				u_long percent, d = current_time - parse->generic->timestarted;
   2650 
   2651 				percent = s_time = PARSE_STATETIME(parse, i);
   2652 
   2653 				while (((u_long)(~0) / 10000) < percent)
   2654 				{
   2655 					percent /= 10;
   2656 					d       /= 10;
   2657 				}
   2658 
   2659 				if (d)
   2660 				    percent = (percent * 10000) / d;
   2661 				else
   2662 				    percent = 10000;
   2663 
   2664 				if (s_time)
   2665 				    msyslog(LOG_INFO, "PARSE receiver #%d: state %18s: %13s (%3ld.%02ld%%)",
   2666 					    CLK_UNIT(parse->peer),
   2667 					    clockstatus((unsigned int)i),
   2668 					    l_mktime(s_time),
   2669 					    percent / 100, percent % 100);
   2670 			}
   2671 		}
   2672 }
   2673 
   2674 /*--------------------------------------------------
   2675  * cparse_statistics - wrapper for statistics call
   2676  */
   2677 static void
   2678 cparse_statistics(
   2679         struct parseunit *parse
   2680 	)
   2681 {
   2682 	if (parse->laststatistic + PARSESTATISTICS < current_time)
   2683 		parse_statistics(parse);
   2684 	parse->laststatistic = current_time;
   2685 }
   2686 
   2687 /**===========================================================================
   2688  ** ntp interface routines
   2689  **/
   2690 
   2691 /*--------------------------------------------------
   2692  * parse_shutdown - shut down a PARSE clock
   2693  */
   2694 static void
   2695 parse_shutdown(
   2696 	int unit,
   2697 	struct peer *peer
   2698 	)
   2699 {
   2700 	struct parseunit *parse = (struct parseunit *)0;
   2701 
   2702 	if (peer && peer->procptr)
   2703 		parse = (struct parseunit *)peer->procptr->unitptr;
   2704 
   2705 	if (!parse)
   2706 	{
   2707 		/* nothing to clean up */
   2708 		return;
   2709 	}
   2710 
   2711         if (!parse->peer)
   2712 	{
   2713 		msyslog(LOG_INFO, "PARSE receiver #%d: INTERNAL ERROR - unit already inactive - shutdown ignored", unit);
   2714 		return;
   2715 	}
   2716 
   2717 #ifdef HAVE_PPSAPI
   2718 	if (parse->flags & PARSE_PPSCLOCK)
   2719 	{
   2720 		(void)time_pps_destroy(parse->atom.handle);
   2721 	}
   2722 #endif
   2723 	if (parse->generic->io.fd != parse->ppsfd && parse->ppsfd != -1)
   2724 		(void)close(parse->ppsfd);  /* close separate PPS source */
   2725 
   2726 	/*
   2727 	 * print statistics a last time and
   2728 	 * stop statistics machine
   2729 	 */
   2730 	parse_statistics(parse);
   2731 
   2732 	if (parse->parse_type->cl_end)
   2733 	{
   2734 		parse->parse_type->cl_end(parse);
   2735 	}
   2736 
   2737 	/*
   2738 	 * cleanup before leaving this world
   2739 	 */
   2740 	if (parse->binding)
   2741 	    PARSE_END(parse);
   2742 
   2743 	/*
   2744 	 * Tell the I/O module to turn us off.  We're history.
   2745 	 */
   2746 	io_closeclock(&parse->generic->io);
   2747 
   2748 	free_varlist(parse->kv);
   2749 
   2750 	NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
   2751 		msyslog(LOG_INFO, "PARSE receiver #%d: reference clock \"%s\" removed",
   2752 			CLK_UNIT(parse->peer), parse->parse_type->cl_description);
   2753 
   2754 	parse->peer = (struct peer *)0; /* unused now */
   2755 	peer->procptr->unitptr = (caddr_t)0;
   2756 	free(parse);
   2757 }
   2758 
   2759 #ifdef HAVE_PPSAPI
   2760 /*----------------------------------------
   2761  * set up HARDPPS via PPSAPI
   2762  */
   2763 static void
   2764 parse_hardpps(
   2765 	      struct parseunit *parse,
   2766 	      int mode
   2767 	      )
   2768 {
   2769         if (parse->hardppsstate == mode)
   2770 	        return;
   2771 
   2772 	if (CLK_PPS(parse->peer) && (parse->flags & PARSE_PPSKERNEL)) {
   2773 		int	i = 0;
   2774 
   2775 		if (mode == PARSE_HARDPPS_ENABLE)
   2776 		        {
   2777 			        if (parse->flags & PARSE_CLEAR)
   2778 				        i = PPS_CAPTURECLEAR;
   2779 				else
   2780 				        i = PPS_CAPTUREASSERT;
   2781 			}
   2782 
   2783 		if (time_pps_kcbind(parse->atom.handle, PPS_KC_HARDPPS, i,
   2784 		    PPS_TSFMT_TSPEC) < 0) {
   2785 		        msyslog(LOG_ERR, "PARSE receiver #%d: time_pps_kcbind failed: %m",
   2786 				CLK_UNIT(parse->peer));
   2787 		} else {
   2788 		        NLOG(NLOG_CLOCKINFO)
   2789 		                msyslog(LOG_INFO, "PARSE receiver #%d: kernel PPS synchronisation %sabled",
   2790 					CLK_UNIT(parse->peer), (mode == PARSE_HARDPPS_ENABLE) ? "en" : "dis");
   2791 			/*
   2792 			 * tell the rest, that we have a kernel PPS source, iff we ever enable HARDPPS
   2793 			 */
   2794 			if (mode == PARSE_HARDPPS_ENABLE)
   2795 			        pps_enable = 1;
   2796 		}
   2797 	}
   2798 
   2799 	parse->hardppsstate = mode;
   2800 }
   2801 
   2802 /*----------------------------------------
   2803  * set up PPS via PPSAPI
   2804  */
   2805 static int
   2806 parse_ppsapi(
   2807 	     struct parseunit *parse
   2808 	)
   2809 {
   2810 	int cap, mode_ppsoffset;
   2811 	char *cp;
   2812 
   2813 	parse->flags &= ~PARSE_PPSCLOCK;
   2814 
   2815 	/*
   2816 	 * collect PPSAPI offset capability - should move into generic handling
   2817 	 */
   2818 	if (time_pps_getcap(parse->atom.handle, &cap) < 0) {
   2819 		msyslog(LOG_ERR, "PARSE receiver #%d: parse_ppsapi: time_pps_getcap failed: %m",
   2820 			CLK_UNIT(parse->peer));
   2821 
   2822 		return 0;
   2823 	}
   2824 
   2825 	/*
   2826 	 * initialize generic PPSAPI interface
   2827 	 *
   2828 	 * we leave out CLK_FLAG3 as time_pps_kcbind()
   2829 	 * is handled here for now. Ideally this should also
   2830 	 * be part of the generic PPSAPI interface
   2831 	 */
   2832 	if (!refclock_params(parse->flags & (CLK_FLAG1|CLK_FLAG2|CLK_FLAG4), &parse->atom))
   2833 		return 0;
   2834 
   2835 	/* nb. only turn things on, if someone else has turned something
   2836 	 *	on before we get here, leave it alone!
   2837 	 */
   2838 
   2839 	if (parse->flags & PARSE_CLEAR) {
   2840 		cp = "CLEAR";
   2841 		mode_ppsoffset = PPS_OFFSETCLEAR;
   2842 	} else {
   2843 		cp = "ASSERT";
   2844 		mode_ppsoffset = PPS_OFFSETASSERT;
   2845 	}
   2846 
   2847 	msyslog(LOG_INFO, "PARSE receiver #%d: initializing PPS to %s",
   2848 		CLK_UNIT(parse->peer), cp);
   2849 
   2850 	if (!(mode_ppsoffset & cap)) {
   2851 	  msyslog(LOG_WARNING, "PARSE receiver #%d: Cannot set PPS_%sCLEAR, this will increase jitter (PPS API capabilities=0x%x)",
   2852 		  CLK_UNIT(parse->peer), cp, cap);
   2853 		mode_ppsoffset = 0;
   2854 	} else {
   2855 	        if (mode_ppsoffset == PPS_OFFSETCLEAR)
   2856 		        {
   2857 			        parse->atom.pps_params.clear_offset.tv_sec = -parse->ppsphaseadjust;
   2858 			        parse->atom.pps_params.clear_offset.tv_nsec = -1e9*(parse->ppsphaseadjust - (long)parse->ppsphaseadjust);
   2859 			}
   2860 
   2861 		if (mode_ppsoffset == PPS_OFFSETASSERT)
   2862 	                {
   2863 		                parse->atom.pps_params.assert_offset.tv_sec = -parse->ppsphaseadjust;
   2864 				parse->atom.pps_params.assert_offset.tv_nsec = -1e9*(parse->ppsphaseadjust - (long)parse->ppsphaseadjust);
   2865 			}
   2866 	}
   2867 
   2868 	parse->atom.pps_params.mode |= mode_ppsoffset;
   2869 
   2870 	if (time_pps_setparams(parse->atom.handle, &parse->atom.pps_params) < 0) {
   2871 	  msyslog(LOG_ERR, "PARSE receiver #%d: FAILED set PPS parameters: %m",
   2872 		  CLK_UNIT(parse->peer));
   2873 		return 0;
   2874 	}
   2875 
   2876 	parse->flags |= PARSE_PPSCLOCK;
   2877 	return 1;
   2878 }
   2879 #else
   2880 #define parse_hardpps(_PARSE_, _MODE_) /* empty */
   2881 #endif
   2882 
   2883 /*--------------------------------------------------
   2884  * parse_start - open the PARSE devices and initialize data for processing
   2885  */
   2886 static int
   2887 parse_start(
   2888 	int sysunit,
   2889 	struct peer *peer
   2890 	)
   2891 {
   2892 	u_int unit;
   2893 	int fd232;
   2894 #ifdef HAVE_TERMIOS
   2895 	struct termios tio;		/* NEEDED FOR A LONG TIME ! */
   2896 #endif
   2897 #ifdef HAVE_SYSV_TTYS
   2898 	struct termio tio;		/* NEEDED FOR A LONG TIME ! */
   2899 #endif
   2900 	struct parseunit * parse;
   2901 	char parsedev[sizeof(PARSEDEVICE)+20];
   2902 	char parseppsdev[sizeof(PARSEPPSDEVICE)+20];
   2903 	parsectl_t tmp_ctl;
   2904 	u_int type;
   2905 
   2906 	/*
   2907 	 * get out Copyright information once
   2908 	 */
   2909 	if (!notice)
   2910         {
   2911 		NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
   2912 			msyslog(LOG_INFO, "NTP PARSE support: Copyright (c) 1989-2009, Frank Kardel");
   2913 		notice = 1;
   2914 	}
   2915 
   2916 	type = CLK_TYPE(peer);
   2917 	unit = CLK_UNIT(peer);
   2918 
   2919 	if ((type == ~0) || (parse_clockinfo[type].cl_description == (char *)0))
   2920 	{
   2921 		msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: unsupported clock type %d (max %d)",
   2922 			unit, CLK_REALTYPE(peer), ncltypes-1);
   2923 		return 0;
   2924 	}
   2925 
   2926 	/*
   2927 	 * Unit okay, attempt to open the device.
   2928 	 */
   2929 	(void) snprintf(parsedev, sizeof(parsedev), PARSEDEVICE, unit);
   2930 	(void) snprintf(parseppsdev, sizeof(parsedev), PARSEPPSDEVICE, unit);
   2931 
   2932 #ifndef O_NOCTTY
   2933 #define O_NOCTTY 0
   2934 #endif
   2935 
   2936 	fd232 = open(parsedev, O_RDWR | O_NOCTTY
   2937 #ifdef O_NONBLOCK
   2938 		     | O_NONBLOCK
   2939 #endif
   2940 		     , 0777);
   2941 
   2942 	if (fd232 == -1)
   2943 	{
   2944 		msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: open of %s failed: %m", unit, parsedev);
   2945 		return 0;
   2946 	}
   2947 
   2948 	parse = (struct parseunit *)emalloc(sizeof(struct parseunit));
   2949 
   2950 	memset((char *)parse, 0, sizeof(struct parseunit));
   2951 
   2952 	parse->generic = peer->procptr;	 /* link up */
   2953 	parse->generic->unitptr = (caddr_t)parse; /* link down */
   2954 
   2955 	/*
   2956 	 * Set up the structures
   2957 	 */
   2958 	parse->generic->timestarted    = current_time;
   2959 	parse->lastchange     = current_time;
   2960 
   2961 	parse->flags          = 0;
   2962 	parse->pollneeddata   = 0;
   2963 	parse->laststatistic  = current_time;
   2964 	parse->lastformat     = (unsigned short)~0;	/* assume no format known */
   2965 	parse->timedata.parse_status = (unsigned short)~0;	/* be sure to mark initial status change */
   2966 	parse->lastmissed     = 0;	/* assume got everything */
   2967 	parse->ppsserial      = 0;
   2968 	parse->ppsfd	      = -1;
   2969 	parse->localdata      = (void *)0;
   2970 	parse->localstate     = 0;
   2971 	parse->kv             = (struct ctl_var *)0;
   2972 
   2973 	clear_err(parse, ERR_ALL);
   2974 
   2975 	parse->parse_type     = &parse_clockinfo[type];
   2976 
   2977 	parse->maxunsync      = parse->parse_type->cl_maxunsync;
   2978 
   2979 	parse->generic->fudgetime1 = parse->parse_type->cl_basedelay;
   2980 
   2981 	parse->generic->fudgetime2 = 0.0;
   2982 	parse->ppsphaseadjust = parse->generic->fudgetime2;
   2983 
   2984 	parse->generic->clockdesc  = parse->parse_type->cl_description;
   2985 
   2986 	peer->rootdelay       = parse->parse_type->cl_rootdelay;
   2987 	peer->sstclktype      = parse->parse_type->cl_type;
   2988 	peer->precision       = sys_precision;
   2989 
   2990 	peer->stratum         = STRATUM_REFCLOCK;
   2991 
   2992 	if (peer->stratum <= 1)
   2993 	    memmove((char *)&parse->generic->refid, parse->parse_type->cl_id, 4);
   2994 	else
   2995 	    parse->generic->refid = htonl(PARSEHSREFID);
   2996 
   2997 	parse->generic->io.fd = fd232;
   2998 
   2999 	parse->peer = peer;		/* marks it also as busy */
   3000 
   3001 	/*
   3002 	 * configure terminal line
   3003 	 */
   3004 	if (TTY_GETATTR(fd232, &tio) == -1)
   3005 	{
   3006 		msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: tcgetattr(%d, &tio): %m", unit, fd232);
   3007 		parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
   3008 		return 0;
   3009 	}
   3010 	else
   3011 	{
   3012 #ifndef _PC_VDISABLE
   3013 		memset((char *)tio.c_cc, 0, sizeof(tio.c_cc));
   3014 #else
   3015 		int disablec;
   3016 		errno = 0;		/* pathconf can deliver -1 without changing errno ! */
   3017 
   3018 		disablec = fpathconf(parse->generic->io.fd, _PC_VDISABLE);
   3019 		if (disablec == -1 && errno)
   3020 		{
   3021 			msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: fpathconf(fd, _PC_VDISABLE): %m", CLK_UNIT(parse->peer));
   3022 			memset((char *)tio.c_cc, 0, sizeof(tio.c_cc)); /* best guess */
   3023 		}
   3024 		else
   3025 		    if (disablec != -1)
   3026 			memset((char *)tio.c_cc, disablec, sizeof(tio.c_cc));
   3027 #endif
   3028 
   3029 #if defined (VMIN) || defined(VTIME)
   3030 		if ((parse_clockinfo[type].cl_lflag & ICANON) == 0)
   3031 		{
   3032 #ifdef VMIN
   3033 			tio.c_cc[VMIN]   = 1;
   3034 #endif
   3035 #ifdef VTIME
   3036 			tio.c_cc[VTIME]  = 0;
   3037 #endif
   3038 		}
   3039 #endif
   3040 
   3041 		tio.c_cflag = parse_clockinfo[type].cl_cflag;
   3042 		tio.c_iflag = parse_clockinfo[type].cl_iflag;
   3043 		tio.c_oflag = parse_clockinfo[type].cl_oflag;
   3044 		tio.c_lflag = parse_clockinfo[type].cl_lflag;
   3045 
   3046 
   3047 #ifdef HAVE_TERMIOS
   3048 		if ((cfsetospeed(&tio, parse_clockinfo[type].cl_speed) == -1) ||
   3049 		    (cfsetispeed(&tio, parse_clockinfo[type].cl_speed) == -1))
   3050 		{
   3051 			msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: tcset{i,o}speed(&tio, speed): %m", unit);
   3052 			parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
   3053 			return 0;
   3054 		}
   3055 #else
   3056 		tio.c_cflag     |= parse_clockinfo[type].cl_speed;
   3057 #endif
   3058 
   3059 		/*
   3060 		 * set up pps device
   3061 		 * if the PARSEPPSDEVICE can be opened that will be used
   3062 		 * for PPS else PARSEDEVICE will be used
   3063 		 */
   3064 		parse->ppsfd = open(parseppsdev, O_RDWR | O_NOCTTY
   3065 #ifdef O_NONBLOCK
   3066 				    | O_NONBLOCK
   3067 #endif
   3068 				    , 0777);
   3069 
   3070 		if (parse->ppsfd == -1)
   3071 		{
   3072 			parse->ppsfd = fd232;
   3073 		}
   3074 
   3075 /*
   3076  * Linux PPS - the old way
   3077  */
   3078 #if defined(HAVE_TIO_SERIAL_STUFF)		/* Linux hack: define PPS interface */
   3079 		{
   3080 			struct serial_struct	ss;
   3081 			if (ioctl(parse->ppsfd, TIOCGSERIAL, &ss) < 0 ||
   3082 			    (
   3083 #ifdef ASYNC_LOW_LATENCY
   3084 			     ss.flags |= ASYNC_LOW_LATENCY,
   3085 #endif
   3086 #ifndef HAVE_PPSAPI
   3087 #ifdef ASYNC_PPS_CD_NEG
   3088 			     ss.flags |= ASYNC_PPS_CD_NEG,
   3089 #endif
   3090 #endif
   3091 			     ioctl(parse->ppsfd, TIOCSSERIAL, &ss)) < 0) {
   3092 				msyslog(LOG_NOTICE, "refclock_parse: TIOCSSERIAL fd %d, %m", parse->ppsfd);
   3093 				msyslog(LOG_NOTICE,
   3094 					"refclock_parse: optional PPS processing not available");
   3095 			} else {
   3096 				parse->flags    |= PARSE_PPSCLOCK;
   3097 #ifdef ASYNC_PPS_CD_NEG
   3098 				NLOG(NLOG_CLOCKINFO)
   3099 				  msyslog(LOG_INFO,
   3100 					  "refclock_parse: PPS detection on");
   3101 #endif
   3102 			}
   3103 		}
   3104 #endif
   3105 
   3106 /*
   3107  * SUN the Solaris way
   3108  */
   3109 #ifdef HAVE_TIOCSPPS			/* SUN PPS support */
   3110 		if (CLK_PPS(parse->peer))
   3111 		    {
   3112 			int i = 1;
   3113 
   3114 			if (ioctl(parse->ppsfd, TIOCSPPS, (caddr_t)&i) == 0)
   3115 			    {
   3116 				parse->flags |= PARSE_PPSCLOCK;
   3117 			    }
   3118 		    }
   3119 #endif
   3120 
   3121 /*
   3122  * PPS via PPSAPI
   3123  */
   3124 #if defined(HAVE_PPSAPI)
   3125 		parse->hardppsstate = PARSE_HARDPPS_DISABLE;
   3126 		if (CLK_PPS(parse->peer))
   3127 		{
   3128 		  if (!refclock_ppsapi(parse->ppsfd, &parse->atom))
   3129 		    {
   3130 		      msyslog(LOG_NOTICE, "PARSE receiver #%d: parse_start: could not set up PPS: %m", CLK_UNIT(parse->peer));
   3131 		    }
   3132 		  else
   3133 		    {
   3134 		      parse_ppsapi(parse);
   3135 		    }
   3136 		}
   3137 #endif
   3138 
   3139 		if (TTY_SETATTR(fd232, &tio) == -1)
   3140 		{
   3141 			msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: tcsetattr(%d, &tio): %m", unit, fd232);
   3142 			parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
   3143 			return 0;
   3144 		}
   3145 	}
   3146 
   3147 	/*
   3148 	 * pick correct input machine
   3149 	 */
   3150 	parse->generic->io.srcclock = (caddr_t)parse;
   3151 	parse->generic->io.datalen = 0;
   3152 
   3153 	parse->binding = init_iobinding(parse);
   3154 
   3155 	if (parse->binding == (bind_t *)0)
   3156 		{
   3157 			msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: io sub system initialisation failed.", CLK_UNIT(parse->peer));
   3158 			parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
   3159 			return 0;			/* well, ok - special initialisation broke */
   3160 		}
   3161 
   3162 	parse->generic->io.clock_recv = parse->binding->bd_receive; /* pick correct receive routine */
   3163 	parse->generic->io.io_input   = parse->binding->bd_io_input; /* pick correct input routine */
   3164 
   3165 	/*
   3166 	 * as we always(?) get 8 bit chars we want to be
   3167 	 * sure, that the upper bits are zero for less
   3168 	 * than 8 bit I/O - so we pass that information on.
   3169 	 * note that there can be only one bit count format
   3170 	 * per file descriptor
   3171 	 */
   3172 
   3173 	switch (tio.c_cflag & CSIZE)
   3174 	{
   3175 	    case CS5:
   3176 		tmp_ctl.parsesetcs.parse_cs = PARSE_IO_CS5;
   3177 		break;
   3178 
   3179 	    case CS6:
   3180 		tmp_ctl.parsesetcs.parse_cs = PARSE_IO_CS6;
   3181 		break;
   3182 
   3183 	    case CS7:
   3184 		tmp_ctl.parsesetcs.parse_cs = PARSE_IO_CS7;
   3185 		break;
   3186 
   3187 	    case CS8:
   3188 		tmp_ctl.parsesetcs.parse_cs = PARSE_IO_CS8;
   3189 		break;
   3190 	}
   3191 
   3192 	if (!PARSE_SETCS(parse, &tmp_ctl))
   3193 	{
   3194 		msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: parse_setcs() FAILED.", unit);
   3195 		parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
   3196 		return 0;			/* well, ok - special initialisation broke */
   3197 	}
   3198 
   3199 	strncpy(tmp_ctl.parseformat.parse_buffer, parse->parse_type->cl_format, sizeof(tmp_ctl.parseformat.parse_buffer));
   3200 	tmp_ctl.parseformat.parse_count = strlen(tmp_ctl.parseformat.parse_buffer);
   3201 
   3202 	if (!PARSE_SETFMT(parse, &tmp_ctl))
   3203 	{
   3204 		msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: parse_setfmt() 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 	/*
   3210 	 * get rid of all IO accumulated so far
   3211 	 */
   3212 #ifdef HAVE_TERMIOS
   3213 	(void) tcflush(parse->generic->io.fd, TCIOFLUSH);
   3214 #else
   3215 #if defined(TCFLSH) && defined(TCIOFLUSH)
   3216 	{
   3217 		int flshcmd = TCIOFLUSH;
   3218 
   3219 		(void) ioctl(parse->generic->io.fd, TCFLSH, (caddr_t)&flshcmd);
   3220 	}
   3221 #endif
   3222 #endif
   3223 
   3224 	/*
   3225 	 * try to do any special initializations
   3226 	 */
   3227 	if (parse->parse_type->cl_init)
   3228 		{
   3229 			if (parse->parse_type->cl_init(parse))
   3230 				{
   3231 					parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
   3232 					return 0;		/* well, ok - special initialisation broke */
   3233 				}
   3234 		}
   3235 
   3236 	/*
   3237 	 * Insert in async io device list.
   3238 	 */
   3239 	if (!io_addclock(&parse->generic->io))
   3240         {
   3241 		msyslog(LOG_ERR,
   3242 			"PARSE receiver #%d: parse_start: addclock %s fails (ABORT - clock type requires async io)", CLK_UNIT(parse->peer), parsedev);
   3243 		parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
   3244 		return 0;
   3245 	}
   3246 
   3247 	/*
   3248 	 * print out configuration
   3249 	 */
   3250 	NLOG(NLOG_CLOCKINFO)
   3251 		{
   3252 			/* conditional if clause for conditional syslog */
   3253 			msyslog(LOG_INFO, "PARSE receiver #%d: reference clock \"%s\" (I/O device %s, PPS device %s) added",
   3254 				CLK_UNIT(parse->peer),
   3255 				parse->parse_type->cl_description, parsedev,
   3256 				(parse->ppsfd != parse->generic->io.fd) ? parseppsdev : parsedev);
   3257 
   3258 			msyslog(LOG_INFO, "PARSE receiver #%d: Stratum %d, trust time %s, precision %d",
   3259 				CLK_UNIT(parse->peer),
   3260 				parse->peer->stratum,
   3261 				l_mktime(parse->maxunsync), parse->peer->precision);
   3262 
   3263 			msyslog(LOG_INFO, "PARSE receiver #%d: rootdelay %.6f s, phase adjustment %.6f s, PPS phase adjustment %.6f s, %s IO handling",
   3264 				CLK_UNIT(parse->peer),
   3265 				parse->parse_type->cl_rootdelay,
   3266 				parse->generic->fudgetime1,
   3267 				parse->ppsphaseadjust,
   3268                                 parse->binding->bd_description);
   3269 
   3270 			msyslog(LOG_INFO, "PARSE receiver #%d: Format recognition: %s", CLK_UNIT(parse->peer),
   3271 				parse->parse_type->cl_format);
   3272                         msyslog(LOG_INFO, "PARSE receiver #%d: %sPPS support%s", CLK_UNIT(parse->peer),
   3273 				CLK_PPS(parse->peer) ? "" : "NO ",
   3274 				CLK_PPS(parse->peer) ?
   3275 #ifdef PPS_METHOD
   3276 				" (implementation " PPS_METHOD ")"
   3277 #else
   3278 				""
   3279 #endif
   3280 				: ""
   3281 				);
   3282 		}
   3283 
   3284 	return 1;
   3285 }
   3286 
   3287 /*--------------------------------------------------
   3288  * parse_ctl - process changes on flags/time values
   3289  */
   3290 static void
   3291 parse_ctl(
   3292 	    struct parseunit *parse,
   3293 	    struct refclockstat *in
   3294 	    )
   3295 {
   3296         if (in)
   3297 	{
   3298 		if (in->haveflags & (CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4))
   3299 		{
   3300 		  parse->flags = (parse->flags & ~(CLK_FLAG1|CLK_FLAG2|CLK_FLAG3|CLK_FLAG4)) |
   3301 		    (in->flags & (CLK_FLAG1|CLK_FLAG2|CLK_FLAG3|CLK_FLAG4));
   3302 #if defined(HAVE_PPSAPI)
   3303 		  if (CLK_PPS(parse->peer))
   3304 		    {
   3305 		      parse_ppsapi(parse);
   3306 		    }
   3307 #endif
   3308 		}
   3309 
   3310 		if (in->haveflags & CLK_HAVETIME1)
   3311                 {
   3312 		  parse->generic->fudgetime1 = in->fudgetime1;
   3313 		  msyslog(LOG_INFO, "PARSE receiver #%d: new phase adjustment %.6f s",
   3314 			  CLK_UNIT(parse->peer),
   3315 			  parse->generic->fudgetime1);
   3316 		}
   3317 
   3318 		if (in->haveflags & CLK_HAVETIME2)
   3319                 {
   3320 		  parse->generic->fudgetime2 = in->fudgetime2;
   3321 		  if (parse->flags & PARSE_TRUSTTIME)
   3322 		    {
   3323 		      parse->maxunsync = (u_long)ABS(in->fudgetime2);
   3324 		      msyslog(LOG_INFO, "PARSE receiver #%d: new trust time %s",
   3325 			      CLK_UNIT(parse->peer),
   3326 			      l_mktime(parse->maxunsync));
   3327 		    }
   3328 		  else
   3329 		    {
   3330 		      parse->ppsphaseadjust = in->fudgetime2;
   3331 		      msyslog(LOG_INFO, "PARSE receiver #%d: new PPS phase adjustment %.6f s",
   3332 			  CLK_UNIT(parse->peer),
   3333 			      parse->ppsphaseadjust);
   3334 #if defined(HAVE_PPSAPI)
   3335 		      if (CLK_PPS(parse->peer))
   3336 		      {
   3337 			      parse_ppsapi(parse);
   3338 		      }
   3339 #endif
   3340 		    }
   3341 		}
   3342 	}
   3343 }
   3344 
   3345 /*--------------------------------------------------
   3346  * parse_poll - called by the transmit procedure
   3347  */
   3348 static void
   3349 parse_poll(
   3350 	int unit,
   3351 	struct peer *peer
   3352 	)
   3353 {
   3354 	struct parseunit *parse = (struct parseunit *)peer->procptr->unitptr;
   3355 
   3356 	if (peer != parse->peer)
   3357 	{
   3358 		msyslog(LOG_ERR,
   3359 			"PARSE receiver #%d: poll: INTERNAL: peer incorrect",
   3360 			unit);
   3361 		return;
   3362 	}
   3363 
   3364 	/*
   3365 	 * Update clock stat counters
   3366 	 */
   3367 	parse->generic->polls++;
   3368 
   3369 	if (parse->pollneeddata &&
   3370 	    ((current_time - parse->pollneeddata) > (1<<(max(min(parse->peer->hpoll, parse->peer->ppoll), parse->peer->minpoll)))))
   3371 	{
   3372 		/*
   3373 		 * start worrying when exceeding a poll inteval
   3374 		 * bad news - didn't get a response last time
   3375 		 */
   3376 		parse->lastmissed = current_time;
   3377 		parse_event(parse, CEVNT_TIMEOUT);
   3378 
   3379 		ERR(ERR_NODATA)
   3380 			msyslog(LOG_WARNING, "PARSE receiver #%d: no data from device within poll interval (check receiver / wiring)", CLK_UNIT(parse->peer));
   3381 	}
   3382 
   3383 	/*
   3384 	 * we just mark that we want the next sample for the clock filter
   3385 	 */
   3386 	parse->pollneeddata = current_time;
   3387 
   3388 	if (parse->parse_type->cl_poll)
   3389 	{
   3390 		parse->parse_type->cl_poll(parse);
   3391 	}
   3392 
   3393 	cparse_statistics(parse);
   3394 
   3395 	return;
   3396 }
   3397 
   3398 #define LEN_STATES 300		/* length of state string */
   3399 
   3400 /*--------------------------------------------------
   3401  * parse_control - set fudge factors, return statistics
   3402  */
   3403 static void
   3404 parse_control(
   3405 	int unit,
   3406 	struct refclockstat *in,
   3407 	struct refclockstat *out,
   3408 	struct peer *peer
   3409 	)
   3410 {
   3411         struct parseunit *parse = (struct parseunit *)peer->procptr->unitptr;
   3412 	parsectl_t tmpctl;
   3413 
   3414 	static char outstatus[400];	/* status output buffer */
   3415 
   3416 	if (out)
   3417 	{
   3418 		out->lencode       = 0;
   3419 		out->p_lastcode    = 0;
   3420 		out->kv_list       = (struct ctl_var *)0;
   3421 	}
   3422 
   3423 	if (!parse || !parse->peer)
   3424 	{
   3425 		msyslog(LOG_ERR, "PARSE receiver #%d: parse_control: unit invalid (UNIT INACTIVE)",
   3426 			unit);
   3427 		return;
   3428 	}
   3429 
   3430 	unit = CLK_UNIT(parse->peer);
   3431 
   3432 	/*
   3433 	 * handle changes
   3434 	 */
   3435 	parse_ctl(parse, in);
   3436 
   3437 	/*
   3438 	 * supply data
   3439 	 */
   3440 	if (out)
   3441 	{
   3442 		u_long sum = 0;
   3443 		char *tt, *start;
   3444 		int i;
   3445 
   3446 		outstatus[0] = '\0';
   3447 
   3448 		out->type       = REFCLK_PARSE;
   3449 
   3450 		/*
   3451 		 * keep fudgetime2 in sync with TRUSTTIME/MAXUNSYNC flag1
   3452 		 */
   3453 		parse->generic->fudgetime2 = (parse->flags & PARSE_TRUSTTIME) ? (double)parse->maxunsync : parse->ppsphaseadjust;
   3454 
   3455 		/*
   3456 		 * figure out skew between PPS and RS232 - just for informational
   3457 		 * purposes
   3458 		 */
   3459 		if (PARSE_SYNC(parse->timedata.parse_state))
   3460 		{
   3461 			if (PARSE_PPS(parse->timedata.parse_state) && PARSE_TIMECODE(parse->timedata.parse_state))
   3462 			{
   3463 				l_fp off;
   3464 
   3465 				/*
   3466 				 * we have a PPS and RS232 signal - calculate the skew
   3467 				 * WARNING: assumes on TIMECODE == PULSE (timecode after pulse)
   3468 				 */
   3469 				off = parse->timedata.parse_stime.fp;
   3470 				L_SUB(&off, &parse->timedata.parse_ptime.fp); /* true offset */
   3471 				tt = add_var(&out->kv_list, 80, RO);
   3472 				snprintf(tt, 80, "refclock_ppsskew=%s", lfptoms(&off, 6));
   3473 			}
   3474 		}
   3475 
   3476 		if (PARSE_PPS(parse->timedata.parse_state))
   3477 		{
   3478 			tt = add_var(&out->kv_list, 80, RO|DEF);
   3479 			snprintf(tt, 80, "refclock_ppstime=\"%s\"", gmprettydate(&parse->timedata.parse_ptime.fp));
   3480 		}
   3481 
   3482 		start = tt = add_var(&out->kv_list, 128, RO|DEF);
   3483 		snprintf(tt, 128, "refclock_time=\"");
   3484 		tt += strlen(tt);
   3485 
   3486 		if (parse->timedata.parse_time.fp.l_ui == 0)
   3487 		{
   3488 			strncpy(tt, "<UNDEFINED>\"", BUFFER_SIZES(start, tt, 128));
   3489 		}
   3490 		else
   3491 		{
   3492 			snprintf(tt, 128, "%s\"", gmprettydate(&parse->timedata.parse_time.fp));
   3493 		}
   3494 
   3495 		if (!PARSE_GETTIMECODE(parse, &tmpctl))
   3496 		{
   3497 			ERR(ERR_INTERNAL)
   3498 				msyslog(LOG_ERR, "PARSE receiver #%d: parse_control: parse_timecode() FAILED", unit);
   3499 		}
   3500 		else
   3501 		{
   3502 			start = tt = add_var(&out->kv_list, 512, RO|DEF);
   3503 			snprintf(tt, 512, "refclock_status=\"");
   3504 			tt += strlen(tt);
   3505 
   3506 			/*
   3507 			 * copy PPS flags from last read transaction (informational only)
   3508 			 */
   3509 			tmpctl.parsegettc.parse_state |= parse->timedata.parse_state &
   3510 				(PARSEB_PPS|PARSEB_S_PPS);
   3511 
   3512 			(void) parsestate(tmpctl.parsegettc.parse_state, tt, BUFFER_SIZES(start, tt, 512));
   3513 
   3514 			strncat(tt, "\"", BUFFER_SIZES(start, tt, 512));
   3515 
   3516 			if (tmpctl.parsegettc.parse_count)
   3517 			    mkascii(outstatus+strlen(outstatus), (int)(sizeof(outstatus)- strlen(outstatus) - 1),
   3518 				    tmpctl.parsegettc.parse_buffer, (unsigned)(tmpctl.parsegettc.parse_count));
   3519 
   3520 		}
   3521 
   3522 		tmpctl.parseformat.parse_format = tmpctl.parsegettc.parse_format;
   3523 
   3524 		if (!PARSE_GETFMT(parse, &tmpctl))
   3525 		{
   3526 			ERR(ERR_INTERNAL)
   3527 				msyslog(LOG_ERR, "PARSE receiver #%d: parse_control: parse_getfmt() FAILED", unit);
   3528 		}
   3529 		else
   3530 		{
   3531 			tt = add_var(&out->kv_list, 80, RO|DEF);
   3532 			snprintf(tt, 80, "refclock_format=\"");
   3533 
   3534 			strncat(tt, tmpctl.parseformat.parse_buffer, tmpctl.parseformat.parse_count);
   3535 			strncat(tt,"\"", 80);
   3536 		}
   3537 
   3538 		/*
   3539 		 * gather state statistics
   3540 		 */
   3541 
   3542 		start = tt = add_var(&out->kv_list, LEN_STATES, RO|DEF);
   3543 		strncpy(tt, "refclock_states=\"", LEN_STATES);
   3544 		tt += strlen(tt);
   3545 
   3546 		for (i = 0; i <= CEVNT_MAX; i++)
   3547 		{
   3548 			u_long s_time;
   3549 			u_long d = current_time - parse->generic->timestarted;
   3550 			u_long percent;
   3551 
   3552 			percent = s_time = PARSE_STATETIME(parse, i);
   3553 
   3554 			while (((u_long)(~0) / 10000) < percent)
   3555 			{
   3556 				percent /= 10;
   3557 				d       /= 10;
   3558 			}
   3559 
   3560 			if (d)
   3561 			    percent = (percent * 10000) / d;
   3562 			else
   3563 			    percent = 10000;
   3564 
   3565 			if (s_time)
   3566 			{
   3567 				char item[80];
   3568 				int count;
   3569 
   3570 				snprintf(item, 80, "%s%s%s: %s (%d.%02d%%)",
   3571 					sum ? "; " : "",
   3572 					(parse->generic->currentstatus == i) ? "*" : "",
   3573 					clockstatus((unsigned int)i),
   3574 					l_mktime(s_time),
   3575 					(int)(percent / 100), (int)(percent % 100));
   3576 				if ((count = strlen(item)) < (LEN_STATES - 40 - (tt - start)))
   3577 					{
   3578 						strncpy(tt, item, BUFFER_SIZES(start, tt, LEN_STATES));
   3579 						tt  += count;
   3580 					}
   3581 				sum += s_time;
   3582 			}
   3583 		}
   3584 
   3585 		snprintf(tt, BUFFER_SIZES(start, tt, LEN_STATES), "; running time: %s\"", l_mktime(sum));
   3586 
   3587 		tt = add_var(&out->kv_list, 32, RO);
   3588 		snprintf(tt, 32,  "refclock_id=\"%s\"", parse->parse_type->cl_id);
   3589 
   3590 		tt = add_var(&out->kv_list, 80, RO);
   3591 		snprintf(tt, 80,  "refclock_iomode=\"%s\"", parse->binding->bd_description);
   3592 
   3593 		tt = add_var(&out->kv_list, 128, RO);
   3594 		snprintf(tt, 128, "refclock_driver_version=\"%s\"", rcsid);
   3595 
   3596 		{
   3597 			struct ctl_var *k;
   3598 
   3599 			k = parse->kv;
   3600 			while (k && !(k->flags & EOV))
   3601 			{
   3602 				set_var(&out->kv_list, k->text, strlen(k->text)+1, k->flags);
   3603 				k++;
   3604 			}
   3605 		}
   3606 
   3607 		out->lencode       = strlen(outstatus);
   3608 		out->p_lastcode    = outstatus;
   3609 	}
   3610 }
   3611 
   3612 /**===========================================================================
   3613  ** processing routines
   3614  **/
   3615 
   3616 /*--------------------------------------------------
   3617  * event handling - note that nominal events will also be posted
   3618  * keep track of state dwelling times
   3619  */
   3620 static void
   3621 parse_event(
   3622 	struct parseunit *parse,
   3623 	int event
   3624 	)
   3625 {
   3626 	if (parse->generic->currentstatus != (u_char) event)
   3627 	{
   3628 		parse->statetime[parse->generic->currentstatus] += current_time - parse->lastchange;
   3629 		parse->lastchange              = current_time;
   3630 
   3631 		if (parse->parse_type->cl_event)
   3632 		    parse->parse_type->cl_event(parse, event);
   3633 
   3634 		if (event == CEVNT_NOMINAL)
   3635 		{
   3636 			NLOG(NLOG_CLOCKSTATUS)
   3637 				msyslog(LOG_INFO, "PARSE receiver #%d: SYNCHRONIZED",
   3638 					CLK_UNIT(parse->peer));
   3639 		}
   3640 
   3641 		refclock_report(parse->peer, event);
   3642 	}
   3643 }
   3644 
   3645 /*--------------------------------------------------
   3646  * process a PARSE time sample
   3647  */
   3648 static void
   3649 parse_process(
   3650 	struct parseunit *parse,
   3651 	parsetime_t      *parsetime
   3652 	)
   3653 {
   3654 	l_fp off, rectime, reftime;
   3655 	double fudge;
   3656 
   3657 	/*
   3658 	 * check for changes in conversion status
   3659 	 * (only one for each new status !)
   3660 	 */
   3661 	if (((parsetime->parse_status & CVT_MASK) != CVT_OK) &&
   3662 	    ((parsetime->parse_status & CVT_MASK) != CVT_NONE) &&
   3663 	    (parse->timedata.parse_status != parsetime->parse_status))
   3664 	{
   3665 		char buffer[400];
   3666 
   3667 		NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
   3668 			msyslog(LOG_WARNING, "PARSE receiver #%d: conversion status \"%s\"",
   3669 				CLK_UNIT(parse->peer), parsestatus(parsetime->parse_status, buffer, sizeof(buffer)));
   3670 
   3671 		if ((parsetime->parse_status & CVT_MASK) == CVT_FAIL)
   3672 		{
   3673 			/*
   3674 			 * tell more about the story - list time code
   3675 			 * there is a slight change for a race condition and
   3676 			 * the time code might be overwritten by the next packet
   3677 			 */
   3678 			parsectl_t tmpctl;
   3679 
   3680 			if (!PARSE_GETTIMECODE(parse, &tmpctl))
   3681 			{
   3682 				ERR(ERR_INTERNAL)
   3683 					msyslog(LOG_ERR, "PARSE receiver #%d: parse_process: parse_timecode() FAILED", CLK_UNIT(parse->peer));
   3684 			}
   3685 			else
   3686 			{
   3687 				ERR(ERR_BADDATA)
   3688 					msyslog(LOG_WARNING, "PARSE receiver #%d: FAILED TIMECODE: \"%s\" (check receiver configuration / wiring)",
   3689 						CLK_UNIT(parse->peer), mkascii(buffer, sizeof buffer, tmpctl.parsegettc.parse_buffer, (unsigned)(tmpctl.parsegettc.parse_count - 1)));
   3690 			}
   3691 		}
   3692 	}
   3693 
   3694 	/*
   3695 	 * examine status and post appropriate events
   3696 	 */
   3697 	if ((parsetime->parse_status & CVT_MASK) != CVT_OK)
   3698 	{
   3699 		/*
   3700 		 * got bad data - tell the rest of the system
   3701 		 */
   3702 		switch (parsetime->parse_status & CVT_MASK)
   3703 		{
   3704 		case CVT_NONE:
   3705 			if ((parsetime->parse_status & CVT_ADDITIONAL) &&
   3706 			    parse->parse_type->cl_message)
   3707 				parse->parse_type->cl_message(parse, parsetime);
   3708 			/*
   3709 			 * save PPS information that comes piggyback
   3710 			 */
   3711 			if (PARSE_PPS(parsetime->parse_state))
   3712 			  {
   3713 			    parse->timedata.parse_state |= PARSEB_PPS|PARSEB_S_PPS;
   3714 			    parse->timedata.parse_ptime  = parsetime->parse_ptime;
   3715 			  }
   3716 			break; 		/* well, still waiting - timeout is handled at higher levels */
   3717 
   3718 		case CVT_FAIL:
   3719 			if (parsetime->parse_status & CVT_BADFMT)
   3720 			{
   3721 				parse_event(parse, CEVNT_BADREPLY);
   3722 			}
   3723 			else
   3724 				if (parsetime->parse_status & CVT_BADDATE)
   3725 				{
   3726 					parse_event(parse, CEVNT_BADDATE);
   3727 				}
   3728 				else
   3729 					if (parsetime->parse_status & CVT_BADTIME)
   3730 					{
   3731 						parse_event(parse, CEVNT_BADTIME);
   3732 					}
   3733 					else
   3734 					{
   3735 						parse_event(parse, CEVNT_BADREPLY); /* for the lack of something better */
   3736 					}
   3737 		}
   3738 		return;			/* skip the rest - useless */
   3739 	}
   3740 
   3741 	/*
   3742 	 * check for format changes
   3743 	 * (in case somebody has swapped clocks 8-)
   3744 	 */
   3745 	if (parse->lastformat != parsetime->parse_format)
   3746 	{
   3747 		parsectl_t tmpctl;
   3748 
   3749 		tmpctl.parseformat.parse_format = parsetime->parse_format;
   3750 
   3751 		if (!PARSE_GETFMT(parse, &tmpctl))
   3752 		{
   3753 			ERR(ERR_INTERNAL)
   3754 				msyslog(LOG_ERR, "PARSE receiver #%d: parse_getfmt() FAILED", CLK_UNIT(parse->peer));
   3755 		}
   3756 		else
   3757 		{
   3758 			NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
   3759 				msyslog(LOG_INFO, "PARSE receiver #%d: packet format \"%s\"",
   3760 					CLK_UNIT(parse->peer), tmpctl.parseformat.parse_buffer);
   3761 		}
   3762 		parse->lastformat = parsetime->parse_format;
   3763 	}
   3764 
   3765 	/*
   3766 	 * now, any changes ?
   3767 	 */
   3768 	if ((parse->timedata.parse_state ^ parsetime->parse_state) &
   3769 	    ~(unsigned)(PARSEB_PPS|PARSEB_S_PPS))
   3770 	{
   3771 		char tmp1[200];
   3772 		char tmp2[200];
   3773 		/*
   3774 		 * something happend - except for PPS events
   3775 		 */
   3776 
   3777 		(void) parsestate(parsetime->parse_state, tmp1, sizeof(tmp1));
   3778 		(void) parsestate(parse->timedata.parse_state, tmp2, sizeof(tmp2));
   3779 
   3780 		NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
   3781 			msyslog(LOG_INFO,"PARSE receiver #%d: STATE CHANGE: %s -> %s",
   3782 				CLK_UNIT(parse->peer), tmp2, tmp1);
   3783 	}
   3784 
   3785 	/*
   3786 	 * carry on PPS information if still usable
   3787 	 */
   3788 	if (PARSE_PPS(parse->timedata.parse_state) && !PARSE_PPS(parsetime->parse_state))
   3789         {
   3790 	        parsetime->parse_state |= PARSEB_PPS|PARSEB_S_PPS;
   3791 		parsetime->parse_ptime  = parse->timedata.parse_ptime;
   3792 	}
   3793 
   3794 	/*
   3795 	 * remember for future
   3796 	 */
   3797 	parse->timedata = *parsetime;
   3798 
   3799 	/*
   3800 	 * check to see, whether the clock did a complete powerup or lost PZF signal
   3801 	 * and post correct events for current condition
   3802 	 */
   3803 	if (PARSE_POWERUP(parsetime->parse_state))
   3804 	{
   3805 		/*
   3806 		 * this is bad, as we have completely lost synchronisation
   3807 		 * well this is a problem with the receiver here
   3808 		 * for PARSE Meinberg DCF77 receivers the lost synchronisation
   3809 		 * is true as it is the powerup state and the time is taken
   3810 		 * from a crude real time clock chip
   3811 		 * for the PZF/GPS series this is only partly true, as
   3812 		 * PARSE_POWERUP only means that the pseudo random
   3813 		 * phase shift sequence cannot be found. this is only
   3814 		 * bad, if we have never seen the clock in the SYNC
   3815 		 * state, where the PHASE and EPOCH are correct.
   3816 		 * for reporting events the above business does not
   3817 		 * really matter, but we can use the time code
   3818 		 * even in the POWERUP state after having seen
   3819 		 * the clock in the synchronized state (PZF class
   3820 		 * receivers) unless we have had a telegram disruption
   3821 		 * after having seen the clock in the SYNC state. we
   3822 		 * thus require having seen the clock in SYNC state
   3823 		 * *after* having missed telegrams (noresponse) from
   3824 		 * the clock. one problem remains: we might use erroneously
   3825 		 * POWERUP data if the disruption is shorter than 1 polling
   3826 		 * interval. fortunately powerdowns last usually longer than 64
   3827 		 * seconds and the receiver is at least 2 minutes in the
   3828 		 * POWERUP or NOSYNC state before switching to SYNC
   3829 		 * for GPS receivers this can mean antenna problems and other causes.
   3830 		 * the additional grace period can be enables by a clock
   3831 		 * mode having the PARSE_F_POWERUPTRUST flag in cl_flag set.
   3832 		 */
   3833 		parse_event(parse, CEVNT_FAULT);
   3834 		NLOG(NLOG_CLOCKSTATUS)
   3835 			ERR(ERR_BADSTATUS)
   3836 			msyslog(LOG_ERR,"PARSE receiver #%d: NOT SYNCHRONIZED/RECEIVER PROBLEMS",
   3837 				CLK_UNIT(parse->peer));
   3838 	}
   3839 	else
   3840 	{
   3841 		/*
   3842 		 * we have two states left
   3843 		 *
   3844 		 * SYNC:
   3845 		 *  this state means that the EPOCH (timecode) and PHASE
   3846 		 *  information has be read correctly (at least two
   3847 		 *  successive PARSE timecodes were received correctly)
   3848 		 *  this is the best possible state - full trust
   3849 		 *
   3850 		 * NOSYNC:
   3851 		 *  The clock should be on phase with respect to the second
   3852 		 *  signal, but the timecode has not been received correctly within
   3853 		 *  at least the last two minutes. this is a sort of half baked state
   3854 		 *  for PARSE Meinberg DCF77 clocks this is bad news (clock running
   3855 		 *  without timecode confirmation)
   3856 		 *  PZF 535 has also no time confirmation, but the phase should be
   3857 		 *  very precise as the PZF signal can be decoded
   3858 		 */
   3859 
   3860 		if (PARSE_SYNC(parsetime->parse_state))
   3861 		{
   3862 			/*
   3863 			 * currently completely synchronized - best possible state
   3864 			 */
   3865 			parse->lastsync = current_time;
   3866 			clear_err(parse, ERR_BADSTATUS);
   3867 		}
   3868 		else
   3869 		{
   3870 			/*
   3871 			 * we have had some problems receiving the time code
   3872 			 */
   3873 			parse_event(parse, CEVNT_PROP);
   3874 			NLOG(NLOG_CLOCKSTATUS)
   3875 				ERR(ERR_BADSTATUS)
   3876 				msyslog(LOG_ERR,"PARSE receiver #%d: TIMECODE NOT CONFIRMED",
   3877 					CLK_UNIT(parse->peer));
   3878 		}
   3879 	}
   3880 
   3881 	fudge = parse->generic->fudgetime1; /* standard RS232 Fudgefactor */
   3882 
   3883 	if (PARSE_TIMECODE(parsetime->parse_state))
   3884 	{
   3885 		rectime = parsetime->parse_stime.fp;
   3886 		off = reftime = parsetime->parse_time.fp;
   3887 
   3888 		L_SUB(&off, &rectime); /* prepare for PPS adjustments logic */
   3889 
   3890 #ifdef DEBUG
   3891 		if (debug > 3)
   3892 			printf("PARSE receiver #%d: Reftime %s, Recvtime %s - initial offset %s\n",
   3893 			       CLK_UNIT(parse->peer),
   3894 			       prettydate(&reftime),
   3895 			       prettydate(&rectime),
   3896 			       lfptoa(&off,6));
   3897 #endif
   3898 	}
   3899 
   3900 	if (PARSE_PPS(parsetime->parse_state) && CLK_PPS(parse->peer))
   3901 	{
   3902 		l_fp offset;
   3903 		double ppsphaseadjust = parse->ppsphaseadjust;
   3904 
   3905 #ifdef HAVE_PPSAPI
   3906 		/*
   3907 		 * set fudge = 0.0 if already included in PPS time stamps
   3908 		 */
   3909 		if (parse->atom.pps_params.mode & (PPS_OFFSETCLEAR|PPS_OFFSETASSERT))
   3910 		        {
   3911 			        ppsphaseadjust = 0.0;
   3912 			}
   3913 #endif
   3914 
   3915 		/*
   3916 		 * we have a PPS signal - much better than the RS232 stuff (we hope)
   3917 		 */
   3918 		offset = parsetime->parse_ptime.fp;
   3919 
   3920 #ifdef DEBUG
   3921 		if (debug > 3)
   3922 			printf("PARSE receiver #%d: PPStime %s\n",
   3923 				CLK_UNIT(parse->peer),
   3924 				prettydate(&offset));
   3925 #endif
   3926 		if (PARSE_TIMECODE(parsetime->parse_state))
   3927 		{
   3928 			if (M_ISGEQ(off.l_i, off.l_f, -1, 0x80000000) &&
   3929 			    M_ISGEQ(0, 0x7fffffff, off.l_i, off.l_f))
   3930 			{
   3931 				fudge = ppsphaseadjust; /* pick PPS fudge factor */
   3932 
   3933 				/*
   3934 				 * RS232 offsets within [-0.5..0.5[ - take PPS offsets
   3935 				 */
   3936 
   3937 				if (parse->parse_type->cl_flags & PARSE_F_PPSONSECOND)
   3938 				{
   3939 					reftime = off = offset;
   3940 					if (reftime.l_uf & (unsigned)0x80000000)
   3941 						reftime.l_ui++;
   3942 					reftime.l_uf = 0;
   3943 
   3944 
   3945 					/*
   3946 					 * implied on second offset
   3947 					 */
   3948 					off.l_uf = ~off.l_uf; /* map [0.5..1[ -> [-0.5..0[ */
   3949 					off.l_ui = (off.l_f < 0) ? ~0 : 0; /* sign extend */
   3950 				}
   3951 				else
   3952 				{
   3953 					/*
   3954 					 * time code describes pulse
   3955 					 */
   3956 					reftime = off = parsetime->parse_time.fp;
   3957 
   3958 					L_SUB(&off, &offset); /* true offset */
   3959 				}
   3960 			}
   3961 			/*
   3962 			 * take RS232 offset when PPS when out of bounds
   3963 			 */
   3964 		}
   3965 		else
   3966 		{
   3967 			fudge = ppsphaseadjust; /* pick PPS fudge factor */
   3968 			/*
   3969 			 * Well, no time code to guide us - assume on second pulse
   3970 			 * and pray, that we are within [-0.5..0.5[
   3971 			 */
   3972 			off = offset;
   3973 			reftime = offset;
   3974 			if (reftime.l_uf & (unsigned)0x80000000)
   3975 				reftime.l_ui++;
   3976 			reftime.l_uf = 0;
   3977 			/*
   3978 			 * implied on second offset
   3979 			 */
   3980 			off.l_uf = ~off.l_uf; /* map [0.5..1[ -> [-0.5..0[ */
   3981 			off.l_ui = (off.l_f < 0) ? ~0 : 0; /* sign extend */
   3982 		}
   3983 	}
   3984 	else
   3985 	{
   3986 		if (!PARSE_TIMECODE(parsetime->parse_state))
   3987 		{
   3988 			/*
   3989 			 * Well, no PPS, no TIMECODE, no more work ...
   3990 			 */
   3991 			if ((parsetime->parse_status & CVT_ADDITIONAL) &&
   3992 			    parse->parse_type->cl_message)
   3993 				parse->parse_type->cl_message(parse, parsetime);
   3994 			return;
   3995 		}
   3996 	}
   3997 
   3998 #ifdef DEBUG
   3999 	if (debug > 3)
   4000 		printf("PARSE receiver #%d: Reftime %s, Recvtime %s - final offset %s\n",
   4001 			CLK_UNIT(parse->peer),
   4002 			prettydate(&reftime),
   4003 			prettydate(&rectime),
   4004 			lfptoa(&off,6));
   4005 #endif
   4006 
   4007 
   4008 	rectime = reftime;
   4009 	L_SUB(&rectime, &off);	/* just to keep the ntp interface happy */
   4010 
   4011 #ifdef DEBUG
   4012 	if (debug > 3)
   4013 		printf("PARSE receiver #%d: calculated Reftime %s, Recvtime %s\n",
   4014 			CLK_UNIT(parse->peer),
   4015 			prettydate(&reftime),
   4016 			prettydate(&rectime));
   4017 #endif
   4018 
   4019 	if ((parsetime->parse_status & CVT_ADDITIONAL) &&
   4020 	    parse->parse_type->cl_message)
   4021 		parse->parse_type->cl_message(parse, parsetime);
   4022 
   4023 	if (PARSE_SYNC(parsetime->parse_state))
   4024 	{
   4025 		/*
   4026 		 * log OK status
   4027 		 */
   4028 		parse_event(parse, CEVNT_NOMINAL);
   4029 	}
   4030 
   4031 	clear_err(parse, ERR_BADIO);
   4032 	clear_err(parse, ERR_BADDATA);
   4033 	clear_err(parse, ERR_NODATA);
   4034 	clear_err(parse, ERR_INTERNAL);
   4035 
   4036 	/*
   4037 	 * and now stick it into the clock machine
   4038 	 * samples are only valid iff lastsync is not too old and
   4039 	 * we have seen the clock in sync at least once
   4040 	 * after the last time we didn't see an expected data telegram
   4041 	 * at startup being not in sync is also bad just like
   4042 	 * POWERUP state unless PARSE_F_POWERUPTRUST is set
   4043 	 * see the clock states section above for more reasoning
   4044 	 */
   4045 	if (((current_time - parse->lastsync) > parse->maxunsync)           ||
   4046 	    (parse->lastsync < parse->lastmissed)                           ||
   4047 	    ((parse->lastsync == 0) && !PARSE_SYNC(parsetime->parse_state)) ||
   4048 	    (((parse->parse_type->cl_flags & PARSE_F_POWERUPTRUST) == 0) &&
   4049 	     PARSE_POWERUP(parsetime->parse_state)))
   4050 	{
   4051 		parse->generic->leap = LEAP_NOTINSYNC;
   4052 		parse->lastsync = 0;	/* wait for full sync again */
   4053 	}
   4054 	else
   4055 	{
   4056 		if (PARSE_LEAPADD(parsetime->parse_state))
   4057 		{
   4058 			/*
   4059 			 * we pick this state also for time code that pass leap warnings
   4060 			 * without direction information (as earth is currently slowing
   4061 			 * down).
   4062 			 */
   4063 			parse->generic->leap = (parse->flags & PARSE_LEAP_DELETE) ? LEAP_DELSECOND : LEAP_ADDSECOND;
   4064 		}
   4065 		else
   4066 		    if (PARSE_LEAPDEL(parsetime->parse_state))
   4067 		    {
   4068 			    parse->generic->leap = LEAP_DELSECOND;
   4069 		    }
   4070 		    else
   4071 		    {
   4072 			    parse->generic->leap = LEAP_NOWARNING;
   4073 		    }
   4074 	}
   4075 
   4076 	if (parse->generic->leap != LEAP_NOTINSYNC)
   4077 	{
   4078 	        /*
   4079 		 * only good/trusted samples are interesting
   4080 		 */
   4081 #ifdef DEBUG
   4082 	        if (debug > 2)
   4083 		        {
   4084 			        printf("PARSE receiver #%d: refclock_process_offset(reftime=%s, rectime=%s, Fudge=%f)\n",
   4085 				       CLK_UNIT(parse->peer),
   4086 				       prettydate(&reftime),
   4087 				       prettydate(&rectime),
   4088 				       fudge);
   4089 			}
   4090 #endif
   4091 		parse->generic->lastref = reftime;
   4092 
   4093 		refclock_process_offset(parse->generic, reftime, rectime, fudge);
   4094 
   4095 #ifdef HAVE_PPSAPI
   4096 		/*
   4097 		 * pass PPS information on to PPS clock
   4098 		 */
   4099 		if (PARSE_PPS(parsetime->parse_state) && CLK_PPS(parse->peer))
   4100 		        {
   4101 			  /* refclock_pps includes fudgetime1 - we keep the RS232 offset in there :-( */
   4102 			        double savedtime1 = parse->generic->fudgetime1;
   4103 
   4104 				parse->generic->fudgetime1 = fudge;
   4105 
   4106 				if (refclock_pps(parse->peer, &parse->atom,
   4107 						 parse->flags & (CLK_FLAG1|CLK_FLAG2|CLK_FLAG3|CLK_FLAG4))) {
   4108 					parse->peer->flags |= FLAG_PPS;
   4109 				} else {
   4110 					parse->peer->flags &= ~FLAG_PPS;
   4111 				}
   4112 
   4113 				parse->generic->fudgetime1 = savedtime1;
   4114 
   4115 				parse_hardpps(parse, PARSE_HARDPPS_ENABLE);
   4116 			}
   4117 #endif
   4118 	} else {
   4119 	        parse_hardpps(parse, PARSE_HARDPPS_DISABLE);
   4120 		parse->peer->flags &= ~FLAG_PPS;
   4121 	}
   4122 
   4123 	/*
   4124 	 * ready, unless the machine wants a sample or
   4125 	 * we are in fast startup mode (peer->dist > MAXDISTANCE)
   4126 	 */
   4127 	if (!parse->pollneeddata && parse->peer->disp <= MAXDISTANCE)
   4128 	    return;
   4129 
   4130 	parse->pollneeddata = 0;
   4131 
   4132 	parse->timedata.parse_state &= ~(unsigned)(PARSEB_PPS|PARSEB_S_PPS);
   4133 
   4134 	refclock_receive(parse->peer);
   4135 }
   4136 
   4137 /**===========================================================================
   4139  ** special code for special clocks
   4140  **/
   4141 
   4142 static void
   4143 mk_utcinfo(
   4144 	   char *t,
   4145 	   int wnt,
   4146 	   int wnlsf,
   4147 	   int dn,
   4148 	   int dtls,
   4149 	   int dtlsf,
   4150 	   int size
   4151 	   )
   4152 {
   4153   l_fp leapdate;
   4154   char *start = t;
   4155 
   4156   snprintf(t, size, "current correction %d sec", dtls);
   4157   t += strlen(t);
   4158 
   4159   if (wnlsf < 990)
   4160     wnlsf += 1024;
   4161 
   4162   if (wnt < 990)
   4163     wnt += 1024;
   4164 
   4165   gpstolfp((unsigned short)wnlsf, (unsigned short)dn, 0, &leapdate);
   4166 
   4167   if ((dtlsf != dtls) &&
   4168       ((wnlsf - wnt) < 52))
   4169     {
   4170 	    snprintf(t, BUFFER_SIZES(start, t, size), ", next correction %d sec on %s, new GPS-UTC offset %d",
   4171 	      dtlsf - dtls, gmprettydate(&leapdate), dtlsf);
   4172     }
   4173   else
   4174     {
   4175 	    snprintf(t, BUFFER_SIZES(start, t, size), ", last correction on %s",
   4176 	      gmprettydate(&leapdate));
   4177     }
   4178 }
   4179 
   4180 #ifdef CLOCK_MEINBERG
   4181 /**===========================================================================
   4182  ** Meinberg GPS166/GPS167 support
   4183  **/
   4184 
   4185 /*------------------------------------------------------------
   4186  * gps16x_message - process GPS16x messages
   4187  */
   4188 static void
   4189 gps16x_message(
   4190 	       struct parseunit *parse,
   4191 	       parsetime_t      *parsetime
   4192 	       )
   4193 {
   4194 	if (parse->timedata.parse_msglen && parsetime->parse_msg[0] == SOH)
   4195 	{
   4196 		GPS_MSG_HDR header;
   4197 		unsigned char *bufp = (unsigned char *)parsetime->parse_msg + 1;
   4198 
   4199 #ifdef DEBUG
   4200 		if (debug > 2)
   4201 		{
   4202 			char msgbuffer[600];
   4203 
   4204 			mkreadable(msgbuffer, sizeof(msgbuffer), (char *)parsetime->parse_msg, parsetime->parse_msglen, 1);
   4205 			printf("PARSE receiver #%d: received message (%d bytes) >%s<\n",
   4206 				CLK_UNIT(parse->peer),
   4207 				parsetime->parse_msglen,
   4208 				msgbuffer);
   4209 		}
   4210 #endif
   4211 		get_mbg_header(&bufp, &header);
   4212 		if (header.gps_hdr_csum == mbg_csum(parsetime->parse_msg + 1, 6) &&
   4213 		    (header.gps_len == 0 ||
   4214 		     (header.gps_len < sizeof(parsetime->parse_msg) &&
   4215 		      header.gps_data_csum == mbg_csum(bufp, header.gps_len))))
   4216 		{
   4217 			/*
   4218 			 * clean message
   4219 			 */
   4220 			switch (header.gps_cmd)
   4221 			{
   4222 			case GPS_SW_REV:
   4223 				{
   4224 					char buffer[64];
   4225 					SW_REV gps_sw_rev;
   4226 
   4227 					get_mbg_sw_rev(&bufp, &gps_sw_rev);
   4228 					snprintf(buffer, sizeof(buffer), "meinberg_gps_version=\"%x.%02x%s%s\"",
   4229 						(gps_sw_rev.code >> 8) & 0xFF,
   4230 						gps_sw_rev.code & 0xFF,
   4231 						gps_sw_rev.name[0] ? " " : "",
   4232 						gps_sw_rev.name);
   4233 					set_var(&parse->kv, buffer, strlen(buffer)+1, RO|DEF);
   4234 				}
   4235 			break;
   4236 
   4237 			case GPS_STAT:
   4238 				{
   4239 					static struct state
   4240 					{
   4241 						unsigned short flag; /* status flag */
   4242 						unsigned const char *string; /* bit name */
   4243 					} states[] =
   4244 					  {
   4245 						  { TM_ANT_DISCONN, (const unsigned char *)"ANTENNA FAULTY" },
   4246 						  { TM_SYN_FLAG,    (const unsigned char *)"NO SYNC SIGNAL" },
   4247 						  { TM_NO_SYNC,     (const unsigned char *)"NO SYNC POWERUP" },
   4248 						  { TM_NO_POS,      (const unsigned char *)"NO POSITION" },
   4249 						  { 0, (const unsigned char *)"" }
   4250 					  };
   4251 					unsigned short status;
   4252 					struct state *s = states;
   4253 					char buffer[512];
   4254 					char *p, *b;
   4255 
   4256 					status = get_lsb_short(&bufp);
   4257 					snprintf(buffer, sizeof(buffer), "meinberg_gps_status=\"[0x%04x] ", status);
   4258 
   4259 					if (status)
   4260 					{
   4261 						p = b = buffer + strlen(buffer);
   4262 						while (s->flag)
   4263 						{
   4264 							if (status & s->flag)
   4265 							{
   4266 								if (p != b)
   4267 								{
   4268 									*p++ = ',';
   4269 									*p++ = ' ';
   4270 								}
   4271 
   4272 								strncat(p, (const char *)s->string, sizeof(buffer));
   4273 							}
   4274 							s++;
   4275 						}
   4276 
   4277 						*p++ = '"';
   4278 						*p   = '\0';
   4279 					}
   4280 					else
   4281 					{
   4282 						strncat(buffer, "<OK>\"", sizeof(buffer));
   4283 					}
   4284 
   4285 					set_var(&parse->kv, buffer, strlen(buffer)+1, RO|DEF);
   4286 				}
   4287 			break;
   4288 
   4289 			case GPS_POS_XYZ:
   4290 				{
   4291 					XYZ xyz;
   4292 					char buffer[256];
   4293 
   4294 					get_mbg_xyz(&bufp, xyz);
   4295 					snprintf(buffer, sizeof(buffer), "gps_position(XYZ)=\"%s m, %s m, %s m\"",
   4296 						mfptoa(xyz[XP].l_ui, xyz[XP].l_uf, 1),
   4297 						mfptoa(xyz[YP].l_ui, xyz[YP].l_uf, 1),
   4298 						mfptoa(xyz[ZP].l_ui, xyz[ZP].l_uf, 1));
   4299 
   4300 					set_var(&parse->kv, buffer, sizeof(buffer), RO|DEF);
   4301 				}
   4302 			break;
   4303 
   4304 			case GPS_POS_LLA:
   4305 				{
   4306 					LLA lla;
   4307 					char buffer[256];
   4308 
   4309 					get_mbg_lla(&bufp, lla);
   4310 
   4311 					snprintf(buffer, sizeof(buffer), "gps_position(LLA)=\"%s deg, %s deg, %s m\"",
   4312 						mfptoa(lla[LAT].l_ui, lla[LAT].l_uf, 4),
   4313 						mfptoa(lla[LON].l_ui, lla[LON].l_uf, 4),
   4314 						mfptoa(lla[ALT].l_ui, lla[ALT].l_uf, 1));
   4315 
   4316 					set_var(&parse->kv, buffer, sizeof(buffer), RO|DEF);
   4317 				}
   4318 			break;
   4319 
   4320 			case GPS_TZDL:
   4321 				break;
   4322 
   4323 			case GPS_PORT_PARM:
   4324 				break;
   4325 
   4326 			case GPS_SYNTH:
   4327 				break;
   4328 
   4329 			case GPS_ANT_INFO:
   4330 				{
   4331 					ANT_INFO antinfo;
   4332 					char buffer[512];
   4333 					char *p;
   4334 
   4335 					get_mbg_antinfo(&bufp, &antinfo);
   4336 					snprintf(buffer, sizeof(buffer), "meinberg_antenna_status=\"");
   4337 					p = buffer + strlen(buffer);
   4338 
   4339 					switch (antinfo.status)
   4340 					{
   4341 					case ANT_INVALID:
   4342 						strncat(p, "<OK>", BUFFER_SIZE(buffer, p));
   4343 						p += strlen(p);
   4344 						break;
   4345 
   4346 					case ANT_DISCONN:
   4347 						strncat(p, "DISCONNECTED since ", BUFFER_SIZE(buffer, p));
   4348 						NLOG(NLOG_CLOCKSTATUS)
   4349 							ERR(ERR_BADSTATUS)
   4350 							msyslog(LOG_ERR,"PARSE receiver #%d: ANTENNA FAILURE: %s",
   4351 								CLK_UNIT(parse->peer), p);
   4352 
   4353 						p += strlen(p);
   4354 						mbg_tm_str(&p, &antinfo.tm_disconn, BUFFER_SIZE(buffer, p));
   4355 						*p = '\0';
   4356 						break;
   4357 
   4358 					case ANT_RECONN:
   4359 						strncat(p, "RECONNECTED on ", BUFFER_SIZE(buffer, p));
   4360 						p += strlen(p);
   4361 						mbg_tm_str(&p, &antinfo.tm_reconn, BUFFER_SIZE(buffer, p));
   4362 						snprintf(p, BUFFER_SIZE(buffer, p), ", reconnect clockoffset %c%ld.%07ld s, disconnect time ",
   4363 							(antinfo.delta_t < 0) ? '-' : '+',
   4364 							ABS(antinfo.delta_t) / 10000,
   4365 							ABS(antinfo.delta_t) % 10000);
   4366 						p += strlen(p);
   4367 						mbg_tm_str(&p, &antinfo.tm_disconn, BUFFER_SIZE(buffer, p));
   4368 						*p = '\0';
   4369 						break;
   4370 
   4371 					default:
   4372 						snprintf(p, BUFFER_SIZE(buffer, p), "bad status 0x%04x", antinfo.status);
   4373 						p += strlen(p);
   4374 						break;
   4375 					}
   4376 
   4377 					strncat(p, "\"", BUFFER_SIZE(buffer, p));
   4378 
   4379 					set_var(&parse->kv, buffer, strlen(buffer)+1, RO|DEF);
   4380 				}
   4381 			break;
   4382 
   4383 			case GPS_UCAP:
   4384 				break;
   4385 
   4386 			case GPS_CFGH:
   4387 				{
   4388 					CFGH cfgh;
   4389 					char buffer[512];
   4390 					char *p;
   4391 
   4392 					get_mbg_cfgh(&bufp, &cfgh);
   4393 					if (cfgh.valid)
   4394 					{
   4395 						int i;
   4396 
   4397 						p = buffer;
   4398 						strncpy(buffer, "gps_tot_51=\"", BUFFER_SIZE(buffer, p));
   4399 						p += strlen(p);
   4400 						mbg_tgps_str(&p, &cfgh.tot_51, BUFFER_SIZE(buffer, p));
   4401 						strncpy(p, "\"", BUFFER_SIZE(buffer, p));
   4402 						set_var(&parse->kv, buffer, strlen(buffer)+1, RO);
   4403 
   4404 						p = buffer;
   4405 						strncpy(buffer, "gps_tot_63=\"", BUFFER_SIZE(buffer, p));
   4406 						p += strlen(p);
   4407 						mbg_tgps_str(&p, &cfgh.tot_63, BUFFER_SIZE(buffer, p));
   4408 						strncpy(p, "\"", BUFFER_SIZE(buffer, p));
   4409 						set_var(&parse->kv, buffer, strlen(buffer)+1, RO);
   4410 
   4411 						p = buffer;
   4412 						strncpy(buffer, "gps_t0a=\"", BUFFER_SIZE(buffer, p));
   4413 						p += strlen(p);
   4414 						mbg_tgps_str(&p, &cfgh.t0a, BUFFER_SIZE(buffer, p));
   4415 						strncpy(p, "\"", BUFFER_SIZE(buffer, p));
   4416 						set_var(&parse->kv, buffer, strlen(buffer)+1, RO);
   4417 
   4418 						for (i = MIN_SVNO; i < MAX_SVNO; i++)
   4419 						{
   4420 							p = buffer;
   4421 							snprintf(p, BUFFER_SIZE(buffer, p), "gps_cfg[%d]=\"[0x%x] ", i, cfgh.cfg[i]);
   4422 							p += strlen(p);
   4423 							switch (cfgh.cfg[i] & 0x7)
   4424 							{
   4425 							case 0:
   4426 								strncpy(p, "BLOCK I", BUFFER_SIZE(buffer, p));
   4427 								break;
   4428 							case 1:
   4429 								strncpy(p, "BLOCK II", BUFFER_SIZE(buffer, p));
   4430 								break;
   4431 							default:
   4432 								strncpy(p, "bad CFG", BUFFER_SIZE(buffer, p));
   4433 								break;
   4434 							}
   4435 							strncat(p, "\"", BUFFER_SIZE(buffer, p));
   4436 							set_var(&parse->kv, buffer, strlen(buffer)+1, RO);
   4437 
   4438 							p = buffer;
   4439 							snprintf(p, BUFFER_SIZE(buffer, p), "gps_health[%d]=\"[0x%x] ", i, cfgh.health[i]);
   4440 							p += strlen(p);
   4441 							switch ((cfgh.health[i] >> 5) & 0x7 )
   4442 							{
   4443 							case 0:
   4444 								strncpy(p, "OK;", BUFFER_SIZE(buffer, p));
   4445 								break;
   4446 							case 1:
   4447 								strncpy(p, "PARITY;", BUFFER_SIZE(buffer, p));
   4448 								break;
   4449 							case 2:
   4450 								strncpy(p, "TLM/HOW;", BUFFER_SIZE(buffer, p));
   4451 								break;
   4452 							case 3:
   4453 								strncpy(p, "Z-COUNT;", BUFFER_SIZE(buffer, p));
   4454 								break;
   4455 							case 4:
   4456 								strncpy(p, "SUBFRAME 1,2,3;", BUFFER_SIZE(buffer, p));
   4457 								break;
   4458 							case 5:
   4459 								strncpy(p, "SUBFRAME 4,5;", BUFFER_SIZE(buffer, p));
   4460 								break;
   4461 							case 6:
   4462 								strncpy(p, "UPLOAD BAD;", BUFFER_SIZE(buffer, p));
   4463 								break;
   4464 							case 7:
   4465 								strncpy(p, "DATA BAD;", BUFFER_SIZE(buffer, p));
   4466 								break;
   4467 							}
   4468 
   4469 							p += strlen(p);
   4470 
   4471 							switch (cfgh.health[i] & 0x1F)
   4472 							{
   4473 							case 0:
   4474 								strncpy(p, "SIGNAL OK", BUFFER_SIZE(buffer, p));
   4475 								break;
   4476 							case 0x1C:
   4477 								strncpy(p, "SV TEMP OUT", BUFFER_SIZE(buffer, p));
   4478 								break;
   4479 							case 0x1D:
   4480 								strncpy(p, "SV WILL BE TEMP OUT", BUFFER_SIZE(buffer, p));
   4481 								break;
   4482 							case 0x1E:
   4483 								break;
   4484 							case 0x1F:
   4485 								strncpy(p, "MULTIPLE ERRS", BUFFER_SIZE(buffer, p));
   4486 								break;
   4487 							default:
   4488 								strncpy(p, "TRANSMISSION PROBLEMS", BUFFER_SIZE(buffer, p));
   4489 								break;
   4490 							}
   4491 
   4492 							strncat(p, "\"", sizeof(buffer));
   4493 							set_var(&parse->kv, buffer, strlen(buffer)+1, RO);
   4494 						}
   4495 					}
   4496 				}
   4497 			break;
   4498 
   4499 			case GPS_ALM:
   4500 				break;
   4501 
   4502 			case GPS_EPH:
   4503 				break;
   4504 
   4505 			case GPS_UTC:
   4506 				{
   4507 					UTC utc;
   4508 					char buffer[512];
   4509 					char *p;
   4510 
   4511 					p = buffer;
   4512 
   4513 					get_mbg_utc(&bufp, &utc);
   4514 
   4515 					if (utc.valid)
   4516 					{
   4517 						strncpy(p, "gps_utc_correction=\"", sizeof(buffer));
   4518 						p += strlen(p);
   4519 						mk_utcinfo(p, utc.t0t.wn, utc.WNlsf, utc.DNt, utc.delta_tls, utc.delta_tlsf, BUFFER_SIZE(buffer, p));
   4520 						strncat(p, "\"", BUFFER_SIZE(buffer, p));
   4521 					}
   4522 					else
   4523 					{
   4524 						strncpy(p, "gps_utc_correction=\"<NO UTC DATA>\"", BUFFER_SIZE(buffer, p));
   4525 					}
   4526 					set_var(&parse->kv, buffer, strlen(buffer)+1, RO|DEF);
   4527 				}
   4528 			break;
   4529 
   4530 			case GPS_IONO:
   4531 				break;
   4532 
   4533 			case GPS_ASCII_MSG:
   4534 				{
   4535 					ASCII_MSG gps_ascii_msg;
   4536 					char buffer[128];
   4537 
   4538 					get_mbg_ascii_msg(&bufp, &gps_ascii_msg);
   4539 
   4540 					if (gps_ascii_msg.valid)
   4541 						{
   4542 							char buffer1[128];
   4543 							mkreadable(buffer1, sizeof(buffer1), gps_ascii_msg.s, strlen(gps_ascii_msg.s), (int)0);
   4544 
   4545 							snprintf(buffer, sizeof(buffer), "gps_message=\"%s\"", buffer1);
   4546 						}
   4547 					else
   4548 						strncpy(buffer, "gps_message=<NONE>", sizeof(buffer));
   4549 
   4550 					set_var(&parse->kv, buffer, strlen(buffer)+1, RO|DEF);
   4551 				}
   4552 
   4553 			break;
   4554 
   4555 			default:
   4556 				break;
   4557 			}
   4558 		}
   4559 		else
   4560 		{
   4561 			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)",
   4562 				CLK_UNIT(parse->peer),
   4563 				header.gps_hdr_csum, mbg_csum(parsetime->parse_msg + 1, 6),
   4564 				header.gps_len,
   4565 				header.gps_data_csum, mbg_csum(bufp, (unsigned)((header.gps_len < sizeof(parsetime->parse_msg)) ? header.gps_len : 0)));
   4566 		}
   4567 	}
   4568 
   4569 	return;
   4570 }
   4571 
   4572 /*------------------------------------------------------------
   4573  * gps16x_poll - query the reciver peridically
   4574  */
   4575 static void
   4576 gps16x_poll(
   4577 	    struct peer *peer
   4578 	    )
   4579 {
   4580 	struct parseunit *parse = (struct parseunit *)peer->procptr->unitptr;
   4581 
   4582 	static GPS_MSG_HDR sequence[] =
   4583 	{
   4584 		{ GPS_SW_REV,          0, 0, 0 },
   4585 		{ GPS_STAT,            0, 0, 0 },
   4586 		{ GPS_UTC,             0, 0, 0 },
   4587 		{ GPS_ASCII_MSG,       0, 0, 0 },
   4588 		{ GPS_ANT_INFO,        0, 0, 0 },
   4589 		{ GPS_CFGH,            0, 0, 0 },
   4590 		{ GPS_POS_XYZ,         0, 0, 0 },
   4591 		{ GPS_POS_LLA,         0, 0, 0 },
   4592 		{ (unsigned short)~0,  0, 0, 0 }
   4593 	};
   4594 
   4595 	int rtc;
   4596 	unsigned char cmd_buffer[64];
   4597 	unsigned char *outp = cmd_buffer;
   4598 	GPS_MSG_HDR *header;
   4599 
   4600 	if (((poll_info_t *)parse->parse_type->cl_data)->rate)
   4601 	{
   4602 		parse->peer->nextaction = current_time + ((poll_info_t *)parse->parse_type->cl_data)->rate;
   4603 	}
   4604 
   4605 	if (sequence[parse->localstate].gps_cmd == (unsigned short)~0)
   4606 		parse->localstate = 0;
   4607 
   4608 	header = sequence + parse->localstate++;
   4609 
   4610 	*outp++ = SOH;		/* start command */
   4611 
   4612 	put_mbg_header(&outp, header);
   4613 	outp = cmd_buffer + 1;
   4614 
   4615 	header->gps_hdr_csum = (short)mbg_csum(outp, 6);
   4616 	put_mbg_header(&outp, header);
   4617 
   4618 #ifdef DEBUG
   4619 	if (debug > 2)
   4620 	{
   4621 		char buffer[128];
   4622 
   4623 		mkreadable(buffer, sizeof(buffer), (char *)cmd_buffer, (unsigned)(outp - cmd_buffer), 1);
   4624 		printf("PARSE receiver #%d: transmitted message #%ld (%d bytes) >%s<\n",
   4625 		       CLK_UNIT(parse->peer),
   4626 		       parse->localstate - 1,
   4627 		       (int)(outp - cmd_buffer),
   4628 		       buffer);
   4629 	}
   4630 #endif
   4631 
   4632 	rtc = write(parse->generic->io.fd, cmd_buffer, (unsigned long)(outp - cmd_buffer));
   4633 
   4634 	if (rtc < 0)
   4635 	{
   4636 		ERR(ERR_BADIO)
   4637 			msyslog(LOG_ERR, "PARSE receiver #%d: gps16x_poll: failed to send cmd to clock: %m", CLK_UNIT(parse->peer));
   4638 	}
   4639 	else
   4640 	if (rtc != outp - cmd_buffer)
   4641 	{
   4642 		ERR(ERR_BADIO)
   4643 			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));
   4644 	}
   4645 
   4646 	clear_err(parse, ERR_BADIO);
   4647 	return;
   4648 }
   4649 
   4650 /*--------------------------------------------------
   4651  * init routine - setup timer
   4652  */
   4653 static int
   4654 gps16x_poll_init(
   4655 	struct parseunit *parse
   4656 	)
   4657 {
   4658 	if (((poll_info_t *)parse->parse_type->cl_data)->rate)
   4659 	{
   4660 		parse->peer->action = gps16x_poll;
   4661 		gps16x_poll(parse->peer);
   4662 	}
   4663 
   4664 	return 0;
   4665 }
   4666 
   4667 #else
   4668 static void
   4669 gps16x_message(
   4670 	       struct parseunit *parse,
   4671 	       parsetime_t      *parsetime
   4672 	       )
   4673 {}
   4674 static int
   4675 gps16x_poll_init(
   4676 	struct parseunit *parse
   4677 	)
   4678 {
   4679 	return 1;
   4680 }
   4681 #endif /* CLOCK_MEINBERG */
   4682 
   4683 /**===========================================================================
   4685  ** clock polling support
   4686  **/
   4687 
   4688 /*--------------------------------------------------
   4689  * direct poll routine
   4690  */
   4691 static void
   4692 poll_dpoll(
   4693 	struct parseunit *parse
   4694 	)
   4695 {
   4696 	int rtc;
   4697 	const char *ps = ((poll_info_t *)parse->parse_type->cl_data)->string;
   4698 	int   ct = ((poll_info_t *)parse->parse_type->cl_data)->count;
   4699 
   4700 	rtc = write(parse->generic->io.fd, ps, (unsigned long)ct);
   4701 	if (rtc < 0)
   4702 	{
   4703 		ERR(ERR_BADIO)
   4704 			msyslog(LOG_ERR, "PARSE receiver #%d: poll_dpoll: failed to send cmd to clock: %m", CLK_UNIT(parse->peer));
   4705 	}
   4706 	else
   4707 	    if (rtc != ct)
   4708 	    {
   4709 		    ERR(ERR_BADIO)
   4710 			    msyslog(LOG_ERR, "PARSE receiver #%d: poll_dpoll: failed to send cmd incomplete (%d of %d bytes sent)", CLK_UNIT(parse->peer), rtc, ct);
   4711 	    }
   4712 	clear_err(parse, ERR_BADIO);
   4713 }
   4714 
   4715 /*--------------------------------------------------
   4716  * periodic poll routine
   4717  */
   4718 static void
   4719 poll_poll(
   4720 	struct peer *peer
   4721 	)
   4722 {
   4723 	struct parseunit *parse = (struct parseunit *)peer->procptr->unitptr;
   4724 
   4725 	if (parse->parse_type->cl_poll)
   4726 		parse->parse_type->cl_poll(parse);
   4727 
   4728 	if (((poll_info_t *)parse->parse_type->cl_data)->rate)
   4729 	{
   4730 		parse->peer->nextaction = current_time + ((poll_info_t *)parse->parse_type->cl_data)->rate;
   4731 	}
   4732 }
   4733 
   4734 /*--------------------------------------------------
   4735  * init routine - setup timer
   4736  */
   4737 static int
   4738 poll_init(
   4739 	struct parseunit *parse
   4740 	)
   4741 {
   4742 	if (((poll_info_t *)parse->parse_type->cl_data)->rate)
   4743 	{
   4744 		parse->peer->action = poll_poll;
   4745 		poll_poll(parse->peer);
   4746 	}
   4747 
   4748 	return 0;
   4749 }
   4750 
   4751 /**===========================================================================
   4753  ** Trimble support
   4754  **/
   4755 
   4756 /*-------------------------------------------------------------
   4757  * trimble TAIP init routine - setup EOL and then do poll_init.
   4758  */
   4759 static int
   4760 trimbletaip_init(
   4761 	struct parseunit *parse
   4762 	)
   4763 {
   4764 #ifdef HAVE_TERMIOS
   4765 	struct termios tio;
   4766 #endif
   4767 #ifdef HAVE_SYSV_TTYS
   4768 	struct termio tio;
   4769 #endif
   4770 	/*
   4771 	 * configure terminal line for trimble receiver
   4772 	 */
   4773 	if (TTY_GETATTR(parse->generic->io.fd, &tio) == -1)
   4774 	{
   4775 		msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_init: tcgetattr(fd, &tio): %m", CLK_UNIT(parse->peer));
   4776 		return 0;
   4777 	}
   4778 	else
   4779 	{
   4780 		tio.c_cc[VEOL] = TRIMBLETAIP_EOL;
   4781 
   4782 		if (TTY_SETATTR(parse->generic->io.fd, &tio) == -1)
   4783 		{
   4784 			msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_init: tcsetattr(fd, &tio): %m", CLK_UNIT(parse->peer));
   4785 			return 0;
   4786 		}
   4787 	}
   4788 	return poll_init(parse);
   4789 }
   4790 
   4791 /*--------------------------------------------------
   4792  * trimble TAIP event routine - reset receiver upon data format trouble
   4793  */
   4794 static const char *taipinit[] = {
   4795 	">FPV00000000<",
   4796 	">SRM;ID_FLAG=F;CS_FLAG=T;EC_FLAG=F;FR_FLAG=T;CR_FLAG=F<",
   4797 	">FTM00020001<",
   4798 	(char *)0
   4799 };
   4800 
   4801 static void
   4802 trimbletaip_event(
   4803 	struct parseunit *parse,
   4804 	int event
   4805 	)
   4806 {
   4807 	switch (event)
   4808 	{
   4809 	    case CEVNT_BADREPLY:	/* reset on garbled input */
   4810 	    case CEVNT_TIMEOUT:		/* reset on no input */
   4811 		    {
   4812 			    const char **iv;
   4813 
   4814 			    iv = taipinit;
   4815 			    while (*iv)
   4816 			    {
   4817 				    int rtc = write(parse->generic->io.fd, *iv, strlen(*iv));
   4818 				    if (rtc < 0)
   4819 				    {
   4820 					    msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_event: failed to send cmd to clock: %m", CLK_UNIT(parse->peer));
   4821 					    return;
   4822 				    }
   4823 				    else
   4824 				    {
   4825 					    if (rtc != strlen(*iv))
   4826 					    {
   4827 						    msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_event: failed to send cmd incomplete (%d of %d bytes sent)",
   4828 							    CLK_UNIT(parse->peer), rtc, (int)strlen(*iv));
   4829 						    return;
   4830 					    }
   4831 				    }
   4832 				    iv++;
   4833 			    }
   4834 
   4835 			    NLOG(NLOG_CLOCKINFO)
   4836 				    ERR(ERR_BADIO)
   4837 				    msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_event: RECEIVER INITIALIZED",
   4838 					    CLK_UNIT(parse->peer));
   4839 		    }
   4840 		    break;
   4841 
   4842 	    default:			/* ignore */
   4843 		break;
   4844 	}
   4845 }
   4846 
   4847 /*
   4848  * This driver supports the Trimble SVee Six Plus GPS receiver module.
   4849  * It should support other Trimble receivers which use the Trimble Standard
   4850  * Interface Protocol (see below).
   4851  *
   4852  * The module has a serial I/O port for command/data and a 1 pulse-per-second
   4853  * output, about 1 microsecond wide. The leading edge of the pulse is
   4854  * coincident with the change of the GPS second. This is the same as
   4855  * the change of the UTC second +/- ~1 microsecond. Some other clocks
   4856  * specifically use a feature in the data message as a timing reference, but
   4857  * the SVee Six Plus does not do this. In fact there is considerable jitter
   4858  * on the timing of the messages, so this driver only supports the use
   4859  * of the PPS pulse for accurate timing. Where it is determined that
   4860  * the offset is way off, when first starting up ntpd for example,
   4861  * the timing of the data stream is used until the offset becomes low enough
   4862  * (|offset| < CLOCK_MAX), at which point the pps offset is used.
   4863  *
   4864  * It can use either option for receiving PPS information - the 'ppsclock'
   4865  * stream pushed onto the serial data interface to timestamp the Carrier
   4866  * Detect interrupts, where the 1PPS connects to the CD line. This only
   4867  * works on SunOS 4.1.x currently. To select this, define PPSPPS in
   4868  * Config.local. The other option is to use a pulse-stretcher/level-converter
   4869  * to convert the PPS pulse into a RS232 start pulse & feed this into another
   4870  * tty port. To use this option, define PPSCLK in Config.local. The pps input,
   4871  * by whichever method, is handled in ntp_loopfilter.c
   4872  *
   4873  * The receiver uses a serial message protocol called Trimble Standard
   4874  * Interface Protocol (it can support others but this driver only supports
   4875  * TSIP). Messages in this protocol have the following form:
   4876  *
   4877  * <DLE><id> ... <data> ... <DLE><ETX>
   4878  *
   4879  * Any bytes within the <data> portion of value 10 hex (<DLE>) are doubled
   4880  * on transmission and compressed back to one on reception. Otherwise
   4881  * the values of data bytes can be anything. The serial interface is RS-422
   4882  * asynchronous using 9600 baud, 8 data bits with odd party (**note** 9 bits
   4883  * in total!), and 1 stop bit. The protocol supports byte, integer, single,
   4884  * and double datatypes. Integers are two bytes, sent most significant first.
   4885  * Singles are IEEE754 single precision floating point numbers (4 byte) sent
   4886  * sign & exponent first. Doubles are IEEE754 double precision floating point
   4887  * numbers (8 byte) sent sign & exponent first.
   4888  * The receiver supports a large set of messages, only a small subset of
   4889  * which are used here. From driver to receiver the following are used:
   4890  *
   4891  *  ID    Description
   4892  *
   4893  *  21    Request current time
   4894  *  22    Mode Select
   4895  *  2C    Set/Request operating parameters
   4896  *  2F    Request UTC info
   4897  *  35    Set/Request I/O options
   4898 
   4899  * From receiver to driver the following are recognised:
   4900  *
   4901  *  ID    Description
   4902  *
   4903  *  41    GPS Time
   4904  *  44    Satellite selection, PDOP, mode
   4905  *  46    Receiver health
   4906  *  4B    Machine code/status
   4907  *  4C    Report operating parameters (debug only)
   4908  *  4F    UTC correction data (used to get leap second warnings)
   4909  *  55    I/O options (debug only)
   4910  *
   4911  * All others are accepted but ignored.
   4912  *
   4913  */
   4914 
   4915 #define PI		3.1415926535898	/* lots of sig figs */
   4916 #define D2R		PI/180.0
   4917 
   4918 /*-------------------------------------------------------------------
   4919  * sendcmd, sendbyte, sendetx, sendflt, sendint implement the command
   4920  * interface to the receiver.
   4921  *
   4922  * CAVEAT: the sendflt, sendint routines are byte order dependend and
   4923  * float implementation dependend - these must be converted to portable
   4924  * versions !
   4925  *
   4926  * CURRENT LIMITATION: float implementation. This runs only on systems
   4927  * with IEEE754 floats as native floats
   4928  */
   4929 
   4930 typedef struct trimble
   4931 {
   4932 	u_long last_msg;	/* last message received */
   4933 	u_long last_reset;	/* last time a reset was issued */
   4934 	u_char qtracking;	/* query tracking status */
   4935 	u_long ctrack;		/* current tracking set */
   4936 	u_long ltrack;		/* last tracking set */
   4937 } trimble_t;
   4938 
   4939 union uval {
   4940 	u_char  bd[8];
   4941 	int     iv;
   4942 	float   fv;
   4943 	double  dv;
   4944 };
   4945 
   4946 struct txbuf
   4947 {
   4948 	short idx;			/* index to first unused byte */
   4949 	u_char *txt;			/* pointer to actual data buffer */
   4950 };
   4951 
   4952 void	sendcmd		(struct txbuf *buf, int c);
   4953 void	sendbyte	(struct txbuf *buf, int b);
   4954 void	sendetx		(struct txbuf *buf, struct parseunit *parse);
   4955 void	sendint		(struct txbuf *buf, int a);
   4956 void	sendflt		(struct txbuf *buf, double a);
   4957 
   4958 void
   4959 sendcmd(
   4960 	struct txbuf *buf,
   4961 	int c
   4962 	)
   4963 {
   4964 	buf->txt[0] = DLE;
   4965 	buf->txt[1] = (u_char)c;
   4966 	buf->idx = 2;
   4967 }
   4968 
   4969 void	sendcmd		(struct txbuf *buf, int c);
   4970 void	sendbyte	(struct txbuf *buf, int b);
   4971 void	sendetx		(struct txbuf *buf, struct parseunit *parse);
   4972 void	sendint		(struct txbuf *buf, int a);
   4973 void	sendflt		(struct txbuf *buf, double a);
   4974 
   4975 void
   4976 sendbyte(
   4977 	struct txbuf *buf,
   4978 	int b
   4979 	)
   4980 {
   4981 	if (b == DLE)
   4982 	    buf->txt[buf->idx++] = DLE;
   4983 	buf->txt[buf->idx++] = (u_char)b;
   4984 }
   4985 
   4986 void
   4987 sendetx(
   4988 	struct txbuf *buf,
   4989 	struct parseunit *parse
   4990 	)
   4991 {
   4992 	buf->txt[buf->idx++] = DLE;
   4993 	buf->txt[buf->idx++] = ETX;
   4994 
   4995 	if (write(parse->generic->io.fd, buf->txt, (unsigned long)buf->idx) != buf->idx)
   4996 	{
   4997 		ERR(ERR_BADIO)
   4998 			msyslog(LOG_ERR, "PARSE receiver #%d: sendetx: failed to send cmd to clock: %m", CLK_UNIT(parse->peer));
   4999 	}
   5000 	else
   5001 	{
   5002 #ifdef DEBUG
   5003 	  if (debug > 2)
   5004 	  {
   5005 		  char buffer[256];
   5006 
   5007 		  mkreadable(buffer, sizeof(buffer), (char *)buf->txt, (unsigned)buf->idx, 1);
   5008 		  printf("PARSE receiver #%d: transmitted message (%d bytes) >%s<\n",
   5009 			 CLK_UNIT(parse->peer),
   5010 			 buf->idx, buffer);
   5011 	  }
   5012 #endif
   5013 		clear_err(parse, ERR_BADIO);
   5014 	}
   5015 }
   5016 
   5017 void
   5018 sendint(
   5019 	struct txbuf *buf,
   5020 	int a
   5021 	)
   5022 {
   5023 	/* send 16bit int, msbyte first */
   5024 	sendbyte(buf, (u_char)((a>>8) & 0xff));
   5025 	sendbyte(buf, (u_char)(a & 0xff));
   5026 }
   5027 
   5028 void
   5029 sendflt(
   5030 	struct txbuf *buf,
   5031 	double a
   5032 	)
   5033 {
   5034 	int i;
   5035 	union uval uval;
   5036 
   5037 	uval.fv = a;
   5038 #ifdef WORDS_BIGENDIAN
   5039 	for (i=0; i<=3; i++)
   5040 #else
   5041 	    for (i=3; i>=0; i--)
   5042 #endif
   5043 		sendbyte(buf, uval.bd[i]);
   5044 }
   5045 
   5046 #define TRIM_POS_OPT	0x13	/* output position with high precision */
   5047 #define TRIM_TIME_OPT	0x03	/* use UTC time stamps, on second */
   5048 
   5049 /*--------------------------------------------------
   5050  * trimble TSIP setup routine
   5051  */
   5052 static int
   5053 trimbletsip_setup(
   5054 		  struct parseunit *parse,
   5055 		  const char *reason
   5056 		  )
   5057 {
   5058 	u_char buffer[256];
   5059 	struct txbuf buf;
   5060 	trimble_t *t = parse->localdata;
   5061 
   5062 	if (t && t->last_reset &&
   5063 	    ((t->last_reset + TRIMBLE_RESET_HOLDOFF) > current_time)) {
   5064 		return 1;	/* not yet */
   5065 	}
   5066 
   5067 	if (t)
   5068 		t->last_reset = current_time;
   5069 
   5070 	buf.txt = buffer;
   5071 
   5072 	sendcmd(&buf, CMD_CVERSION);	/* request software versions */
   5073 	sendetx(&buf, parse);
   5074 
   5075 	sendcmd(&buf, CMD_COPERPARAM);	/* set operating parameters */
   5076 	sendbyte(&buf, 4);	/* static */
   5077 	sendflt(&buf, 5.0*D2R);	/* elevation angle mask = 10 deg XXX */
   5078 	sendflt(&buf, 4.0);	/* s/n ratio mask = 6 XXX */
   5079 	sendflt(&buf, 12.0);	/* PDOP mask = 12 */
   5080 	sendflt(&buf, 8.0);	/* PDOP switch level = 8 */
   5081 	sendetx(&buf, parse);
   5082 
   5083 	sendcmd(&buf, CMD_CMODESEL);	/* fix mode select */
   5084 	sendbyte(&buf, 1);	/* time transfer mode */
   5085 	sendetx(&buf, parse);
   5086 
   5087 	sendcmd(&buf, CMD_CMESSAGE);	/* request system message */
   5088 	sendetx(&buf, parse);
   5089 
   5090 	sendcmd(&buf, CMD_CSUPER);	/* superpacket fix */
   5091 	sendbyte(&buf, 0x2);	/* binary mode */
   5092 	sendetx(&buf, parse);
   5093 
   5094 	sendcmd(&buf, CMD_CIOOPTIONS);	/* set I/O options */
   5095 	sendbyte(&buf, TRIM_POS_OPT);	/* position output */
   5096 	sendbyte(&buf, 0x00);	/* no velocity output */
   5097 	sendbyte(&buf, TRIM_TIME_OPT);	/* UTC, compute on seconds */
   5098 	sendbyte(&buf, 0x00);	/* no raw measurements */
   5099 	sendetx(&buf, parse);
   5100 
   5101 	sendcmd(&buf, CMD_CUTCPARAM);	/* request UTC correction data */
   5102 	sendetx(&buf, parse);
   5103 
   5104 	NLOG(NLOG_CLOCKINFO)
   5105 		ERR(ERR_BADIO)
   5106 		msyslog(LOG_ERR, "PARSE receiver #%d: trimbletsip_setup: RECEIVER RE-INITIALIZED (%s)", CLK_UNIT(parse->peer), reason);
   5107 
   5108 	return 0;
   5109 }
   5110 
   5111 /*--------------------------------------------------
   5112  * TRIMBLE TSIP check routine
   5113  */
   5114 static void
   5115 trimble_check(
   5116 	      struct peer *peer
   5117 	      )
   5118 {
   5119 	struct parseunit *parse = (struct parseunit *)peer->procptr->unitptr;
   5120 	trimble_t *t = parse->localdata;
   5121 	u_char buffer[256];
   5122 	struct txbuf buf;
   5123 	buf.txt = buffer;
   5124 
   5125 	if (t)
   5126 	{
   5127 		if (current_time > t->last_msg + TRIMBLETSIP_IDLE_TIME)
   5128 			(void)trimbletsip_setup(parse, "message timeout");
   5129 	}
   5130 
   5131 	poll_poll(parse->peer);	/* emit query string and re-arm timer */
   5132 
   5133 	if (t && t->qtracking)
   5134 	{
   5135 		u_long oldsats = t->ltrack & ~t->ctrack;
   5136 
   5137 		t->qtracking = 0;
   5138 		t->ltrack = t->ctrack;
   5139 
   5140 		if (oldsats)
   5141 		{
   5142 			int i;
   5143 
   5144 			for (i = 0; oldsats; i++) {
   5145 				if (oldsats & (1 << i))
   5146 					{
   5147 						sendcmd(&buf, CMD_CSTATTRACK);
   5148 						sendbyte(&buf, i+1);	/* old sat */
   5149 						sendetx(&buf, parse);
   5150 					}
   5151 				oldsats &= ~(1 << i);
   5152 			}
   5153 		}
   5154 
   5155 		sendcmd(&buf, CMD_CSTATTRACK);
   5156 		sendbyte(&buf, 0x00);	/* current tracking set */
   5157 		sendetx(&buf, parse);
   5158 	}
   5159 }
   5160 
   5161 /*--------------------------------------------------
   5162  * TRIMBLE TSIP end routine
   5163  */
   5164 static void
   5165 trimbletsip_end(
   5166 	      struct parseunit *parse
   5167 	      )
   5168 {	trimble_t *t = parse->localdata;
   5169 
   5170 	if (t)
   5171 	{
   5172 		free(t);
   5173 		parse->localdata = (void *)0;
   5174 	}
   5175 	parse->peer->nextaction = 0;
   5176 	parse->peer->action = (void (*) (struct peer *))0;
   5177 }
   5178 
   5179 /*--------------------------------------------------
   5180  * TRIMBLE TSIP init routine
   5181  */
   5182 static int
   5183 trimbletsip_init(
   5184 	struct parseunit *parse
   5185 	)
   5186 {
   5187 #if defined(VEOL) || defined(VEOL2)
   5188 #ifdef HAVE_TERMIOS
   5189 	struct termios tio;		/* NEEDED FOR A LONG TIME ! */
   5190 #endif
   5191 #ifdef HAVE_SYSV_TTYS
   5192 	struct termio tio;		/* NEEDED FOR A LONG TIME ! */
   5193 #endif
   5194 	/*
   5195 	 * allocate local data area
   5196 	 */
   5197 	if (!parse->localdata)
   5198 	{
   5199 		trimble_t *t;
   5200 
   5201 		t = (trimble_t *)(parse->localdata = emalloc(sizeof(trimble_t)));
   5202 
   5203 		if (t)
   5204 		{
   5205 			memset((char *)t, 0, sizeof(trimble_t));
   5206 			t->last_msg = current_time;
   5207 		}
   5208 	}
   5209 
   5210 	parse->peer->action     = trimble_check;
   5211 	parse->peer->nextaction = current_time;
   5212 
   5213 	/*
   5214 	 * configure terminal line for ICANON mode with VEOL characters
   5215 	 */
   5216 	if (TTY_GETATTR(parse->generic->io.fd, &tio) == -1)
   5217 	{
   5218 		msyslog(LOG_ERR, "PARSE receiver #%d: trimbletsip_init: tcgetattr(%d, &tio): %m", CLK_UNIT(parse->peer), parse->generic->io.fd);
   5219 		return 0;
   5220 	}
   5221 	else
   5222 	{
   5223 		if ((parse_clockinfo[CLK_TYPE(parse->peer)].cl_lflag & ICANON))
   5224 		{
   5225 #ifdef VEOL
   5226 			tio.c_cc[VEOL]  = ETX;
   5227 #endif
   5228 #ifdef VEOL2
   5229 			tio.c_cc[VEOL2]  = DLE;
   5230 #endif
   5231 		}
   5232 
   5233 		if (TTY_SETATTR(parse->generic->io.fd, &tio) == -1)
   5234 		{
   5235 			msyslog(LOG_ERR, "PARSE receiver #%d: trimbletsip_init: tcsetattr(%d, &tio): %m", CLK_UNIT(parse->peer), parse->generic->io.fd);
   5236 			return 0;
   5237 		}
   5238 	}
   5239 #endif
   5240 	return trimbletsip_setup(parse, "initial startup");
   5241 }
   5242 
   5243 /*------------------------------------------------------------
   5244  * trimbletsip_event - handle Trimble events
   5245  * simple evente handler - attempt to re-initialize receiver
   5246  */
   5247 static void
   5248 trimbletsip_event(
   5249 	struct parseunit *parse,
   5250 	int event
   5251 	)
   5252 {
   5253 	switch (event)
   5254 	{
   5255 	    case CEVNT_BADREPLY:	/* reset on garbled input */
   5256 	    case CEVNT_TIMEOUT:		/* reset on no input */
   5257 		    (void)trimbletsip_setup(parse, "event BAD_REPLY/TIMEOUT");
   5258 		    break;
   5259 
   5260 	    default:			/* ignore */
   5261 		break;
   5262 	}
   5263 }
   5264 
   5265 /*
   5266  * getflt, getint convert fields in the incoming data into the
   5267  * appropriate type of item
   5268  *
   5269  * CAVEAT: these routines are currently definitely byte order dependent
   5270  * and assume Representation(float) == IEEE754
   5271  * These functions MUST be converted to portable versions (especially
   5272  * converting the float representation into ntp_fp formats in order
   5273  * to avoid floating point operations at all!
   5274  */
   5275 
   5276 static float
   5277 getflt(
   5278 	u_char *bp
   5279 	)
   5280 {
   5281 	union uval uval;
   5282 
   5283 #ifdef WORDS_BIGENDIAN
   5284 	uval.bd[0] = *bp++;
   5285 	uval.bd[1] = *bp++;
   5286 	uval.bd[2] = *bp++;
   5287 	uval.bd[3] = *bp;
   5288 #else  /* ! WORDS_BIGENDIAN */
   5289 	uval.bd[3] = *bp++;
   5290 	uval.bd[2] = *bp++;
   5291 	uval.bd[1] = *bp++;
   5292 	uval.bd[0] = *bp;
   5293 #endif /* ! WORDS_BIGENDIAN */
   5294 	return uval.fv;
   5295 }
   5296 
   5297 static double
   5298 getdbl(
   5299 	u_char *bp
   5300 	)
   5301 {
   5302 	union uval uval;
   5303 
   5304 #ifdef WORDS_BIGENDIAN
   5305 	uval.bd[0] = *bp++;
   5306 	uval.bd[1] = *bp++;
   5307 	uval.bd[2] = *bp++;
   5308 	uval.bd[3] = *bp++;
   5309 	uval.bd[4] = *bp++;
   5310 	uval.bd[5] = *bp++;
   5311 	uval.bd[6] = *bp++;
   5312 	uval.bd[7] = *bp;
   5313 #else  /* ! WORDS_BIGENDIAN */
   5314 	uval.bd[7] = *bp++;
   5315 	uval.bd[6] = *bp++;
   5316 	uval.bd[5] = *bp++;
   5317 	uval.bd[4] = *bp++;
   5318 	uval.bd[3] = *bp++;
   5319 	uval.bd[2] = *bp++;
   5320 	uval.bd[1] = *bp++;
   5321 	uval.bd[0] = *bp;
   5322 #endif /* ! WORDS_BIGENDIAN */
   5323 	return uval.dv;
   5324 }
   5325 
   5326 static int
   5327 getshort(
   5328 	 unsigned char *p
   5329 	 )
   5330 {
   5331 	return get_msb_short(&p);
   5332 }
   5333 
   5334 /*--------------------------------------------------
   5335  * trimbletsip_message - process trimble messages
   5336  */
   5337 #define RTOD (180.0 / 3.1415926535898)
   5338 #define mb(_X_) (buffer[2+(_X_)]) /* shortcut for buffer access */
   5339 
   5340 static void
   5341 trimbletsip_message(
   5342 		    struct parseunit *parse,
   5343 		    parsetime_t      *parsetime
   5344 		    )
   5345 {
   5346 	unsigned char *buffer = parsetime->parse_msg;
   5347 	unsigned int   size   = parsetime->parse_msglen;
   5348 
   5349 	if ((size < 4) ||
   5350 	    (buffer[0]      != DLE) ||
   5351 	    (buffer[size-1] != ETX) ||
   5352 	    (buffer[size-2] != DLE))
   5353 	{
   5354 #ifdef DEBUG
   5355 		if (debug > 2) {
   5356 			int i;
   5357 
   5358 			printf("TRIMBLE BAD packet, size %d:\n	", size);
   5359 			for (i = 0; i < size; i++) {
   5360 				printf ("%2.2x, ", buffer[i]&0xff);
   5361 				if (i%16 == 15) printf("\n\t");
   5362 			}
   5363 			printf("\n");
   5364 		}
   5365 #endif
   5366 		return;
   5367 	}
   5368 	else
   5369 	{
   5370 		int var_flag;
   5371 		trimble_t *tr = parse->localdata;
   5372 		unsigned int cmd = buffer[1];
   5373 		char pbuffer[200];
   5374 		char *t = pbuffer;
   5375 		cmd_info_t *s;
   5376 
   5377 #ifdef DEBUG
   5378 		if (debug > 3) {
   5379 			int i;
   5380 
   5381 			printf("TRIMBLE packet 0x%02x, size %d:\n	", cmd, size);
   5382 			for (i = 0; i < size; i++) {
   5383 				printf ("%2.2x, ", buffer[i]&0xff);
   5384 				if (i%16 == 15) printf("\n\t");
   5385 			}
   5386 			printf("\n");
   5387 		}
   5388 #endif
   5389 
   5390 		if (tr)
   5391 			tr->last_msg = current_time;
   5392 
   5393 		s = trimble_convert(cmd, trimble_rcmds);
   5394 
   5395 		if (s)
   5396 		{
   5397 			snprintf(t, BUFFER_SIZE(pbuffer, t), "%s=\"", s->varname);
   5398 		}
   5399 		else
   5400 		{
   5401 			DPRINTF(1, ("TRIMBLE UNKNOWN COMMAND 0x%02x\n", cmd));
   5402 			return;
   5403 		}
   5404 
   5405 		var_flag = s->varmode;
   5406 
   5407 		t += strlen(t);
   5408 
   5409 		switch(cmd)
   5410 		{
   5411 		case CMD_RCURTIME:
   5412 			snprintf(t, BUFFER_SIZE(pbuffer, t), "%f, %d, %f",
   5413 				 getflt((unsigned char *)&mb(0)), getshort((unsigned char *)&mb(4)),
   5414 				 getflt((unsigned char *)&mb(6)));
   5415 			break;
   5416 
   5417 		case CMD_RBEST4:
   5418 			strncpy(t, "mode: ", BUFFER_SIZE(pbuffer, t));
   5419 			t += strlen(t);
   5420 			switch (mb(0) & 0xF)
   5421 			{
   5422 			default:
   5423 				snprintf(t, BUFFER_SIZE(pbuffer, t), "0x%x", mb(0) & 0x7);
   5424 				break;
   5425 
   5426 			case 1:
   5427 				strncpy(t, "0D", BUFFER_SIZE(pbuffer, t));
   5428 				break;
   5429 
   5430 			case 3:
   5431 				strncpy(t, "2D", BUFFER_SIZE(pbuffer, t));
   5432 				break;
   5433 
   5434 			case 4:
   5435 				strncpy(t, "3D", BUFFER_SIZE(pbuffer, t));
   5436 				break;
   5437 			}
   5438 			t += strlen(t);
   5439 			if (mb(0) & 0x10)
   5440 				strncpy(t, "-MANUAL, ", BUFFER_SIZE(pbuffer, t));
   5441 			else
   5442 				strncpy(t, "-AUTO, ", BUFFER_SIZE(pbuffer, t));
   5443 			t += strlen(t);
   5444 
   5445 			snprintf(t, BUFFER_SIZE(pbuffer, t), "satellites %02d %02d %02d %02d, PDOP %.2f, HDOP %.2f, VDOP %.2f, TDOP %.2f",
   5446 				mb(1), mb(2), mb(3), mb(4),
   5447 				getflt((unsigned char *)&mb(5)),
   5448 				getflt((unsigned char *)&mb(9)),
   5449 				getflt((unsigned char *)&mb(13)),
   5450 				getflt((unsigned char *)&mb(17)));
   5451 
   5452 			break;
   5453 
   5454 		case CMD_RVERSION:
   5455 			snprintf(t, BUFFER_SIZE(pbuffer, t), "%d.%d (%d/%d/%d)",
   5456 				mb(0)&0xff, mb(1)&0xff, 1900+(mb(4)&0xff), mb(2)&0xff, mb(3)&0xff);
   5457 			break;
   5458 
   5459 		case CMD_RRECVHEALTH:
   5460 		{
   5461 			static const char *msgs[] =
   5462 			{
   5463 				"Battery backup failed",
   5464 				"Signal processor error",
   5465 				"Alignment error, channel or chip 1",
   5466 				"Alignment error, channel or chip 2",
   5467 				"Antenna feed line fault",
   5468 				"Excessive ref freq. error",
   5469 				"<BIT 6>",
   5470 				"<BIT 7>"
   5471 			};
   5472 
   5473 			int i, bits;
   5474 
   5475 			switch (mb(0) & 0xFF)
   5476 			{
   5477 			default:
   5478 				snprintf(t, BUFFER_SIZE(pbuffer, t), "illegal value 0x%02x", mb(0) & 0xFF);
   5479 				break;
   5480 			case 0x00:
   5481 				strncpy(t, "doing position fixes", BUFFER_SIZE(pbuffer, t));
   5482 				break;
   5483 			case 0x01:
   5484 				strncpy(t, "no GPS time yet", BUFFER_SIZE(pbuffer, t));
   5485 				break;
   5486 			case 0x03:
   5487 				strncpy(t, "PDOP too high", BUFFER_SIZE(pbuffer, t));
   5488 				break;
   5489 			case 0x08:
   5490 				strncpy(t, "no usable satellites", BUFFER_SIZE(pbuffer, t));
   5491 				break;
   5492 			case 0x09:
   5493 				strncpy(t, "only ONE usable satellite", BUFFER_SIZE(pbuffer, t));
   5494 				break;
   5495 			case 0x0A:
   5496 				strncpy(t, "only TWO usable satellites", BUFFER_SIZE(pbuffer, t));
   5497 				break;
   5498 			case 0x0B:
   5499 				strncpy(t, "only THREE usable satellites", BUFFER_SIZE(pbuffer, t));
   5500 				break;
   5501 			case 0x0C:
   5502 				strncpy(t, "the chosen satellite is unusable", BUFFER_SIZE(pbuffer, t));
   5503 				break;
   5504 			}
   5505 
   5506 			t += strlen(t);
   5507 
   5508 			bits = mb(1) & 0xFF;
   5509 
   5510 			for (i = 0; i < 8; i++)
   5511 				if (bits & (0x1<<i))
   5512 				{
   5513 					snprintf(t, BUFFER_SIZE(pbuffer, t), ", %s", msgs[i]);
   5514 					t += strlen(t);
   5515 				}
   5516 		}
   5517 		break;
   5518 
   5519 		case CMD_RMESSAGE:
   5520 			mkreadable(t, (int)BUFFER_SIZE(pbuffer, t), (char *)&mb(0), (unsigned)(size - 2 - (&mb(0) - buffer)), 0);
   5521 			break;
   5522 
   5523 		case CMD_RMACHSTAT:
   5524 		{
   5525 			static const char *msgs[] =
   5526 			{
   5527 				"Synthesizer Fault",
   5528 				"Battery Powered Time Clock Fault",
   5529 				"A-to-D Converter Fault",
   5530 				"The almanac stored in the receiver is not complete and current",
   5531 				"<BIT 4>",
   5532 				"<BIT 5",
   5533 				"<BIT 6>",
   5534 				"<BIT 7>"
   5535 			};
   5536 
   5537 			int i, bits;
   5538 
   5539 			snprintf(t, BUFFER_SIZE(pbuffer, t), "machine id 0x%02x", mb(0) & 0xFF);
   5540 			t += strlen(t);
   5541 
   5542 			bits = mb(1) & 0xFF;
   5543 
   5544 			for (i = 0; i < 8; i++)
   5545 				if (bits & (0x1<<i))
   5546 				{
   5547 					snprintf(t, BUFFER_SIZE(pbuffer, t), ", %s", msgs[i]);
   5548 					t += strlen(t);
   5549 				}
   5550 
   5551 			snprintf(t, BUFFER_SIZE(pbuffer, t), ", Superpackets %ssupported", (mb(2) & 0xFF) ? "" :"un" );
   5552 		}
   5553 		break;
   5554 
   5555 		case CMD_ROPERPARAM:
   5556 			snprintf(t, BUFFER_SIZE(pbuffer, t), "%2x %.1f %.1f %.1f %.1f",
   5557 				mb(0), getflt((unsigned char *)&mb(1)), getflt((unsigned char *)&mb(5)),
   5558 				getflt((unsigned char *)&mb(9)), getflt((unsigned char *)&mb(13)));
   5559 			break;
   5560 
   5561 		case CMD_RUTCPARAM:
   5562 		{
   5563 			float t0t = getflt((unsigned char *)&mb(14));
   5564 			short wnt = getshort((unsigned char *)&mb(18));
   5565 			short dtls = getshort((unsigned char *)&mb(12));
   5566 			short wnlsf = getshort((unsigned char *)&mb(20));
   5567 			short dn = getshort((unsigned char *)&mb(22));
   5568 			short dtlsf = getshort((unsigned char *)&mb(24));
   5569 
   5570 			if ((int)t0t != 0)
   5571 			  {
   5572 				  mk_utcinfo(t, wnt, wnlsf, dn, dtls, dtlsf, BUFFER_SIZE(pbuffer, t));
   5573 			  }
   5574 			else
   5575 			  {
   5576 			    strncpy(t, "<NO UTC DATA>", BUFFER_SIZE(pbuffer, t));
   5577 			  }
   5578 		}
   5579 		break;
   5580 
   5581 		case CMD_RSAT1BIAS:
   5582 			snprintf(t, BUFFER_SIZE(pbuffer, t), "%.1fm %.2fm/s at %.1fs",
   5583 				getflt(&mb(0)), getflt(&mb(4)), getflt(&mb(8)));
   5584 			break;
   5585 
   5586 		case CMD_RIOOPTIONS:
   5587 		{
   5588 			snprintf(t, BUFFER_SIZE(pbuffer, t), "%02x %02x %02x %02x",
   5589 				mb(0), mb(1), mb(2), mb(3));
   5590 			if (mb(0) != TRIM_POS_OPT ||
   5591 			    mb(2) != TRIM_TIME_OPT)
   5592 			{
   5593 				(void)trimbletsip_setup(parse, "bad io options");
   5594 			}
   5595 		}
   5596 		break;
   5597 
   5598 		case CMD_RSPOSXYZ:
   5599 		{
   5600 			double x = getflt((unsigned char *)&mb(0));
   5601 			double y = getflt((unsigned char *)&mb(4));
   5602 			double z = getflt((unsigned char *)&mb(8));
   5603 			double f = getflt((unsigned char *)&mb(12));
   5604 
   5605 			if (f > 0.0)
   5606 			  snprintf(t, BUFFER_SIZE(pbuffer, t), "x= %.1fm, y= %.1fm, z= %.1fm, time_of_fix= %f sec",
   5607 				  x, y, z,
   5608 				  f);
   5609 			else
   5610 			  return;
   5611 		}
   5612 		break;
   5613 
   5614 		case CMD_RSLLAPOS:
   5615 		{
   5616 			double lat = getflt((unsigned char *)&mb(0));
   5617 			double lng = getflt((unsigned char *)&mb(4));
   5618 			double f   = getflt((unsigned char *)&mb(12));
   5619 
   5620 			if (f > 0.0)
   5621 			  snprintf(t, BUFFER_SIZE(pbuffer, t), "lat %f %c, long %f %c, alt %.2fm",
   5622 				  ((lat < 0.0) ? (-lat) : (lat))*RTOD, (lat < 0.0 ? 'S' : 'N'),
   5623 				  ((lng < 0.0) ? (-lng) : (lng))*RTOD, (lng < 0.0 ? 'W' : 'E'),
   5624 				  getflt((unsigned char *)&mb(8)));
   5625 			else
   5626 			  return;
   5627 		}
   5628 		break;
   5629 
   5630 		case CMD_RDOUBLEXYZ:
   5631 		{
   5632 			double x = getdbl((unsigned char *)&mb(0));
   5633 			double y = getdbl((unsigned char *)&mb(8));
   5634 			double z = getdbl((unsigned char *)&mb(16));
   5635 			snprintf(t, BUFFER_SIZE(pbuffer, t), "x= %.1fm, y= %.1fm, z= %.1fm",
   5636 				x, y, z);
   5637 		}
   5638 		break;
   5639 
   5640 		case CMD_RDOUBLELLA:
   5641 		{
   5642 			double lat = getdbl((unsigned char *)&mb(0));
   5643 			double lng = getdbl((unsigned char *)&mb(8));
   5644 			snprintf(t, BUFFER_SIZE(pbuffer, t), "lat %f %c, lon %f %c, alt %.2fm",
   5645 				((lat < 0.0) ? (-lat) : (lat))*RTOD, (lat < 0.0 ? 'S' : 'N'),
   5646 				((lng < 0.0) ? (-lng) : (lng))*RTOD, (lng < 0.0 ? 'W' : 'E'),
   5647 				getdbl((unsigned char *)&mb(16)));
   5648 		}
   5649 		break;
   5650 
   5651 		case CMD_RALLINVIEW:
   5652 		{
   5653 			int i, sats;
   5654 
   5655 			strncpy(t, "mode: ", BUFFER_SIZE(pbuffer, t));
   5656 			t += strlen(t);
   5657 			switch (mb(0) & 0x7)
   5658 			{
   5659 			default:
   5660 				snprintf(t, BUFFER_SIZE(pbuffer, t), "0x%x", mb(0) & 0x7);
   5661 				break;
   5662 
   5663 			case 3:
   5664 				strncpy(t, "2D", BUFFER_SIZE(pbuffer, t));
   5665 				break;
   5666 
   5667 			case 4:
   5668 				strncpy(t, "3D", BUFFER_SIZE(pbuffer, t));
   5669 				break;
   5670 			}
   5671 			t += strlen(t);
   5672 			if (mb(0) & 0x8)
   5673 				strncpy(t, "-MANUAL, ", BUFFER_SIZE(pbuffer, t));
   5674 			else
   5675 				strncpy(t, "-AUTO, ", BUFFER_SIZE(pbuffer, t));
   5676 			t += strlen(t);
   5677 
   5678 			sats = (mb(0)>>4) & 0xF;
   5679 
   5680 			snprintf(t, BUFFER_SIZE(pbuffer, t), "PDOP %.2f, HDOP %.2f, VDOP %.2f, TDOP %.2f, %d satellite%s in view: ",
   5681 				getflt((unsigned char *)&mb(1)),
   5682 				getflt((unsigned char *)&mb(5)),
   5683 				getflt((unsigned char *)&mb(9)),
   5684 				getflt((unsigned char *)&mb(13)),
   5685 				sats, (sats == 1) ? "" : "s");
   5686 			t += strlen(t);
   5687 
   5688 			for (i=0; i < sats; i++)
   5689 			{
   5690 				snprintf(t, BUFFER_SIZE(pbuffer, t), "%s%02d", i ? ", " : "", mb(17+i));
   5691 				t += strlen(t);
   5692 				if (tr)
   5693 					tr->ctrack |= (1 << (mb(17+i)-1));
   5694 			}
   5695 
   5696 			if (tr)
   5697                         { /* mark for tracking status query */
   5698 				tr->qtracking = 1;
   5699 			}
   5700 		}
   5701 		break;
   5702 
   5703 		case CMD_RSTATTRACK:
   5704 		{
   5705 			snprintf(t-2, BUFFER_SIZE(pbuffer, t-2), "[%02d]=\"", mb(0)); /* add index to var name */
   5706 			t += strlen(t);
   5707 
   5708 			if (getflt((unsigned char *)&mb(4)) < 0.0)
   5709 			{
   5710 				strncpy(t, "<NO MEASUREMENTS>", BUFFER_SIZE(pbuffer, t));
   5711 				var_flag &= ~DEF;
   5712 			}
   5713 			else
   5714 			{
   5715 				snprintf(t, BUFFER_SIZE(pbuffer, t), "ch=%d, acq=%s, eph=%d, signal_level= %5.2f, elevation= %5.2f, azimuth= %6.2f",
   5716 					(mb(1) & 0xFF)>>3,
   5717 					mb(2) ? ((mb(2) == 1) ? "ACQ" : "SRCH") : "NEVER",
   5718 					mb(3),
   5719 					getflt((unsigned char *)&mb(4)),
   5720 					getflt((unsigned char *)&mb(12)) * RTOD,
   5721 					getflt((unsigned char *)&mb(16)) * RTOD);
   5722 				t += strlen(t);
   5723 				if (mb(20))
   5724 				{
   5725 					var_flag &= ~DEF;
   5726 					strncpy(t, ", OLD", BUFFER_SIZE(pbuffer, t));
   5727 				}
   5728 				t += strlen(t);
   5729 				if (mb(22))
   5730 				{
   5731 					if (mb(22) == 1)
   5732 						strncpy(t, ", BAD PARITY", BUFFER_SIZE(pbuffer, t));
   5733 					else
   5734 						if (mb(22) == 2)
   5735 							strncpy(t, ", BAD EPH HEALTH", BUFFER_SIZE(pbuffer, t));
   5736 				}
   5737 				t += strlen(t);
   5738 				if (mb(23))
   5739 					strncpy(t, ", collecting data", BUFFER_SIZE(pbuffer, t));
   5740 			}
   5741 		}
   5742 		break;
   5743 
   5744 		default:
   5745 			strncpy(t, "<UNDECODED>", BUFFER_SIZE(pbuffer, t));
   5746 			break;
   5747 		}
   5748 		t += strlen(t);
   5749 
   5750 		strncpy(t,"\"", BUFFER_SIZE(pbuffer, t));
   5751 		set_var(&parse->kv, pbuffer, sizeof(pbuffer), var_flag);
   5752 	}
   5753 }
   5754 
   5755 
   5756 /**============================================================
   5758  ** RAWDCF support
   5759  **/
   5760 
   5761 /*--------------------------------------------------
   5762  * rawdcf_init_1 - set up modem lines for RAWDCF receivers
   5763  * SET DTR line
   5764  */
   5765 #if defined(TIOCMSET) && (defined(TIOCM_DTR) || defined(CIOCM_DTR))
   5766 static int
   5767 rawdcf_init_1(
   5768 	struct parseunit *parse
   5769 	)
   5770 {
   5771 	/* fixed 2000 for using with Linux by Wolfram Pienkoss <wp (at) bszh.de> */
   5772 	/*
   5773 	 * You can use the RS232 to supply the power for a DCF77 receiver.
   5774 	 * Here a voltage between the DTR and the RTS line is used. Unfortunately
   5775 	 * the name has changed from CIOCM_DTR to TIOCM_DTR recently.
   5776 	 */
   5777 	int sl232;
   5778 
   5779 	if (ioctl(parse->generic->io.fd, TIOCMGET, (caddr_t)&sl232) == -1)
   5780 	{
   5781 		msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_1: WARNING: ioctl(fd, TIOCMGET, [C|T]IOCM_DTR): %m", CLK_UNIT(parse->peer));
   5782 		return 0;
   5783 	}
   5784 
   5785 #ifdef TIOCM_DTR
   5786 	sl232 = (sl232 & ~TIOCM_RTS) | TIOCM_DTR;	/* turn on DTR, clear RTS for power supply */
   5787 #else
   5788 	sl232 = (sl232 & ~CIOCM_RTS) | CIOCM_DTR;	/* turn on DTR, clear RTS for power supply */
   5789 #endif
   5790 
   5791 	if (ioctl(parse->generic->io.fd, TIOCMSET, (caddr_t)&sl232) == -1)
   5792 	{
   5793 		msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_1: WARNING: ioctl(fd, TIOCMSET, [C|T]IOCM_DTR): %m", CLK_UNIT(parse->peer));
   5794 	}
   5795 	return 0;
   5796 }
   5797 #else
   5798 static int
   5799 rawdcfdtr_init_1(
   5800 	struct parseunit *parse
   5801 	)
   5802 {
   5803 	msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_1: WARNING: OS interface incapable of setting DTR to power DCF modules", CLK_UNIT(parse->peer));
   5804 	return 0;
   5805 }
   5806 #endif  /* DTR initialisation type */
   5807 
   5808 /*--------------------------------------------------
   5809  * rawdcf_init_2 - set up modem lines for RAWDCF receivers
   5810  * CLR DTR line, SET RTS line
   5811  */
   5812 #if defined(TIOCMSET) &&  (defined(TIOCM_RTS) || defined(CIOCM_RTS))
   5813 static int
   5814 rawdcf_init_2(
   5815 	struct parseunit *parse
   5816 	)
   5817 {
   5818 	/* fixed 2000 for using with Linux by Wolfram Pienkoss <wp (at) bszh.de> */
   5819 	/*
   5820 	 * You can use the RS232 to supply the power for a DCF77 receiver.
   5821 	 * Here a voltage between the DTR and the RTS line is used. Unfortunately
   5822 	 * the name has changed from CIOCM_DTR to TIOCM_DTR recently.
   5823 	 */
   5824 	int sl232;
   5825 
   5826 	if (ioctl(parse->generic->io.fd, TIOCMGET, (caddr_t)&sl232) == -1)
   5827 	{
   5828 		msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_2: WARNING: ioctl(fd, TIOCMGET, [C|T]IOCM_RTS): %m", CLK_UNIT(parse->peer));
   5829 		return 0;
   5830 	}
   5831 
   5832 #ifdef TIOCM_RTS
   5833 	sl232 = (sl232 & ~TIOCM_DTR) | TIOCM_RTS;	/* turn on RTS, clear DTR for power supply */
   5834 #else
   5835 	sl232 = (sl232 & ~CIOCM_DTR) | CIOCM_RTS;	/* turn on RTS, clear DTR for power supply */
   5836 #endif
   5837 
   5838 	if (ioctl(parse->generic->io.fd, TIOCMSET, (caddr_t)&sl232) == -1)
   5839 	{
   5840 		msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_2: WARNING: ioctl(fd, TIOCMSET, [C|T]IOCM_RTS): %m", CLK_UNIT(parse->peer));
   5841 	}
   5842 	return 0;
   5843 }
   5844 #else
   5845 static int
   5846 rawdcf_init_2(
   5847 	struct parseunit *parse
   5848 	)
   5849 {
   5850 	msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_2: WARNING: OS interface incapable of setting RTS to power DCF modules", CLK_UNIT(parse->peer));
   5851 	return 0;
   5852 }
   5853 #endif  /* DTR initialisation type */
   5854 
   5855 #else	/* defined(REFCLOCK) && defined(PARSE) */
   5856 int refclock_parse_bs;
   5857 #endif	/* defined(REFCLOCK) && defined(PARSE) */
   5858 
   5859 /*
   5860  * History:
   5861  *
   5862  * refclock_parse.c,v
   5863  * Revision 4.81  2009/05/01 10:15:29  kardel
   5864  * use new refclock_ppsapi interface
   5865  *
   5866  * Revision 4.80  2007/08/11 12:06:29  kardel
   5867  * update comments wrt/ to PPS
   5868  *
   5869  * Revision 4.79  2007/08/11 11:52:23  kardel
   5870  * - terminate io bindings before io_closeclock() will close our file descriptor
   5871  *
   5872  * Revision 4.78  2006/12/22 20:08:27  kardel
   5873  * Bug 746 (RFE): add configuration for Expert mouseCLOCK USB v2.0 as mode 19
   5874  *
   5875  * Revision 4.77  2006/08/05 07:44:49  kardel
   5876  * support optionally separate PPS devices via /dev/refclockpps-{0..3}
   5877  *
   5878  * Revision 4.76  2006/06/22 18:40:47  kardel
   5879  * clean up signedness (gcc 4)
   5880  *
   5881  * Revision 4.75  2006/06/22 16:58:10  kardel
   5882  * Bug #632: call parse_ppsapi() in parse_ctl() when updating
   5883  * the PPS offset. Fix sign of offset passed to kernel.
   5884  *
   5885  * Revision 4.74  2006/06/18 21:18:37  kardel
   5886  * NetBSD Coverity CID 3796: possible NULL deref
   5887  *
   5888  * Revision 4.73  2006/05/26 14:23:46  kardel
   5889  * cleanup of copyright info
   5890  *
   5891  * Revision 4.72  2006/05/26 14:19:43  kardel
   5892  * cleanup of ioctl cruft
   5893  *
   5894  * Revision 4.71  2006/05/26 14:15:57  kardel
   5895  * delay adding refclock to async refclock io after all initializations
   5896  *
   5897  * Revision 4.70  2006/05/25 18:20:50  kardel
   5898  * bug #619
   5899  * terminate parse io engine after de-registering
   5900  * from refclock io engine
   5901  *
   5902  * Revision 4.69  2006/05/25 17:28:02  kardel
   5903  * complete refclock io structure initialization *before* inserting it into the
   5904  * refclock input machine (avoids null pointer deref) (bug #619)
   5905  *
   5906  * Revision 4.68  2006/05/01 17:02:51  kardel
   5907  * copy receiver method also for newlwy created receive buffers
   5908  *
   5909  * Revision 4.67  2006/05/01 14:37:29  kardel
   5910  * If an input buffer parses into more than one message do insert the
   5911  * parsed message in a new input buffer instead of processing it
   5912  * directly. This avoids deed complicated processing in signal
   5913  * handling.
   5914  *
   5915  * Revision 4.66  2006/03/18 00:45:30  kardel
   5916  * coverity fixes found in NetBSD coverity scan
   5917  *
   5918  * Revision 4.65  2006/01/26 06:08:33  kardel
   5919  * output errno on PPS setup failure
   5920  *
   5921  * Revision 4.64  2005/11/09 20:44:47  kardel
   5922  * utilize full PPS timestamp resolution from PPS API
   5923  *
   5924  * Revision 4.63  2005/10/07 22:10:25  kardel
   5925  * bounded buffer implementation
   5926  *
   5927  * Revision 4.62.2.2  2005/09/25 10:20:16  kardel
   5928  * avoid unexpected buffer overflows due to sprintf("%f") on strange floats:
   5929  * replace almost all str* and *printf functions be their buffer bounded
   5930  * counterparts
   5931  *
   5932  * Revision 4.62.2.1  2005/08/27 16:19:27  kardel
   5933  * limit re-set rate of trimble clocks
   5934  *
   5935  * Revision 4.62  2005/08/06 17:40:00  kardel
   5936  * cleanup size handling wrt/ to buffer boundaries
   5937  *
   5938  * Revision 4.61  2005/07/27 21:16:19  kardel
   5939  * fix a long (> 11 years) misconfiguration wrt/ Meinberg cflag factory
   5940  * default setup. CSTOPB was missing for the 7E2 default data format of
   5941  * the DCF77 clocks.
   5942  *
   5943  * Revision 4.60  2005/07/17 21:14:44  kardel
   5944  * change contents of version string to include the RCS/CVS Id
   5945  *
   5946  * Revision 4.59  2005/07/06 06:56:38  kardel
   5947  * syntax error
   5948  *
   5949  * Revision 4.58  2005/07/04 13:10:40  kardel
   5950  * fix bug 455: tripping over NULL pointer on cleanup
   5951  * fix shadow storage logic for ppsphaseadjust and trustime wrt/ time2
   5952  * fix compiler warnings for some platforms wrt/ printf formatstrings and
   5953  *     varying structure element sizes
   5954  * reorder assignment in binding to avoid tripping over NULL pointers
   5955  *
   5956  * Revision 4.57  2005/06/25 09:25:19  kardel
   5957  * sort out log output sequence
   5958  *
   5959  * Revision 4.56  2005/06/14 21:47:27  kardel
   5960  * collect samples only if samples are ok (sync or trusted flywheel)
   5961  * propagate pps phase adjustment value to kernel via PPSAPI to help HARDPPS
   5962  * en- and dis-able HARDPPS in correlation to receiver sync state
   5963  *
   5964  * Revision 4.55  2005/06/02 21:28:31  kardel
   5965  * clarify trust logic
   5966  *
   5967  * Revision 4.54  2005/06/02 17:06:49  kardel
   5968  * change status reporting to use fixed refclock_report()
   5969  *
   5970  * Revision 4.53  2005/06/02 16:33:31  kardel
   5971  * fix acceptance of clocks unsync clocks right at start
   5972  *
   5973  * Revision 4.52  2005/05/26 21:55:06  kardel
   5974  * cleanup status reporting
   5975  *
   5976  * Revision 4.51  2005/05/26 19:19:14  kardel
   5977  * implement fast refclock startup
   5978  *
   5979  * Revision 4.50  2005/04/16 20:51:35  kardel
   5980  * set pps_enable = 1 when binding a kernel PPS source
   5981  *
   5982  * Revision 4.49  2005/04/16 17:29:26  kardel
   5983  * add non polling clock type 18 for just listenning to Meinberg clocks
   5984  *
   5985  * Revision 4.48  2005/04/16 16:22:27  kardel
   5986  * bk sync 20050415 ntp-dev
   5987  *
   5988  * Revision 4.47  2004/11/29 10:42:48  kardel
   5989  * bk sync ntp-dev 20041129
   5990  *
   5991  * Revision 4.46  2004/11/29 10:26:29  kardel
   5992  * keep fudgetime2 in sync with trusttime/ppsphaseadjust depending in flag1
   5993  *
   5994  * Revision 4.45  2004/11/14 20:53:20  kardel
   5995  * clear PPS flags after using them
   5996  *
   5997  * Revision 4.44  2004/11/14 15:29:41  kardel
   5998  * support PPSAPI, upgrade Copyright to Berkeley style
   5999  *
   6000  * Revision 4.43  2001/05/26 22:53:16  kardel
   6001  * 20010526 reconcilation
   6002  *
   6003  * Revision 4.42  2000/05/14 15:31:51  kardel
   6004  * PPSAPI && RAWDCF modemline support
   6005  *
   6006  * Revision 4.41  2000/04/09 19:50:45  kardel
   6007  * fixed rawdcfdtr_init() -> rawdcf_init_1
   6008  *
   6009  * Revision 4.40  2000/04/09 15:27:55  kardel
   6010  * modem line fiddle in rawdcf_init_2
   6011  *
   6012  * Revision 4.39  2000/03/18 09:16:55  kardel
   6013  * PPSAPI integration
   6014  *
   6015  * Revision 4.38  2000/03/05 20:25:06  kardel
   6016  * support PPSAPI
   6017  *
   6018  * Revision 4.37  2000/03/05 20:11:14  kardel
   6019  * 4.0.99g reconcilation
   6020  *
   6021  * Revision 4.36  1999/11/28 17:18:20  kardel
   6022  * disabled burst mode
   6023  *
   6024  * Revision 4.35  1999/11/28 09:14:14  kardel
   6025  * RECON_4_0_98F
   6026  *
   6027  * Revision 4.34  1999/05/14 06:08:05  kardel
   6028  * store current_time in a suitable container (u_long)
   6029  *
   6030  * Revision 4.33  1999/05/13 21:48:38  kardel
   6031  * double the no response timeout interval
   6032  *
   6033  * Revision 4.32  1999/05/13 20:09:13  kardel
   6034  * complain only about missing polls after a full poll interval
   6035  *
   6036  * Revision 4.31  1999/05/13 19:59:32  kardel
   6037  * add clock type 16 for RTS set DTR clr in RAWDCF
   6038  *
   6039  * Revision 4.30  1999/02/28 20:36:43  kardel
   6040  * fixed printf fmt
   6041  *
   6042  * Revision 4.29  1999/02/28 19:58:23  kardel
   6043  * updated copyright information
   6044  *
   6045  * Revision 4.28  1999/02/28 19:01:50  kardel
   6046  * improved debug out on sent Meinberg messages
   6047  *
   6048  * Revision 4.27  1999/02/28 18:05:55  kardel
   6049  * no linux/ppsclock.h stuff
   6050  *
   6051  * Revision 4.26  1999/02/28 15:27:27  kardel
   6052  * wharton clock integration
   6053  *
   6054  * Revision 4.25  1999/02/28 14:04:46  kardel
   6055  * added missing double quotes to UTC information string
   6056  *
   6057  * Revision 4.24  1999/02/28 12:06:50  kardel
   6058  * (parse_control): using gmprettydate instead of prettydate()
   6059  * (mk_utcinfo): new function for formatting GPS derived UTC information
   6060  * (gps16x_message): changed to use mk_utcinfo()
   6061  * (trimbletsip_message): changed to use mk_utcinfo()
   6062  * ignoring position information in unsynchronized mode
   6063  * (parse_start): augument linux support for optional ASYNC_LOW_LATENCY
   6064  *
   6065  * Revision 4.23  1999/02/23 19:47:53  kardel
   6066  * fixed #endifs
   6067  * (stream_receive): fixed formats
   6068  *
   6069  * Revision 4.22  1999/02/22 06:21:02  kardel
   6070  * use new autoconfig symbols
   6071  *
   6072  * Revision 4.21  1999/02/21 12:18:13  kardel
   6073  * 4.91f reconcilation
   6074  *
   6075  * Revision 4.20  1999/02/21 10:53:36  kardel
   6076  * initial Linux PPSkit version
   6077  *
   6078  * Revision 4.19  1999/02/07 09:10:45  kardel
   6079  * clarify STREAMS mitigation rules in comment
   6080  *
   6081  * Revision 4.18  1998/12/20 23:45:34  kardel
   6082  * fix types and warnings
   6083  *
   6084  * Revision 4.17  1998/11/15 21:24:51  kardel
   6085  * cannot access mbg_ routines when CLOCK_MEINBERG
   6086  * is not defined
   6087  *
   6088  * Revision 4.16  1998/11/15 20:28:17  kardel
   6089  * Release 4.0.73e13 reconcilation
   6090  *
   6091  * Revision 4.15  1998/08/22 21:56:08  kardel
   6092  * fixed IO handling for non-STREAM IO
   6093  *
   6094  * Revision 4.14  1998/08/16 19:00:48  kardel
   6095  * (gps16x_message): reduced UTC parameter information (dropped A0,A1)
   6096  * made uval a local variable (killed one of the last globals)
   6097  * (sendetx): added logging of messages when in debug mode
   6098  * (trimble_check): added periodic checks to facilitate re-initialization
   6099  * (trimbletsip_init): made use of EOL character if in non-kernel operation
   6100  * (trimbletsip_message): extended message interpretation
   6101  * (getdbl): fixed data conversion
   6102  *
   6103  * Revision 4.13  1998/08/09 22:29:13  kardel
   6104  * Trimble TSIP support
   6105  *
   6106  * Revision 4.12  1998/07/11 10:05:34  kardel
   6107  * Release 4.0.73d reconcilation
   6108  *
   6109  * Revision 4.11  1998/06/14 21:09:42  kardel
   6110  * Sun acc cleanup
   6111  *
   6112  * Revision 4.10  1998/06/13 12:36:45  kardel
   6113  * signed/unsigned, name clashes
   6114  *
   6115  * Revision 4.9  1998/06/12 15:30:00  kardel
   6116  * prototype fixes
   6117  *
   6118  * Revision 4.8  1998/06/12 11:19:42  kardel
   6119  * added direct input processing routine for refclocks in
   6120  * order to avaiod that single character io gobbles up all
   6121  * receive buffers and drops input data. (Problem started
   6122  * with fast machines so a character a buffer was possible
   6123  * one of the few cases where faster machines break existing
   6124  * allocation algorithms)
   6125  *
   6126  * Revision 4.7  1998/06/06 18:35:20  kardel
   6127  * (parse_start): added BURST mode initialisation
   6128  *
   6129  * Revision 4.6  1998/05/27 06:12:46  kardel
   6130  * RAWDCF_BASEDELAY default added
   6131  * old comment removed
   6132  * casts for ioctl()
   6133  *
   6134  * Revision 4.5  1998/05/25 22:05:09  kardel
   6135  * RAWDCF_SETDTR option removed
   6136  * clock type 14 attempts to set DTR for
   6137  * power supply of RAWDCF receivers
   6138  *
   6139  * Revision 4.4  1998/05/24 16:20:47  kardel
   6140  * updated comments referencing Meinberg clocks
   6141  * added RAWDCF clock with DTR set option as type 14
   6142  *
   6143  * Revision 4.3  1998/05/24 10:48:33  kardel
   6144  * calibrated CONRAD RAWDCF default fudge factor
   6145  *
   6146  * Revision 4.2  1998/05/24 09:59:35  kardel
   6147  * corrected version information (ntpq support)
   6148  *
   6149  * Revision 4.1  1998/05/24 09:52:31  kardel
   6150  * use fixed format only (new IO model)
   6151  * output debug to stdout instead of msyslog()
   6152  * don't include >"< in ASCII output in order not to confuse
   6153  * ntpq parsing
   6154  *
   6155  * Revision 4.0  1998/04/10 19:52:11  kardel
   6156  * Start 4.0 release version numbering
   6157  *
   6158  * Revision 1.2  1998/04/10 19:28:04  kardel
   6159  * initial NTP VERSION 4 integration of PARSE with GPS166 binary support
   6160  * derived from 3.105.1.2 from V3 tree
   6161  *
   6162  * Revision information 3.1 - 3.105 from log deleted 1998/04/10 kardel
   6163  *
   6164  */
   6165