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