xref: /freebsd/contrib/ntp/ntpd/refclock_nmea.c (revision 884a2a699669ec61e2366e3e358342dbc94be24a)
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 #ifdef HAVE_CONFIG_H
7 #include <config.h>
8 #endif
9 
10 #if defined(REFCLOCK) && defined(CLOCK_NMEA)
11 
12 #include <stdio.h>
13 #include <ctype.h>
14 
15 #include "ntpd.h"
16 #include "ntp_io.h"
17 #include "ntp_unixtime.h"
18 #include "ntp_refclock.h"
19 #include "ntp_stdlib.h"
20 
21 #ifdef HAVE_PPSAPI
22 # include "ppsapi_timepps.h"
23 #endif /* HAVE_PPSAPI */
24 
25 #ifdef SYS_WINNT
26 extern int async_write(int, const void *, unsigned int);
27 #undef write
28 #define write(fd, data, octets)	async_write(fd, data, octets)
29 #endif
30 
31 /*
32  * This driver supports the NMEA GPS Receiver with
33  *
34  * Protype was refclock_trak.c, Thanks a lot.
35  *
36  * The receiver used spits out the NMEA sentences for boat navigation.
37  * And you thought it was an information superhighway.  Try a raging river
38  * filled with rapids and whirlpools that rip away your data and warp time.
39  *
40  * If HAVE_PPSAPI is defined code to use the PPSAPI will be compiled in.
41  * On startup if initialization of the PPSAPI fails, it will fall back
42  * to the "normal" timestamps.
43  *
44  * The PPSAPI part of the driver understands fudge flag2 and flag3. If
45  * flag2 is set, it will use the clear edge of the pulse. If flag3 is
46  * set, kernel hardpps is enabled.
47  *
48  * GPS sentences other than RMC (the default) may be enabled by setting
49  * the relevent bits of 'mode' in the server configuration line
50  * server 127.127.20.x mode X
51  *
52  * bit 0 - enables RMC (1)
53  * bit 1 - enables GGA (2)
54  * bit 2 - enables GLL (4)
55  * multiple sentences may be selected
56  */
57 
58 /*
59  * Definitions
60  */
61 #ifdef SYS_WINNT
62 # define DEVICE "COM%d:" 	/* COM 1 - 3 supported */
63 #else
64 # define DEVICE	"/dev/gps%d"	/* name of radio device */
65 #endif
66 #define	SPEED232	B4800	/* uart speed (4800 bps) */
67 #define	PRECISION	(-9)	/* precision assumed (about 2 ms) */
68 #define	PPS_PRECISION	(-20)	/* precision assumed (about 1 us) */
69 #define	REFID		"GPS\0"	/* reference id */
70 #define	DESCRIPTION	"NMEA GPS Clock" /* who we are */
71 #define NANOSECOND	1000000000 /* one second (ns) */
72 #define RANGEGATE	500000	/* range gate (ns) */
73 
74 #define LENNMEA		75	/* min timecode length */
75 
76 /*
77  * Tables to compute the ddd of year form icky dd/mm timecode. Viva la
78  * leap.
79  */
80 static int day1tab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
81 static int day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
82 
83 /*
84  * Unit control structure
85  */
86 struct nmeaunit {
87 	int	pollcnt;	/* poll message counter */
88 	int	polled;		/* Hand in a sample? */
89 	l_fp	tstamp;		/* timestamp of last poll */
90 #ifdef HAVE_PPSAPI
91 	struct timespec ts;	/* last timestamp */
92 	pps_params_t pps_params; /* pps parameters */
93 	pps_info_t pps_info;	/* last pps data */
94 	pps_handle_t handle;	/* pps handlebars */
95 #endif /* HAVE_PPSAPI */
96 };
97 
98 /*
99  * Function prototypes
100  */
101 static	int	nmea_start	P((int, struct peer *));
102 static	void	nmea_shutdown	P((int, struct peer *));
103 #ifdef HAVE_PPSAPI
104 static	void	nmea_control	P((int, struct refclockstat *, struct
105 				    refclockstat *, struct peer *));
106 static	int	nmea_ppsapi	P((struct peer *, int, int));
107 static	int	nmea_pps	P((struct nmeaunit *, l_fp *));
108 #endif /* HAVE_PPSAPI */
109 static	void	nmea_receive	P((struct recvbuf *));
110 static	void	nmea_poll	P((int, struct peer *));
111 static	void	gps_send	P((int, const char *, struct peer *));
112 static	char	*field_parse	P((char *, int));
113 
114 /*
115  * Transfer vector
116  */
117 struct	refclock refclock_nmea = {
118 	nmea_start,		/* start up driver */
119 	nmea_shutdown,	/* shut down driver */
120 	nmea_poll,		/* transmit poll message */
121 #ifdef HAVE_PPSAPI
122 	nmea_control,		/* fudge control */
123 #else
124 	noentry,		/* fudge control */
125 #endif /* HAVE_PPSAPI */
126 	noentry,		/* initialize driver */
127 	noentry,		/* buginfo */
128 	NOFLAGS			/* not used */
129 };
130 
131 /*
132  * nmea_start - open the GPS devices and initialize data for processing
133  */
134 static int
135 nmea_start(
136 	int unit,
137 	struct peer *peer
138 	)
139 {
140 	register struct nmeaunit *up;
141 	struct refclockproc *pp;
142 	int fd;
143 	char device[20];
144 
145 	/*
146 	 * Open serial port. Use CLK line discipline, if available.
147 	 */
148 	(void)sprintf(device, DEVICE, unit);
149 
150 	fd = refclock_open(device, SPEED232, LDISC_CLK);
151 	if (fd <= 0) {
152 #ifdef HAVE_READLINK
153           /* nmead support added by Jon Miner (cp_n18@yahoo.com)
154            *
155            * See http://home.hiwaay.net/~taylorc/gps/nmea-server/
156            * for information about nmead
157            *
158            * To use this, you need to create a link from /dev/gpsX to
159            * the server:port where nmead is running.  Something like this:
160            *
161            * ln -s server:port /dev/gps1
162            */
163           char buffer[80];
164           char *nmea_host;
165           int   nmea_port;
166           int   len;
167           struct hostent *he;
168           struct protoent *p;
169           struct sockaddr_in so_addr;
170 
171           if ((len = readlink(device,buffer,sizeof(buffer))) == -1)
172             return(0);
173           buffer[len] = 0;
174 
175           if ((nmea_host = strtok(buffer,":")) == NULL)
176             return(0);
177 
178           nmea_port = atoi(strtok(NULL,":"));
179 
180           if ((he = gethostbyname(nmea_host)) == NULL)
181             return(0);
182           if ((p = getprotobyname("ip")) == NULL)
183             return(0);
184           so_addr.sin_family = AF_INET;
185           so_addr.sin_port = htons(nmea_port);
186           so_addr.sin_addr = *((struct in_addr *) he->h_addr);
187 
188           if ((fd = socket(PF_INET,SOCK_STREAM,p->p_proto)) == -1)
189             return(0);
190           if (connect(fd,(struct sockaddr *)&so_addr,SOCKLEN(&so_addr)) == -1) {
191             close(fd);
192             return (0);
193           }
194 #else
195             return (0);
196 #endif
197         }
198 
199 	/*
200 	 * Allocate and initialize unit structure
201 	 */
202 	up = (struct nmeaunit *)emalloc(sizeof(struct nmeaunit));
203 	if (up == NULL) {
204 		(void) close(fd);
205 		return (0);
206 	}
207 	memset((char *)up, 0, sizeof(struct nmeaunit));
208 	pp = peer->procptr;
209 	pp->io.clock_recv = nmea_receive;
210 	pp->io.srcclock = (caddr_t)peer;
211 	pp->io.datalen = 0;
212 	pp->io.fd = fd;
213 	if (!io_addclock(&pp->io)) {
214 		(void) close(fd);
215 		free(up);
216 		return (0);
217 	}
218 	pp->unitptr = (caddr_t)up;
219 
220 	/*
221 	 * Initialize miscellaneous variables
222 	 */
223 	peer->precision = PRECISION;
224 	pp->clockdesc = DESCRIPTION;
225 	memcpy((char *)&pp->refid, REFID, 4);
226 	up->pollcnt = 2;
227 	gps_send(pp->io.fd,"$PMOTG,RMC,0000*1D\r\n", peer);
228 
229 #ifdef HAVE_PPSAPI
230 	/*
231 	 * Start the PPSAPI interface if it is there. Default to use
232 	 * the assert edge and do not enable the kernel hardpps.
233 	 */
234 	if (time_pps_create(fd, &up->handle) < 0) {
235 		up->handle = 0;
236 		msyslog(LOG_ERR,
237 		    "refclock_nmea: time_pps_create failed: %m");
238 		return (1);
239 	}
240 	return(nmea_ppsapi(peer, 0, 0));
241 #else
242 	return (1);
243 #endif /* HAVE_PPSAPI */
244 }
245 
246 /*
247  * nmea_shutdown - shut down a GPS clock
248  */
249 static void
250 nmea_shutdown(
251 	int unit,
252 	struct peer *peer
253 	)
254 {
255 	register struct nmeaunit *up;
256 	struct refclockproc *pp;
257 
258 	pp = peer->procptr;
259 	up = (struct nmeaunit *)pp->unitptr;
260 #ifdef HAVE_PPSAPI
261 	if (up->handle != 0)
262 		time_pps_destroy(up->handle);
263 #endif /* HAVE_PPSAPI */
264 	io_closeclock(&pp->io);
265 	free(up);
266 }
267 
268 #ifdef HAVE_PPSAPI
269 /*
270  * nmea_control - fudge control
271  */
272 static void
273 nmea_control(
274 	int unit,		/* unit (not used */
275 	struct refclockstat *in, /* input parameters (not uded) */
276 	struct refclockstat *out, /* output parameters (not used) */
277 	struct peer *peer	/* peer structure pointer */
278 	)
279 {
280 	struct refclockproc *pp;
281 
282 	pp = peer->procptr;
283 	nmea_ppsapi(peer, pp->sloppyclockflag & CLK_FLAG2,
284 	    pp->sloppyclockflag & CLK_FLAG3);
285 }
286 
287 
288 /*
289  * Initialize PPSAPI
290  */
291 int
292 nmea_ppsapi(
293 	struct peer *peer,	/* peer structure pointer */
294 	int enb_clear,		/* clear enable */
295 	int enb_hardpps		/* hardpps enable */
296 	)
297 {
298 	struct refclockproc *pp;
299 	struct nmeaunit *up;
300 	int capability;
301 
302 	pp = peer->procptr;
303 	up = (struct nmeaunit *)pp->unitptr;
304 	if (time_pps_getcap(up->handle, &capability) < 0) {
305 		msyslog(LOG_ERR,
306 		    "refclock_nmea: time_pps_getcap failed: %m");
307 		return (0);
308 	}
309 	memset(&up->pps_params, 0, sizeof(pps_params_t));
310 	if (enb_clear)
311 		up->pps_params.mode = capability & PPS_CAPTURECLEAR;
312 	else
313 		up->pps_params.mode = capability & PPS_CAPTUREASSERT;
314 	if (!up->pps_params.mode) {
315 		msyslog(LOG_ERR,
316 		    "refclock_nmea: invalid capture edge %d",
317 		    !enb_clear);
318 		return (0);
319 	}
320 	up->pps_params.mode |= PPS_TSFMT_TSPEC;
321 	if (time_pps_setparams(up->handle, &up->pps_params) < 0) {
322 		msyslog(LOG_ERR,
323 		    "refclock_nmea: time_pps_setparams failed: %m");
324 		return (0);
325 	}
326 	if (enb_hardpps) {
327 		if (time_pps_kcbind(up->handle, PPS_KC_HARDPPS,
328 				    up->pps_params.mode & ~PPS_TSFMT_TSPEC,
329 				    PPS_TSFMT_TSPEC) < 0) {
330 			msyslog(LOG_ERR,
331 			    "refclock_nmea: time_pps_kcbind failed: %m");
332 			return (0);
333 		}
334 		pps_enable = 1;
335 	}
336 	peer->precision = PPS_PRECISION;
337 
338 #if DEBUG
339 	if (debug) {
340 		time_pps_getparams(up->handle, &up->pps_params);
341 		printf(
342 		    "refclock_ppsapi: capability 0x%x version %d mode 0x%x kern %d\n",
343 		    capability, up->pps_params.api_version,
344 		    up->pps_params.mode, enb_hardpps);
345 	}
346 #endif
347 
348 	return (1);
349 }
350 
351 /*
352  * Get PPSAPI timestamps.
353  *
354  * Return 0 on failure and 1 on success.
355  */
356 static int
357 nmea_pps(
358 	struct nmeaunit *up,
359 	l_fp *tsptr
360 	)
361 {
362 	pps_info_t pps_info;
363 	struct timespec timeout, ts;
364 	double dtemp;
365 	l_fp tstmp;
366 
367 	/*
368 	 * Convert the timespec nanoseconds field to ntp l_fp units.
369 	 */
370 	if (up->handle == 0)
371 		return (0);
372 	timeout.tv_sec = 0;
373 	timeout.tv_nsec = 0;
374 	memcpy(&pps_info, &up->pps_info, sizeof(pps_info_t));
375 	if (time_pps_fetch(up->handle, PPS_TSFMT_TSPEC, &up->pps_info,
376 	    &timeout) < 0)
377 		return (0);
378 	if (up->pps_params.mode & PPS_CAPTUREASSERT) {
379 		if (pps_info.assert_sequence ==
380 		    up->pps_info.assert_sequence)
381 			return (0);
382 		ts = up->pps_info.assert_timestamp;
383 	} else if (up->pps_params.mode & PPS_CAPTURECLEAR) {
384 		if (pps_info.clear_sequence ==
385 		    up->pps_info.clear_sequence)
386 			return (0);
387 		ts = up->pps_info.clear_timestamp;
388 	} else {
389 		return (0);
390 	}
391 	if ((up->ts.tv_sec == ts.tv_sec) && (up->ts.tv_nsec == ts.tv_nsec))
392 		return (0);
393 	up->ts = ts;
394 
395 	tstmp.l_ui = ts.tv_sec + JAN_1970;
396 	dtemp = ts.tv_nsec * FRAC / 1e9;
397 	tstmp.l_uf = (u_int32)dtemp;
398 	*tsptr = tstmp;
399 	return (1);
400 }
401 #endif /* HAVE_PPSAPI */
402 
403 /*
404  * nmea_receive - receive data from the serial interface
405  */
406 static void
407 nmea_receive(
408 	struct recvbuf *rbufp
409 	)
410 {
411 	register struct nmeaunit *up;
412 	struct refclockproc *pp;
413 	struct peer *peer;
414 	int month, day;
415 	int i;
416 	char *cp, *dp;
417 	int cmdtype;
418 	/* Use these variables to hold data until we decide its worth keeping */
419 	char	rd_lastcode[BMAX];
420 	l_fp	rd_tmp;
421 	u_short	rd_lencode;
422 
423 	/*
424 	 * Initialize pointers and read the timecode and timestamp
425 	 */
426 	peer = (struct peer *)rbufp->recv_srcclock;
427 	pp = peer->procptr;
428 	up = (struct nmeaunit *)pp->unitptr;
429 	rd_lencode = (u_short)refclock_gtlin(rbufp, rd_lastcode, BMAX, &rd_tmp);
430 
431 	/*
432 	 * There is a case that a <CR><LF> gives back a "blank" line
433 	 */
434 	if (rd_lencode == 0)
435 	    return;
436 
437 #ifdef DEBUG
438 	if (debug)
439 	    printf("nmea: gpsread %d %s\n", rd_lencode,
440 		   rd_lastcode);
441 #endif
442 
443 	/*
444 	 * We check the timecode format and decode its contents. The
445 	 * we only care about a few of them.  The most important being
446 	 * the $GPRMC format
447 	 * $GPRMC,hhmmss,a,fddmm.xx,n,dddmmm.xx,w,zz.z,yyy.,ddmmyy,dd,v*CC
448 	 * For Magellan (ColorTrak) GLL probably datum (order of sentences)
449 	 * also mode (0,1,2,3) select sentence ANY/ALL, RMC, GGA, GLL
450 	 * $GPGLL,3513.8385,S,14900.7851,E,232420.594,A*21
451   	 * $GPGGA,232420.59,3513.8385,S,14900.7851,E,1,05,3.4,00519,M,,,,*3F
452 	 * $GPRMB,...
453 	 * $GPRMC,232418.19,A,3513.8386,S,14900.7853,E,00.0,000.0,121199,12.,E*77
454 	 * $GPAPB,...
455 	 * $GPGSA,...
456 	 * $GPGSV,...
457 	 * $GPGSV,...
458 	 */
459 #define GPXXX	0
460 #define GPRMC	1
461 #define GPGGA	2
462 #define GPGLL	4
463 	cp = rd_lastcode;
464 	cmdtype=0;
465 	if(strncmp(cp,"$GPRMC",6)==0) {
466 		cmdtype=GPRMC;
467 	}
468 	else if(strncmp(cp,"$GPGGA",6)==0) {
469 		cmdtype=GPGGA;
470 	}
471 	else if(strncmp(cp,"$GPGLL",6)==0) {
472 		cmdtype=GPGLL;
473 	}
474 	else if(strncmp(cp,"$GPXXX",6)==0) {
475 		cmdtype=GPXXX;
476 	}
477 	else
478 	    return;
479 
480 
481 	/* See if I want to process this message type */
482 	if ( ((peer->ttl == 0) && (cmdtype != GPRMC))
483            || ((peer->ttl != 0) && !(cmdtype & peer->ttl)) )
484 		return;
485 
486 	pp->lencode = rd_lencode;
487 	strcpy(pp->a_lastcode,rd_lastcode);
488 	cp = pp->a_lastcode;
489 
490 	pp->lastrec = up->tstamp = rd_tmp;
491 	up->pollcnt = 2;
492 
493 #ifdef DEBUG
494 	if (debug)
495 	    printf("nmea: timecode %d %s\n", pp->lencode,
496 		   pp->a_lastcode);
497 #endif
498 
499 
500 	/* Grab field depending on clock string type */
501 	switch( cmdtype ) {
502 	    case GPRMC:
503 		/*
504 		 * Test for synchronization.  Check for quality byte.
505 		 */
506 		dp = field_parse(cp,2);
507 		if( dp[0] != 'A')
508 			pp->leap = LEAP_NOTINSYNC;
509 		else
510 			pp->leap = LEAP_NOWARNING;
511 
512 		/* Now point at the time field */
513 		dp = field_parse(cp,1);
514 		break;
515 
516 
517 	    case GPGGA:
518 		/*
519 		 * Test for synchronization.  Check for quality byte.
520 		 */
521 		dp = field_parse(cp,6);
522 		if( dp[0] == '0')
523 			pp->leap = LEAP_NOTINSYNC;
524 		else
525 			pp->leap = LEAP_NOWARNING;
526 
527 		/* Now point at the time field */
528 		dp = field_parse(cp,1);
529 		break;
530 
531 
532 	    case GPGLL:
533 		/*
534 		 * Test for synchronization.  Check for quality byte.
535 		 */
536 		dp = field_parse(cp,6);
537 		if( dp[0] != 'A')
538 			pp->leap = LEAP_NOTINSYNC;
539 		else
540 			pp->leap = LEAP_NOWARNING;
541 
542 		/* Now point at the time field */
543 		dp = field_parse(cp,5);
544 		break;
545 
546 
547 	    case GPXXX:
548 		return;
549 	    default:
550 		return;
551 
552 	}
553 
554 		/*
555 		 *	Check time code format of NMEA
556 		 */
557 
558 		if( !isdigit((int)dp[0]) ||
559 		    !isdigit((int)dp[1]) ||
560 		    !isdigit((int)dp[2]) ||
561 		    !isdigit((int)dp[3]) ||
562 		    !isdigit((int)dp[4]) ||
563 		    !isdigit((int)dp[5])
564 		    ) {
565 			refclock_report(peer, CEVNT_BADREPLY);
566 			return;
567 		}
568 
569 
570 	/*
571 	 * Convert time and check values.
572 	 */
573 	pp->hour = ((dp[0] - '0') * 10) + dp[1] - '0';
574 	pp->minute = ((dp[2] - '0') * 10) + dp[3] -  '0';
575 	pp->second = ((dp[4] - '0') * 10) + dp[5] - '0';
576 	/* Default to 0 milliseconds, if decimal convert milliseconds in
577 	   one, two or three digits
578 	*/
579 	pp->nsec = 0;
580 	if (dp[6] == '.') {
581 		if (isdigit((int)dp[7])) {
582 			pp->nsec = (dp[7] - '0') * 100000000;
583 			if (isdigit((int)dp[8])) {
584 				pp->nsec += (dp[8] - '0') * 10000000;
585 				if (isdigit((int)dp[9])) {
586 					pp->nsec += (dp[9] - '0') * 1000000;
587 				}
588 			}
589 		}
590 	}
591 
592 	if (pp->hour > 23 || pp->minute > 59 || pp->second > 59
593 	  || pp->nsec > 1000000000) {
594 		refclock_report(peer, CEVNT_BADTIME);
595 		return;
596 	}
597 
598 
599 	/*
600 	 * Convert date and check values.
601 	 */
602 	if (cmdtype==GPRMC) {
603 	    dp = field_parse(cp,9);
604 	    day = dp[0] - '0';
605 	    day = (day * 10) + dp[1] - '0';
606 	    month = dp[2] - '0';
607 	    month = (month * 10) + dp[3] - '0';
608 	    pp->year = dp[4] - '0';
609 	    pp->year = (pp->year * 10) + dp[5] - '0';
610 	}
611 	else {
612 	/* only time */
613 	    time_t tt = time(NULL);
614 	    struct tm * t = gmtime(&tt);
615 	    day = t->tm_mday;
616 	    month = t->tm_mon + 1;
617 	    pp->year= t->tm_year;
618 	}
619 
620 	if (month < 1 || month > 12 || day < 1) {
621 		refclock_report(peer, CEVNT_BADTIME);
622 		return;
623 	}
624 
625         /* Hmmmm this will be a nono for 2100,2200,2300 but I don't think I'll be here */
626         /* good thing that 2000 is a leap year */
627 	/* pp->year will be 00-99 if read from GPS, 00->  (years since 1900) from tm_year */
628 	if (pp->year % 4) {
629 		if (day > day1tab[month - 1]) {
630 			refclock_report(peer, CEVNT_BADTIME);
631 			return;
632 		}
633 		for (i = 0; i < month - 1; i++)
634 		    day += day1tab[i];
635 	} else {
636 		if (day > day2tab[month - 1]) {
637 			refclock_report(peer, CEVNT_BADTIME);
638 			return;
639 		}
640 		for (i = 0; i < month - 1; i++)
641 		    day += day2tab[i];
642 	}
643 	pp->day = day;
644 
645 
646 #ifdef HAVE_PPSAPI
647 	/*
648 	 * If the PPSAPI is working, rather use its timestamps.
649 	 * assume that the PPS occurs on the second so blow any msec
650 	 */
651 	if (nmea_pps(up, &rd_tmp) == 1) {
652 		pp->lastrec = up->tstamp = rd_tmp;
653 		pp->nsec = 0;
654 	}
655 #endif /* HAVE_PPSAPI */
656 
657 	/*
658 	 * Process the new sample in the median filter and determine the
659 	 * reference clock offset and dispersion. We use lastrec as both
660 	 * the reference time and receive time, in order to avoid being
661 	 * cute, like setting the reference time later than the receive
662 	 * time, which may cause a paranoid protocol module to chuck out
663 	 * the data.
664 	 */
665 
666 	if (!refclock_process(pp)) {
667 		refclock_report(peer, CEVNT_BADTIME);
668 		return;
669 	}
670 
671 
672 
673 	/*
674 	 * Only go on if we had been polled.
675 	 */
676 	if (!up->polled)
677 	    return;
678 	up->polled = 0;
679 	pp->lastref = pp->lastrec;
680 	refclock_receive(peer);
681 
682         /* If we get here - what we got from the clock is OK, so say so */
683          refclock_report(peer, CEVNT_NOMINAL);
684 
685 	record_clock_stats(&peer->srcadr, pp->a_lastcode);
686 
687 }
688 
689 /*
690  * nmea_poll - called by the transmit procedure
691  *
692  * We go to great pains to avoid changing state here, since there may be
693  * more than one eavesdropper receiving the same timecode.
694  */
695 static void
696 nmea_poll(
697 	int unit,
698 	struct peer *peer
699 	)
700 {
701 	register struct nmeaunit *up;
702 	struct refclockproc *pp;
703 
704 	pp = peer->procptr;
705 	up = (struct nmeaunit *)pp->unitptr;
706 	if (up->pollcnt == 0)
707 	    refclock_report(peer, CEVNT_TIMEOUT);
708 	else
709 	    up->pollcnt--;
710 	pp->polls++;
711 	up->polled = 1;
712 
713 	/*
714 	 * usually nmea_receive can get a timestamp every second
715 	 */
716 
717 	gps_send(pp->io.fd,"$PMOTG,RMC,0000*1D\r\n", peer);
718 }
719 
720 /*
721  *
722  *	gps_send(fd,cmd, peer)  Sends a command to the GPS receiver.
723  *	 as	gps_send(fd,"rqts,u\r", peer);
724  *
725  *	We don't currently send any data, but would like to send
726  *	RTCM SC104 messages for differential positioning. It should
727  *	also give us better time. Without a PPS output, we're
728  *	Just fooling ourselves because of the serial code paths
729  *
730  */
731 static void
732 gps_send(
733 	int fd,
734 	const char *cmd,
735 	struct peer *peer
736 	)
737 {
738 
739 	if (write(fd, cmd, strlen(cmd)) == -1) {
740 		refclock_report(peer, CEVNT_FAULT);
741 	}
742 }
743 
744 static char *
745 field_parse(
746 	char *cp,
747 	int fn
748 	)
749 {
750 	char *tp;
751 	int i = fn;
752 
753 	for (tp = cp; *tp != '\0'; tp++) {
754 		if (*tp == ',')
755 		    i--;
756 		if (i == 0)
757 		    break;
758 	}
759 	return (++tp);
760 }
761 #else
762 int refclock_nmea_bs;
763 #endif /* REFCLOCK */
764