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

📄 refclock_jupiter.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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# include "ppsapi_timepps.h"#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 sunchar *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 */	u_int hardpps;			/* enable kernel mode */	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_PPSAPIstatic	int	jupiter_ppsapi	P((struct instance *));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 intjupiter_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	instance->assert = 1;	instance->hardpps = 0;	/*	 * 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))		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 voidjupiter_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 intjupiter_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 */intjupiter_ppsapi(	struct instance *instance	/* unit structure pointer */	){	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 (!instance->assert)		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",		    instance->assert);		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 (instance->hardpps) {		if (time_pps_kcbind(instance->pps_handle, PPS_KC_HARDPPS,				    instance->pps_params.mode & ~PPS_TSFMT_TSPEC,				    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, instance->hardpps);	}#endif	return (1);}/* * Get PPSAPI timestamps. * * Return 0 on failure and 1 on success. */static intjupiter_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 voidjupiter_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 voidjupiter_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);#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 voidjupiter_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;

⌨️ 快捷键说明

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