📄 173
字号:
X while (i > 0) {X L_RSHIFT(&lftmp);X i--;X }X offset = lftmp;X } else {X i = (n + i) / 2;X offset = off[i];X }XX /*X * The payload: filtered offset and dispersion.X */XX pp->offset = offset;X pp->dispersion = disp;XX return (NULL);XX}XX/* Compare two l_fp's, used with qsort() */XintX#ifdef QSORT_USES_VOID_PXjupiter_cmpl_fp(register const void *p1, register const void *p2)X#elseXjupiter_cmpl_fp(register const l_fp *fp1, register const l_fp *fp2)X#endifX{X#ifdef QSORT_USES_VOID_PX register const l_fp *fp1 = (const l_fp *)p1;X register const l_fp *fp2 = (const l_fp *)p2;X#endifXX if (!L_ISGEQ(fp1, fp2))X return (-1);X if (L_ISEQU(fp1, fp2))X return (0);X return (1);X}XXstatic char *Xjupiter_parse_t(register struct peer *peer, register u_short *sp)X{X register struct refclockproc *pp;X register struct jupiterunit *up;X register struct tm *tm;X register char *cp;X register struct jpulse *jp;X register struct calendar *jt;X register u_int32 sweek;X register u_int32 last_timecode;X register u_short flags;X time_t t;X struct calendar cal;XX pp = peer->procptr;X up = (struct jupiterunit *)pp->unitptr;X jp = (struct jpulse *)sp;XX /* The timecode is presented as seconds into the current GPS week */X sweek = DS2UI(jp->sweek);XX /*X * If we don't know the current GPS week, calculate it from theX * current time. (It's too bad they didn't include thisX * important value in the pulse message). We'd like to pick itX * up from one of the other messages like gpos or chan but theyX * don't appear to be synchronous with time keeping and changesX * too soon (something like 10 seconds before the new GPSX * week).X *X * If we already know the current GPS week, increment it whenX * we wrap into a new week.X */X if (up->gweek == 0)X up->gweek = (time(NULL) - GPS_EPOCH) / WEEKSECS;X else if (sweek == 0 && up->lastsweek == WEEKSECS - 1) {X ++up->gweek;X jupiter_debug(peer,X "jupiter_parse_t: NEW gps week %u\n", up->gweek);X }XX /*X * See if the sweek stayed the same (this happens when there isX * no pps pulse).X *X * Otherwise, look for time warps:X *X * - we have stored at least one lastsweek andX * - the sweek didn't increase by one andX * - we didn't wrap to a new GPS weekX *X * Then we warped.X */X if (up->lastsweek == sweek)X jupiter_debug(peer,X "jupiter_parse_t: gps sweek not incrementing (%d)\n",X sweek);X else if (up->lastsweek != 2 * WEEKSECS &&X up->lastsweek + 1 != sweek &&X !(sweek == 0 && up->lastsweek == WEEKSECS - 1))X jupiter_debug(peer,X "jupiter_parse_t: gps sweek jumped (was %d, now %d)\n",X up->lastsweek, sweek);X up->lastsweek = sweek;XX /* This timecode describes next pulse */X last_timecode = up->timecode;X up->timecode = (u_int32)JAN_1970 +X GPS_EPOCH + (up->gweek * WEEKSECS) + sweek;XX if (last_timecode == 0)X /* XXX debugging */X jupiter_debug(peer,X "jupiter_parse_t: UTC <none> (gweek/sweek %u/%u)\n",X up->gweek, sweek);X else {X /* XXX debugging */X t = last_timecode - (u_int32)JAN_1970;X tm = gmtime(&t);X cp = asctime(tm);XX jupiter_debug(peer,X "jupiter_parse_t: UTC %.24s (gweek/sweek %u/%u)\n",X cp, up->gweek, sweek);XX /* Billboard last_timecode (which is now the current time) */X jt = &cal;X caljulian(last_timecode, jt);X pp = peer->procptr;X pp->year = jt->year;X pp->day = jt->yearday;X pp->hour = jt->hour;X pp->minute = jt->minute;X pp->second = jt->second;X pp->msec = 0;X pp->usec = 0;X }XX /* XXX debugging */X tm = gmtime(&up->ppsev.tv.tv_sec);X cp = asctime(tm);X flags = getshort(jp->flags);X jupiter_debug(peer,X "jupiter_parse_t: PPS %.19s.%06lu %.4s (serial %u)%s\n",X cp, up->ppsev.tv.tv_usec, cp + 20, up->ppsev.serial,X (flags & JUPITER_O_PULSE_VALID) == 0 ?X " NOT VALID" : "");XX /* Toss if not designated "valid" by the gps */X if ((flags & JUPITER_O_PULSE_VALID) == 0) {X refclock_report(peer, CEVNT_BADTIME);X return ("time mark not valid");X }XX /* We better be sync'ed to UTC... */X if ((flags & JUPITER_O_PULSE_UTC) == 0) {X refclock_report(peer, CEVNT_BADTIME);X return ("time mark not sync'ed to UTC");X }XX return (NULL);X}XX/*X * Process a PPS signal, returning a timestamp.X */Xstatic intXjupiter_pps(register struct peer *peer)X{X register struct refclockproc *pp;X register struct jupiterunit *up;X register int firsttime;X struct timeval ntp_tv;XX pp = peer->procptr;X up = (struct jupiterunit *)pp->unitptr;XX /*X * Grab the timestamp of the PPS signal.X */X firsttime = (up->ppsev.tv.tv_sec == 0);X if (ioctl(pp->io.fd, CIOGETEV, (caddr_t)&up->ppsev) < 0) {X /* XXX Actually, if this fails, we're pretty much screwed */X jupiter_debug(peer, "jupiter_pps: CIOGETEV: %s\n",X strerror(errno));X refclock_report(peer, CEVNT_FAULT);X return (1);X }XX /*X * Check pps serial number against last oneX */X if (!firsttime && up->lastserial + 1 != up->ppsev.serial) {X if (up->ppsev.serial == up->lastserial)X jupiter_debug(peer, "jupiter_pps: no new pps event\n");X elseX jupiter_debug(peer,X "jupiter_pps: missed %d pps events\n",X up->ppsev.serial - up->lastserial - 1);X up->lastserial = up->ppsev.serial;X refclock_report(peer, CEVNT_FAULT);X return (1);X }X up->lastserial = up->ppsev.serial;XX /*X * Return the timestamp in pp->lastrecX */X ntp_tv = up->ppsev.tv;X ntp_tv.tv_sec += (u_int32)JAN_1970;X TVTOTS(&ntp_tv, &pp->lastrec);XX return (0);X}XX/*X * jupiter_debug - print debug messagesX */X#if __STDC__Xstatic voidXjupiter_debug(struct peer *peer, char *fmt, ...)X#elseXstatic voidXjupiter_debug(peer, fmt, va_alist)X struct peer *peer;X char *fmt;X#endifX{X va_list ap;XX if (debug) {XX#if __STDC__X va_start(ap, fmt);X#elseX va_start(ap);X#endifX /*X * Print debug message to stdoutX * In the future, we may want to get get more creative...X */X vfprintf(stderr, fmt, ap);XX va_end(ap);X }X}XX/* Checksum and transmit a message to the Jupiter */Xstatic char *Xjupiter_send(register struct peer *peer, register struct jheader *hp)X{X register u_int len, size;X register int cc;X register u_short *sp;X static char errstr[132];XX size = sizeof(*hp);X hp->hsum = putshort(jupiter_cksum((u_short *)hp,X (size / sizeof(u_short)) - 1));X len = getshort(hp->len);X if (len > 0) {X sp = (u_short *)(hp + 1);X sp[len] = putshort(jupiter_cksum(sp, len));X size += (len + 1) * sizeof(u_short);X }XX if ((cc = write(peer->procptr->io.fd, (char *)hp, size)) < 0) {X (void)sprintf(errstr, "write: %s", strerror(errno));X return (errstr);X } else if (cc != size) {X (void)sprintf(errstr, "short write (%d != %d)", cc, size);X return (errstr);X }X return (NULL);X}XX/* Request periodic message output */Xstatic struct {X struct jheader jheader;X struct jrequest jrequest;X} reqmsg = {X { putshort(JUPITER_SYNC), 0,X putshort((sizeof(struct jrequest) / sizeof(u_short)) - 1),X 0, putshort(JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK |X JUPITER_FLAG_CONN | JUPITER_FLAG_LOG), 0 },X { 0, 0, 0, 0 }X};XX/* An interval of zero means to output on trigger */Xstatic voidXjupiter_reqmsg(register struct peer *peer, register u_int id,X register u_int interval)X{X register struct jheader *hp;X register struct jrequest *rp;X register char *cp;XX hp = &reqmsg.jheader;X hp->id = putshort(id);X rp = &reqmsg.jrequest;X rp->trigger = putshort(interval == 0);X rp->interval = putshort(interval);X if ((cp = jupiter_send(peer, hp)) != NULL)X jupiter_debug(peer, "jupiter_reqmsg: %u: %s\n", id, cp);X}XX/* Cancel periodic message output */Xstatic struct jheader canmsg = {X putshort(JUPITER_SYNC), 0, 0, 0,X putshort(JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK | JUPITER_FLAG_DISC),X 0X};XXstatic voidXjupiter_canmsg(register struct peer *peer, register u_int id)X{X register struct jheader *hp;X register char *cp;XX hp = &canmsg;X hp->id = putshort(id);X if ((cp = jupiter_send(peer, hp)) != NULL)X jupiter_debug(peer, "jupiter_canmsg: %u: %s\n", id, cp);X}XX/* Request a single message output */Xstatic struct jheader reqonemsg = {X putshort(JUPITER_SYNC), 0, 0, 0,X putshort(JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK | JUPITER_FLAG_QUERY),X 0X};XXstatic voidXjupiter_reqonemsg(register struct peer *peer, register u_int id)X{X register struct jheader *hp;X register char *cp;XX hp = &reqonemsg;X hp->id = putshort(id);X if ((cp = jupiter_send(peer, hp)) != NULL)X jupiter_debug(peer, "jupiter_reqonemsg: %u: %s\n", id, cp);X}XX/* Set the platform dynamics */Xstatic struct {X struct jheader jheader;X struct jplat jplat;X} platmsg = {X { putshort(JUPITER_SYNC), putshort(JUPITER_I_PLAT),X putshort((sizeof(struct jplat) / sizeof(u_short)) - 1), 0,X putshort(JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK), 0 },X { 0, 0, 0 }X};XXstatic voidXjupiter_platform(register struct peer *peer, register u_int platform)X{X register struct jheader *hp;X register struct jplat *pp;X register char *cp;XX hp = &platmsg.jheader;X pp = &platmsg.jplat;X pp->platform = putshort(platform);X if ((cp = jupiter_send(peer, hp)) != NULL)X jupiter_debug(peer, "jupiter_platform: %u: %s\n", platform, cp);X}XX/* Checksum "len" shorts */Xstatic u_shortXjupiter_cksum(register u_short *sp, register u_int len)X{X register u_short sum, x;XX sum = 0;X while (len-- > 0) {X x = *sp++;X sum += getshort(x);X }X return (~sum + 1);X}XX/* Return the size of the next message (or zero if we don't have it all yet) */Xstatic intXjupiter_recv(register struct peer *peer)X{X register int n, len, size, cc;X register struct refclockproc *pp;X register struct jupiterunit *up;X register struct jheader *hp;X register u_char *bp;X register u_short *sp;XX pp = peer->procptr;X up = (struct jupiterunit *)pp->unitptr;XX /* Must have at least a header's worth */X cc = sizeof(*hp);X size = up->ssize;X if (size < cc)X return (0);XX /* Search for the sync short if missing */X sp = up->sbuf;X hp = (struct jheader *)sp;X if (getshort(hp->sync) != JUPITER_SYNC) {X /* Wasn't at the front, sync up */X jupiter_debug(peer, "syncing");X bp = (u_char *)sp;X n = size;X while (n >= 2) {X if (bp[0] != (JUPITER_SYNC & 0xff)) {X jupiter_debug(peer, "{0x%x}", bp[0]);X ++bp;X --n;X continue;X }X if (bp[1] == ((JUPITER_SYNC >> 8) & 0xff))X break;X jupiter_debug(peer, "{0x%x 0x%x}", bp[0], bp[1]);X bp += 2;X n -= 2;X }X jupiter_debug(peer, "\n");X /* Shuffle data to front of input buffer */X if (n > 0)X memcpy(sp, bp, n);X size = n;X up->ssize = size;X if (size < cc || hp->sync != JUPITER_SYNC)X return (0);X }XX if (jupiter_cksum(sp, (cc / sizeof(u_short) - 1)) !=X getshort(hp->hsum)) {X jupiter_debug(peer, "jupiter_recv: bad header checksum!\n");X /* This is drastic but checksum errors should be rare */X up->ssize = 0;X return (0);X }XX /* Check for a payload */X len = getshort(hp->len);X if (len > 0) {X n = (len + 1) * sizeof(u_short);X /* Not enough data yet */X if (size < cc + n)X return (0);XX /* Check payload checksum */X sp = (u_short *)(hp + 1);X if (jupiter_cksum
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -