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