⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 refclock_jupiter.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 2 页
字号:
			}			/*			 * 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)",			    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 voidjupiter_debug(struct peer *peer, char *function, char *fmt, ...)#elsestatic voidjupiter_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, 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 voidjupiter_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,	JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK | JUPITER_FLAG_DISC,	0};static voidjupiter_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,	JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK | JUPITER_FLAG_QUERY,	0};static voidjupiter_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,	    JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK, 0 },	{ 0, 0, 0 }};static voidjupiter_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_shortjupiter_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 intjupiter_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) */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -