1/*
2 * refclock_nmea.c - clock driver for an NMEA GPS CLOCK
3 *		Michael Petry Jun 20, 1994
4 *		 based on refclock_heathn.c
5 *
6 * Updated to add support for Accord GPS Clock
7 * 		Venu Gopal Dec 05, 2007
8 * 		neo.venu@gmail.com, venugopal_d@pgad.gov.in
9 *
10 * Updated to process 'time1' fudge factor
11 *		Venu Gopal May 05, 2008
12 *
13 * Converted to common PPSAPI code, separate PPS fudge time1
14 * from serial timecode fudge time2.
15 *		Dave Hart July 1, 2009
16 *		hart@ntp.org, davehart@davehart.com
17 */
18#ifdef HAVE_CONFIG_H
19#include <config.h>
20#endif
21
22#if defined(REFCLOCK) && defined(CLOCK_NMEA)
23
24#include <sys/stat.h>
25#include <stdio.h>
26#include <ctype.h>
27
28#include "ntpd.h"
29#include "ntp_io.h"
30#include "ntp_unixtime.h"
31#include "ntp_refclock.h"
32#include "ntp_stdlib.h"
33
34#ifdef HAVE_PPSAPI
35# include "ppsapi_timepps.h"
36#include "refclock_atom.h"
37#endif /* HAVE_PPSAPI */
38
39#ifdef SYS_WINNT
40#undef write	/* ports/winnt/include/config.h: #define write _write */
41extern int async_write(int, const void *, unsigned int);
42#define write(fd, data, octets)	async_write(fd, data, octets)
43#endif
44
45/*
46 * This driver supports NMEA-compatible GPS receivers
47 *
48 * Prototype was refclock_trak.c, Thanks a lot.
49 *
50 * The receiver used spits out the NMEA sentences for boat navigation.
51 * And you thought it was an information superhighway.  Try a raging river
52 * filled with rapids and whirlpools that rip away your data and warp time.
53 *
54 * If HAVE_PPSAPI is defined code to use the PPSAPI will be compiled in.
55 * On startup if initialization of the PPSAPI fails, it will fall back
56 * to the "normal" timestamps.
57 *
58 * The PPSAPI part of the driver understands fudge flag2 and flag3. If
59 * flag2 is set, it will use the clear edge of the pulse. If flag3 is
60 * set, kernel hardpps is enabled.
61 *
62 * GPS sentences other than RMC (the default) may be enabled by setting
63 * the relevent bits of 'mode' in the server configuration line
64 * server 127.127.20.x mode X
65 *
66 * bit 0 - enables RMC (1)
67 * bit 1 - enables GGA (2)
68 * bit 2 - enables GLL (4)
69 * bit 3 - enables ZDA (8) - Standard Time & Date
70 * bit 3 - enables ZDG (8) - Accord GPS Clock's custom sentence with GPS time
71 *			     very close to standard ZDA
72 *
73 * Multiple sentences may be selected except when ZDG/ZDA is selected.
74 *
75 * bit 4/5/6 - selects the baudrate for serial port :
76 *		0 for 4800 (default)
77 *		1 for 9600
78 *		2 for 19200
79 *		3 for 38400
80 *		4 for 57600
81 *		5 for 115200
82 */
83#define NMEA_MESSAGE_MASK_OLD    0x07
84#define NMEA_MESSAGE_MASK_SINGLE 0x08
85#define NMEA_MESSAGE_MASK        (NMEA_MESSAGE_MASK_OLD | NMEA_MESSAGE_MASK_SINGLE)
86
87#define NMEA_BAUDRATE_MASK       0x70
88#define NMEA_BAUDRATE_SHIFT      4
89
90/*
91 * Definitions
92 */
93#define	DEVICE		"/dev/gps%d"	/* GPS serial device */
94#define	PPSDEV		"/dev/gpspps%d"	/* PPSAPI device override */
95#define	SPEED232	B4800	/* uart speed (4800 bps) */
96#define	PRECISION	(-9)	/* precision assumed (about 2 ms) */
97#define	PPS_PRECISION	(-20)	/* precision assumed (about 1 us) */
98#define	REFID		"GPS\0"	/* reference id */
99#define	DESCRIPTION	"NMEA GPS Clock" /* who we are */
100#define NANOSECOND	1000000000 /* one second (ns) */
101#define RANGEGATE	500000	/* range gate (ns) */
102#ifndef O_NOCTTY
103#define M_NOCTTY	0
104#else
105#define M_NOCTTY	O_NOCTTY
106#endif
107#ifndef O_NONBLOCK
108#define M_NONBLOCK	0
109#else
110#define M_NONBLOCK	O_NONBLOCK
111#endif
112#define PPSOPENMODE	(O_RDWR | M_NOCTTY | M_NONBLOCK)
113
114/*
115 * Unit control structure
116 */
117struct nmeaunit {
118#ifdef HAVE_PPSAPI
119	struct refclock_atom atom; /* PPSAPI structure */
120	int	ppsapi_tried;	/* attempt PPSAPI once */
121	int	ppsapi_lit;	/* time_pps_create() worked */
122	int	ppsapi_fd;	/* fd used with PPSAPI */
123	int	tcount;		/* timecode sample counter */
124	int	pcount;		/* PPS sample counter */
125#endif /* HAVE_PPSAPI */
126	l_fp	tstamp;		/* timestamp of last poll */
127	int	gps_time;	/* 0 UTC, 1 GPS time */
128};
129
130/*
131 * Function prototypes
132 */
133static	int	nmea_start	(int, struct peer *);
134static	void	nmea_shutdown	(int, struct peer *);
135static	void	nmea_receive	(struct recvbuf *);
136static	void	nmea_poll	(int, struct peer *);
137#ifdef HAVE_PPSAPI
138static	void	nmea_control	(int, struct refclockstat *,
139				 struct refclockstat *, struct peer *);
140static  void	nmea_timer	(int, struct peer *);
141#define		NMEA_CONTROL	nmea_control
142#define		NMEA_TIMER	nmea_timer
143#else
144#define		NMEA_CONTROL	noentry
145#define		NMEA_TIMER	noentry
146#endif /* HAVE_PPSAPI */
147static	void	gps_send	(int, const char *, struct peer *);
148static	char *	field_parse	(char *, int);
149static	int	nmea_checksum_ok(const char *);
150
151/*
152 * Transfer vector
153 */
154struct	refclock refclock_nmea = {
155	nmea_start,		/* start up driver */
156	nmea_shutdown,		/* shut down driver */
157	nmea_poll,		/* transmit poll message */
158	NMEA_CONTROL,		/* fudge control */
159	noentry,		/* initialize driver */
160	noentry,		/* buginfo */
161	NMEA_TIMER		/* called once per second */
162};
163
164/*
165 * nmea_start - open the GPS devices and initialize data for processing
166 */
167static int
168nmea_start(
169	int unit,
170	struct peer *peer
171	)
172{
173	register struct nmeaunit *up;
174	struct refclockproc *pp;
175	int fd;
176	char device[20];
177	int baudrate;
178	char *baudtext;
179
180	pp = peer->procptr;
181
182	/*
183	 * Open serial port. Use CLK line discipline, if available.
184	 */
185	snprintf(device, sizeof(device), DEVICE, unit);
186
187	/*
188	 * Opening the serial port with appropriate baudrate
189	 * based on the value of bit 4/5/6
190	 */
191	switch ((peer->ttl & NMEA_BAUDRATE_MASK) >> NMEA_BAUDRATE_SHIFT) {
192	    case 0:
193	    case 6:
194	    case 7:
195	    default:
196		baudrate = SPEED232;
197		baudtext = "4800";
198		break;
199	    case 1:
200		baudrate = B9600;
201		baudtext = "9600";
202		break;
203	    case 2:
204		baudrate = B19200;
205		baudtext = "19200";
206		break;
207	    case 3:
208		baudrate = B38400;
209		baudtext = "38400";
210		break;
211#ifdef B57600
212	    case 4:
213		baudrate = B57600;
214		baudtext = "57600";
215		break;
216#endif
217#ifdef B115200
218	    case 5:
219		baudrate = B115200;
220		baudtext = "115200";
221		break;
222#endif
223	}
224
225	fd = refclock_open(device, baudrate, LDISC_CLK);
226
227	if (fd <= 0) {
228#ifdef HAVE_READLINK
229		/* nmead support added by Jon Miner (cp_n18@yahoo.com)
230		 *
231		 * See http://home.hiwaay.net/~taylorc/gps/nmea-server/
232		 * for information about nmead
233		 *
234		 * To use this, you need to create a link from /dev/gpsX to
235		 * the server:port where nmead is running.  Something like this:
236		 *
237		 * ln -s server:port /dev/gps1
238		 */
239		char buffer[80];
240		char *nmea_host, *nmea_tail;
241		int   nmea_port;
242		int   len;
243		struct hostent *he;
244		struct protoent *p;
245		struct sockaddr_in so_addr;
246
247		if ((len = readlink(device,buffer,sizeof(buffer))) == -1)
248			return(0);
249		buffer[len] = 0;
250
251		if ((nmea_host = strtok(buffer,":")) == NULL)
252			return(0);
253		if ((nmea_tail = strtok(NULL,":")) == NULL)
254			return(0);
255
256		nmea_port = atoi(nmea_tail);
257
258		if ((he = gethostbyname(nmea_host)) == NULL)
259			return(0);
260		if ((p = getprotobyname("ip")) == NULL)
261			return(0);
262		memset(&so_addr, 0, sizeof(so_addr));
263		so_addr.sin_family = AF_INET;
264		so_addr.sin_port = htons(nmea_port);
265		so_addr.sin_addr = *((struct in_addr *) he->h_addr);
266
267		if ((fd = socket(PF_INET,SOCK_STREAM,p->p_proto)) == -1)
268			return(0);
269		if (connect(fd,(struct sockaddr *)&so_addr, sizeof(so_addr)) == -1) {
270			close(fd);
271			return (0);
272		}
273#else
274		pp->io.fd = -1;
275		return (0);
276#endif
277	}
278
279	msyslog(LOG_NOTICE, "%s serial %s open at %s bps",
280		refnumtoa(&peer->srcadr), device, baudtext);
281
282	/*
283	 * Allocate and initialize unit structure
284	 */
285	up = emalloc(sizeof(*up));
286	memset(up, 0, sizeof(*up));
287	pp->io.clock_recv = nmea_receive;
288	pp->io.srcclock = (caddr_t)peer;
289	pp->io.datalen = 0;
290	pp->io.fd = fd;
291	if (!io_addclock(&pp->io)) {
292		pp->io.fd = -1;
293		close(fd);
294		free(up);
295		return (0);
296	}
297	pp->unitptr = (caddr_t)up;
298
299	/*
300	 * Initialize miscellaneous variables
301	 */
302	peer->precision = PRECISION;
303	pp->clockdesc = DESCRIPTION;
304	memcpy(&pp->refid, REFID, 4);
305
306	gps_send(fd,"$PMOTG,RMC,0000*1D\r\n", peer);
307
308	return (1);
309}
310
311
312/*
313 * nmea_shutdown - shut down a GPS clock
314 *
315 * NOTE this routine is called after nmea_start() returns failure,
316 * as well as during a normal shutdown due to ntpq :config unpeer.
317 */
318static void
319nmea_shutdown(
320	int unit,
321	struct peer *peer
322	)
323{
324	register struct nmeaunit *up;
325	struct refclockproc *pp;
326
327	UNUSED_ARG(unit);
328
329	pp = peer->procptr;
330	up = (struct nmeaunit *)pp->unitptr;
331	if (up != NULL) {
332#ifdef HAVE_PPSAPI
333		if (up->ppsapi_lit) {
334			time_pps_destroy(up->atom.handle);
335			if (up->ppsapi_fd != pp->io.fd)
336				close(up->ppsapi_fd);
337		}
338#endif
339		free(up);
340	}
341	if (-1 != pp->io.fd)
342		io_closeclock(&pp->io);
343}
344
345/*
346 * nmea_control - configure fudge params
347 */
348#ifdef HAVE_PPSAPI
349static void
350nmea_control(
351	int unit,
352	struct refclockstat *in_st,
353	struct refclockstat *out_st,
354	struct peer *peer
355	)
356{
357	char device[32];
358	register struct nmeaunit *up;
359	struct refclockproc *pp;
360	int pps_fd;
361
362	UNUSED_ARG(in_st);
363	UNUSED_ARG(out_st);
364
365	pp = peer->procptr;
366	up = (struct nmeaunit *)pp->unitptr;
367
368	if (!(CLK_FLAG1 & pp->sloppyclockflag)) {
369		if (!up->ppsapi_tried)
370			return;
371		up->ppsapi_tried = 0;
372		if (!up->ppsapi_lit)
373			return;
374		peer->flags &= ~FLAG_PPS;
375		peer->precision = PRECISION;
376		time_pps_destroy(up->atom.handle);
377		if (up->ppsapi_fd != pp->io.fd)
378			close(up->ppsapi_fd);
379		up->atom.handle = 0;
380		up->ppsapi_lit = 0;
381		up->ppsapi_fd = -1;
382		return;
383	}
384
385	if (up->ppsapi_tried)
386		return;
387	/*
388	 * Light up the PPSAPI interface.
389	 */
390	up->ppsapi_tried = 1;
391
392	/*
393	 * if /dev/gpspps$UNIT can be opened that will be used for
394	 * PPSAPI.  Otherwise, the GPS serial device /dev/gps$UNIT
395	 * already opened is used for PPSAPI as well.
396	 */
397	snprintf(device, sizeof(device), PPSDEV, unit);
398
399	pps_fd = open(device, PPSOPENMODE, S_IRUSR | S_IWUSR);
400
401	if (-1 == pps_fd)
402		pps_fd = pp->io.fd;
403
404	if (refclock_ppsapi(pps_fd, &up->atom)) {
405		up->ppsapi_lit = 1;
406		up->ppsapi_fd = pps_fd;
407		return;
408	}
409
410	NLOG(NLOG_CLOCKINFO)
411		msyslog(LOG_WARNING, "%s flag1 1 but PPSAPI fails",
412			refnumtoa(&peer->srcadr));
413}
414#endif	/* HAVE_PPSAPI */
415
416
417/*
418 * nmea_timer - called once per second, fetches PPS
419 *		timestamp and stuffs in median filter.
420 */
421#ifdef HAVE_PPSAPI
422static void
423nmea_timer(
424	int		unit,
425	struct peer *	peer
426	)
427{
428	struct nmeaunit *up;
429	struct refclockproc *pp;
430
431	UNUSED_ARG(unit);
432
433	pp = peer->procptr;
434	up = (struct nmeaunit *)pp->unitptr;
435
436	if (up->ppsapi_lit &&
437	    refclock_pps(peer, &up->atom, pp->sloppyclockflag) > 0) {
438		up->pcount++,
439		peer->flags |= FLAG_PPS;
440		peer->precision = PPS_PRECISION;
441	}
442}
443#endif	/* HAVE_PPSAPI */
444
445
446/*
447 * nmea_receive - receive data from the serial interface
448 */
449static void
450nmea_receive(
451	struct recvbuf *rbufp
452	)
453{
454	register struct nmeaunit *up;
455	struct refclockproc *pp;
456	struct peer *peer;
457	int month, day;
458	char *cp, *dp, *msg;
459	int cmdtype;
460	int cmdtypezdg = 0;
461	/* Use these variables to hold data until we decide its worth keeping */
462	char	rd_lastcode[BMAX];
463	l_fp	rd_timestamp;
464	int	rd_lencode;
465
466	/*
467	 * Initialize pointers and read the timecode and timestamp
468	 */
469	peer = rbufp->recv_peer;
470	pp = peer->procptr;
471	up = (struct nmeaunit *)pp->unitptr;
472
473	rd_lencode = refclock_gtlin(
474			rbufp,
475			rd_lastcode,
476			sizeof(rd_lastcode),
477			&rd_timestamp);
478
479	/*
480	 * There is a case that a <CR><LF> gives back a "blank" line
481	 */
482	if (rd_lencode == 0)
483		return;
484
485	DPRINTF(1, ("nmea: gpsread %d %s\n", rd_lencode, rd_lastcode));
486
487	/*
488	 * We check the timecode format and decode its contents. The
489	 * we only care about a few of them.  The most important being
490	 * the $GPRMC format
491	 * $GPRMC,hhmmss,a,fddmm.xx,n,dddmmm.xx,w,zz.z,yyy.,ddmmyy,dd,v*CC
492	 * mode (0,1,2,3) selects sentence ANY/ALL, RMC, GGA, GLL, ZDA
493	 * $GPGLL,3513.8385,S,14900.7851,E,232420.594,A*21
494	 * $GPGGA,232420.59,3513.8385,S,14900.7851,E,1,05,3.4,00519,M,,,,*3F
495	 * $GPRMC,232418.19,A,3513.8386,S,14900.7853,E,00.0,000.0,121199,12.,E*77
496	 *
497	 * Defining GPZDA to support Standard Time & Date
498	 * sentence. The sentence has the following format
499	 *
500	 *  $--ZDA,HHMMSS.SS,DD,MM,YYYY,TH,TM,*CS<CR><LF>
501	 *
502	 *  Apart from the familiar fields,
503	 *  'TH'    Time zone Hours
504	 *  'TM'    Time zone Minutes
505	 *
506	 * Defining GPZDG to support Accord GPS Clock's custom NMEA
507	 * sentence. The sentence has the following format
508	 *
509	 *  $GPZDG,HHMMSS.S,DD,MM,YYYY,AA.BB,V*CS<CR><LF>
510	 *
511	 *  It contains the GPS timestamp valid for next PPS pulse.
512	 *  Apart from the familiar fields,
513	 *  'AA.BB' denotes the signal strength( should be < 05.00 )
514	 *  'V'     denotes the GPS sync status :
515	 *	   '0' indicates INVALID time,
516	 *	   '1' indicates accuracy of +/-20 ms
517	 *	   '2' indicates accuracy of +/-100 ns
518	 */
519#define GPXXX		0	/* any/all */
520#define GPRMC		1
521#define GPGGA		2
522#define GPGLL		4
523#define GPZDG_ZDA	8
524
525	cp = rd_lastcode;
526	cmdtype=0;
527	if (cp[0] == '$') {
528		/* Allow for GLGGA and GPGGA etc. */
529		msg = cp + 3;
530
531		if (strncmp(msg, "RMC", 3) == 0)
532			cmdtype = GPRMC;
533		else if (strncmp(msg, "GGA", 3) == 0)
534			cmdtype = GPGGA;
535		else if (strncmp(msg, "GLL", 3) == 0)
536			cmdtype = GPGLL;
537		else if (strncmp(msg, "ZD", 2) == 0) {
538			cmdtype = GPZDG_ZDA;
539			if ('G' == msg[2])
540				cmdtypezdg = 1;
541			else if ('A' != msg[2])
542				return;
543		} else
544			return;
545	} else
546		return;
547
548	/* See if I want to process this message type */
549	if (peer->ttl && !(cmdtype & (peer->ttl & NMEA_MESSAGE_MASK)))
550		return;
551
552	/*
553	 * $GPZDG provides GPS time not UTC, and the two mix poorly.
554	 * Once have processed a $GPZDG, do not process any further
555	 * UTC sentences (all but $GPZDG currently).
556	 */
557	if (up->gps_time && !cmdtypezdg)
558		return;
559
560	/* make sure it came in clean */
561	if (!nmea_checksum_ok(rd_lastcode)) {
562		refclock_report(peer, CEVNT_BADREPLY);
563		return;
564	}
565
566	pp->lencode = (u_short) rd_lencode;
567	memcpy(pp->a_lastcode, rd_lastcode, pp->lencode + 1);
568	cp = pp->a_lastcode;
569
570	up->tstamp = rd_timestamp;
571	pp->lastrec = up->tstamp;
572
573	DPRINTF(1, ("nmea: timecode %d %s\n", pp->lencode, pp->a_lastcode));
574
575	/* Grab field depending on clock string type */
576	switch (cmdtype) {
577
578	case GPRMC:
579		/*
580		 * Test for synchronization.  Check for quality byte.
581		 */
582		dp = field_parse(cp, 2);
583		if (dp[0] != 'A')
584			pp->leap = LEAP_NOTINSYNC;
585		else
586			pp->leap = LEAP_NOWARNING;
587
588		/* Now point at the time field */
589		dp = field_parse(cp, 1);
590		break;
591
592	case GPGGA:
593		/*
594		 * Test for synchronization.  Check for quality byte.
595		 */
596		dp = field_parse(cp, 6);
597		if (dp[0] == '0')
598			pp->leap = LEAP_NOTINSYNC;
599		else
600			pp->leap = LEAP_NOWARNING;
601
602		/* Now point at the time field */
603		dp = field_parse(cp, 1);
604		break;
605
606	case GPGLL:
607		/*
608		 * Test for synchronization.  Check for quality byte.
609		 */
610		dp = field_parse(cp, 6);
611		if (dp[0] != 'A')
612			pp->leap = LEAP_NOTINSYNC;
613		else
614			pp->leap = LEAP_NOWARNING;
615
616		/* Now point at the time field */
617		dp = field_parse(cp, 5);
618		break;
619
620	case GPZDG_ZDA:
621		/*
622		 * Test for synchronization.  For $GPZDG check for validity of GPS time.
623		 */
624		if (cmdtypezdg) {
625			dp = field_parse(cp, 6);
626			if (dp[0] == '0')
627				pp->leap = LEAP_NOTINSYNC;
628			else
629				pp->leap = LEAP_NOWARNING;
630		} else
631			pp->leap = LEAP_NOWARNING;
632
633		/* Now point at the time field */
634		dp = field_parse(cp, 1);
635		break;
636
637	default:
638		return;
639	}
640
641	/*
642	 * Check time code format of NMEA
643	 */
644	if (!isdigit((int)dp[0]) ||
645	    !isdigit((int)dp[1]) ||
646	    !isdigit((int)dp[2]) ||
647	    !isdigit((int)dp[3]) ||
648	    !isdigit((int)dp[4]) ||
649	    !isdigit((int)dp[5])) {
650
651		DPRINTF(1, ("NMEA time code %c%c%c%c%c%c non-numeric",
652			    dp[0], dp[1], dp[2], dp[3], dp[4], dp[5]));
653		refclock_report(peer, CEVNT_BADTIME);
654		return;
655	}
656
657	/*
658	 * Convert time and check values.
659	 */
660	pp->hour = ((dp[0] - '0') * 10) + dp[1] - '0';
661	pp->minute = ((dp[2] - '0') * 10) + dp[3] -  '0';
662	pp->second = ((dp[4] - '0') * 10) + dp[5] - '0';
663	/*
664	 * Default to 0 milliseconds, if decimal convert milliseconds in
665	 * one, two or three digits
666	 */
667	pp->nsec = 0;
668	if (dp[6] == '.') {
669		if (isdigit((int)dp[7])) {
670			pp->nsec = (dp[7] - '0') * 100000000;
671			if (isdigit((int)dp[8])) {
672				pp->nsec += (dp[8] - '0') * 10000000;
673				if (isdigit((int)dp[9])) {
674					pp->nsec += (dp[9] - '0') * 1000000;
675				}
676			}
677		}
678	}
679
680	/*
681	 * Manipulating GPS timestamp in GPZDG as the seconds field
682	 * is valid for next PPS tick. Just rolling back the second,
683	 * minute and hour fields appopriately
684	 */
685	if (cmdtypezdg) {
686		if (pp->second == 0) {
687			pp->second = 59;
688			if (pp->minute == 0) {
689				pp->minute = 59;
690				if (pp->hour == 0)
691					pp->hour = 23;
692			}
693		} else
694			pp->second -= 1;
695	}
696
697	if (pp->hour > 23 || pp->minute > 59 ||
698	    pp->second > 59 || pp->nsec > 1000000000) {
699
700		DPRINTF(1, ("NMEA hour/min/sec/nsec range %02d:%02d:%02d.%09ld\n",
701			    pp->hour, pp->minute, pp->second, pp->nsec));
702		refclock_report(peer, CEVNT_BADTIME);
703		return;
704	}
705
706	/*
707	 * Convert date and check values.
708	 */
709	if (GPRMC == cmdtype) {
710
711		dp = field_parse(cp,9);
712		day = dp[0] - '0';
713		day = (day * 10) + dp[1] - '0';
714		month = dp[2] - '0';
715		month = (month * 10) + dp[3] - '0';
716		pp->year = dp[4] - '0';
717		pp->year = (pp->year * 10) + dp[5] - '0';
718
719	} else if (GPZDG_ZDA == cmdtype) {
720
721		dp = field_parse(cp, 2);
722		day = 10 * (dp[0] - '0') + (dp[1] - '0');
723		dp = field_parse(cp, 3);
724		month = 10 * (dp[0] - '0') + (dp[1] - '0');
725		dp = field_parse(cp, 4);
726		pp->year = /* 1000 * (dp[0] - '0') + 100 * (dp[1] - '0') + */ 10 * (dp[2] - '0') + (dp[3] - '0');
727
728	} else {
729		/* only time */
730		time_t tt = time(NULL);
731		struct tm * t = gmtime(&tt);
732		day = t->tm_mday;
733		month = t->tm_mon + 1;
734		pp->year= t->tm_year + 1900;
735	}
736
737	if (month < 1 || month > 12 || day < 1) {
738		refclock_report(peer, CEVNT_BADDATE);
739		return;
740	}
741
742	/* pp->year will be 2 or 4 digits if read from GPS, 4 from gmtime */
743	if (pp->year < 100) {
744		if (pp->year < 9)	/* year of our line of code is 2009 */
745			pp->year += 2100;
746		else
747			pp->year += 2000;
748	}
749
750	/* pp->year now 4 digits as ymd2yd requires */
751	day = ymd2yd(pp->year, month, day);
752	if (-1 == day) {
753		refclock_report(peer, CEVNT_BADDATE);
754		return;
755	}
756	pp->day = day;
757
758	/*
759	 * If "fudge 127.127.20.__ flag4 1" is configured in ntp.conf,
760	 * remove the location and checksum from the NMEA sentence
761	 * recorded as the last timecode and visible to remote users
762	 * with:
763	 *
764	 * ntpq -c clockvar <server>
765	 *
766	 * Note that this also removes the location from the clockstats
767	 * log (if it is enabled).  Some NTP operators monitor their
768	 * NMEA GPS using the change in location in clockstats over
769	 * time as as a proxy for the quality of GPS reception and
770	 * thereby time reported.
771	 */
772	if (CLK_FLAG4 & pp->sloppyclockflag) {
773		/*
774		 * Start by pointing cp and dp at the fields with
775		 * longitude and latitude in the last timecode.
776		 */
777		switch (cmdtype) {
778
779		case GPGLL:
780			cp = field_parse(pp->a_lastcode, 1);
781			dp = field_parse(cp, 2);
782			break;
783
784		case GPGGA:
785			cp = field_parse(pp->a_lastcode, 2);
786			dp = field_parse(cp, 2);
787			break;
788
789		case GPRMC:
790			cp = field_parse(pp->a_lastcode, 3);
791			dp = field_parse(cp, 2);
792			break;
793
794		case GPZDG_ZDA:
795		default:
796			cp = dp = NULL;
797		}
798
799		/* Blank the entire latitude & longitude. */
800		while (cp) {
801			while (',' != *cp) {
802				if ('.' != *cp)
803					*cp = '_';
804				cp++;
805			}
806
807			/* Longitude at cp then latitude at dp */
808			if (cp < dp)
809				cp = dp;
810			else
811				cp = NULL;
812		}
813
814		/* Blank the checksum, the last two characters */
815		if (dp) {
816			cp = pp->a_lastcode + pp->lencode - 2;
817			if (0 == cp[2])
818				cp[0] = cp[1] = '_';
819		}
820
821	}
822
823	/*
824	 * Note if we're only using GPS timescale from now on.
825	 */
826	if (cmdtypezdg && !up->gps_time) {
827		up->gps_time = 1;
828		NLOG(NLOG_CLOCKINFO)
829			msyslog(LOG_INFO, "%s using only $GPZDG",
830				refnumtoa(&peer->srcadr));
831	}
832
833	/*
834	 * Process the new sample in the median filter and determine the
835	 * timecode timestamp, but only if the PPS is not in control.
836	 */
837#ifdef HAVE_PPSAPI
838	up->tcount++;
839	if (peer->flags & FLAG_PPS)
840		return;
841#endif /* HAVE_PPSAPI */
842	if (!refclock_process_f(pp, pp->fudgetime2))
843		refclock_report(peer, CEVNT_BADTIME);
844}
845
846
847/*
848 * nmea_poll - called by the transmit procedure
849 *
850 * We go to great pains to avoid changing state here, since there may be
851 * more than one eavesdropper receiving the same timecode.
852 */
853static void
854nmea_poll(
855	int unit,
856	struct peer *peer
857	)
858{
859	register struct nmeaunit *up;
860	struct refclockproc *pp;
861
862	pp = peer->procptr;
863	up = (struct nmeaunit *)pp->unitptr;
864
865	/*
866	 * Process median filter samples. If none received, declare a
867	 * timeout and keep going.
868	 */
869#ifdef HAVE_PPSAPI
870	if (up->pcount == 0) {
871		peer->flags &= ~FLAG_PPS;
872		peer->precision = PRECISION;
873	}
874	if (up->tcount == 0) {
875		pp->coderecv = pp->codeproc;
876		refclock_report(peer, CEVNT_TIMEOUT);
877		return;
878	}
879	up->pcount = up->tcount = 0;
880#else /* HAVE_PPSAPI */
881	if (pp->coderecv == pp->codeproc) {
882		refclock_report(peer, CEVNT_TIMEOUT);
883		return;
884	}
885#endif /* HAVE_PPSAPI */
886
887	pp->polls++;
888	pp->lastref = pp->lastrec;
889	refclock_receive(peer);
890	record_clock_stats(&peer->srcadr, pp->a_lastcode);
891
892	/*
893	 * usually nmea_receive can get a timestamp every second,
894	 * but at least one Motorola unit needs prompting each
895	 * time.
896	 */
897
898	gps_send(pp->io.fd,"$PMOTG,RMC,0000*1D\r\n", peer);
899}
900
901
902/*
903 *
904 *	gps_send(fd,cmd, peer)  Sends a command to the GPS receiver.
905 *	 as	gps_send(fd,"rqts,u\r", peer);
906 *
907 *	We don't currently send any data, but would like to send
908 *	RTCM SC104 messages for differential positioning. It should
909 *	also give us better time. Without a PPS output, we're
910 *	Just fooling ourselves because of the serial code paths
911 *
912 */
913static void
914gps_send(
915	int fd,
916	const char *cmd,
917	struct peer *peer
918	)
919{
920	if (write(fd, cmd, strlen(cmd)) == -1) {
921		refclock_report(peer, CEVNT_FAULT);
922	}
923}
924
925
926static char *
927field_parse(
928	char *cp,
929	int fn
930	)
931{
932	char *tp;
933	int i = fn;
934
935	for (tp = cp; i && *tp; tp++)
936		if (*tp == ',')
937			i--;
938
939	return tp;
940}
941
942
943/*
944 * nmea_checksum_ok verifies 8-bit XOR checksum is correct then returns 1
945 *
946 * format is $XXXXX,1,2,3,4*ML
947 *
948 * 8-bit XOR of characters between $ and * noninclusive is transmitted
949 * in last two chars M and L holding most and least significant nibbles
950 * in hex representation such as:
951 *
952 *   $GPGLL,5057.970,N,00146.110,E,142451,A*27
953 *   $GPVTG,089.0,T,,,15.2,N,,*7F
954 */
955int
956nmea_checksum_ok(
957	const char *sentence
958	)
959{
960	u_char my_cs;
961	u_long input_cs;
962	const char *p;
963
964	my_cs = 0;
965	p = sentence;
966
967	if ('$' != *p++)
968		return 0;
969
970	for ( ; *p && '*' != *p; p++) {
971
972		my_cs ^= *p;
973	}
974
975	if ('*' != *p++)
976		return 0;
977
978	if (0 == p[0] || 0 == p[1] || 0 != p[2])
979		return 0;
980
981	if (0 == hextoint(p, &input_cs))
982		return 0;
983
984	if (my_cs != input_cs)
985		return 0;
986
987	return 1;
988}
989#else
990int refclock_nmea_bs;
991#endif /* REFCLOCK && CLOCK_NMEA */
992