Annotation of embedaddon/ntp/ntpd/refclock_jupiter.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (c) 1997, 1998, 2003
                      3:  *     The Regents of the University of California.  All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. All advertising materials mentioning features or use of this software
                     14:  *    must display the following acknowledgement:
                     15:  *     This product includes software developed by the University of
                     16:  *     California, Lawrence Berkeley Laboratory.
                     17:  * 4. The name of the University may not be used to endorse or promote
                     18:  *    products derived from this software without specific prior
                     19:  *    written permission.
                     20:  *
                     21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     31:  * SUCH DAMAGE.
                     32:  */
                     33: 
                     34: #ifdef HAVE_CONFIG_H
                     35: # include <config.h>
                     36: #endif
                     37: 
                     38: #if defined(REFCLOCK) && defined(CLOCK_JUPITER) && defined(HAVE_PPSAPI)
                     39: 
                     40: #include "ntpd.h"
                     41: #include "ntp_io.h"
                     42: #include "ntp_refclock.h"
                     43: #include "ntp_unixtime.h"
                     44: #include "ntp_stdlib.h"
                     45: 
                     46: #include <stdio.h>
                     47: #include <ctype.h>
                     48: 
                     49: #include "jupiter.h"
                     50: 
                     51: #ifdef HAVE_PPSAPI
                     52: # include "ppsapi_timepps.h"
                     53: #endif
                     54: 
                     55: #ifdef XNTP_BIG_ENDIAN
                     56: #define getshort(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff))
                     57: #define putshort(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff))
                     58: #else
                     59: #define getshort(s) (s)
                     60: #define putshort(s) (s)
                     61: #endif
                     62: 
                     63: /* XXX */
                     64: #ifdef sun
                     65: char *strerror(int);
                     66: #endif
                     67: 
                     68: /*
                     69:  * This driver supports the Rockwell Jupiter GPS Receiver board
                     70:  * adapted to precision timing applications.  It requires the
                     71:  * ppsclock line discipline or streams module described in the
                     72:  * Line Disciplines and Streams Drivers page. It also requires a
                     73:  * gadget box and 1-PPS level converter, such as described in the
                     74:  * Pulse-per-second (PPS) Signal Interfacing page.
                     75:  *
                     76:  * It may work (with minor modifications) with other Rockwell GPS
                     77:  * receivers such as the CityTracker.
                     78:  */
                     79: 
                     80: /*
                     81:  * GPS Definitions
                     82:  */
                     83: #define        DEVICE          "/dev/gps%d"    /* device name and unit */
                     84: #define        SPEED232        B9600           /* baud */
                     85: 
                     86: /*
                     87:  * Radio interface parameters
                     88:  */
                     89: #define        PRECISION       (-18)   /* precision assumed (about 4 us) */
                     90: #define        REFID   "GPS\0"         /* reference id */
                     91: #define        DESCRIPTION     "Rockwell Jupiter GPS Receiver" /* who we are */
                     92: #define        DEFFUDGETIME    0       /* default fudge time (ms) */
                     93: 
                     94: /* Unix timestamp for the GPS epoch: January 6, 1980 */
                     95: #define GPS_EPOCH 315964800
                     96: 
                     97: /* Double short to unsigned int */
                     98: #define DS2UI(p) ((getshort((p)[1]) << 16) | getshort((p)[0]))
                     99: 
                    100: /* Double short to signed int */
                    101: #define DS2I(p) ((getshort((p)[1]) << 16) | getshort((p)[0]))
                    102: 
                    103: /* One week's worth of seconds */
                    104: #define WEEKSECS (7 * 24 * 60 * 60)
                    105: 
                    106: /*
                    107:  * Jupiter unit control structure.
                    108:  */
                    109: struct instance {
                    110:        struct peer *peer;              /* peer */
                    111:        u_int  pollcnt;                 /* poll message counter */
                    112:        u_int  polled;                  /* Hand in a time sample? */
                    113: #ifdef HAVE_PPSAPI
                    114:        pps_params_t pps_params;        /* pps parameters */
                    115:        pps_info_t pps_info;            /* last pps data */
                    116:        pps_handle_t pps_handle;        /* pps handle */
                    117:        u_int assert;                   /* pps edge to use */
                    118:        u_int hardpps;                  /* enable kernel mode */
                    119:        struct timespec ts;             /* last timestamp */
                    120: #endif
                    121:        l_fp limit;
                    122:        u_int gpos_gweek;               /* Current GPOS GPS week number */
                    123:        u_int gpos_sweek;               /* Current GPOS GPS seconds into week */
                    124:        u_int gweek;                    /* current GPS week number */
                    125:        u_int32 lastsweek;              /* last seconds into GPS week */
                    126:        time_t timecode;                /* current ntp timecode */
                    127:        u_int32 stime;                  /* used to detect firmware bug */
                    128:        int wantid;                     /* don't reconfig on channel id msg */
                    129:        u_int  moving;                  /* mobile platform? */
                    130:        u_char sloppyclockflag;         /* fudge flags */
                    131:        u_short sbuf[512];              /* local input buffer */
                    132:        int ssize;                      /* space used in sbuf */
                    133: };
                    134: 
                    135: /*
                    136:  * Function prototypes
                    137:  */
                    138: static void    jupiter_canmsg  (struct instance *, u_int);
                    139: static u_short jupiter_cksum   (u_short *, u_int);
                    140: static int     jupiter_config  (struct instance *);
                    141: static void    jupiter_debug   (struct peer *, char *, char *, ...)
                    142:     __attribute__ ((format (printf, 3, 4)));
                    143: static char *  jupiter_parse_t (struct instance *, u_short *);
                    144: static char *  jupiter_parse_gpos      (struct instance *, u_short *);
                    145: static void    jupiter_platform        (struct instance *, u_int);
                    146: static void    jupiter_poll    (int, struct peer *);
                    147: static void    jupiter_control (int, struct refclockstat *, struct
                    148:                                    refclockstat *, struct peer *);
                    149: #ifdef HAVE_PPSAPI
                    150: static int     jupiter_ppsapi  (struct instance *);
                    151: static int     jupiter_pps     (struct instance *);
                    152: #endif /* HAVE_PPSAPI */
                    153: static int     jupiter_recv    (struct instance *);
                    154: static void    jupiter_receive (struct recvbuf *rbufp);
                    155: static void    jupiter_reqmsg  (struct instance *, u_int, u_int);
                    156: static void    jupiter_reqonemsg       (struct instance *, u_int);
                    157: static char *  jupiter_send    (struct instance *, struct jheader *);
                    158: static void    jupiter_shutdown        (int, struct peer *);
                    159: static int     jupiter_start   (int, struct peer *);
                    160: 
                    161: /*
                    162:  * Transfer vector
                    163:  */
                    164: struct refclock refclock_jupiter = {
                    165:        jupiter_start,          /* start up driver */
                    166:        jupiter_shutdown,       /* shut down driver */
                    167:        jupiter_poll,           /* transmit poll message */
                    168:        jupiter_control,        /* (clock control) */
                    169:        noentry,                /* (clock init) */
                    170:        noentry,                /* (clock buginfo) */
                    171:        NOFLAGS                 /* not used */
                    172: };
                    173: 
                    174: /*
                    175:  * jupiter_start - open the devices and initialize data for processing
                    176:  */
                    177: static int
                    178: jupiter_start(
                    179:        int unit,
                    180:        struct peer *peer
                    181:        )
                    182: {
                    183:        struct refclockproc *pp;
                    184:        struct instance *instance;
                    185:        int fd = -1;
                    186:        char gpsdev[20];
                    187: 
                    188:        /*
                    189:         * Open serial port
                    190:         */
                    191:        snprintf(gpsdev, sizeof(gpsdev), DEVICE, unit);
                    192:        fd = refclock_open(gpsdev, SPEED232, LDISC_RAW);
                    193:        if (fd == 0) {
                    194:                jupiter_debug(peer, "jupiter_start", "open %s: %s",
                    195:                    gpsdev, strerror(errno));
                    196:                return (0);
                    197:        }
                    198: 
                    199:        /* Allocate unit structure */
                    200:        instance = emalloc(sizeof(*instance));
                    201:        memset(instance, 0, sizeof(*instance));
                    202:        instance->peer = peer;
                    203:        pp = peer->procptr;
                    204:        pp->io.clock_recv = jupiter_receive;
                    205:        pp->io.srcclock = (caddr_t)peer;
                    206:        pp->io.datalen = 0;
                    207:        pp->io.fd = fd;
                    208:        if (!io_addclock(&pp->io)) {
                    209:                close(fd);
                    210:                free(instance);
                    211:                return (0);
                    212:        }
                    213:        pp->unitptr = (caddr_t)instance;
                    214: 
                    215:        /*
                    216:         * Initialize miscellaneous variables
                    217:         */
                    218:        peer->precision = PRECISION;
                    219:        pp->clockdesc = DESCRIPTION;
                    220:        memcpy((char *)&pp->refid, REFID, 4);
                    221: 
                    222: #ifdef HAVE_PPSAPI
                    223:        instance->assert = 1;
                    224:        instance->hardpps = 0;
                    225:        /*
                    226:         * Start the PPSAPI interface if it is there. Default to use
                    227:         * the assert edge and do not enable the kernel hardpps.
                    228:         */
                    229:        if (time_pps_create(fd, &instance->pps_handle) < 0) {
                    230:                instance->pps_handle = 0;
                    231:                msyslog(LOG_ERR,
                    232:                        "refclock_jupiter: time_pps_create failed: %m");
                    233:        }
                    234:        else if (!jupiter_ppsapi(instance))
                    235:                goto clean_up;
                    236: #endif /* HAVE_PPSAPI */
                    237: 
                    238:        /* Ensure the receiver is properly configured */
                    239:        if (!jupiter_config(instance))
                    240:                goto clean_up;
                    241: 
                    242:        return (1);
                    243: 
                    244: clean_up:
                    245:        jupiter_shutdown(unit, peer);
                    246:        pp->unitptr = 0;
                    247:        return (0);
                    248: }
                    249: 
                    250: /*
                    251:  * jupiter_shutdown - shut down the clock
                    252:  */
                    253: static void
                    254: jupiter_shutdown(int unit, struct peer *peer)
                    255: {
                    256:        struct instance *instance;
                    257:        struct refclockproc *pp;
                    258: 
                    259:        pp = peer->procptr;
                    260:        instance = (struct instance *)pp->unitptr;
                    261:        if (!instance)
                    262:                return;
                    263: 
                    264: #ifdef HAVE_PPSAPI
                    265:        if (instance->pps_handle) {
                    266:                time_pps_destroy(instance->pps_handle);
                    267:                instance->pps_handle = 0;
                    268:        }
                    269: #endif /* HAVE_PPSAPI */
                    270: 
                    271:        io_closeclock(&pp->io);
                    272:        free(instance);
                    273: }
                    274: 
                    275: /*
                    276:  * jupiter_config - Configure the receiver
                    277:  */
                    278: static int
                    279: jupiter_config(struct instance *instance)
                    280: {
                    281:        jupiter_debug(instance->peer, "jupiter_config", "init receiver");
                    282: 
                    283:        /*
                    284:         * Initialize the unit variables
                    285:         */
                    286:        instance->sloppyclockflag = instance->peer->procptr->sloppyclockflag;
                    287:        instance->moving = !!(instance->sloppyclockflag & CLK_FLAG2);
                    288:        if (instance->moving)
                    289:                jupiter_debug(instance->peer, "jupiter_config",
                    290:                        "mobile platform");
                    291: 
                    292:        instance->pollcnt     = 2;
                    293:        instance->polled      = 0;
                    294:        instance->gpos_gweek = 0;
                    295:        instance->gpos_sweek = 0;
                    296:        instance->gweek = 0;
                    297:        instance->lastsweek = 2 * WEEKSECS;
                    298:        instance->timecode = 0;
                    299:        instance->stime = 0;
                    300:        instance->ssize = 0;
                    301: 
                    302:        /* Stop outputting all messages */
                    303:        jupiter_canmsg(instance, JUPITER_ALL);
                    304: 
                    305:        /* Request the receiver id so we can syslog the firmware version */
                    306:        jupiter_reqonemsg(instance, JUPITER_O_ID);
                    307: 
                    308:        /* Flag that this the id was requested (so we don't get called again) */
                    309:        instance->wantid = 1;
                    310: 
                    311:        /* Request perodic time mark pulse messages */
                    312:        jupiter_reqmsg(instance, JUPITER_O_PULSE, 1);
                    313: 
                    314:        /* Request perodic geodetic position status */
                    315:        jupiter_reqmsg(instance, JUPITER_O_GPOS, 1);
                    316: 
                    317:        /* Set application platform type */
                    318:        if (instance->moving)
                    319:                jupiter_platform(instance, JUPITER_I_PLAT_MED);
                    320:        else
                    321:                jupiter_platform(instance, JUPITER_I_PLAT_LOW);
                    322: 
                    323:        return (1);
                    324: }
                    325: 
                    326: #ifdef HAVE_PPSAPI
                    327: /*
                    328:  * Initialize PPSAPI
                    329:  */
                    330: int
                    331: jupiter_ppsapi(
                    332:        struct instance *instance       /* unit structure pointer */
                    333:        )
                    334: {
                    335:        int capability;
                    336: 
                    337:        if (time_pps_getcap(instance->pps_handle, &capability) < 0) {
                    338:                msyslog(LOG_ERR,
                    339:                    "refclock_jupiter: time_pps_getcap failed: %m");
                    340:                return (0);
                    341:        }
                    342:        memset(&instance->pps_params, 0, sizeof(pps_params_t));
                    343:        if (!instance->assert)
                    344:                instance->pps_params.mode = capability & PPS_CAPTURECLEAR;
                    345:        else
                    346:                instance->pps_params.mode = capability & PPS_CAPTUREASSERT;
                    347:        if (!(instance->pps_params.mode & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR))) {
                    348:                msyslog(LOG_ERR,
                    349:                    "refclock_jupiter: invalid capture edge %d",
                    350:                    instance->assert);
                    351:                return (0);
                    352:        }
                    353:        instance->pps_params.mode |= PPS_TSFMT_TSPEC;
                    354:        if (time_pps_setparams(instance->pps_handle, &instance->pps_params) < 0) {
                    355:                msyslog(LOG_ERR,
                    356:                    "refclock_jupiter: time_pps_setparams failed: %m");
                    357:                return (0);
                    358:        }
                    359:        if (instance->hardpps) {
                    360:                if (time_pps_kcbind(instance->pps_handle, PPS_KC_HARDPPS,
                    361:                                    instance->pps_params.mode & ~PPS_TSFMT_TSPEC,
                    362:                                    PPS_TSFMT_TSPEC) < 0) {
                    363:                        msyslog(LOG_ERR,
                    364:                            "refclock_jupiter: time_pps_kcbind failed: %m");
                    365:                        return (0);
                    366:                }
                    367:                pps_enable = 1;
                    368:        }
                    369: /*     instance->peer->precision = PPS_PRECISION; */
                    370: 
                    371: #if DEBUG
                    372:        if (debug) {
                    373:                time_pps_getparams(instance->pps_handle, &instance->pps_params);
                    374:                jupiter_debug(instance->peer, "refclock_jupiter",
                    375:                        "pps capability 0x%x version %d mode 0x%x kern %d",
                    376:                        capability, instance->pps_params.api_version,
                    377:                        instance->pps_params.mode, instance->hardpps);
                    378:        }
                    379: #endif
                    380: 
                    381:        return (1);
                    382: }
                    383: 
                    384: /*
                    385:  * Get PPSAPI timestamps.
                    386:  *
                    387:  * Return 0 on failure and 1 on success.
                    388:  */
                    389: static int
                    390: jupiter_pps(struct instance *instance)
                    391: {
                    392:        pps_info_t pps_info;
                    393:        struct timespec timeout, ts;
                    394:        double dtemp;
                    395:        l_fp tstmp;
                    396: 
                    397:        /*
                    398:         * Convert the timespec nanoseconds field to ntp l_fp units.
                    399:         */ 
                    400:        if (instance->pps_handle == 0)
                    401:                return 1;
                    402:        timeout.tv_sec = 0;
                    403:        timeout.tv_nsec = 0;
                    404:        memcpy(&pps_info, &instance->pps_info, sizeof(pps_info_t));
                    405:        if (time_pps_fetch(instance->pps_handle, PPS_TSFMT_TSPEC, &instance->pps_info,
                    406:            &timeout) < 0)
                    407:                return 1;
                    408:        if (instance->pps_params.mode & PPS_CAPTUREASSERT) {
                    409:                if (pps_info.assert_sequence ==
                    410:                    instance->pps_info.assert_sequence)
                    411:                        return 1;
                    412:                ts = instance->pps_info.assert_timestamp;
                    413:        } else if (instance->pps_params.mode & PPS_CAPTURECLEAR) {
                    414:                if (pps_info.clear_sequence ==
                    415:                    instance->pps_info.clear_sequence)
                    416:                        return 1;
                    417:                ts = instance->pps_info.clear_timestamp;
                    418:        } else {
                    419:                return 1;
                    420:        }
                    421:        if ((instance->ts.tv_sec == ts.tv_sec) && (instance->ts.tv_nsec == ts.tv_nsec))
                    422:                return 1;
                    423:        instance->ts = ts;
                    424: 
                    425:        tstmp.l_ui = ts.tv_sec + JAN_1970;
                    426:        dtemp = ts.tv_nsec * FRAC / 1e9;
                    427:        tstmp.l_uf = (u_int32)dtemp;
                    428:        instance->peer->procptr->lastrec = tstmp;
                    429:        return 0;
                    430: }
                    431: #endif /* HAVE_PPSAPI */
                    432: 
                    433: /*
                    434:  * jupiter_poll - jupiter watchdog routine
                    435:  */
                    436: static void
                    437: jupiter_poll(int unit, struct peer *peer)
                    438: {
                    439:        struct instance *instance;
                    440:        struct refclockproc *pp;
                    441: 
                    442:        pp = peer->procptr;
                    443:        instance = (struct instance *)pp->unitptr;
                    444: 
                    445:        /*
                    446:         * You don't need to poll this clock.  It puts out timecodes
                    447:         * once per second.  If asked for a timestamp, take note.
                    448:         * The next time a timecode comes in, it will be fed back.
                    449:         */
                    450: 
                    451:        /*
                    452:         * If we haven't had a response in a while, reset the receiver.
                    453:         */
                    454:        if (instance->pollcnt > 0) {
                    455:                instance->pollcnt--;
                    456:        } else {
                    457:                refclock_report(peer, CEVNT_TIMEOUT);
                    458: 
                    459:                /* Request the receiver id to trigger a reconfig */
                    460:                jupiter_reqonemsg(instance, JUPITER_O_ID);
                    461:                instance->wantid = 0;
                    462:        }
                    463: 
                    464:        /*
                    465:         * polled every 64 seconds. Ask jupiter_receive to hand in
                    466:         * a timestamp.
                    467:         */
                    468:        instance->polled = 1;
                    469:        pp->polls++;
                    470: }
                    471: 
                    472: /*
                    473:  * jupiter_control - fudge control
                    474:  */
                    475: static void
                    476: jupiter_control(
                    477:        int unit,               /* unit (not used) */
                    478:        struct refclockstat *in, /* input parameters (not used) */
                    479:        struct refclockstat *out, /* output parameters (not used) */
                    480:        struct peer *peer       /* peer structure pointer */
                    481:        )
                    482: {
                    483:        struct refclockproc *pp;
                    484:        struct instance *instance;
                    485:        u_char sloppyclockflag;
                    486: 
                    487:        pp = peer->procptr;
                    488:        instance = (struct instance *)pp->unitptr;
                    489: 
                    490:        DTOLFP(pp->fudgetime2, &instance->limit);
                    491:        /* Force positive value. */
                    492:        if (L_ISNEG(&instance->limit))
                    493:                L_NEG(&instance->limit);
                    494: 
                    495: #ifdef HAVE_PPSAPI
                    496:        instance->assert = !(pp->sloppyclockflag & CLK_FLAG3);
                    497:        jupiter_ppsapi(instance);
                    498: #endif /* HAVE_PPSAPI */
                    499: 
                    500:        sloppyclockflag = instance->sloppyclockflag;
                    501:        instance->sloppyclockflag = pp->sloppyclockflag;
                    502:        if ((instance->sloppyclockflag & CLK_FLAG2) !=
                    503:            (sloppyclockflag & CLK_FLAG2)) {
                    504:                jupiter_debug(peer,
                    505:                    "jupiter_control",
                    506:                    "mode switch: reset receiver");
                    507:                jupiter_config(instance);
                    508:                return;
                    509:        }
                    510: }
                    511: 
                    512: /*
                    513:  * jupiter_receive - receive gps data
                    514:  * Gag me!
                    515:  */
                    516: static void
                    517: jupiter_receive(struct recvbuf *rbufp)
                    518: {
                    519:        int bpcnt, cc, size, ppsret;
                    520:        time_t last_timecode;
                    521:        u_int32 laststime;
                    522:        char *cp;
                    523:        u_char *bp;
                    524:        u_short *sp;
                    525:        struct jid *ip;
                    526:        struct jheader *hp;
                    527:        struct peer *peer;
                    528:        struct refclockproc *pp;
                    529:        struct instance *instance;
                    530:        l_fp tstamp;
                    531: 
                    532:        /* Initialize pointers and read the timecode and timestamp */
                    533:        peer = (struct peer *)rbufp->recv_srcclock;
                    534:        pp = peer->procptr;
                    535:        instance = (struct instance *)pp->unitptr;
                    536: 
                    537:        bp = (u_char *)rbufp->recv_buffer;
                    538:        bpcnt = rbufp->recv_length;
                    539: 
                    540:        /* This shouldn't happen */
                    541:        if (bpcnt > sizeof(instance->sbuf) - instance->ssize)
                    542:                bpcnt = sizeof(instance->sbuf) - instance->ssize;
                    543: 
                    544:        /* Append to input buffer */
                    545:        memcpy((u_char *)instance->sbuf + instance->ssize, bp, bpcnt);
                    546:        instance->ssize += bpcnt;
                    547: 
                    548:        /* While there's at least a header and we parse an intact message */
                    549:        while (instance->ssize > sizeof(*hp) && (cc = jupiter_recv(instance)) > 0) {
                    550:                instance->pollcnt = 2;
                    551: 
                    552:                tstamp = rbufp->recv_time;
                    553:                hp = (struct jheader *)instance->sbuf;
                    554:                sp = (u_short *)(hp + 1);
                    555:                size = cc - sizeof(*hp);
                    556:                switch (getshort(hp->id)) {
                    557: 
                    558:                case JUPITER_O_PULSE:
                    559:                        if (size != sizeof(struct jpulse)) {
                    560:                                jupiter_debug(peer,
                    561:                                    "jupiter_receive", "pulse: len %d != %u",
                    562:                                    size, (int)sizeof(struct jpulse));
                    563:                                refclock_report(peer, CEVNT_BADREPLY);
                    564:                                break;
                    565:                        }
                    566: 
                    567:                        /*
                    568:                         * There appears to be a firmware bug related
                    569:                         * to the pulse message; in addition to the one
                    570:                         * per second messages, we get an extra pulse
                    571:                         * message once an hour (on the anniversary of
                    572:                         * the cold start). It seems to come 200 ms
                    573:                         * after the one requested. So if we've seen a
                    574:                         * pulse message in the last 210 ms, we skip
                    575:                         * this one.
                    576:                         */
                    577:                        laststime = instance->stime;
                    578:                        instance->stime = DS2UI(((struct jpulse *)sp)->stime);
                    579:                        if (laststime != 0 && instance->stime - laststime <= 21) {
                    580:                                jupiter_debug(peer, "jupiter_receive", 
                    581:                                "avoided firmware bug (stime %.2f, laststime %.2f)",
                    582:                                (double)instance->stime * 0.01, (double)laststime * 0.01);
                    583:                                break;
                    584:                        }
                    585: 
                    586:                        /* Retrieve pps timestamp */
                    587:                        ppsret = jupiter_pps(instance);
                    588: 
                    589:                        /*
                    590:                         * Add one second if msg received early
                    591:                         * (i.e. before limit, a.k.a. fudgetime2) in
                    592:                         * the second.
                    593:                         */
                    594:                        L_SUB(&tstamp, &pp->lastrec);
                    595:                        if (!L_ISGEQ(&tstamp, &instance->limit))
                    596:                                ++pp->lastrec.l_ui;
                    597: 
                    598:                        /* Parse timecode (even when there's no pps) */
                    599:                        last_timecode = instance->timecode;
                    600:                        if ((cp = jupiter_parse_t(instance, sp)) != NULL) {
                    601:                                jupiter_debug(peer,
                    602:                                    "jupiter_receive", "pulse: %s", cp);
                    603:                                break;
                    604:                        }
                    605: 
                    606:                        /* Bail if we didn't get a pps timestamp */
                    607:                        if (ppsret)
                    608:                                break;
                    609: 
                    610:                        /* Bail if we don't have the last timecode yet */
                    611:                        if (last_timecode == 0)
                    612:                                break;
                    613: 
                    614:                        /* Add the new sample to a median filter */
                    615:                        tstamp.l_ui = JAN_1970 + last_timecode;
                    616:                        tstamp.l_uf = 0;
                    617: 
                    618:                        refclock_process_offset(pp, tstamp, pp->lastrec, pp->fudgetime1);
                    619: 
                    620:                        /*
                    621:                         * The clock will blurt a timecode every second
                    622:                         * but we only want one when polled.  If we
                    623:                         * havn't been polled, bail out.
                    624:                         */
                    625:                        if (!instance->polled)
                    626:                                break;
                    627:                        instance->polled = 0;
                    628: 
                    629:                        /*
                    630:                         * It's a live one!  Remember this time.
                    631:                         */
                    632: 
                    633:                        pp->lastref = pp->lastrec;
                    634:                        refclock_receive(peer);
                    635: 
                    636:                        /*
                    637:                         * If we get here - what we got from the clock is
                    638:                         * OK, so say so
                    639:                         */
                    640:                        refclock_report(peer, CEVNT_NOMINAL);
                    641: 
                    642:                        /*
                    643:                         * We have succeeded in answering the poll.
                    644:                         * Turn off the flag and return
                    645:                         */
                    646:                        instance->polled = 0;
                    647:                        break;
                    648: 
                    649:                case JUPITER_O_GPOS:
                    650:                        if (size != sizeof(struct jgpos)) {
                    651:                                jupiter_debug(peer,
                    652:                                    "jupiter_receive", "gpos: len %d != %u",
                    653:                                    size, (int)sizeof(struct jgpos));
                    654:                                refclock_report(peer, CEVNT_BADREPLY);
                    655:                                break;
                    656:                        }
                    657: 
                    658:                        if ((cp = jupiter_parse_gpos(instance, sp)) != NULL) {
                    659:                                jupiter_debug(peer,
                    660:                                    "jupiter_receive", "gpos: %s", cp);
                    661:                                break;
                    662:                        }
                    663:                        break;
                    664: 
                    665:                case JUPITER_O_ID:
                    666:                        if (size != sizeof(struct jid)) {
                    667:                                jupiter_debug(peer,
                    668:                                    "jupiter_receive", "id: len %d != %u",
                    669:                                    size, (int)sizeof(struct jid));
                    670:                                refclock_report(peer, CEVNT_BADREPLY);
                    671:                                break;
                    672:                        }
                    673:                        /*
                    674:                         * If we got this message because the Jupiter
                    675:                         * just powered instance, it needs to be reconfigured.
                    676:                         */
                    677:                        ip = (struct jid *)sp;
                    678:                        jupiter_debug(peer,
                    679:                            "jupiter_receive", "%s chan ver %s, %s (%s)",
                    680:                            ip->chans, ip->vers, ip->date, ip->opts);
                    681:                        msyslog(LOG_DEBUG,
                    682:                            "jupiter_receive: %s chan ver %s, %s (%s)",
                    683:                            ip->chans, ip->vers, ip->date, ip->opts);
                    684:                        if (instance->wantid)
                    685:                                instance->wantid = 0;
                    686:                        else {
                    687:                                jupiter_debug(peer,
                    688:                                    "jupiter_receive", "reset receiver");
                    689:                                jupiter_config(instance);
                    690:                                /*
                    691:                                 * Restore since jupiter_config() just
                    692:                                 * zeroed it
                    693:                                 */
                    694:                                instance->ssize = cc;
                    695:                        }
                    696:                        break;
                    697: 
                    698:                default:
                    699:                        jupiter_debug(peer,
                    700:                            "jupiter_receive", "unknown message id %d",
                    701:                            getshort(hp->id));
                    702:                        break;
                    703:                }
                    704:                instance->ssize -= cc;
                    705:                if (instance->ssize < 0) {
                    706:                        fprintf(stderr, "jupiter_recv: negative ssize!\n");
                    707:                        abort();
                    708:                } else if (instance->ssize > 0)
                    709:                        memcpy(instance->sbuf, (u_char *)instance->sbuf + cc, instance->ssize);
                    710:        }
                    711: }
                    712: 
                    713: static char *
                    714: jupiter_parse_t(struct instance *instance, u_short *sp)
                    715: {
                    716:        struct tm *tm;
                    717:        char *cp;
                    718:        struct jpulse *jp;
                    719:        u_int32 sweek;
                    720:        time_t last_timecode;
                    721:        u_short flags;
                    722: 
                    723:        jp = (struct jpulse *)sp;
                    724: 
                    725:        /* The timecode is presented as seconds into the current GPS week */
                    726:        sweek = DS2UI(jp->sweek) % WEEKSECS;
                    727: 
                    728:        /*
                    729:         * If we don't know the current GPS week, calculate it from the
                    730:         * current time. (It's too bad they didn't include this
                    731:         * important value in the pulse message). We'd like to pick it
                    732:         * up from one of the other messages like gpos or chan but they
                    733:         * don't appear to be synchronous with time keeping and changes
                    734:         * too soon (something like 10 seconds before the new GPS
                    735:         * week).
                    736:         *
                    737:         * If we already know the current GPS week, increment it when
                    738:         * we wrap into a new week.
                    739:         */
                    740:        if (instance->gweek == 0) {
                    741:                if (!instance->gpos_gweek) {
                    742:                        return ("jupiter_parse_t: Unknown gweek");
                    743:                }
                    744: 
                    745:                instance->gweek = instance->gpos_gweek;
                    746: 
                    747:                /*
                    748:                 * Fix warps. GPOS has GPS time and PULSE has UTC.
                    749:                 * Plus, GPOS need not be completely in synch with
                    750:                 * the PPS signal.
                    751:                 */
                    752:                if (instance->gpos_sweek >= sweek) {
                    753:                        if ((instance->gpos_sweek - sweek) > WEEKSECS / 2)
                    754:                                ++instance->gweek;
                    755:                }
                    756:                else {
                    757:                        if ((sweek - instance->gpos_sweek) > WEEKSECS / 2)
                    758:                                --instance->gweek;
                    759:                }
                    760:        }
                    761:        else if (sweek == 0 && instance->lastsweek == WEEKSECS - 1) {
                    762:                ++instance->gweek;
                    763:                jupiter_debug(instance->peer,
                    764:                    "jupiter_parse_t", "NEW gps week %u", instance->gweek);
                    765:        }
                    766: 
                    767:        /*
                    768:         * See if the sweek stayed the same (this happens when there is
                    769:         * no pps pulse).
                    770:         *
                    771:         * Otherwise, look for time warps:
                    772:         *
                    773:         *   - we have stored at least one lastsweek and
                    774:         *   - the sweek didn't increase by one and
                    775:         *   - we didn't wrap to a new GPS week
                    776:         *
                    777:         * Then we warped.
                    778:         */
                    779:        if (instance->lastsweek == sweek)
                    780:                jupiter_debug(instance->peer,
                    781:                    "jupiter_parse_t", "gps sweek not incrementing (%d)",
                    782:                    sweek);
                    783:        else if (instance->lastsweek != 2 * WEEKSECS &&
                    784:            instance->lastsweek + 1 != sweek &&
                    785:            !(sweek == 0 && instance->lastsweek == WEEKSECS - 1))
                    786:                jupiter_debug(instance->peer,
                    787:                    "jupiter_parse_t", "gps sweek jumped (was %d, now %d)",
                    788:                    instance->lastsweek, sweek);
                    789:        instance->lastsweek = sweek;
                    790: 
                    791:        /* This timecode describes next pulse */
                    792:        last_timecode = instance->timecode;
                    793:        instance->timecode =
                    794:            GPS_EPOCH + (instance->gweek * WEEKSECS) + sweek;
                    795: 
                    796:        if (last_timecode == 0)
                    797:                /* XXX debugging */
                    798:                jupiter_debug(instance->peer,
                    799:                    "jupiter_parse_t", "UTC <none> (gweek/sweek %u/%u)",
                    800:                    instance->gweek, sweek);
                    801:        else {
                    802:                /* XXX debugging */
                    803:                tm = gmtime(&last_timecode);
                    804:                cp = asctime(tm);
                    805: 
                    806:                jupiter_debug(instance->peer,
                    807:                    "jupiter_parse_t", "UTC %.24s (gweek/sweek %u/%u)",
                    808:                    cp, instance->gweek, sweek);
                    809: 
                    810:                /* Billboard last_timecode (which is now the current time) */
                    811:                instance->peer->procptr->year   = tm->tm_year + 1900;
                    812:                instance->peer->procptr->day    = tm->tm_yday + 1;
                    813:                instance->peer->procptr->hour   = tm->tm_hour;
                    814:                instance->peer->procptr->minute = tm->tm_min;
                    815:                instance->peer->procptr->second = tm->tm_sec;
                    816:        }
                    817: 
                    818:        flags = getshort(jp->flags);
                    819: 
                    820:        /* Toss if not designated "valid" by the gps */
                    821:        if ((flags & JUPITER_O_PULSE_VALID) == 0) {
                    822:                refclock_report(instance->peer, CEVNT_BADTIME);
                    823:                return ("time mark not valid");
                    824:        }
                    825: 
                    826:        /* We better be sync'ed to UTC... */
                    827:        if ((flags & JUPITER_O_PULSE_UTC) == 0) {
                    828:                refclock_report(instance->peer, CEVNT_BADTIME);
                    829:                return ("time mark not sync'ed to UTC");
                    830:        }
                    831: 
                    832:        return (NULL);
                    833: }
                    834: 
                    835: static char *
                    836: jupiter_parse_gpos(struct instance *instance, u_short *sp)
                    837: {
                    838:        struct jgpos *jg;
                    839:        time_t t;
                    840:        struct tm *tm;
                    841:        char *cp;
                    842: 
                    843:        jg = (struct jgpos *)sp;
                    844: 
                    845:        if (jg->navval != 0) {
                    846:                /*
                    847:                 * Solution not valid. Use caution and refuse
                    848:                 * to determine GPS week from this message.
                    849:                 */
                    850:                instance->gpos_gweek = 0;
                    851:                instance->gpos_sweek = 0;
                    852:                return ("Navigation solution not valid");
                    853:        }
                    854: 
                    855:        instance->gpos_gweek = jg->gweek;
                    856:        instance->gpos_sweek = DS2UI(jg->sweek);
                    857:        while(instance->gpos_sweek >= WEEKSECS) {
                    858:                instance->gpos_sweek -= WEEKSECS;
                    859:                ++instance->gpos_gweek;
                    860:        }
                    861:        instance->gweek = 0;
                    862: 
                    863:        t = GPS_EPOCH + (instance->gpos_gweek * WEEKSECS) + instance->gpos_sweek;
                    864:        tm = gmtime(&t);
                    865:        cp = asctime(tm);
                    866: 
                    867:        jupiter_debug(instance->peer,
                    868:                "jupiter_parse_g", "GPS %.24s (gweek/sweek %u/%u)",
                    869:                cp, instance->gpos_gweek, instance->gpos_sweek);
                    870:        return (NULL);
                    871: }
                    872: 
                    873: /*
                    874:  * jupiter_debug - print debug messages
                    875:  */
                    876: #if defined(__STDC__) || defined(SYS_WINNT)
                    877: static void
                    878: jupiter_debug(struct peer *peer, char *function, char *fmt, ...)
                    879: #else
                    880: static void
                    881: jupiter_debug(peer, function, fmt, va_alist)
                    882:        struct peer *peer;
                    883:        char *function;
                    884:        char *fmt;
                    885: #endif /* __STDC__ */
                    886: {
                    887:        char buffer[200];
                    888:        va_list ap;
                    889: 
                    890: #if defined(__STDC__) || defined(SYS_WINNT)
                    891:        va_start(ap, fmt);
                    892: #else
                    893:        va_start(ap);
                    894: #endif /* __STDC__ */
                    895:        /*
                    896:         * Print debug message to stdout
                    897:         * In the future, we may want to get get more creative...
                    898:         */
                    899:        vsnprintf(buffer, sizeof(buffer), fmt, ap);
                    900:        record_clock_stats(&(peer->srcadr), buffer);
                    901: #ifdef DEBUG
                    902:        if (debug) {
                    903:                fprintf(stdout, "%s: ", function);
                    904:                fprintf(stdout, buffer);
                    905:                fprintf(stdout, "\n");
                    906:                fflush(stdout);
                    907:        }
                    908: #endif
                    909: 
                    910:        va_end(ap);
                    911: }
                    912: 
                    913: /* Checksum and transmit a message to the Jupiter */
                    914: static char *
                    915: jupiter_send(struct instance *instance, struct jheader *hp)
                    916: {
                    917:        u_int len, size;
                    918:        int cc;
                    919:        u_short *sp;
                    920:        static char errstr[132];
                    921: 
                    922:        size = sizeof(*hp);
                    923:        hp->hsum = putshort(jupiter_cksum((u_short *)hp,
                    924:            (size / sizeof(u_short)) - 1));
                    925:        len = getshort(hp->len);
                    926:        if (len > 0) {
                    927:                sp = (u_short *)(hp + 1);
                    928:                sp[len] = putshort(jupiter_cksum(sp, len));
                    929:                size += (len + 1) * sizeof(u_short);
                    930:        }
                    931: 
                    932:        if ((cc = write(instance->peer->procptr->io.fd, (char *)hp, size)) < 0) {
                    933:                snprintf(errstr, sizeof(errstr), "write: %s", strerror(errno));
                    934:                return (errstr);
                    935:        } else if (cc != size) {
                    936:                snprintf(errstr, sizeof(errstr), "short write (%d != %d)", cc, size);
                    937:                return (errstr);
                    938:        }
                    939:        return (NULL);
                    940: }
                    941: 
                    942: /* Request periodic message output */
                    943: static struct {
                    944:        struct jheader jheader;
                    945:        struct jrequest jrequest;
                    946: } reqmsg = {
                    947:        { putshort(JUPITER_SYNC), 0,
                    948:            putshort((sizeof(struct jrequest) / sizeof(u_short)) - 1),
                    949:            0, JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK |
                    950:            JUPITER_FLAG_CONN | JUPITER_FLAG_LOG, 0 },
                    951:        { 0, 0, 0, 0 }
                    952: };
                    953: 
                    954: /* An interval of zero means to output on trigger */
                    955: static void
                    956: jupiter_reqmsg(struct instance *instance, u_int id,
                    957:     u_int interval)
                    958: {
                    959:        struct jheader *hp;
                    960:        struct jrequest *rp;
                    961:        char *cp;
                    962: 
                    963:        hp = &reqmsg.jheader;
                    964:        hp->id = putshort(id);
                    965:        rp = &reqmsg.jrequest;
                    966:        rp->trigger = putshort(interval == 0);
                    967:        rp->interval = putshort(interval);
                    968:        if ((cp = jupiter_send(instance, hp)) != NULL)
                    969:                jupiter_debug(instance->peer, "jupiter_reqmsg", "%u: %s", id, cp);
                    970: }
                    971: 
                    972: /* Cancel periodic message output */
                    973: static struct jheader canmsg = {
                    974:        putshort(JUPITER_SYNC), 0, 0, 0,
                    975:        JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK | JUPITER_FLAG_DISC,
                    976:        0
                    977: };
                    978: 
                    979: static void
                    980: jupiter_canmsg(struct instance *instance, u_int id)
                    981: {
                    982:        struct jheader *hp;
                    983:        char *cp;
                    984: 
                    985:        hp = &canmsg;
                    986:        hp->id = putshort(id);
                    987:        if ((cp = jupiter_send(instance, hp)) != NULL)
                    988:                jupiter_debug(instance->peer, "jupiter_canmsg", "%u: %s", id, cp);
                    989: }
                    990: 
                    991: /* Request a single message output */
                    992: static struct jheader reqonemsg = {
                    993:        putshort(JUPITER_SYNC), 0, 0, 0,
                    994:        JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK | JUPITER_FLAG_QUERY,
                    995:        0
                    996: };
                    997: 
                    998: static void
                    999: jupiter_reqonemsg(struct instance *instance, u_int id)
                   1000: {
                   1001:        struct jheader *hp;
                   1002:        char *cp;
                   1003: 
                   1004:        hp = &reqonemsg;
                   1005:        hp->id = putshort(id);
                   1006:        if ((cp = jupiter_send(instance, hp)) != NULL)
                   1007:                jupiter_debug(instance->peer, "jupiter_reqonemsg", "%u: %s", id, cp);
                   1008: }
                   1009: 
                   1010: /* Set the platform dynamics */
                   1011: static struct {
                   1012:        struct jheader jheader;
                   1013:        struct jplat jplat;
                   1014: } platmsg = {
                   1015:        { putshort(JUPITER_SYNC), putshort(JUPITER_I_PLAT),
                   1016:            putshort((sizeof(struct jplat) / sizeof(u_short)) - 1), 0,
                   1017:            JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK, 0 },
                   1018:        { 0, 0, 0 }
                   1019: };
                   1020: 
                   1021: static void
                   1022: jupiter_platform(struct instance *instance, u_int platform)
                   1023: {
                   1024:        struct jheader *hp;
                   1025:        struct jplat *pp;
                   1026:        char *cp;
                   1027: 
                   1028:        hp = &platmsg.jheader;
                   1029:        pp = &platmsg.jplat;
                   1030:        pp->platform = putshort(platform);
                   1031:        if ((cp = jupiter_send(instance, hp)) != NULL)
                   1032:                jupiter_debug(instance->peer, "jupiter_platform", "%u: %s", platform, cp);
                   1033: }
                   1034: 
                   1035: /* Checksum "len" shorts */
                   1036: static u_short
                   1037: jupiter_cksum(u_short *sp, u_int len)
                   1038: {
                   1039:        u_short sum, x;
                   1040: 
                   1041:        sum = 0;
                   1042:        while (len-- > 0) {
                   1043:                x = *sp++;
                   1044:                sum += getshort(x);
                   1045:        }
                   1046:        return (~sum + 1);
                   1047: }
                   1048: 
                   1049: /* Return the size of the next message (or zero if we don't have it all yet) */
                   1050: static int
                   1051: jupiter_recv(struct instance *instance)
                   1052: {
                   1053:        int n, len, size, cc;
                   1054:        struct jheader *hp;
                   1055:        u_char *bp;
                   1056:        u_short *sp;
                   1057: 
                   1058:        /* Must have at least a header's worth */
                   1059:        cc = sizeof(*hp);
                   1060:        size = instance->ssize;
                   1061:        if (size < cc)
                   1062:                return (0);
                   1063: 
                   1064:        /* Search for the sync short if missing */
                   1065:        sp = instance->sbuf;
                   1066:        hp = (struct jheader *)sp;
                   1067:        if (getshort(hp->sync) != JUPITER_SYNC) {
                   1068:                /* Wasn't at the front, sync up */
                   1069:                jupiter_debug(instance->peer, "jupiter_recv", "syncing");
                   1070:                bp = (u_char *)sp;
                   1071:                n = size;
                   1072:                while (n >= 2) {
                   1073:                        if (bp[0] != (JUPITER_SYNC & 0xff)) {
                   1074:                                /*
                   1075:                                jupiter_debug(instance->peer, "{0x%x}", bp[0]);
                   1076:                                */
                   1077:                                ++bp;
                   1078:                                --n;
                   1079:                                continue;
                   1080:                        }
                   1081:                        if (bp[1] == ((JUPITER_SYNC >> 8) & 0xff))
                   1082:                                break;
                   1083:                        /*
                   1084:                        jupiter_debug(instance->peer, "{0x%x 0x%x}", bp[0], bp[1]);
                   1085:                        */
                   1086:                        bp += 2;
                   1087:                        n -= 2;
                   1088:                }
                   1089:                /*
                   1090:                jupiter_debug(instance->peer, "\n");
                   1091:                */
                   1092:                /* Shuffle data to front of input buffer */
                   1093:                if (n > 0)
                   1094:                        memcpy(sp, bp, n);
                   1095:                size = n;
                   1096:                instance->ssize = size;
                   1097:                if (size < cc || hp->sync != JUPITER_SYNC)
                   1098:                        return (0);
                   1099:        }
                   1100: 
                   1101:        if (jupiter_cksum(sp, (cc / sizeof(u_short) - 1)) !=
                   1102:            getshort(hp->hsum)) {
                   1103:            jupiter_debug(instance->peer, "jupiter_recv", "bad header checksum!");
                   1104:                /* This is drastic but checksum errors should be rare */
                   1105:                instance->ssize = 0;
                   1106:                return (0);
                   1107:        }
                   1108: 
                   1109:        /* Check for a payload */
                   1110:        len = getshort(hp->len);
                   1111:        if (len > 0) {
                   1112:                n = (len + 1) * sizeof(u_short);
                   1113:                /* Not enough data yet */
                   1114:                if (size < cc + n)
                   1115:                        return (0);
                   1116: 
                   1117:                /* Check payload checksum */
                   1118:                sp = (u_short *)(hp + 1);
                   1119:                if (jupiter_cksum(sp, len) != getshort(sp[len])) {
                   1120:                        jupiter_debug(instance->peer,
                   1121:                            "jupiter_recv", "bad payload checksum!");
                   1122:                        /* This is drastic but checksum errors should be rare */
                   1123:                        instance->ssize = 0;
                   1124:                        return (0);
                   1125:                }
                   1126:                cc += n;
                   1127:        }
                   1128:        return (cc);
                   1129: }
                   1130: 
                   1131: #else /* not (REFCLOCK && CLOCK_JUPITER && HAVE_PPSAPI) */
                   1132: int refclock_jupiter_bs;
                   1133: #endif /* not (REFCLOCK && CLOCK_JUPITER && HAVE_PPSAPI) */

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