Annotation of embedaddon/ntp/ntpd/refclock_jupiter.c, revision 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>