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

📄 refclock_nmea.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * refclock_nmea.c - clock driver for an NMEA GPS CLOCK *		Michael Petry Jun 20, 1994 *		 based on refclock_heathn.c */#ifdef HAVE_CONFIG_H#include <config.h>#endif#if defined(SYS_WINNT)#undef close#define close closesocket#endif#if defined(REFCLOCK) && defined(CLOCK_NMEA)#include <stdio.h>#include <ctype.h>#include "ntpd.h"#include "ntp_io.h"#include "ntp_unixtime.h"#include "ntp_refclock.h"#include "ntp_stdlib.h"#ifdef HAVE_PPSAPI# include "ppsapi_timepps.h"#endif /* HAVE_PPSAPI *//* * This driver supports the NMEA GPS Receiver with * * Protype was refclock_trak.c, Thanks a lot. * * The receiver used spits out the NMEA sentences for boat navigation. * And you thought it was an information superhighway.  Try a raging river * filled with rapids and whirlpools that rip away your data and warp time. * * If HAVE_PPSAPI is defined code to use the PPSAPI will be compiled in. * On startup if initialization of the PPSAPI fails, it will fall back * to the "normal" timestamps. * * The PPSAPI part of the driver understands fudge flag2 and flag3. If * flag2 is set, it will use the clear edge of the pulse. If flag3 is * set, kernel hardpps is enabled. * * GPS sentences other than RMC (the default) may be enabled by setting * the relevent bits of 'mode' in the server configuration line * server 127.127.20.x mode X *  * bit 0 - enables RMC (1) * bit 1 - enables GGA (2) * bit 2 - enables GLL (4) * multiple sentences may be selected *//* * Definitions */#ifdef SYS_WINNT# define DEVICE "COM%d:" 	/* COM 1 - 3 supported */#else# define DEVICE	"/dev/gps%d"	/* name of radio device */#endif#define	SPEED232	B4800	/* uart speed (4800 bps) */#define	PRECISION	(-9)	/* precision assumed (about 2 ms) */#define	PPS_PRECISION	(-20)	/* precision assumed (about 1 us) */#define	REFID		"GPS\0"	/* reference id */#define	DESCRIPTION	"NMEA GPS Clock" /* who we are */#define NANOSECOND	1000000000 /* one second (ns) */#define RANGEGATE	500000	/* range gate (ns) */#define LENNMEA		75	/* min timecode length *//* * Tables to compute the ddd of year form icky dd/mm timecode. Viva la * leap. */static int day1tab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};static int day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};/* * Unit control structure */struct nmeaunit {	int	pollcnt;	/* poll message counter */	int	polled;		/* Hand in a sample? */	l_fp	tstamp;		/* timestamp of last poll */#ifdef HAVE_PPSAPI	struct timespec ts;	/* last timestamp */	pps_params_t pps_params; /* pps parameters */	pps_info_t pps_info;	/* last pps data */	pps_handle_t handle;	/* pps handlebars */#endif /* HAVE_PPSAPI */};/* * Function prototypes */static	int	nmea_start	P((int, struct peer *));static	void	nmea_shutdown	P((int, struct peer *));#ifdef HAVE_PPSAPIstatic	void	nmea_control	P((int, struct refclockstat *, struct				    refclockstat *, struct peer *));static	int	nmea_ppsapi	P((struct peer *, int, int));static	int	nmea_pps	P((struct nmeaunit *, l_fp *));#endif /* HAVE_PPSAPI */static	void	nmea_receive	P((struct recvbuf *));static	void	nmea_poll	P((int, struct peer *));static	void	gps_send	P((int, const char *, struct peer *));static	char	*field_parse	P((char *, int));/* * Transfer vector */struct	refclock refclock_nmea = {	nmea_start,		/* start up driver */	nmea_shutdown,	/* shut down driver */	nmea_poll,		/* transmit poll message */#ifdef HAVE_PPSAPI	nmea_control,		/* fudge control */#else	noentry,		/* fudge control */#endif /* HAVE_PPSAPI */	noentry,		/* initialize driver */	noentry,		/* buginfo */	NOFLAGS			/* not used */};/* * nmea_start - open the GPS devices and initialize data for processing */static intnmea_start(	int unit,	struct peer *peer	){	register struct nmeaunit *up;	struct refclockproc *pp;	int fd;	char device[20];	/*	 * Open serial port. Use CLK line discipline, if available.	 */	(void)sprintf(device, DEVICE, unit);	fd = refclock_open(device, SPEED232, LDISC_CLK);	if (fd <= 0) {#ifdef HAVE_READLINK          /* nmead support added by Jon Miner (cp_n18@yahoo.com)           *           * See http://home.hiwaay.net/~taylorc/gps/nmea-server/           * for information about nmead           *           * To use this, you need to create a link from /dev/gpsX to           * the server:port where nmead is running.  Something like this:           *           * ln -s server:port /dev/gps1           */          char buffer[80];          char *nmea_host;          int   nmea_port;          int   len;          struct hostent *he;          struct protoent *p;          struct sockaddr_in so_addr;          if ((len = readlink(device,buffer,sizeof(buffer))) == -1)            return(0);          buffer[len] = 0;          if ((nmea_host = strtok(buffer,":")) == NULL)            return(0);                   nmea_port = atoi(strtok(NULL,":"));          if ((he = gethostbyname(nmea_host)) == NULL)            return(0);          if ((p = getprotobyname("ip")) == NULL)            return(0);          so_addr.sin_family = AF_INET;          so_addr.sin_port = htons(nmea_port);          so_addr.sin_addr = *((struct in_addr *) he->h_addr);          if ((fd = socket(PF_INET,SOCK_STREAM,p->p_proto)) == -1)            return(0);          if (connect(fd,(struct sockaddr *)&so_addr,SOCKLEN(&so_addr)) == -1) {            close(fd);            return (0);          }#else            return (0);#endif        }	/*	 * Allocate and initialize unit structure	 */	up = (struct nmeaunit *)emalloc(sizeof(struct nmeaunit));	if (up == NULL) {		(void) close(fd);		return (0);	}	memset((char *)up, 0, sizeof(struct nmeaunit));	pp = peer->procptr;	pp->io.clock_recv = nmea_receive;	pp->io.srcclock = (caddr_t)peer;	pp->io.datalen = 0;	pp->io.fd = fd;	if (!io_addclock(&pp->io)) {		(void) close(fd);		free(up);		return (0);	}	pp->unitptr = (caddr_t)up;	/*	 * Initialize miscellaneous variables	 */	peer->precision = PRECISION;	pp->clockdesc = DESCRIPTION;	memcpy((char *)&pp->refid, REFID, 4);	up->pollcnt = 2;	gps_send(pp->io.fd,"$PMOTG,RMC,0000*1D\r\n", peer);#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, &up->handle) < 0) {		up->handle = 0;		msyslog(LOG_ERR,		    "refclock_nmea: time_pps_create failed: %m");		return (1);	}	return(nmea_ppsapi(peer, 0, 0));#else	return (1);#endif /* HAVE_PPSAPI */}/* * nmea_shutdown - shut down a GPS clock */static voidnmea_shutdown(	int unit,	struct peer *peer	){	register struct nmeaunit *up;	struct refclockproc *pp;	pp = peer->procptr;	up = (struct nmeaunit *)pp->unitptr;#ifdef HAVE_PPSAPI	if (up->handle != 0)		time_pps_destroy(up->handle);#endif /* HAVE_PPSAPI */	io_closeclock(&pp->io);	free(up);}#ifdef HAVE_PPSAPI/* * nmea_control - fudge control */static voidnmea_control(	int unit,		/* unit (not used */	struct refclockstat *in, /* input parameters (not uded) */	struct refclockstat *out, /* output parameters (not used) */	struct peer *peer	/* peer structure pointer */	){	struct refclockproc *pp;	pp = peer->procptr;	nmea_ppsapi(peer, pp->sloppyclockflag & CLK_FLAG2,	    pp->sloppyclockflag & CLK_FLAG3);}/* * Initialize PPSAPI */intnmea_ppsapi(	struct peer *peer,	/* peer structure pointer */	int enb_clear,		/* clear enable */	int enb_hardpps		/* hardpps enable */	){	struct refclockproc *pp;	struct nmeaunit *up;	int capability;	pp = peer->procptr;	up = (struct nmeaunit *)pp->unitptr;	if (time_pps_getcap(up->handle, &capability) < 0) {		msyslog(LOG_ERR,		    "refclock_nmea: time_pps_getcap failed: %m");		return (0);	}	memset(&up->pps_params, 0, sizeof(pps_params_t));	if (enb_clear)		up->pps_params.mode = capability & PPS_CAPTURECLEAR;	else		up->pps_params.mode = capability & PPS_CAPTUREASSERT;	if (!up->pps_params.mode) {		msyslog(LOG_ERR,		    "refclock_nmea: invalid capture edge %d",		    !enb_clear);		return (0);	}	up->pps_params.mode |= PPS_TSFMT_TSPEC;	if (time_pps_setparams(up->handle, &up->pps_params) < 0) {		msyslog(LOG_ERR,		    "refclock_nmea: time_pps_setparams failed: %m");		return (0);	}	if (enb_hardpps) {		if (time_pps_kcbind(up->handle, PPS_KC_HARDPPS,				    up->pps_params.mode & ~PPS_TSFMT_TSPEC,				    PPS_TSFMT_TSPEC) < 0) {			msyslog(LOG_ERR,			    "refclock_nmea: time_pps_kcbind failed: %m");			return (0);		}		pps_enable = 1;	}	peer->precision = PPS_PRECISION;#if DEBUG	if (debug) {		time_pps_getparams(up->handle, &up->pps_params);		printf(		    "refclock_ppsapi: capability 0x%x version %d mode 0x%x kern %d\n",		    capability, up->pps_params.api_version,		    up->pps_params.mode, enb_hardpps);	}#endif	return (1);}/* * Get PPSAPI timestamps. * * Return 0 on failure and 1 on success. */static intnmea_pps(	struct nmeaunit *up,	l_fp *tsptr	){	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 (up->handle == 0)		return (0);	timeout.tv_sec = 0;	timeout.tv_nsec = 0;	memcpy(&pps_info, &up->pps_info, sizeof(pps_info_t));	if (time_pps_fetch(up->handle, PPS_TSFMT_TSPEC, &up->pps_info,	    &timeout) < 0)		return (0);	if (up->pps_params.mode & PPS_CAPTUREASSERT) {		if (pps_info.assert_sequence ==		    up->pps_info.assert_sequence)			return (0);		ts = up->pps_info.assert_timestamp;	} else if (up->pps_params.mode & PPS_CAPTURECLEAR) {

⌨️ 快捷键说明

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