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