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