diff options
author | roberto <roberto@FreeBSD.org> | 2008-08-17 17:37:33 +0000 |
---|---|---|
committer | roberto <roberto@FreeBSD.org> | 2008-08-17 17:37:33 +0000 |
commit | 4ded1c1fa0bc21c61f91a2dbe864835986745121 (patch) | |
tree | 16d100fbc9dae63888d48b464e471ba0e5065193 /contrib/ntp/ntpd/refclock_jupiter.c | |
parent | 8b5a86d4fda08a9c68231415812edcb26be52f79 (diff) | |
download | FreeBSD-src-4ded1c1fa0bc21c61f91a2dbe864835986745121.zip FreeBSD-src-4ded1c1fa0bc21c61f91a2dbe864835986745121.tar.gz |
Flatten the dist and various 4.n.n trees in preparation of future ntp imports.
Diffstat (limited to 'contrib/ntp/ntpd/refclock_jupiter.c')
-rw-r--r-- | contrib/ntp/ntpd/refclock_jupiter.c | 1140 |
1 files changed, 0 insertions, 1140 deletions
diff --git a/contrib/ntp/ntpd/refclock_jupiter.c b/contrib/ntp/ntpd/refclock_jupiter.c deleted file mode 100644 index eff088b..0000000 --- a/contrib/ntp/ntpd/refclock_jupiter.c +++ /dev/null @@ -1,1140 +0,0 @@ -/* - * Copyright (c) 1997, 1998, 2003 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Lawrence Berkeley Laboratory. - * 4. The name of the University may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - -#if defined(REFCLOCK) && defined(CLOCK_JUPITER) && defined(HAVE_PPSAPI) - -#include "ntpd.h" -#include "ntp_io.h" -#include "ntp_refclock.h" -#include "ntp_unixtime.h" -#include "ntp_stdlib.h" - -#include <stdio.h> -#include <ctype.h> - -#include "jupiter.h" - -#ifdef HAVE_PPSAPI -# ifdef HAVE_TIMEPPS_H -# include <timepps.h> -# else -# ifdef HAVE_SYS_TIMEPPS_H -# include <sys/timepps.h> -# endif -# endif -#endif - -#ifdef XNTP_BIG_ENDIAN -#define getshort(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) -#define putshort(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) -#else -#define getshort(s) (s) -#define putshort(s) (s) -#endif - -/* XXX */ -#ifdef sun -char *strerror(int); -#endif - -/* - * This driver supports the Rockwell Jupiter GPS Receiver board - * adapted to precision timing applications. It requires the - * ppsclock line discipline or streams module described in the - * Line Disciplines and Streams Drivers page. It also requires a - * gadget box and 1-PPS level converter, such as described in the - * Pulse-per-second (PPS) Signal Interfacing page. - * - * It may work (with minor modifications) with other Rockwell GPS - * receivers such as the CityTracker. - */ - -/* - * GPS Definitions - */ -#define DEVICE "/dev/gps%d" /* device name and unit */ -#define SPEED232 B9600 /* baud */ - -/* - * Radio interface parameters - */ -#define PRECISION (-18) /* precision assumed (about 4 us) */ -#define REFID "GPS\0" /* reference id */ -#define DESCRIPTION "Rockwell Jupiter GPS Receiver" /* who we are */ -#define DEFFUDGETIME 0 /* default fudge time (ms) */ - -/* Unix timestamp for the GPS epoch: January 6, 1980 */ -#define GPS_EPOCH 315964800 - -/* Double short to unsigned int */ -#define DS2UI(p) ((getshort((p)[1]) << 16) | getshort((p)[0])) - -/* Double short to signed int */ -#define DS2I(p) ((getshort((p)[1]) << 16) | getshort((p)[0])) - -/* One week's worth of seconds */ -#define WEEKSECS (7 * 24 * 60 * 60) - -/* - * Jupiter unit control structure. - */ -struct instance { - struct peer *peer; /* peer */ - u_int pollcnt; /* poll message counter */ - u_int polled; /* Hand in a time sample? */ -#ifdef HAVE_PPSAPI - pps_params_t pps_params; /* pps parameters */ - pps_info_t pps_info; /* last pps data */ - pps_handle_t pps_handle; /* pps handle */ - u_int assert; /* pps edge to use */ - struct timespec ts; /* last timestamp */ -#endif - l_fp limit; - u_int gpos_gweek; /* Current GPOS GPS week number */ - u_int gpos_sweek; /* Current GPOS GPS seconds into week */ - u_int gweek; /* current GPS week number */ - u_int32 lastsweek; /* last seconds into GPS week */ - time_t timecode; /* current ntp timecode */ - u_int32 stime; /* used to detect firmware bug */ - int wantid; /* don't reconfig on channel id msg */ - u_int moving; /* mobile platform? */ - u_char sloppyclockflag; /* fudge flags */ - u_short sbuf[512]; /* local input buffer */ - int ssize; /* space used in sbuf */ -}; - -/* - * Function prototypes - */ -static void jupiter_canmsg P((struct instance *, u_int)); -static u_short jupiter_cksum P((u_short *, u_int)); -static int jupiter_config P((struct instance *)); -static void jupiter_debug P((struct peer *, char *, char *, ...)) - __attribute__ ((format (printf, 3, 4))); -static char * jupiter_parse_t P((struct instance *, u_short *)); -static char * jupiter_parse_gpos P((struct instance *, u_short *)); -static void jupiter_platform P((struct instance *, u_int)); -static void jupiter_poll P((int, struct peer *)); -static void jupiter_control P((int, struct refclockstat *, struct - refclockstat *, struct peer *)); -#ifdef HAVE_PPSAPI -static int jupiter_ppsapi P((struct instance *, int, int)); -static int jupiter_pps P((struct instance *)); -#endif /* HAVE_PPSAPI */ -static int jupiter_recv P((struct instance *)); -static void jupiter_receive P((struct recvbuf *rbufp)); -static void jupiter_reqmsg P((struct instance *, u_int, u_int)); -static void jupiter_reqonemsg P((struct instance *, u_int)); -static char * jupiter_send P((struct instance *, struct jheader *)); -static void jupiter_shutdown P((int, struct peer *)); -static int jupiter_start P((int, struct peer *)); - -/* - * Transfer vector - */ -struct refclock refclock_jupiter = { - jupiter_start, /* start up driver */ - jupiter_shutdown, /* shut down driver */ - jupiter_poll, /* transmit poll message */ - jupiter_control, /* (clock control) */ - noentry, /* (clock init) */ - noentry, /* (clock buginfo) */ - NOFLAGS /* not used */ -}; - -/* - * jupiter_start - open the devices and initialize data for processing - */ -static int -jupiter_start( - int unit, - struct peer *peer - ) -{ - struct refclockproc *pp; - struct instance *instance; - int fd = -1; - char gpsdev[20]; - - /* - * Open serial port - */ - (void)sprintf(gpsdev, DEVICE, unit); - fd = refclock_open(gpsdev, SPEED232, LDISC_RAW); - if (fd == 0) { - jupiter_debug(peer, "jupiter_start", "open %s: %s", - gpsdev, strerror(errno)); - return (0); - } - - /* Allocate unit structure */ - if ((instance = (struct instance *) - emalloc(sizeof(struct instance))) == NULL) { - (void) close(fd); - return (0); - } - memset((char *)instance, 0, sizeof(struct instance)); - instance->peer = peer; - pp = peer->procptr; - pp->io.clock_recv = jupiter_receive; - pp->io.srcclock = (caddr_t)peer; - pp->io.datalen = 0; - pp->io.fd = fd; - if (!io_addclock(&pp->io)) { - (void) close(fd); - free(instance); - return (0); - } - pp->unitptr = (caddr_t)instance; - - /* - * Initialize miscellaneous variables - */ - peer->precision = PRECISION; - pp->clockdesc = DESCRIPTION; - memcpy((char *)&pp->refid, REFID, 4); - -#ifdef HAVE_PPSAPI - /* - * Start the PPSAPI interface if it is there. Default to use - * the assert edge and do not enable the kernel hardpps. - */ - if (time_pps_create(fd, &instance->pps_handle) < 0) { - instance->pps_handle = 0; - msyslog(LOG_ERR, - "refclock_jupiter: time_pps_create failed: %m"); - } - else if (!jupiter_ppsapi(instance, 0, 0)) - goto clean_up; -#endif /* HAVE_PPSAPI */ - - /* Ensure the receiver is properly configured */ - if (!jupiter_config(instance)) - goto clean_up; - - return (1); - -clean_up: - jupiter_shutdown(unit, peer); - pp->unitptr = 0; - return (0); -} - -/* - * jupiter_shutdown - shut down the clock - */ -static void -jupiter_shutdown(int unit, struct peer *peer) -{ - struct instance *instance; - struct refclockproc *pp; - - pp = peer->procptr; - instance = (struct instance *)pp->unitptr; - if(!instance) - return; - -#ifdef HAVE_PPSAPI - if (instance->pps_handle) { - time_pps_destroy(instance->pps_handle); - instance->pps_handle = 0; - } -#endif /* HAVE_PPSAPI */ - - io_closeclock(&pp->io); - free(instance); -} - -/* - * jupiter_config - Configure the receiver - */ -static int -jupiter_config(struct instance *instance) -{ - jupiter_debug(instance->peer, "jupiter_config", "init receiver"); - - /* - * Initialize the unit variables - */ - instance->sloppyclockflag = instance->peer->procptr->sloppyclockflag; - instance->moving = !!(instance->sloppyclockflag & CLK_FLAG2); - if (instance->moving) - jupiter_debug(instance->peer, "jupiter_config", - "mobile platform"); - - instance->pollcnt = 2; - instance->polled = 0; - instance->gpos_gweek = 0; - instance->gpos_sweek = 0; - instance->gweek = 0; - instance->lastsweek = 2 * WEEKSECS; - instance->timecode = 0; - instance->stime = 0; - instance->ssize = 0; - - /* Stop outputting all messages */ - jupiter_canmsg(instance, JUPITER_ALL); - - /* Request the receiver id so we can syslog the firmware version */ - jupiter_reqonemsg(instance, JUPITER_O_ID); - - /* Flag that this the id was requested (so we don't get called again) */ - instance->wantid = 1; - - /* Request perodic time mark pulse messages */ - jupiter_reqmsg(instance, JUPITER_O_PULSE, 1); - - /* Request perodic geodetic position status */ - jupiter_reqmsg(instance, JUPITER_O_GPOS, 1); - - /* Set application platform type */ - if (instance->moving) - jupiter_platform(instance, JUPITER_I_PLAT_MED); - else - jupiter_platform(instance, JUPITER_I_PLAT_LOW); - - return (1); -} - -#ifdef HAVE_PPSAPI -/* - * Initialize PPSAPI - */ -int -jupiter_ppsapi( - struct instance *instance, /* unit structure pointer */ - int enb_clear, /* clear enable */ - int enb_hardpps /* hardpps enable */ - ) -{ - int capability; - - if (time_pps_getcap(instance->pps_handle, &capability) < 0) { - msyslog(LOG_ERR, - "refclock_jupiter: time_pps_getcap failed: %m"); - return (0); - } - memset(&instance->pps_params, 0, sizeof(pps_params_t)); - if (enb_clear) - instance->pps_params.mode = capability & PPS_CAPTURECLEAR; - else - instance->pps_params.mode = capability & PPS_CAPTUREASSERT; - if (!(instance->pps_params.mode & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR))) { - msyslog(LOG_ERR, - "refclock_jupiter: invalid capture edge %d", - !enb_clear); - return (0); - } - instance->pps_params.mode |= PPS_TSFMT_TSPEC; - if (time_pps_setparams(instance->pps_handle, &instance->pps_params) < 0) { - msyslog(LOG_ERR, - "refclock_jupiter: time_pps_setparams failed: %m"); - return (0); - } - if (enb_hardpps) { - if (time_pps_kcbind(instance->pps_handle, PPS_KC_HARDPPS, - instance->pps_params.mode & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR), - PPS_TSFMT_TSPEC) < 0) { - msyslog(LOG_ERR, - "refclock_jupiter: time_pps_kcbind failed: %m"); - return (0); - } - pps_enable = 1; - } -/* instance->peer->precision = PPS_PRECISION; */ - -#if DEBUG - if (debug) { - time_pps_getparams(instance->pps_handle, &instance->pps_params); - jupiter_debug(instance->peer, "refclock_jupiter", - "pps capability 0x%x version %d mode 0x%x kern %d", - capability, instance->pps_params.api_version, - instance->pps_params.mode, enb_hardpps); - } -#endif - - return (1); -} - -/* - * Get PPSAPI timestamps. - * - * Return 0 on failure and 1 on success. - */ -static int -jupiter_pps(struct instance *instance) -{ - pps_info_t pps_info; - struct timespec timeout, ts; - double dtemp; - l_fp tstmp; - - /* - * Convert the timespec nanoseconds field to ntp l_fp units. - */ - if (instance->pps_handle == 0) - return 1; - timeout.tv_sec = 0; - timeout.tv_nsec = 0; - memcpy(&pps_info, &instance->pps_info, sizeof(pps_info_t)); - if (time_pps_fetch(instance->pps_handle, PPS_TSFMT_TSPEC, &instance->pps_info, - &timeout) < 0) - return 1; - if (instance->pps_params.mode & PPS_CAPTUREASSERT) { - if (pps_info.assert_sequence == - instance->pps_info.assert_sequence) - return 1; - ts = instance->pps_info.assert_timestamp; - } else if (instance->pps_params.mode & PPS_CAPTURECLEAR) { - if (pps_info.clear_sequence == - instance->pps_info.clear_sequence) - return 1; - ts = instance->pps_info.clear_timestamp; - } else { - return 1; - } - if ((instance->ts.tv_sec == ts.tv_sec) && (instance->ts.tv_nsec == ts.tv_nsec)) - return 1; - instance->ts = ts; - - tstmp.l_ui = ts.tv_sec + JAN_1970; - dtemp = ts.tv_nsec * FRAC / 1e9; - tstmp.l_uf = (u_int32)dtemp; - instance->peer->procptr->lastrec = tstmp; - return 0; -} -#endif /* HAVE_PPSAPI */ - -/* - * jupiter_poll - jupiter watchdog routine - */ -static void -jupiter_poll(int unit, struct peer *peer) -{ - struct instance *instance; - struct refclockproc *pp; - - pp = peer->procptr; - instance = (struct instance *)pp->unitptr; - - /* - * You don't need to poll this clock. It puts out timecodes - * once per second. If asked for a timestamp, take note. - * The next time a timecode comes in, it will be fed back. - */ - - /* - * If we haven't had a response in a while, reset the receiver. - */ - if (instance->pollcnt > 0) { - instance->pollcnt--; - } else { - refclock_report(peer, CEVNT_TIMEOUT); - - /* Request the receiver id to trigger a reconfig */ - jupiter_reqonemsg(instance, JUPITER_O_ID); - instance->wantid = 0; - } - - /* - * polled every 64 seconds. Ask jupiter_receive to hand in - * a timestamp. - */ - instance->polled = 1; - pp->polls++; -} - -/* - * jupiter_control - fudge control - */ -static void -jupiter_control( - int unit, /* unit (not used) */ - struct refclockstat *in, /* input parameters (not used) */ - struct refclockstat *out, /* output parameters (not used) */ - struct peer *peer /* peer structure pointer */ - ) -{ - struct refclockproc *pp; - struct instance *instance; - u_char sloppyclockflag; - - pp = peer->procptr; - instance = (struct instance *)pp->unitptr; - - DTOLFP(pp->fudgetime2, &instance->limit); - /* Force positive value. */ - if (L_ISNEG(&instance->limit)) - L_NEG(&instance->limit); - -#ifdef HAVE_PPSAPI - instance->assert = !(pp->sloppyclockflag & CLK_FLAG3); - jupiter_ppsapi(instance, !instance->assert, 0); -#endif /* HAVE_PPSAPI */ - - sloppyclockflag = instance->sloppyclockflag; - instance->sloppyclockflag = pp->sloppyclockflag; - if ((instance->sloppyclockflag & CLK_FLAG2) != - (sloppyclockflag & CLK_FLAG2)) { - jupiter_debug(peer, - "jupiter_control", - "mode switch: reset receiver"); - jupiter_config(instance); - return; - } -} - -/* - * jupiter_receive - receive gps data - * Gag me! - */ -static void -jupiter_receive(struct recvbuf *rbufp) -{ - int bpcnt, cc, size, ppsret; - time_t last_timecode; - u_int32 laststime; - char *cp; - u_char *bp; - u_short *sp; - struct jid *ip; - struct jheader *hp; - struct peer *peer; - struct refclockproc *pp; - struct instance *instance; - l_fp tstamp; - - /* Initialize pointers and read the timecode and timestamp */ - peer = (struct peer *)rbufp->recv_srcclock; - pp = peer->procptr; - instance = (struct instance *)pp->unitptr; - - bp = (u_char *)rbufp->recv_buffer; - bpcnt = rbufp->recv_length; - - /* This shouldn't happen */ - if (bpcnt > sizeof(instance->sbuf) - instance->ssize) - bpcnt = sizeof(instance->sbuf) - instance->ssize; - - /* Append to input buffer */ - memcpy((u_char *)instance->sbuf + instance->ssize, bp, bpcnt); - instance->ssize += bpcnt; - - /* While there's at least a header and we parse an intact message */ - while (instance->ssize > sizeof(*hp) && (cc = jupiter_recv(instance)) > 0) { - instance->pollcnt = 2; - - tstamp = rbufp->recv_time; - hp = (struct jheader *)instance->sbuf; - sp = (u_short *)(hp + 1); - size = cc - sizeof(*hp); - switch (getshort(hp->id)) { - - case JUPITER_O_PULSE: - if (size != sizeof(struct jpulse)) { - jupiter_debug(peer, - "jupiter_receive", "pulse: len %d != %u", - size, (int)sizeof(struct jpulse)); - refclock_report(peer, CEVNT_BADREPLY); - break; - } - - /* - * There appears to be a firmware bug related - * to the pulse message; in addition to the one - * per second messages, we get an extra pulse - * message once an hour (on the anniversary of - * the cold start). It seems to come 200 ms - * after the one requested. So if we've seen a - * pulse message in the last 210 ms, we skip - * this one. - */ - laststime = instance->stime; - instance->stime = DS2UI(((struct jpulse *)sp)->stime); - if (laststime != 0 && instance->stime - laststime <= 21) { - jupiter_debug(peer, "jupiter_receive", - "avoided firmware bug (stime %.2f, laststime %.2f)", - (double)instance->stime * 0.01, (double)laststime * 0.01); - break; - } - - /* Retrieve pps timestamp */ - ppsret = jupiter_pps(instance); - - /* - * Add one second if msg received early - * (i.e. before limit, a.k.a. fudgetime2) in - * the second. - */ - L_SUB(&tstamp, &pp->lastrec); - if (!L_ISGEQ(&tstamp, &instance->limit)) - ++pp->lastrec.l_ui; - - /* Parse timecode (even when there's no pps) */ - last_timecode = instance->timecode; - if ((cp = jupiter_parse_t(instance, sp)) != NULL) { - jupiter_debug(peer, - "jupiter_receive", "pulse: %s", cp); - break; - } - - /* Bail if we didn't get a pps timestamp */ - if (ppsret) - break; - - /* Bail if we don't have the last timecode yet */ - if (last_timecode == 0) - break; - - /* Add the new sample to a median filter */ - tstamp.l_ui = JAN_1970 + last_timecode; - tstamp.l_uf = 0; - - refclock_process_offset(pp, tstamp, pp->lastrec, pp->fudgetime1); - - /* - * The clock will blurt a timecode every second - * but we only want one when polled. If we - * havn't been polled, bail out. - */ - if (!instance->polled) - break; - instance->polled = 0; - - /* - * It's a live one! Remember this time. - */ - - pp->lastref = pp->lastrec; - refclock_receive(peer); - - /* - * If we get here - what we got from the clock is - * OK, so say so - */ - refclock_report(peer, CEVNT_NOMINAL); - - /* - * We have succeeded in answering the poll. - * Turn off the flag and return - */ - instance->polled = 0; - break; - - case JUPITER_O_GPOS: - if (size != sizeof(struct jgpos)) { - jupiter_debug(peer, - "jupiter_receive", "gpos: len %d != %u", - size, (int)sizeof(struct jgpos)); - refclock_report(peer, CEVNT_BADREPLY); - break; - } - - if ((cp = jupiter_parse_gpos(instance, sp)) != NULL) { - jupiter_debug(peer, - "jupiter_receive", "gpos: %s", cp); - break; - } - break; - - case JUPITER_O_ID: - if (size != sizeof(struct jid)) { - jupiter_debug(peer, - "jupiter_receive", "id: len %d != %u", - size, (int)sizeof(struct jid)); - refclock_report(peer, CEVNT_BADREPLY); - break; - } - /* - * If we got this message because the Jupiter - * just powered instance, it needs to be reconfigured. - */ - ip = (struct jid *)sp; - jupiter_debug(peer, - "jupiter_receive", "%s chan ver %s, %s (%s)", - ip->chans, ip->vers, ip->date, ip->opts); - msyslog(LOG_DEBUG, - "jupiter_receive: %s chan ver %s, %s (%s)\n", - ip->chans, ip->vers, ip->date, ip->opts); - if (instance->wantid) - instance->wantid = 0; - else { - jupiter_debug(peer, - "jupiter_receive", "reset receiver"); - jupiter_config(instance); - /* - * Restore since jupiter_config() just - * zeroed it - */ - instance->ssize = cc; - } - break; - - default: - jupiter_debug(peer, - "jupiter_receive", "unknown message id %d", - getshort(hp->id)); - break; - } - instance->ssize -= cc; - if (instance->ssize < 0) { - fprintf(stderr, "jupiter_recv: negative ssize!\n"); - abort(); - } else if (instance->ssize > 0) - memcpy(instance->sbuf, (u_char *)instance->sbuf + cc, instance->ssize); - } -} - -static char * -jupiter_parse_t(struct instance *instance, u_short *sp) -{ - struct tm *tm; - char *cp; - struct jpulse *jp; - u_int32 sweek; - time_t last_timecode; - u_short flags; - - jp = (struct jpulse *)sp; - - /* The timecode is presented as seconds into the current GPS week */ - sweek = DS2UI(jp->sweek) % WEEKSECS; - - /* - * If we don't know the current GPS week, calculate it from the - * current time. (It's too bad they didn't include this - * important value in the pulse message). We'd like to pick it - * up from one of the other messages like gpos or chan but they - * don't appear to be synchronous with time keeping and changes - * too soon (something like 10 seconds before the new GPS - * week). - * - * If we already know the current GPS week, increment it when - * we wrap into a new week. - */ - if (instance->gweek == 0) { - if (!instance->gpos_gweek) { - return ("jupiter_parse_t: Unknown gweek"); - } - - instance->gweek = instance->gpos_gweek; - - /* - * Fix warps. GPOS has GPS time and PULSE has UTC. - * Plus, GPOS need not be completely in synch with - * the PPS signal. - */ - if (instance->gpos_sweek >= sweek) { - if ((instance->gpos_sweek - sweek) > WEEKSECS / 2) - ++instance->gweek; - } - else { - if ((sweek - instance->gpos_sweek) > WEEKSECS / 2) - --instance->gweek; - } - } - else if (sweek == 0 && instance->lastsweek == WEEKSECS - 1) { - ++instance->gweek; - jupiter_debug(instance->peer, - "jupiter_parse_t", "NEW gps week %u", instance->gweek); - } - - /* - * See if the sweek stayed the same (this happens when there is - * no pps pulse). - * - * Otherwise, look for time warps: - * - * - we have stored at least one lastsweek and - * - the sweek didn't increase by one and - * - we didn't wrap to a new GPS week - * - * Then we warped. - */ - if (instance->lastsweek == sweek) - jupiter_debug(instance->peer, - "jupiter_parse_t", "gps sweek not incrementing (%d)", - sweek); - else if (instance->lastsweek != 2 * WEEKSECS && - instance->lastsweek + 1 != sweek && - !(sweek == 0 && instance->lastsweek == WEEKSECS - 1)) - jupiter_debug(instance->peer, - "jupiter_parse_t", "gps sweek jumped (was %d, now %d)", - instance->lastsweek, sweek); - instance->lastsweek = sweek; - - /* This timecode describes next pulse */ - last_timecode = instance->timecode; - instance->timecode = - GPS_EPOCH + (instance->gweek * WEEKSECS) + sweek; - - if (last_timecode == 0) - /* XXX debugging */ - jupiter_debug(instance->peer, - "jupiter_parse_t", "UTC <none> (gweek/sweek %u/%u)", - instance->gweek, sweek); - else { - /* XXX debugging */ - tm = gmtime(&last_timecode); - cp = asctime(tm); - - jupiter_debug(instance->peer, - "jupiter_parse_t", "UTC %.24s (gweek/sweek %u/%u)", - cp, instance->gweek, sweek); - - /* Billboard last_timecode (which is now the current time) */ - instance->peer->procptr->year = tm->tm_year + 1900; - instance->peer->procptr->day = tm->tm_yday + 1; - instance->peer->procptr->hour = tm->tm_hour; - instance->peer->procptr->minute = tm->tm_min; - instance->peer->procptr->second = tm->tm_sec; - } - - flags = getshort(jp->flags); - - /* Toss if not designated "valid" by the gps */ - if ((flags & JUPITER_O_PULSE_VALID) == 0) { - refclock_report(instance->peer, CEVNT_BADTIME); - return ("time mark not valid"); - } - - /* We better be sync'ed to UTC... */ - if ((flags & JUPITER_O_PULSE_UTC) == 0) { - refclock_report(instance->peer, CEVNT_BADTIME); - return ("time mark not sync'ed to UTC"); - } - - return (NULL); -} - -static char * -jupiter_parse_gpos(struct instance *instance, u_short *sp) -{ - struct jgpos *jg; - time_t t; - struct tm *tm; - char *cp; - - jg = (struct jgpos *)sp; - - if (jg->navval != 0) { - /* - * Solution not valid. Use caution and refuse - * to determine GPS week from this message. - */ - instance->gpos_gweek = 0; - instance->gpos_sweek = 0; - return ("Navigation solution not valid"); - } - - instance->gpos_gweek = jg->gweek; - instance->gpos_sweek = DS2UI(jg->sweek); - while(instance->gpos_sweek >= WEEKSECS) { - instance->gpos_sweek -= WEEKSECS; - ++instance->gpos_gweek; - } - instance->gweek = 0; - - t = GPS_EPOCH + (instance->gpos_gweek * WEEKSECS) + instance->gpos_sweek; - tm = gmtime(&t); - cp = asctime(tm); - - jupiter_debug(instance->peer, - "jupiter_parse_g", "GPS %.24s (gweek/sweek %u/%u)", - cp, instance->gpos_gweek, instance->gpos_sweek); - return (NULL); -} - -/* - * jupiter_debug - print debug messages - */ -#if defined(__STDC__) || defined(SYS_WINNT) -static void -jupiter_debug(struct peer *peer, char *function, char *fmt, ...) -#else -static void -jupiter_debug(peer, function, fmt, va_alist) - struct peer *peer; - char *function; - char *fmt; -#endif /* __STDC__ */ -{ - char buffer[200]; - va_list ap; - -#if defined(__STDC__) || defined(SYS_WINNT) - va_start(ap, fmt); -#else - va_start(ap); -#endif /* __STDC__ */ - /* - * Print debug message to stdout - * In the future, we may want to get get more creative... - */ - vsnprintf(buffer, sizeof(buffer), fmt, ap); - record_clock_stats(&(peer->srcadr), buffer); - if (debug) { - fprintf(stdout, "%s: ", function); - fprintf(stdout, buffer); - fprintf(stdout, "\n"); - fflush(stdout); - } - - va_end(ap); -} - -/* Checksum and transmit a message to the Jupiter */ -static char * -jupiter_send(struct instance *instance, struct jheader *hp) -{ - u_int len, size; - int cc; - u_short *sp; - static char errstr[132]; - - size = sizeof(*hp); - hp->hsum = putshort(jupiter_cksum((u_short *)hp, - (size / sizeof(u_short)) - 1)); - len = getshort(hp->len); - if (len > 0) { - sp = (u_short *)(hp + 1); - sp[len] = putshort(jupiter_cksum(sp, len)); - size += (len + 1) * sizeof(u_short); - } - - if ((cc = write(instance->peer->procptr->io.fd, (char *)hp, size)) < 0) { - (void)sprintf(errstr, "write: %s", strerror(errno)); - return (errstr); - } else if (cc != size) { - (void)sprintf(errstr, "short write (%d != %d)", cc, size); - return (errstr); - } - return (NULL); -} - -/* Request periodic message output */ -static struct { - struct jheader jheader; - struct jrequest jrequest; -} reqmsg = { - { putshort(JUPITER_SYNC), 0, - putshort((sizeof(struct jrequest) / sizeof(u_short)) - 1), - 0, (u_char)putshort(JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK | - JUPITER_FLAG_CONN | JUPITER_FLAG_LOG), 0 }, - { 0, 0, 0, 0 } -}; - -/* An interval of zero means to output on trigger */ -static void -jupiter_reqmsg(struct instance *instance, u_int id, - u_int interval) -{ - struct jheader *hp; - struct jrequest *rp; - char *cp; - - hp = &reqmsg.jheader; - hp->id = putshort(id); - rp = &reqmsg.jrequest; - rp->trigger = putshort(interval == 0); - rp->interval = putshort(interval); - if ((cp = jupiter_send(instance, hp)) != NULL) - jupiter_debug(instance->peer, "jupiter_reqmsg", "%u: %s", id, cp); -} - -/* Cancel periodic message output */ -static struct jheader canmsg = { - putshort(JUPITER_SYNC), 0, 0, 0, - (u_char)putshort(JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK | JUPITER_FLAG_DISC), - 0 -}; - -static void -jupiter_canmsg(struct instance *instance, u_int id) -{ - struct jheader *hp; - char *cp; - - hp = &canmsg; - hp->id = putshort(id); - if ((cp = jupiter_send(instance, hp)) != NULL) - jupiter_debug(instance->peer, "jupiter_canmsg", "%u: %s", id, cp); -} - -/* Request a single message output */ -static struct jheader reqonemsg = { - putshort(JUPITER_SYNC), 0, 0, 0, - (u_char)putshort(JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK | JUPITER_FLAG_QUERY), - 0 -}; - -static void -jupiter_reqonemsg(struct instance *instance, u_int id) -{ - struct jheader *hp; - char *cp; - - hp = &reqonemsg; - hp->id = putshort(id); - if ((cp = jupiter_send(instance, hp)) != NULL) - jupiter_debug(instance->peer, "jupiter_reqonemsg", "%u: %s", id, cp); -} - -/* Set the platform dynamics */ -static struct { - struct jheader jheader; - struct jplat jplat; -} platmsg = { - { putshort(JUPITER_SYNC), putshort(JUPITER_I_PLAT), - putshort((sizeof(struct jplat) / sizeof(u_short)) - 1), 0, - (u_char)putshort(JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK), 0 }, - { 0, 0, 0 } -}; - -static void -jupiter_platform(struct instance *instance, u_int platform) -{ - struct jheader *hp; - struct jplat *pp; - char *cp; - - hp = &platmsg.jheader; - pp = &platmsg.jplat; - pp->platform = putshort(platform); - if ((cp = jupiter_send(instance, hp)) != NULL) - jupiter_debug(instance->peer, "jupiter_platform", "%u: %s", platform, cp); -} - -/* Checksum "len" shorts */ -static u_short -jupiter_cksum(u_short *sp, u_int len) -{ - u_short sum, x; - - sum = 0; - while (len-- > 0) { - x = *sp++; - sum += getshort(x); - } - return (~sum + 1); -} - -/* Return the size of the next message (or zero if we don't have it all yet) */ -static int -jupiter_recv(struct instance *instance) -{ - int n, len, size, cc; - struct jheader *hp; - u_char *bp; - u_short *sp; - - /* Must have at least a header's worth */ - cc = sizeof(*hp); - size = instance->ssize; - if (size < cc) - return (0); - - /* Search for the sync short if missing */ - sp = instance->sbuf; - hp = (struct jheader *)sp; - if (getshort(hp->sync) != JUPITER_SYNC) { - /* Wasn't at the front, sync up */ - jupiter_debug(instance->peer, "jupiter_recv", "syncing"); - bp = (u_char *)sp; - n = size; - while (n >= 2) { - if (bp[0] != (JUPITER_SYNC & 0xff)) { - /* - jupiter_debug(instance->peer, "{0x%x}", bp[0]); - */ - ++bp; - --n; - continue; - } - if (bp[1] == ((JUPITER_SYNC >> 8) & 0xff)) - break; - /* - jupiter_debug(instance->peer, "{0x%x 0x%x}", bp[0], bp[1]); - */ - bp += 2; - n -= 2; - } - /* - jupiter_debug(instance->peer, "\n"); - */ - /* Shuffle data to front of input buffer */ - if (n > 0) - memcpy(sp, bp, n); - size = n; - instance->ssize = size; - if (size < cc || hp->sync != JUPITER_SYNC) - return (0); - } - - if (jupiter_cksum(sp, (cc / sizeof(u_short) - 1)) != - getshort(hp->hsum)) { - jupiter_debug(instance->peer, "jupiter_recv", "bad header checksum!"); - /* This is drastic but checksum errors should be rare */ - instance->ssize = 0; - return (0); - } - - /* Check for a payload */ - len = getshort(hp->len); - if (len > 0) { - n = (len + 1) * sizeof(u_short); - /* Not enough data yet */ - if (size < cc + n) - return (0); - - /* Check payload checksum */ - sp = (u_short *)(hp + 1); - if (jupiter_cksum(sp, len) != getshort(sp[len])) { - jupiter_debug(instance->peer, - "jupiter_recv", "bad payload checksum!"); - /* This is drastic but checksum errors should be rare */ - instance->ssize = 0; - return (0); - } - cc += n; - } - return (cc); -} - -#else /* not (REFCLOCK && CLOCK_JUPITER && HAVE_PPSAPI) */ -int refclock_jupiter_bs; -#endif /* not (REFCLOCK && CLOCK_JUPITER && HAVE_PPSAPI) */ |