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