Annotation of embedaddon/ntp/ntpd/refclock_parse.c, revision 1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>