Change the default for ntpd back to -s, the bug which triggered this
[dragonfly.git] / contrib / ntp / ntpd / refclock_nmea.c
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 "ntpd.h"
13 #include "ntp_io.h"
14 #include "ntp_unixtime.h"
15 #include "ntp_refclock.h"
16 #include "ntp_stdlib.h"
17
18 #include <stdio.h>
19 #include <ctype.h>
20
21 #ifdef HAVE_PPSAPI
22 # ifdef HAVE_TIMEPPS_H
23 #  include <timepps.h>
24 # else
25 #  ifdef HAVE_SYS_TIMEPPS_H
26 #   include <sys/timepps.h>
27 #  endif
28 # endif
29 #endif /* HAVE_PPSAPI */
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         if (!(fd = refclock_open(device, SPEED232, LDISC_CLK)))
151             return (0);
152
153         /*
154          * Allocate and initialize unit structure
155          */
156         if (!(up = (struct nmeaunit *)
157               emalloc(sizeof(struct nmeaunit)))) {
158                 (void) close(fd);
159                 return (0);
160         }
161         memset((char *)up, 0, sizeof(struct nmeaunit));
162         pp = peer->procptr;
163         pp->io.clock_recv = nmea_receive;
164         pp->io.srcclock = (caddr_t)peer;
165         pp->io.datalen = 0;
166         pp->io.fd = fd;
167         if (!io_addclock(&pp->io)) {
168                 (void) close(fd);
169                 free(up);
170                 return (0);
171         }
172         pp->unitptr = (caddr_t)up;
173
174         /*
175          * Initialize miscellaneous variables
176          */
177         peer->precision = PRECISION;
178         pp->clockdesc = DESCRIPTION;
179         memcpy((char *)&pp->refid, REFID, 4);
180         up->pollcnt = 2;
181         gps_send(pp->io.fd,"$PMOTG,RMC,0000*1D\r\n", peer);
182
183 #ifdef HAVE_PPSAPI
184         /*
185          * Start the PPSAPI interface if it is there. Default to use
186          * the assert edge and do not enable the kernel hardpps.
187          */
188         if (time_pps_create(fd, &up->handle) < 0) {
189                 up->handle = 0;
190                 msyslog(LOG_ERR,
191                     "refclock_nmea: time_pps_create failed: %m");
192                 return (1);
193         }
194         return(nmea_ppsapi(peer, 0, 0));
195 #else
196         return (1);
197 #endif /* HAVE_PPSAPI */
198 }
199
200 /*
201  * nmea_shutdown - shut down a GPS clock
202  */
203 static void
204 nmea_shutdown(
205         int unit,
206         struct peer *peer
207         )
208 {
209         register struct nmeaunit *up;
210         struct refclockproc *pp;
211
212         pp = peer->procptr;
213         up = (struct nmeaunit *)pp->unitptr;
214 #ifdef HAVE_PPSAPI
215         if (up->handle != 0)
216                 time_pps_destroy(up->handle);
217 #endif /* HAVE_PPSAPI */
218         io_closeclock(&pp->io);
219         free(up);
220 }
221
222 #ifdef HAVE_PPSAPI
223 /*
224  * nmea_control - fudge control
225  */
226 static void
227 nmea_control(
228         int unit,               /* unit (not used */
229         struct refclockstat *in, /* input parameters (not uded) */
230         struct refclockstat *out, /* output parameters (not used) */
231         struct peer *peer       /* peer structure pointer */
232         )
233 {
234         struct refclockproc *pp;
235
236         pp = peer->procptr;
237         nmea_ppsapi(peer, pp->sloppyclockflag & CLK_FLAG2,
238             pp->sloppyclockflag & CLK_FLAG3);
239 }
240
241
242 /*
243  * Initialize PPSAPI
244  */
245 int
246 nmea_ppsapi(
247         struct peer *peer,      /* peer structure pointer */
248         int enb_clear,          /* clear enable */
249         int enb_hardpps         /* hardpps enable */
250         )
251 {
252         struct refclockproc *pp;
253         struct nmeaunit *up;
254         int capability;
255
256         pp = peer->procptr;
257         up = (struct nmeaunit *)pp->unitptr;
258         if (time_pps_getcap(up->handle, &capability) < 0) {
259                 msyslog(LOG_ERR,
260                     "refclock_nmea: time_pps_getcap failed: %m");
261                 return (0);
262         }
263         memset(&up->pps_params, 0, sizeof(pps_params_t));
264         if (enb_clear)
265                 up->pps_params.mode = capability & PPS_CAPTURECLEAR;
266         else
267                 up->pps_params.mode = capability & PPS_CAPTUREASSERT;
268         if (!up->pps_params.mode) {
269                 msyslog(LOG_ERR,
270                     "refclock_nmea: invalid capture edge %d",
271                     !enb_clear);
272                 return (0);
273         }
274         up->pps_params.mode |= PPS_TSFMT_TSPEC;
275         if (time_pps_setparams(up->handle, &up->pps_params) < 0) {
276                 msyslog(LOG_ERR,
277                     "refclock_nmea: time_pps_setparams failed: %m");
278                 return (0);
279         }
280         if (enb_hardpps) {
281                 if (time_pps_kcbind(up->handle, PPS_KC_HARDPPS,
282                                     up->pps_params.mode & ~PPS_TSFMT_TSPEC,
283                                     PPS_TSFMT_TSPEC) < 0) {
284                         msyslog(LOG_ERR,
285                             "refclock_nmea: time_pps_kcbind failed: %m");
286                         return (0);
287                 }
288                 pps_enable = 1;
289         }
290         peer->precision = PPS_PRECISION;
291
292 #if DEBUG
293         if (debug) {
294                 time_pps_getparams(up->handle, &up->pps_params);
295                 printf(
296                     "refclock_ppsapi: capability 0x%x version %d mode 0x%x kern %d\n",
297                     capability, up->pps_params.api_version,
298                     up->pps_params.mode, enb_hardpps);
299         }
300 #endif
301
302         return (1);
303 }
304
305 /*
306  * Get PPSAPI timestamps.
307  *
308  * Return 0 on failure and 1 on success.
309  */
310 static int
311 nmea_pps(
312         struct nmeaunit *up,
313         l_fp *tsptr
314         )
315 {
316         pps_info_t pps_info;
317         struct timespec timeout, ts;
318         double dtemp;
319         l_fp tstmp;
320
321         /*
322          * Convert the timespec nanoseconds field to ntp l_fp units.
323          */ 
324         if (up->handle == 0)
325                 return (0);
326         timeout.tv_sec = 0;
327         timeout.tv_nsec = 0;
328         memcpy(&pps_info, &up->pps_info, sizeof(pps_info_t));
329         if (time_pps_fetch(up->handle, PPS_TSFMT_TSPEC, &up->pps_info,
330             &timeout) < 0)
331                 return (0);
332         if (up->pps_params.mode & PPS_CAPTUREASSERT) {
333                 if (pps_info.assert_sequence ==
334                     up->pps_info.assert_sequence)
335                         return (0);
336                 ts = up->pps_info.assert_timestamp;
337         } else if (up->pps_params.mode & PPS_CAPTURECLEAR) {
338                 if (pps_info.clear_sequence ==
339                     up->pps_info.clear_sequence)
340                         return (0);
341                 ts = up->pps_info.clear_timestamp;
342         } else {
343                 return (0);
344         }
345         if ((up->ts.tv_sec == ts.tv_sec) && (up->ts.tv_nsec == ts.tv_nsec))
346                 return (0);
347         up->ts = ts;
348
349         tstmp.l_ui = ts.tv_sec + JAN_1970;
350         dtemp = ts.tv_nsec * FRAC / 1e9;
351         tstmp.l_uf = (u_int32)dtemp;
352         *tsptr = tstmp;
353         return (1);
354 }
355 #endif /* HAVE_PPSAPI */
356
357 /*
358  * nmea_receive - receive data from the serial interface
359  */
360 static void
361 nmea_receive(
362         struct recvbuf *rbufp
363         )
364 {
365         register struct nmeaunit *up;
366         struct refclockproc *pp;
367         struct peer *peer;
368         int month, day;
369         int i;
370         char *cp, *dp;
371         int cmdtype;
372         /* Use these variables to hold data until we decide its worth keeping */
373         char    rd_lastcode[BMAX];
374         l_fp    rd_tmp;
375         u_short rd_lencode;
376
377         /*
378          * Initialize pointers and read the timecode and timestamp
379          */
380         peer = (struct peer *)rbufp->recv_srcclock;
381         pp = peer->procptr;
382         up = (struct nmeaunit *)pp->unitptr;
383         rd_lencode = refclock_gtlin(rbufp, rd_lastcode, BMAX, &rd_tmp);
384
385         /*
386          * There is a case that a <CR><LF> gives back a "blank" line
387          */
388         if (rd_lencode == 0)
389             return;
390
391 #ifdef DEBUG
392         if (debug)
393             printf("nmea: gpsread %d %s\n", rd_lencode,
394                    rd_lastcode);
395 #endif
396
397         /*
398          * We check the timecode format and decode its contents. The
399          * we only care about a few of them.  The most important being
400          * the $GPRMC format
401          * $GPRMC,hhmmss,a,fddmm.xx,n,dddmmm.xx,w,zz.z,yyy.,ddmmyy,dd,v*CC
402          * For Magellan (ColorTrak) GLL probably datum (order of sentences)
403          * also mode (0,1,2,3) select sentence ANY/ALL, RMC, GGA, GLL
404          * $GPGLL,3513.8385,S,14900.7851,E,232420.594,A*21
405          * $GPGGA,232420.59,3513.8385,S,14900.7851,E,1,05,3.4,00519,M,,,,*3F
406          * $GPRMB,...
407          * $GPRMC,232418.19,A,3513.8386,S,14900.7853,E,00.0,000.0,121199,12.,E*77
408          * $GPAPB,...
409          * $GPGSA,...
410          * $GPGSV,...
411          * $GPGSV,...
412          */
413 #define GPXXX   0
414 #define GPRMC   1
415 #define GPGGA   2
416 #define GPGLL   4
417         cp = rd_lastcode;
418         cmdtype=0;
419         if(strncmp(cp,"$GPRMC",6)==0) {
420                 cmdtype=GPRMC;
421         }
422         else if(strncmp(cp,"$GPGGA",6)==0) {
423                 cmdtype=GPGGA;
424         }
425         else if(strncmp(cp,"$GPGLL",6)==0) {
426                 cmdtype=GPGLL;
427         }
428         else if(strncmp(cp,"$GPXXX",6)==0) {
429                 cmdtype=GPXXX;
430         }
431         else
432             return;
433
434
435         /* See if I want to process this message type */
436         if ( ((peer->ttlmax == 0) && (cmdtype != GPRMC))
437            || ((peer->ttlmax != 0) && !(cmdtype & peer->ttlmax)) )
438                 return;
439
440         pp->lencode = rd_lencode;
441         strcpy(pp->a_lastcode,rd_lastcode);
442         cp = pp->a_lastcode;
443
444         pp->lastrec = up->tstamp = rd_tmp;
445         up->pollcnt = 2;
446
447 #ifdef DEBUG
448         if (debug)
449             printf("nmea: timecode %d %s\n", pp->lencode,
450                    pp->a_lastcode);
451 #endif
452
453
454         /* Grab field depending on clock string type */
455         switch( cmdtype ) {
456             case GPRMC:
457                 /*
458                  * Test for synchronization.  Check for quality byte.
459                  */
460                 dp = field_parse(cp,2);
461                 if( dp[0] != 'A')
462                         pp->leap = LEAP_NOTINSYNC;
463                 else
464                         pp->leap = LEAP_NOWARNING;
465
466                 /* Now point at the time field */
467                 dp = field_parse(cp,1);
468                 break;
469
470
471             case GPGGA:
472                 /*
473                  * Test for synchronization.  Check for quality byte.
474                  */
475                 dp = field_parse(cp,6);
476                 if( dp[0] == '0')
477                         pp->leap = LEAP_NOTINSYNC;
478                 else
479                         pp->leap = LEAP_NOWARNING;
480
481                 /* Now point at the time field */
482                 dp = field_parse(cp,1);
483                 break;
484
485
486             case GPGLL:
487                 /*
488                  * Test for synchronization.  Check for quality byte.
489                  */
490                 dp = field_parse(cp,6);
491                 if( dp[0] != 'A')
492                         pp->leap = LEAP_NOTINSYNC;
493                 else
494                         pp->leap = LEAP_NOWARNING;
495
496                 /* Now point at the time field */
497                 dp = field_parse(cp,5);
498                 break;
499
500
501             case GPXXX:
502                 return;
503             default:
504                 return;
505
506         }
507
508                 /*
509                  *      Check time code format of NMEA
510                  */
511
512                 if( !isdigit((int)dp[0]) ||
513                     !isdigit((int)dp[1]) ||
514                     !isdigit((int)dp[2]) ||
515                     !isdigit((int)dp[3]) ||
516                     !isdigit((int)dp[4]) ||
517                     !isdigit((int)dp[5])        
518                     ) {
519                         refclock_report(peer, CEVNT_BADREPLY);
520                         return;
521                 }
522
523
524         /*
525          * Convert time and check values.
526          */
527         pp->hour = ((dp[0] - '0') * 10) + dp[1] - '0';
528         pp->minute = ((dp[2] - '0') * 10) + dp[3] -  '0';
529         pp->second = ((dp[4] - '0') * 10) + dp[5] - '0';
530         /* Default to 0 milliseconds, if decimal convert milliseconds in
531            one, two or three digits
532         */
533         pp->msec = 0; 
534         if (dp[6] == '.') {
535                 if (isdigit((int)dp[7])) {
536                         pp->msec = (dp[7] - '0') * 100;
537                         if (isdigit((int)dp[8])) {
538                                 pp->msec += (dp[8] - '0') * 10;
539                                 if (isdigit((int)dp[9])) {
540                                         pp->msec += (dp[9] - '0');
541                                 }
542                         }
543                 }
544         }
545
546         if (pp->hour > 23 || pp->minute > 59 || pp->second > 59
547           || pp->msec > 1000) {
548                 refclock_report(peer, CEVNT_BADTIME);
549                 return;
550         }
551
552
553         /*
554          * Convert date and check values.
555          */
556         if (cmdtype==GPRMC) {
557             dp = field_parse(cp,9);
558             day = dp[0] - '0';
559             day = (day * 10) + dp[1] - '0';
560             month = dp[2] - '0';
561             month = (month * 10) + dp[3] - '0';
562             pp->year = dp[4] - '0';
563             pp->year = (pp->year * 10) + dp[5] - '0';
564         }
565         else {
566         /* only time */
567             time_t tt = time(NULL);
568             struct tm * t = gmtime(&tt);
569             day = t->tm_mday;
570             month = t->tm_mon + 1;
571             pp->year= t->tm_year;
572         }
573
574         if (month < 1 || month > 12 || day < 1) {
575                 refclock_report(peer, CEVNT_BADTIME);
576                 return;
577         }
578
579         /* Hmmmm this will be a nono for 2100,2200,2300 but I don't think I'll be here */
580         /* good thing that 2000 is a leap year */
581         /* pp->year will be 00-99 if read from GPS, 00->  (years since 1900) from tm_year */
582         if (pp->year % 4) {
583                 if (day > day1tab[month - 1]) {
584                         refclock_report(peer, CEVNT_BADTIME);
585                         return;
586                 }
587                 for (i = 0; i < month - 1; i++)
588                     day += day1tab[i];
589         } else {
590                 if (day > day2tab[month - 1]) {
591                         refclock_report(peer, CEVNT_BADTIME);
592                         return;
593                 }
594                 for (i = 0; i < month - 1; i++)
595                     day += day2tab[i];
596         }
597         pp->day = day;
598
599
600 #ifdef HAVE_PPSAPI
601         /*
602          * If the PPSAPI is working, rather use its timestamps.
603          * assume that the PPS occurs on the second so blow any msec
604          */
605         if (nmea_pps(up, &rd_tmp) == 1) {
606                 pp->lastrec = up->tstamp = rd_tmp;
607                 pp->msec = 0;
608         }
609 #endif /* HAVE_PPSAPI */
610
611         /*
612          * Process the new sample in the median filter and determine the
613          * reference clock offset and dispersion. We use lastrec as both
614          * the reference time and receive time, in order to avoid being
615          * cute, like setting the reference time later than the receive
616          * time, which may cause a paranoid protocol module to chuck out
617          * the data.
618          */
619
620         if (!refclock_process(pp)) {
621                 refclock_report(peer, CEVNT_BADTIME);
622                 return;
623         }
624
625
626
627         /*
628          * Only go on if we had been polled.
629          */
630         if (!up->polled)
631             return;
632         up->polled = 0;
633
634         refclock_receive(peer);
635
636         /* If we get here - what we got from the clock is OK, so say so */
637          refclock_report(peer, CEVNT_NOMINAL);
638
639         record_clock_stats(&peer->srcadr, pp->a_lastcode);
640
641 }
642
643 /*
644  * nmea_poll - called by the transmit procedure
645  *
646  * We go to great pains to avoid changing state here, since there may be
647  * more than one eavesdropper receiving the same timecode.
648  */
649 static void
650 nmea_poll(
651         int unit,
652         struct peer *peer
653         )
654 {
655         register struct nmeaunit *up;
656         struct refclockproc *pp;
657
658         pp = peer->procptr;
659         up = (struct nmeaunit *)pp->unitptr;
660         if (up->pollcnt == 0)
661             refclock_report(peer, CEVNT_TIMEOUT);
662         else
663             up->pollcnt--;
664         pp->polls++;
665         up->polled = 1;
666
667         /*
668          * usually nmea_receive can get a timestamp every second
669          */
670
671         gps_send(pp->io.fd,"$PMOTG,RMC,0000*1D\r\n", peer);
672 }
673
674 /*
675  *
676  *      gps_send(fd,cmd, peer)  Sends a command to the GPS receiver.
677  *       as     gps_send(fd,"rqts,u\r", peer);
678  *
679  *      We don't currently send any data, but would like to send
680  *      RTCM SC104 messages for differential positioning. It should
681  *      also give us better time. Without a PPS output, we're
682  *      Just fooling ourselves because of the serial code paths
683  *
684  */
685 static void
686 gps_send(
687         int fd,
688         const char *cmd,
689         struct peer *peer
690         )
691 {
692
693         if (write(fd, cmd, strlen(cmd)) == -1) {
694                 refclock_report(peer, CEVNT_FAULT);
695         }
696 }
697
698 static char *
699 field_parse(
700         char *cp,
701         int fn
702         )
703 {
704         char *tp;
705         int i = fn;
706
707         for (tp = cp; *tp != '\0'; tp++) {
708                 if (*tp == ',')
709                     i--;
710                 if (i == 0)
711                     break;
712         }
713         return (++tp);
714 }
715 #else
716 int refclock_nmea_bs;
717 #endif /* REFCLOCK */