1 /* 2 * This software was developed by the Software and Component Technologies 3 * group of Trimble Navigation, Ltd. 4 * 5 * Copyright (c) 1997, 1998, 1999, 2000 Trimble Navigation Ltd. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by Trimble Navigation, Ltd. 19 * 4. The name of Trimble Navigation Ltd. may not be used to endorse or 20 * promote products derived from this software without specific prior 21 * written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY TRIMBLE NAVIGATION LTD. ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL TRIMBLE NAVIGATION LTD. BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 /* 37 * refclock_palisade - clock driver for the Trimble Palisade GPS 38 * timing receiver 39 * 40 * For detailed information on this program, please refer to the html 41 * Refclock 29 page accompanying the NTP distribution. 42 * 43 * for questions / bugs / comments, contact: 44 * sven_dietrich@trimble.com 45 * 46 * Sven-Thorsten Dietrich 47 * 645 North Mary Avenue 48 * Post Office Box 3642 49 * Sunnyvale, CA 94088-3642 50 * 51 * Version 2.45; July 14, 1999 52 * 53 * 54 * 55 * 31/03/06: Added support for Thunderbolt GPS Disciplined Clock. 56 * Contact: Fernando Pablo Hauscarriaga 57 * E-mail: fernandoph@iar.unlp.edu.ar 58 * Home page: www.iar.unlp.edu.ar/~fernandoph 59 * Instituto Argentino de Radioastronomia 60 * www.iar.unlp.edu.ar 61 * 62 * 14/01/07: Conditinal compilation for Thunderbolt support no longer needed 63 * now we use mode 2 for decode thunderbolt packets. 64 * Fernando P. Hauscarriaga 65 * 66 * 30/08/09: Added support for Trimble Acutime Gold Receiver. 67 * Fernando P. Hauscarriaga (fernandoph@iar.unlp.edu.ar) 68 * 69 * 21/04/18: Added support for Resolution devices. 70 * 71 * 03/09/19: Added support for ACE III & Copernicus II. 72 */ 73 74 #ifdef HAVE_CONFIG_H 75 # include "config.h" 76 #endif 77 78 #if defined(REFCLOCK) && defined(CLOCK_PALISADE) 79 80 #ifdef SYS_WINNT 81 extern int async_write(int, const void *, unsigned int); 82 #undef write 83 #define write(fd, data, octets) async_write(fd, data, octets) 84 #endif 85 86 #include "refclock_palisade.h" 87 88 #ifdef DEBUG 89 const char * Tracking_Status[15][15] = { 90 { "Doing Fixes\0" }, { "Good 1SV\0" }, { "Approx. 1SV\0" }, 91 {"Need Time\0" }, { "Need INIT\0" }, { "PDOP too High\0" }, 92 { "Bad 1SV\0" }, { "0SV Usable\0" }, { "1SV Usable\0" }, 93 { "2SV Usable\0" }, { "3SV Usable\0" }, { "No Integrity\0" }, 94 { "Diff Corr\0" }, { "Overdet Clock\0" }, { "Invalid\0" } }; 95 #endif 96 97 /* 98 * Transfer vector 99 */ 100 struct refclock refclock_palisade = { 101 palisade_start, /* start up driver */ 102 palisade_shutdown, /* shut down driver */ 103 palisade_poll, /* transmit poll message */ 104 noentry, /* not used */ 105 noentry, /* initialize driver (not used) */ 106 noentry, /* not used */ 107 NOFLAGS /* not used */ 108 }; 109 110 static int decode_date(struct refclockproc *pp, const char *cp); 111 112 /* Extract the clock type from the mode setting */ 113 #define CLK_TYPE(x) ((int)(((x)->ttl) & 0x7F)) 114 115 /* Supported clock types */ 116 #define CLK_TRIMBLE 0 /* Trimble Palisade */ 117 #define CLK_PRAECIS 1 /* Endrun Technologies Praecis */ 118 #define CLK_THUNDERBOLT 2 /* Trimble Thunderbolt GPS Receiver */ 119 #define CLK_ACUTIME 3 /* Trimble Acutime Gold */ 120 #define CLK_ACUTIMEB 4 /* Trimble Actutime Gold Port B */ 121 #define CLK_RESOLUTION 5 /* Trimble Resolution Receivers */ 122 #define CLK_ACE 6 /* Trimble ACE III */ 123 #define CLK_COPERNICUS 7 /* Trimble Copernicus II */ 124 125 int praecis_msg; 126 static void praecis_parse(struct recvbuf *rbufp, struct peer *peer); 127 128 /* These routines are for sending packets to the Thunderbolt receiver 129 * They are taken from Markus Prosch 130 */ 131 132 /* 133 * sendcmd - Build data packet for sending 134 */ 135 static void 136 sendcmd ( 137 struct packettx *buffer, 138 int c 139 ) 140 { 141 *buffer->data = DLE; 142 *(buffer->data + 1) = (unsigned char)c; 143 buffer->size = 2; 144 } 145 146 /* 147 * sendsupercmd - Build super data packet for sending 148 */ 149 static void 150 sendsupercmd ( 151 struct packettx *buffer, 152 int c1, 153 int c2 154 ) 155 { 156 *buffer->data = DLE; 157 *(buffer->data + 1) = (unsigned char)c1; 158 *(buffer->data + 2) = (unsigned char)c2; 159 buffer->size = 3; 160 } 161 162 /* 163 * sendbyte - 164 */ 165 static void 166 sendbyte ( 167 struct packettx *buffer, 168 int b 169 ) 170 { 171 if (b == DLE) 172 *(buffer->data+buffer->size++) = DLE; 173 *(buffer->data+buffer->size++) = (unsigned char)b; 174 } 175 176 /* 177 * sendint - 178 */ 179 static void 180 sendint ( 181 struct packettx *buffer, 182 int a 183 ) 184 { 185 sendbyte(buffer, (unsigned char)((a>>8) & 0xff)); 186 sendbyte(buffer, (unsigned char)(a & 0xff)); 187 } 188 189 /* 190 * sendetx - Send packet or super packet to the device 191 */ 192 static int 193 sendetx ( 194 struct packettx *buffer, 195 int fd 196 ) 197 { 198 int result; 199 200 *(buffer->data+buffer->size++) = DLE; 201 *(buffer->data+buffer->size++) = ETX; 202 result = write(fd, buffer->data, (unsigned long)buffer->size); 203 204 if (result != -1) 205 return (result); 206 else 207 return (-1); 208 } 209 210 /* 211 * init_thunderbolt - Prepares Thunderbolt receiver to be used with 212 * NTP (also taken from Markus Prosch). 213 */ 214 static void 215 init_thunderbolt ( 216 int fd 217 ) 218 { 219 struct packettx tx; 220 221 tx.size = 0; 222 tx.data = (u_char *) emalloc(100); 223 224 /* set UTC time */ 225 sendsupercmd (&tx, 0x8E, 0xA2); 226 sendbyte (&tx, 0x3); 227 sendetx (&tx, fd); 228 229 /* activate packets 0x8F-AB and 0x8F-AC */ 230 sendsupercmd (&tx, 0x8E, 0xA5); 231 sendint (&tx, 0x5); 232 sendetx (&tx, fd); 233 234 free(tx.data); 235 } 236 237 /* 238 * init_acutime - Prepares Acutime Receiver to be used with NTP 239 */ 240 static void 241 init_acutime ( 242 int fd 243 ) 244 { 245 /* Disable all outputs, Enable Event-Polling on PortA so 246 we can ask for time packets */ 247 struct packettx tx; 248 249 tx.size = 0; 250 tx.data = (u_char *) emalloc(100); 251 252 sendsupercmd(&tx, 0x8E, 0xA5); 253 sendbyte(&tx, 0x02); 254 sendbyte(&tx, 0x00); 255 sendbyte(&tx, 0x00); 256 sendbyte(&tx, 0x00); 257 sendetx(&tx, fd); 258 259 free(tx.data); 260 } 261 262 /* 263 * init_resolution - Prepares Resolution receiver to be used with NTP 264 */ 265 static void 266 init_resolution ( 267 int fd 268 ) 269 { 270 struct packettx tx; 271 272 tx.size = 0; 273 tx.data = (u_char *) emalloc(100); 274 275 /* set UTC time */ 276 sendsupercmd (&tx, 0x8E, 0xA2); 277 sendbyte (&tx, 0x3); 278 sendetx (&tx, fd); 279 280 /* squelch PPS output unless locked to at least one satellite */ 281 sendsupercmd (&tx, 0x8E, 0x4E); 282 sendbyte (&tx, 0x3); 283 sendetx (&tx, fd); 284 285 /* activate packets 0x8F-AB and 0x8F-AC */ 286 sendsupercmd (&tx, 0x8E, 0xA5); 287 sendint (&tx, 0x5); 288 sendetx (&tx, fd); 289 290 free(tx.data); 291 } 292 293 /* 294 * palisade_start - open the devices and initialize data for processing 295 */ 296 static int 297 palisade_start ( 298 int unit, 299 struct peer *peer 300 ) 301 { 302 struct palisade_unit *up; 303 struct refclockproc *pp; 304 int fd; 305 char gpsdev[20]; 306 struct termios tio; 307 u_int speed; 308 309 snprintf(gpsdev, sizeof(gpsdev), DEVICE, unit); 310 311 /* 312 * Open serial port. 313 */ 314 speed = (CLK_TYPE(peer) == CLK_COPERNICUS) ? SPEED232COP : SPEED232; 315 fd = refclock_open(&peer->srcadr, gpsdev, speed, LDISC_RAW); 316 if (fd <= 0) { 317 #ifdef DEBUG 318 printf("Palisade(%d) start: open %s failed\n", unit, gpsdev); 319 #endif 320 return 0; 321 } 322 323 msyslog(LOG_NOTICE, "Palisade(%d) fd: %d dev: %s", unit, fd, 324 gpsdev); 325 326 if (tcgetattr(fd, &tio) < 0) { 327 msyslog(LOG_ERR, 328 "Palisade(%d) tcgetattr(fd, &tio): %m",unit); 329 #ifdef DEBUG 330 printf("Palisade(%d) tcgetattr(fd, &tio)\n",unit); 331 #endif 332 close(fd); 333 return (0); 334 } 335 336 tio.c_cflag |= (PARENB|PARODD); 337 tio.c_iflag &= ~ICRNL; 338 339 /* 340 * Allocate and initialize unit structure 341 */ 342 up = emalloc_zero(sizeof(*up)); 343 344 up->type = CLK_TYPE(peer); 345 switch (up->type) { 346 case CLK_TRIMBLE: 347 /* Normal mode, do nothing */ 348 break; 349 case CLK_PRAECIS: 350 msyslog(LOG_NOTICE, "Palisade(%d) Praecis mode enabled" 351 ,unit); 352 break; 353 case CLK_THUNDERBOLT: 354 msyslog(LOG_NOTICE, "Palisade(%d) Thunderbolt mode enabled" 355 ,unit); 356 tio.c_cflag = (CS8|CLOCAL|CREAD); 357 break; 358 case CLK_ACUTIME: 359 msyslog(LOG_NOTICE, "Palisade(%d) Acutime Gold mode enabled" 360 ,unit); 361 break; 362 case CLK_RESOLUTION: 363 msyslog(LOG_NOTICE, "Palisade(%d) Resolution mode enabled" 364 ,unit); 365 tio.c_cflag = (CS8|CLOCAL|CREAD|PARENB|PARODD); 366 break; 367 case CLK_ACE: 368 msyslog(LOG_NOTICE, "Palisade(%d) ACE III mode enabled" 369 ,unit); 370 tio.c_cflag = (CS8|CLOCAL|CREAD|PARENB|PARODD); 371 break; 372 case CLK_COPERNICUS: 373 msyslog(LOG_NOTICE, "Palisade(%d) Copernicus II mode enabled" 374 ,unit); 375 /* Must use ORing/ANDing to set/clear c_cflag bits otherwise 376 CBAUD gets set back to 0. This ought to be an issue for 377 the other modes above but it seems that the baud rate 378 defaults to 9600 if CBAUD gets set to 0. */ 379 tio.c_cflag &= ~(PARENB|PARODD); 380 break; 381 default: 382 msyslog(LOG_NOTICE, "Palisade(%d) mode unknown",unit); 383 break; 384 } 385 if (tcsetattr(fd, TCSANOW, &tio) == -1) { 386 msyslog(LOG_ERR, "Palisade(%d) tcsetattr(fd, &tio): %m",unit); 387 #ifdef DEBUG 388 printf("Palisade(%d) tcsetattr(fd, &tio)\n",unit); 389 #endif 390 close(fd); 391 free(up); 392 return 0; 393 } 394 395 pp = peer->procptr; 396 pp->io.clock_recv = palisade_io; 397 pp->io.srcclock = peer; 398 pp->io.datalen = 0; 399 pp->io.fd = fd; 400 if (!io_addclock(&pp->io)) { 401 #ifdef DEBUG 402 printf("Palisade(%d) io_addclock\n",unit); 403 #endif 404 close(fd); 405 pp->io.fd = -1; 406 free(up); 407 return (0); 408 } 409 410 /* 411 * Initialize miscellaneous variables 412 */ 413 pp->unitptr = up; 414 pp->clockdesc = DESCRIPTION; 415 416 peer->precision = PRECISION; 417 peer->sstclktype = CTL_SST_TS_UHF; 418 peer->minpoll = TRMB_MINPOLL; 419 peer->maxpoll = TRMB_MAXPOLL; 420 memcpy((char *)&pp->refid, REFID, 4); 421 422 up->leap_status = 0; 423 up->unit = (short) unit; 424 up->rpt_status = TSIP_PARSED_EMPTY; 425 up->rpt_cnt = 0; 426 427 if (up->type == CLK_THUNDERBOLT) 428 init_thunderbolt(fd); 429 if (up->type == CLK_ACUTIME) 430 init_acutime(fd); 431 if (up->type == CLK_RESOLUTION) 432 init_resolution(fd); 433 434 return 1; 435 } 436 437 438 /* 439 * palisade_shutdown - shut down the clock 440 */ 441 static void 442 palisade_shutdown ( 443 int unit, 444 struct peer *peer 445 ) 446 { 447 struct palisade_unit *up; 448 struct refclockproc *pp; 449 pp = peer->procptr; 450 up = pp->unitptr; 451 if (-1 != pp->io.fd) 452 io_closeclock(&pp->io); 453 if (NULL != up) 454 free(up); 455 } 456 457 458 /* 459 * unpack helpers 460 */ 461 462 static inline uint8_t 463 get_u8( 464 const char *cp) 465 { 466 return ((const u_char*)cp)[0]; 467 } 468 469 static inline uint16_t 470 get_u16( 471 const char *cp) 472 { 473 return ((uint16_t)get_u8(cp) << 8) | get_u8(cp + 1); 474 } 475 476 /* 477 * unpack & fix date (the receiver provides a valid time for 1024 weeks 478 * after 1997-12-14 and therefore folds back in 2017, 2037,...) 479 * 480 * Returns -1 on error, day-of-month + (month * 32) othertwise. 481 */ 482 int 483 decode_date( 484 struct refclockproc *pp, 485 const char *cp) 486 { 487 static int32_t s_baseday = 0; 488 489 struct calendar jd; 490 int32_t rd; 491 492 if (0 == s_baseday) { 493 if (!ntpcal_get_build_date(&jd)) { 494 jd.year = 2015; 495 jd.month = 1; 496 jd.monthday = 1; 497 } 498 s_baseday = ntpcal_date_to_rd(&jd); 499 } 500 501 /* get date fields and convert to RDN */ 502 jd.monthday = get_u8 ( cp ); 503 jd.month = get_u8 (cp + 1); 504 jd.year = get_u16(cp + 2); 505 rd = ntpcal_date_to_rd(&jd); 506 507 /* for the paranoid: do reverse calculation and cross-check */ 508 ntpcal_rd_to_date(&jd, rd); 509 if ((jd.monthday != get_u8 ( cp )) || 510 (jd.month != get_u8 (cp + 1)) || 511 (jd.year != get_u16(cp + 2)) ) 512 return - 1; 513 514 /* calculate cycle shift to base day and calculate re-folded 515 * date 516 * 517 * One could do a proper modulo calculation here, but a counting 518 * loop is probably faster for the next few rollovers... 519 */ 520 while (rd < s_baseday) 521 rd += 7*1024; 522 ntpcal_rd_to_date(&jd, rd); 523 524 /* fill refclock structure & indicate success */ 525 pp->day = jd.yearday; 526 pp->year = jd.year; 527 return ((int)jd.month << 5) | jd.monthday; 528 } 529 530 531 /* 532 * TSIP_decode - decode the TSIP data packets 533 */ 534 int 535 TSIP_decode ( 536 struct peer *peer 537 ) 538 { 539 int st; 540 long secint; 541 double secs; 542 double secfrac; 543 unsigned short event = 0; 544 int mmday; 545 long tow; 546 uint16_t wn; 547 int GPS_UTC_Offset; 548 549 struct palisade_unit *up; 550 struct refclockproc *pp; 551 552 pp = peer->procptr; 553 up = pp->unitptr; 554 555 /* 556 * Check the time packet, decode its contents. 557 * If the timecode has invalid length or is not in 558 * proper format, declare bad format and exit. 559 */ 560 561 if ((up->type != CLK_THUNDERBOLT) && 562 (up->type != CLK_ACUTIME ) && 563 (up->type != CLK_RESOLUTION ) && 564 (up->type != CLK_ACE ) && 565 (up->type != CLK_COPERNICUS ) ) 566 { 567 if ((up->rpt_buf[0] == (char) 0x41) || 568 (up->rpt_buf[0] == (char) 0x46) || 569 (up->rpt_buf[0] == (char) 0x54) || 570 (up->rpt_buf[0] == (char) 0x4B) || 571 (up->rpt_buf[0] == (char) 0x6D)) { 572 573 /* standard time packet - GPS time and GPS week number */ 574 #ifdef DEBUG 575 printf("Palisade Port B packets detected. Connect to Port A\n"); 576 #endif 577 578 return 0; 579 } 580 } 581 582 /* 583 * We cast both to u_char as 0x8f uses the sign bit on a char 584 */ 585 if ((u_char) up->rpt_buf[0] == (u_char) 0x8f) { 586 /* 587 * Superpackets 588 */ 589 event = (unsigned short) (getint((u_char *) &mb(1)) & 0xffff); 590 if (!((pp->sloppyclockflag & CLK_FLAG2) || event)) 591 /* Ignore Packet */ 592 return 0; 593 594 switch (mb(0) & 0xff) { 595 596 case PACKET_8F0B: 597 598 if (up->polled <= 0) 599 return 0; 600 601 if (up->rpt_cnt != LENCODE_8F0B) /* check length */ 602 break; 603 604 #ifdef DEBUG 605 if (debug > 1) { 606 int ts; 607 double lat, lon, alt; 608 lat = getdbl((u_char *) &mb(42)) * R2D; 609 lon = getdbl((u_char *) &mb(50)) * R2D; 610 alt = getdbl((u_char *) &mb(58)); 611 612 printf("TSIP_decode: unit %d: Latitude: %03.4f Longitude: %03.4f Alt: %05.2f m\n", 613 up->unit, lat,lon,alt); 614 printf("TSIP_decode: unit %d: Sats:", 615 up->unit); 616 for (st = 66, ts = 0; st <= 73; st++) 617 if (mb(st)) { 618 if (mb(st) > 0) ts++; 619 printf(" %02d", mb(st)); 620 } 621 printf(" : Tracking %d\n", ts); 622 } 623 #endif 624 625 GPS_UTC_Offset = getint((u_char *) &mb(16)); 626 if (GPS_UTC_Offset == 0) { /* Check UTC offset */ 627 #ifdef DEBUG 628 printf("TSIP_decode: UTC Offset Unknown\n"); 629 #endif 630 break; 631 } 632 633 secs = getdbl((u_char *) &mb(3)); 634 secint = (long) secs; 635 secfrac = secs - secint; /* 0.0 <= secfrac < 1.0 */ 636 637 pp->nsec = (long) (secfrac * 1000000000); 638 639 secint %= 86400; /* Only care about today */ 640 pp->hour = secint / 3600; 641 secint %= 3600; 642 pp->minute = secint / 60; 643 secint %= 60; 644 pp->second = secint % 60; 645 646 mmday = decode_date(pp, &mb(11)); 647 if (mmday < 0) 648 break; 649 650 #ifdef DEBUG 651 if (debug > 1) 652 printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%09ld %02d/%02d/%04d UTC %02d\n", 653 up->unit, mb(0) & 0xff, event, pp->hour, pp->minute, 654 pp->second, pp->nsec, (mmday >> 5), (mmday & 31), pp->year, GPS_UTC_Offset); 655 #endif 656 /* Only use this packet when no 657 * 8F-AD's are being received 658 */ 659 660 if (up->leap_status) { 661 up->leap_status = 0; 662 return 0; 663 } 664 665 return 2; 666 break; 667 668 case PACKET_NTP: 669 /* Palisade-NTP Packet */ 670 671 if (up->rpt_cnt != LENCODE_NTP) /* check length */ 672 break; 673 674 up->leap_status = mb(19); 675 676 if (up->polled <= 0) 677 return 0; 678 679 /* Check Tracking Status */ 680 st = mb(18); 681 if (st < 0 || st > 14) 682 st = 14; 683 if ((st >= 2 && st <= 7) || st == 11 || st == 12) { 684 #ifdef DEBUG 685 printf("TSIP_decode: Not Tracking Sats : %s\n", 686 *Tracking_Status[st]); 687 #endif 688 refclock_report(peer, CEVNT_BADTIME); 689 up->polled = -1; 690 return 0; 691 break; 692 } 693 694 mmday = decode_date(pp, &mb(14)); 695 if (mmday < 0) 696 break; 697 up->month = (mmday >> 5); /* Save for LEAP check */ 698 699 if ( (up->leap_status & PALISADE_LEAP_PENDING) && 700 /* Avoid early announce: https://bugs.ntp.org/2773 */ 701 (6 == up->month || 12 == up->month) ) { 702 if (up->leap_status & PALISADE_UTC_TIME) 703 pp->leap = LEAP_ADDSECOND; 704 else 705 pp->leap = LEAP_DELSECOND; 706 } 707 else if (up->leap_status) 708 pp->leap = LEAP_NOWARNING; 709 710 else { /* UTC flag is not set: 711 * Receiver may have been reset, and lost 712 * its UTC almanac data */ 713 pp->leap = LEAP_NOTINSYNC; 714 #ifdef DEBUG 715 printf("TSIP_decode: UTC Almanac unavailable: %d\n", 716 mb(19)); 717 #endif 718 refclock_report(peer, CEVNT_BADTIME); 719 up->polled = -1; 720 return 0; 721 } 722 723 pp->nsec = (long) (getdbl((u_char *) &mb(3)) 724 * 1000000000); 725 726 pp->hour = mb(11); 727 pp->minute = mb(12); 728 pp->second = mb(13); 729 730 #ifdef DEBUG 731 if (debug > 1) 732 printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%09ld %02d/%02d/%04d UTC %02x %s\n", 733 up->unit, mb(0) & 0xff, event, pp->hour, pp->minute, 734 pp->second, pp->nsec, (mmday >> 5), (mmday & 31), pp->year, 735 mb(19), *Tracking_Status[st]); 736 #endif 737 return 1; 738 break; 739 740 case PACKET_8FAC: 741 if (up->polled <= 0) 742 return 0; 743 744 if (up->rpt_cnt != LENCODE_8FAC)/* check length */ 745 break; 746 747 #ifdef DEBUG 748 if (debug > 1) { 749 double lat, lon, alt; 750 lat = getdbl((u_char *) &mb(36)) * R2D; 751 lon = getdbl((u_char *) &mb(44)) * R2D; 752 alt = getdbl((u_char *) &mb(52)); 753 754 printf("TSIP_decode: unit %d: Latitude: %03.4f Longitude: %03.4f Alt: %05.2f m\n", 755 up->unit, lat,lon,alt); 756 printf("TSIP_decode: unit %d\n", up->unit); 757 } 758 #endif 759 if ( (getint((u_char *) &mb(10)) & 0x80) && 760 /* Avoid early announce: https://bugs.ntp.org/2773 */ 761 (6 == up->month || 12 == up->month) ) 762 pp->leap = LEAP_ADDSECOND; /* we ASSUME addsecond */ 763 else 764 pp->leap = LEAP_NOWARNING; 765 766 #ifdef DEBUG 767 if (debug > 1) 768 printf("TSIP_decode: unit %d: 0x%02x leap %d\n", 769 up->unit, mb(0) & 0xff, pp->leap); 770 if (debug > 1) { 771 printf("Receiver MODE: 0x%02X\n", (u_char)mb(1)); 772 if (mb(1) == 0x00) 773 printf(" AUTOMATIC\n"); 774 if (mb(1) == 0x01) 775 printf(" SINGLE SATELLITE\n"); 776 if (mb(1) == 0x03) 777 printf(" HORIZONTAL(2D)\n"); 778 if (mb(1) == 0x04) 779 printf(" FULL POSITION(3D)\n"); 780 if (mb(1) == 0x05) 781 printf(" DGPR REFERENCE\n"); 782 if (mb(1) == 0x06) 783 printf(" CLOCK HOLD(2D)\n"); 784 if (mb(1) == 0x07) 785 printf(" OVERDETERMINED CLOCK\n"); 786 787 printf("\n** Disciplining MODE 0x%02X:\n", (u_char)mb(2)); 788 if (mb(2) == 0x00) 789 printf(" NORMAL\n"); 790 if (mb(2) == 0x01) 791 printf(" POWER-UP\n"); 792 if (mb(2) == 0x02) 793 printf(" AUTO HOLDOVER\n"); 794 if (mb(2) == 0x03) 795 printf(" MANUAL HOLDOVER\n"); 796 if (mb(2) == 0x04) 797 printf(" RECOVERY\n"); 798 if (mb(2) == 0x06) 799 printf(" DISCIPLINING DISABLED\n"); 800 } 801 #endif 802 return 0; 803 break; 804 805 case PACKET_8FAB: 806 /* Thunderbolt Primary Timing Packet */ 807 808 if (up->rpt_cnt != LENCODE_8FAB) /* check length */ 809 break; 810 811 if (up->polled <= 0) 812 return 0; 813 814 GPS_UTC_Offset = getint((u_char *) &mb(7)); 815 816 if (GPS_UTC_Offset == 0){ /* Check UTC Offset */ 817 #ifdef DEBUG 818 printf("TSIP_decode: UTC Offset Unknown\n"); 819 #endif 820 break; 821 } 822 823 824 if ((mb(9) & 0x1d) == 0x0) { 825 /* if we know the GPS time and the UTC offset, 826 we expect UTC timing information !!! */ 827 828 pp->leap = LEAP_NOTINSYNC; 829 refclock_report(peer, CEVNT_BADTIME); 830 up->polled = -1; 831 return 0; 832 } 833 834 pp->nsec = 0; 835 #ifdef DEBUG 836 printf("\nTiming Flags are:\n"); 837 printf("Timing flag value is: 0x%X\n", mb(9)); 838 if ((mb(9) & 0x01) != 0) 839 printf (" Getting UTC time\n"); 840 else 841 printf (" Getting GPS time\n"); 842 if ((mb(9) & 0x02) != 0) 843 printf (" PPS is from UTC\n"); 844 else 845 printf (" PPS is from GPS\n"); 846 if ((mb(9) & 0x04) != 0) 847 printf (" Time is not Set\n"); 848 else 849 printf (" Time is Set\n"); 850 if ((mb(9) & 0x08) != 0) 851 printf(" I dont have UTC info\n"); 852 else 853 printf (" I have UTC info\n"); 854 if ((mb(9) & 0x10) != 0) 855 printf (" Time is from USER\n\n"); 856 else 857 printf (" Time is from GPS\n\n"); 858 #endif 859 860 mmday = decode_date(pp, &mb(13)); 861 if (mmday < 0) 862 break; 863 tow = getlong((u_char *) &mb(1)); 864 #ifdef DEBUG 865 if (debug > 1) { 866 printf("pp->day: %d\n", pp->day); 867 printf("TOW: %ld\n", tow); 868 printf("DAY: %d\n", (mmday & 31)); 869 } 870 #endif 871 pp->hour = mb(12); 872 pp->minute = mb(11); 873 pp->second = mb(10); 874 875 876 #ifdef DEBUG 877 if (debug > 1) 878 printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%09ld %02d/%02d/%04d ", 879 up->unit, mb(0) & 0xff, event, pp->hour, pp->minute, pp->second, 880 pp->nsec, (mmday >> 5), (mmday & 31), pp->year); 881 #endif 882 return 1; 883 break; 884 885 default: 886 /* Ignore Packet */ 887 return 0; 888 } /* switch */ 889 } /* if 8F packets */ 890 891 else if (up->rpt_buf[0] == (u_char)0x42) { 892 printf("0x42\n"); 893 return 0; 894 } 895 else if (up->rpt_buf[0] == (u_char)0x43) { 896 printf("0x43\n"); 897 return 0; 898 } 899 else if ((up->rpt_buf[0] == PACKET_41) & (up->type == CLK_THUNDERBOLT)){ 900 printf("Undocumented 0x41 packet on Thunderbolt\n"); 901 return 0; 902 } 903 else if ((up->rpt_buf[0] == PACKET_41A) & (up->type == CLK_ACUTIME)) { 904 #ifdef DEBUG 905 printf("GPS TOW: %ld\n", (long)getlong((u_char *) &mb(0))); 906 printf("GPS WN: %d\n", getint((u_char *) &mb(4))); 907 printf("GPS UTC-GPS Offset: %ld\n", (long)getlong((u_char *) &mb(6))); 908 #endif 909 return 0; 910 } 911 912 /* GPS time packet for ACE III or Copernicus II receiver */ 913 else if ((up->rpt_buf[0] == PACKET_41) && 914 ((up->type == CLK_ACE) || (up->type == CLK_COPERNICUS))) { 915 #ifdef DEBUG 916 if ((debug > 1) && (up->type == CLK_ACE)) 917 printf("TSIP_decode: Packet 0x41 seen in ACE III mode\n"); 918 if ((debug > 1) && (up->type == CLK_COPERNICUS)) 919 printf("TSIP_decode: Packet 0x41 seen in Copernicus II mode\n"); 920 #endif 921 if (up->rpt_cnt != LENCODE_41) { /* check length */ 922 refclock_report(peer, CEVNT_BADREPLY); 923 up->polled = -1; 924 #ifdef DEBUG 925 printf("TSIP_decode: unit %d: bad packet %02x len %d\n", 926 up->unit, up->rpt_buf[0] & 0xff, up->rpt_cnt); 927 #endif 928 return 0; 929 } 930 if (up->polled <= 0) 931 return 0; 932 tow = (long)getsingle((u_char *) &mb(0)); 933 wn = (uint16_t)getint((u_char *) &mb(4)); 934 GPS_UTC_Offset = (int)getsingle((u_char *) &mb(6)); 935 if (GPS_UTC_Offset == 0){ /* Check UTC Offset */ 936 #ifdef DEBUG 937 printf("TSIP_decode: UTC Offset Unknown\n"); 938 #endif 939 refclock_report(peer, CEVNT_BADREPLY); 940 up->polled = -1; 941 return 0; 942 } 943 /* Get date & time from WN & ToW minus offset */ 944 { 945 TCivilDate cd; 946 TGpsDatum wd; 947 l_fp ugo; /* UTC-GPS offset, negative number */ 948 ugo.Ul_i.Xl_i = (int32_t)-GPS_UTC_Offset; 949 ugo.l_uf = 0; 950 wd = gpscal_from_gpsweek((wn % 1024), (int32_t)tow, ugo); 951 gpscal_to_calendar(&cd, &wd); 952 pp->year = cd.year; 953 pp->day = cd.yearday; 954 pp->hour = cd.hour; 955 pp->minute = cd.minute; 956 pp->second = cd.second; 957 pp->nsec = 0; 958 pp->leap = LEAP_NOWARNING; 959 #ifdef DEBUG 960 if (debug > 1) { 961 printf("GPS TOW: %ld\n", tow); 962 printf("GPS WN: %d\n", wn); 963 printf("GPS UTC-GPS Offset: %d\n", GPS_UTC_Offset); 964 printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%09ld %02d/%02d/%04d ", 965 up->unit, mb(0) & 0xff, event, pp->hour, pp->minute, pp->second, 966 pp->nsec, cd.month, cd.monthday, pp->year); 967 } 968 #endif 969 } 970 return 1; 971 } 972 973 /* Health Status for Acutime Receiver */ 974 else if ((up->rpt_buf[0] == PACKET_46) & (up->type == CLK_ACUTIME)) { 975 #ifdef DEBUG 976 if (debug > 1) 977 /* Status Codes */ 978 switch (mb(0)) { 979 case 0x00: 980 printf ("Doing Position Fixes\n"); 981 break; 982 case 0x01: 983 printf ("Do not have GPS time yet\n"); 984 break; 985 case 0x03: 986 printf ("PDOP is too high\n"); 987 break; 988 case 0x08: 989 printf ("No usable satellites\n"); 990 break; 991 case 0x09: 992 printf ("Only 1 usable satellite\n"); 993 break; 994 case 0x0A: 995 printf ("Only 2 usable satellites\n"); 996 break; 997 case 0x0B: 998 printf ("Only 3 usable satellites\n"); 999 break; 1000 case 0x0C: 1001 printf("The Chosen satellite is unusable\n"); 1002 break; 1003 } 1004 #endif 1005 /* Error Codes */ 1006 if (mb(1) != 0) { 1007 1008 refclock_report(peer, CEVNT_BADTIME); 1009 up->polled = -1; 1010 #ifdef DEBUG 1011 if (debug > 1) { 1012 if (mb(1) & 0x01) 1013 printf ("Signal Processor Error, reset unit.\n"); 1014 if (mb(1) & 0x02) 1015 printf ("Alignment error, channel or chip 1, reset unit.\n"); 1016 if (mb(1) & 0x03) 1017 printf ("Alignment error, channel or chip 2, reset unit.\n"); 1018 if (mb(1) & 0x04) 1019 printf ("Antenna feed line fault (open or short)\n"); 1020 if (mb(1) & 0x05) 1021 printf ("Excessive reference frequency error, refer to packet 0x2D and packet 0x4D documentation for further information\n"); 1022 } 1023 #endif 1024 1025 return 0; 1026 } 1027 } 1028 1029 /* Health Status for Copernicus II Receiver */ 1030 else if ((up->rpt_buf[0] == PACKET_46) && (up->type == CLK_COPERNICUS)) { 1031 #ifdef DEBUG 1032 if (debug > 1) 1033 /* Status Codes */ 1034 switch (mb(0)) { 1035 case 0x00: 1036 printf ("Doing Position Fixes\n"); 1037 break; 1038 case 0x01: 1039 printf ("Do not have GPS time yet\n"); 1040 break; 1041 case 0x03: 1042 printf ("PDOP is too high\n"); 1043 break; 1044 case 0x04: 1045 printf("The Chosen satellite is unusable\n"); 1046 break; 1047 case 0x08: 1048 printf ("No usable satellites\n"); 1049 break; 1050 case 0x09: 1051 printf ("Only 1 usable satellite\n"); 1052 break; 1053 case 0x0A: 1054 printf ("Only 2 usable satellites\n"); 1055 break; 1056 case 0x0B: 1057 printf ("Only 3 usable satellites\n"); 1058 break; 1059 } 1060 #endif 1061 /* Error Codes */ 1062 if ((mb(1) & 0x3E) != 0) { /* Don't regard bits 0 and 6 as errors */ 1063 refclock_report(peer, CEVNT_BADTIME); 1064 up->polled = -1; 1065 #ifdef DEBUG 1066 if (debug > 1) { 1067 if ((mb(1) & 0x18) == 0x08) 1068 printf ("Antenna feed line fault (open)\n"); 1069 if ((mb(1) & 0x18) == 0x18) 1070 printf ("Antenna feed line fault (short)\n"); 1071 } 1072 #endif 1073 } 1074 return 0; 1075 } 1076 1077 /* Other packets output by ACE III & Copernicus II Receivers, dropped silently */ 1078 else if (((up->rpt_buf[0] == (char) 0x4A) || 1079 (up->rpt_buf[0] == (char) 0x4B) || 1080 (up->rpt_buf[0] == (char) 0x56) || 1081 (up->rpt_buf[0] == (char) 0x5F) || 1082 (up->rpt_buf[0] == (char) 0x6D) || 1083 (up->rpt_buf[0] == (char) 0x82) || 1084 (up->rpt_buf[0] == (char) 0x84)) && 1085 ((up->type == CLK_ACE) || (up->type == CLK_COPERNICUS))) { 1086 #ifdef DEBUG 1087 if ((debug > 1) && (up->type == CLK_ACE)) 1088 printf("TSIP_decode: Packet 0x%2x seen in ACE III mode\n", (up->rpt_buf[0] & 0XFF)); 1089 if ((debug > 1) && (up->type == CLK_COPERNICUS)) 1090 printf("TSIP_decode: Packet 0x%2x seen in Copernicus II mode\n", (up->rpt_buf[0] & 0XFF)); 1091 #endif 1092 return 0; 1093 } 1094 1095 else if (up->rpt_buf[0] == 0x54) 1096 return 0; 1097 1098 else if (up->rpt_buf[0] == PACKET_6D) { 1099 #ifdef DEBUG 1100 int sats; 1101 1102 if ((mb(0) & 0x01) && (mb(0) & 0x02)) 1103 printf("2d Fix Dimension\n"); 1104 if (mb(0) & 0x04) 1105 printf("3d Fix Dimension\n"); 1106 1107 if (mb(0) & 0x08) 1108 printf("Fix Mode is MANUAL\n"); 1109 else 1110 printf("Fix Mode is AUTO\n"); 1111 1112 sats = mb(0) & 0xF0; 1113 sats = sats >> 4; 1114 printf("Tracking %d Satellites\n", sats); 1115 #endif 1116 return 0; 1117 } /* else if not super packet */ 1118 refclock_report(peer, CEVNT_BADREPLY); 1119 up->polled = -1; 1120 #ifdef DEBUG 1121 printf("TSIP_decode: unit %d: bad packet %02x-%02x event %d len %d\n", 1122 up->unit, up->rpt_buf[0] & 0xff, mb(0) & 0xff, 1123 event, up->rpt_cnt); 1124 #endif 1125 return 0; 1126 } 1127 1128 /* 1129 * palisade__receive - receive data from the serial interface 1130 */ 1131 1132 static void 1133 palisade_receive ( 1134 struct peer * peer 1135 ) 1136 { 1137 struct palisade_unit *up; 1138 struct refclockproc *pp; 1139 1140 /* 1141 * Initialize pointers and read the timecode and timestamp. 1142 */ 1143 pp = peer->procptr; 1144 up = pp->unitptr; 1145 1146 if (! TSIP_decode(peer)) return; 1147 1148 if (up->polled <= 0) 1149 return; /* no poll pending, already received or timeout */ 1150 1151 up->polled = 0; /* Poll reply received */ 1152 pp->lencode = 0; /* clear time code */ 1153 #ifdef DEBUG 1154 if (debug) 1155 printf( 1156 "palisade_receive: unit %d: %4d %03d %02d:%02d:%02d.%09ld\n", 1157 up->unit, pp->year, pp->day, pp->hour, pp->minute, 1158 pp->second, pp->nsec); 1159 #endif 1160 1161 /* 1162 * Process the sample 1163 * Generate timecode: YYYY DoY HH:MM:SS.microsec 1164 * report and process 1165 */ 1166 1167 snprintf(pp->a_lastcode, sizeof(pp->a_lastcode), 1168 "%4d %03d %02d:%02d:%02d.%09ld", 1169 pp->year, pp->day, 1170 pp->hour,pp->minute, pp->second, pp->nsec); 1171 pp->lencode = 24; 1172 1173 if (!refclock_process(pp)) { 1174 refclock_report(peer, CEVNT_BADTIME); 1175 1176 #ifdef DEBUG 1177 printf("palisade_receive: unit %d: refclock_process failed!\n", 1178 up->unit); 1179 #endif 1180 return; 1181 } 1182 1183 record_clock_stats(&peer->srcadr, pp->a_lastcode); 1184 1185 #ifdef DEBUG 1186 if (debug) 1187 printf("palisade_receive: unit %d: %s\n", 1188 up->unit, prettydate(&pp->lastrec)); 1189 #endif 1190 pp->lastref = pp->lastrec; 1191 refclock_receive(peer); 1192 } 1193 1194 1195 /* 1196 * palisade_poll - called by the transmit procedure 1197 * 1198 */ 1199 static void 1200 palisade_poll ( 1201 int unit, 1202 struct peer *peer 1203 ) 1204 { 1205 struct palisade_unit *up; 1206 struct refclockproc *pp; 1207 1208 pp = peer->procptr; 1209 up = pp->unitptr; 1210 1211 pp->polls++; 1212 if (up->polled > 0) /* last reply never arrived or error */ 1213 refclock_report(peer, CEVNT_TIMEOUT); 1214 1215 up->polled = 2; /* synchronous packet + 1 event */ 1216 1217 #ifdef DEBUG 1218 if (debug) 1219 printf("palisade_poll: unit %d: polling %s\n", unit, 1220 (pp->sloppyclockflag & CLK_FLAG2) ? 1221 "synchronous packet" : "event"); 1222 #endif 1223 1224 if (pp->sloppyclockflag & CLK_FLAG2) 1225 return; /* using synchronous packet input */ 1226 1227 if(up->type == CLK_PRAECIS) { 1228 if (write(peer->procptr->io.fd,"SPSTAT\r\n",8) < 0) { 1229 msyslog(LOG_ERR, "Palisade(%d) write: %m:",unit); 1230 } else { 1231 praecis_msg = 1; 1232 return; 1233 } 1234 } 1235 1236 if (HW_poll(pp) < 0) 1237 refclock_report(peer, CEVNT_FAULT); 1238 } 1239 1240 static void 1241 praecis_parse ( 1242 struct recvbuf *rbufp, 1243 struct peer *peer 1244 ) 1245 { 1246 static char buf[100]; 1247 static int p = 0; 1248 struct refclockproc *pp; 1249 1250 pp = peer->procptr; 1251 1252 if (p + rbufp->recv_length >= sizeof buf) { 1253 struct palisade_unit *up; 1254 up = pp->unitptr; 1255 1256 /* 1257 * We COULD see if there is a \r\n in the incoming 1258 * buffer before it overflows, and then process the 1259 * current line. 1260 * 1261 * Similarly, if we already have a hunk of data that 1262 * we're now flushing, that will cause the line of 1263 * data we're in the process of collecting to be garbage. 1264 * 1265 * Since we now check for this overflow and log when it 1266 * happens, we're now in a better place to easily see 1267 * what's going on and perhaps better choices can be made. 1268 */ 1269 1270 /* Do we need to log the size of the overflow? */ 1271 msyslog(LOG_ERR, "Palisade(%d) praecis_parse(): input buffer overflow", 1272 up->unit); 1273 1274 p = 0; 1275 praecis_msg = 0; 1276 1277 refclock_report(peer, CEVNT_BADREPLY); 1278 1279 return; 1280 } 1281 1282 memcpy(buf+p, rbufp->recv_buffer, rbufp->recv_length); 1283 p += rbufp->recv_length; 1284 1285 if ( p >= 2 1286 && buf[p-2] == '\r' 1287 && buf[p-1] == '\n') { 1288 buf[p-2] = '\0'; 1289 record_clock_stats(&peer->srcadr, buf); 1290 1291 p = 0; 1292 praecis_msg = 0; 1293 1294 if (HW_poll(pp) < 0) { 1295 refclock_report(peer, CEVNT_FAULT); 1296 } 1297 } 1298 return; 1299 } 1300 1301 static void 1302 palisade_io ( 1303 struct recvbuf *rbufp 1304 ) 1305 { 1306 /* 1307 * Initialize pointers and read the timecode and timestamp. 1308 */ 1309 struct palisade_unit *up; 1310 struct refclockproc *pp; 1311 struct peer *peer; 1312 1313 char * c, * d; 1314 1315 peer = rbufp->recv_peer; 1316 pp = peer->procptr; 1317 up = pp->unitptr; 1318 1319 if(up->type == CLK_PRAECIS) { 1320 if(praecis_msg) { 1321 praecis_parse(rbufp,peer); 1322 return; 1323 } 1324 } 1325 1326 c = (char *) &rbufp->recv_space; 1327 d = c + rbufp->recv_length; 1328 1329 while (c != d) { 1330 1331 /* Build time packet */ 1332 switch (up->rpt_status) { 1333 1334 case TSIP_PARSED_DLE_1: 1335 switch (*c) 1336 { 1337 case 0: 1338 case DLE: 1339 case ETX: 1340 up->rpt_status = TSIP_PARSED_EMPTY; 1341 break; 1342 1343 default: 1344 up->rpt_status = TSIP_PARSED_DATA; 1345 /* save packet ID */ 1346 up->rpt_buf[0] = *c; 1347 break; 1348 } 1349 break; 1350 1351 case TSIP_PARSED_DATA: 1352 if (*c == DLE) 1353 up->rpt_status = TSIP_PARSED_DLE_2; 1354 else 1355 mb(up->rpt_cnt++) = *c; 1356 break; 1357 1358 case TSIP_PARSED_DLE_2: 1359 if (*c == DLE) { 1360 up->rpt_status = TSIP_PARSED_DATA; 1361 mb(up->rpt_cnt++) = 1362 *c; 1363 } 1364 else if (*c == ETX) 1365 up->rpt_status = TSIP_PARSED_FULL; 1366 else { 1367 /* error: start new report packet */ 1368 up->rpt_status = TSIP_PARSED_DLE_1; 1369 up->rpt_buf[0] = *c; 1370 } 1371 break; 1372 1373 case TSIP_PARSED_FULL: 1374 case TSIP_PARSED_EMPTY: 1375 default: 1376 if ( *c != DLE) 1377 up->rpt_status = TSIP_PARSED_EMPTY; 1378 else 1379 up->rpt_status = TSIP_PARSED_DLE_1; 1380 break; 1381 } 1382 1383 c++; 1384 1385 if (up->rpt_status == TSIP_PARSED_DLE_1) { 1386 up->rpt_cnt = 0; 1387 if (pp->sloppyclockflag & CLK_FLAG2) 1388 /* stamp it */ 1389 get_systime(&pp->lastrec); 1390 } 1391 else if (up->rpt_status == TSIP_PARSED_EMPTY) 1392 up->rpt_cnt = 0; 1393 1394 else if (up->rpt_cnt > BMAX) 1395 up->rpt_status =TSIP_PARSED_EMPTY; 1396 1397 if (up->rpt_status == TSIP_PARSED_FULL) 1398 palisade_receive(peer); 1399 1400 } /* while chars in buffer */ 1401 } 1402 1403 1404 /* 1405 * Trigger the Palisade's event input, which is driven off the RTS 1406 * 1407 * Take a system time stamp to match the GPS time stamp. 1408 * 1409 */ 1410 long 1411 HW_poll ( 1412 struct refclockproc * pp /* pointer to unit structure */ 1413 ) 1414 { 1415 int x; /* state before & after RTS set */ 1416 struct palisade_unit *up; 1417 struct packettx tx; 1418 1419 up = pp->unitptr; 1420 1421 if (up->type == CLK_ACE) { 1422 /* Poll by sending a 0x21 command */ 1423 tx.size = 0; 1424 tx.data = (u_char *) emalloc(100); 1425 sendcmd (&tx, 0x21); 1426 sendetx (&tx, pp->io.fd); 1427 free(tx.data); 1428 } else { 1429 1430 /* read the current status, so we put things back right */ 1431 if (ioctl(pp->io.fd, TIOCMGET, &x) < 0) { 1432 DPRINTF(1, ("Palisade HW_poll: unit %d: GET %m\n", 1433 up->unit)); 1434 msyslog(LOG_ERR, "Palisade(%d) HW_poll: ioctl(fd,GET): %m", 1435 up->unit); 1436 return -1; 1437 } 1438 1439 x |= TIOCM_RTS; /* turn on RTS */ 1440 1441 /* Edge trigger */ 1442 if (up->type == CLK_ACUTIME) 1443 if (write (pp->io.fd, "", 1) != 1) 1444 msyslog(LOG_WARNING, 1445 "Palisade(%d) HW_poll: failed to send trigger: %m", 1446 up->unit); 1447 1448 if (ioctl(pp->io.fd, TIOCMSET, &x) < 0) { 1449 #ifdef DEBUG 1450 if (debug) 1451 printf("Palisade HW_poll: unit %d: SET \n", up->unit); 1452 #endif 1453 msyslog(LOG_ERR, 1454 "Palisade(%d) HW_poll: ioctl(fd, SET, RTS_on): %m", 1455 up->unit); 1456 return -1; 1457 } 1458 1459 x &= ~TIOCM_RTS; /* turn off RTS */ 1460 1461 } /* (up->type != CLK_ACE) */ 1462 1463 /* poll timestamp */ 1464 get_systime(&pp->lastrec); 1465 1466 if (up->type != CLK_ACE) { 1467 if (ioctl(pp->io.fd, TIOCMSET, &x) == -1) { 1468 #ifdef DEBUG 1469 if (debug) 1470 printf("Palisade HW_poll: unit %d: UNSET \n", up->unit); 1471 #endif 1472 msyslog(LOG_ERR, 1473 "Palisade(%d) HW_poll: ioctl(fd, UNSET, RTS_off): %m", 1474 up->unit); 1475 return -1; 1476 } 1477 } 1478 1479 return 0; 1480 } 1481 1482 /* 1483 * copy/swap a big-endian palisade double into a host double 1484 */ 1485 static double 1486 getdbl ( 1487 u_char *bp 1488 ) 1489 { 1490 #ifdef WORDS_BIGENDIAN 1491 double out; 1492 1493 memcpy(&out, bp, sizeof(out)); 1494 return out; 1495 #else 1496 union { 1497 u_char ch[8]; 1498 u_int32 u32[2]; 1499 } ui; 1500 1501 union { 1502 double out; 1503 u_int32 u32[2]; 1504 } uo; 1505 1506 memcpy(ui.ch, bp, sizeof(ui.ch)); 1507 /* least-significant 32 bits of double from swapped bp[4] to bp[7] */ 1508 uo.u32[0] = ntohl(ui.u32[1]); 1509 /* most-significant 32 bits from swapped bp[0] to bp[3] */ 1510 uo.u32[1] = ntohl(ui.u32[0]); 1511 1512 return uo.out; 1513 #endif 1514 } 1515 1516 /* 1517 * copy/swap a big-endian palisade short into a host short 1518 */ 1519 static short 1520 getint ( 1521 u_char *bp 1522 ) 1523 { 1524 u_short us; 1525 1526 memcpy(&us, bp, sizeof(us)); 1527 return (short)ntohs(us); 1528 } 1529 1530 /* 1531 * copy/swap a big-endian palisade 32-bit int into a host 32-bit int 1532 */ 1533 static int32 1534 getlong( 1535 u_char *bp 1536 ) 1537 { 1538 u_int32 u32; 1539 1540 memcpy(&u32, bp, sizeof(u32)); 1541 return (int32)(u_int32)ntohl(u32); 1542 } 1543 1544 /* 1545 * copy/swap a big-endian 32-bit single-precision floating point into a host 32-bit int 1546 */ 1547 static int32 1548 getsingle( 1549 u_char *bp 1550 ) 1551 { 1552 u_int32 mantissa; 1553 int8_t exponent; 1554 uint8_t sign, exp_field; 1555 int32 res; 1556 1557 memcpy(&mantissa, bp, sizeof(mantissa)); 1558 mantissa = ((u_int32)ntohl(mantissa) & 0x7FFFFF) | 0x800000; 1559 exp_field = ((uint8_t)bp[0] << 1) + ((uint8_t)bp[1] >> 7); 1560 exponent = (int8_t)exp_field - 127; 1561 sign = ((uint8_t)bp[0] >> 7); 1562 if (exponent > 23) 1563 res = (int32)(mantissa << (exponent - 23)); 1564 else 1565 res = (int32)(mantissa >> (23 - exponent)); 1566 return sign ? -res : res; 1567 } 1568 1569 #else /* REFCLOCK && CLOCK_PALISADE*/ 1570 NONEMPTY_TRANSLATION_UNIT 1571 #endif 1572