1 /* $NetBSD: refclock_palisade.c,v 1.8 2020/05/25 20:47:25 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 310 snprintf(gpsdev, sizeof(gpsdev), DEVICE, unit); 311 312 /* 313 * Open serial port. 314 */ 315 u_int speed; 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 TCivilDate cd; 947 TGpsDatum wd; 948 l_fp ugo; /* UTC-GPS offset, negative number */ 949 ugo.Ul_i.Xl_i = (int32_t)-GPS_UTC_Offset; 950 ugo.l_uf = 0; 951 wd = gpscal_from_gpsweek((wn % 1024), (int32_t)tow, ugo); 952 gpscal_to_calendar(&cd, &wd); 953 pp->year = cd.year; 954 pp->day = cd.yearday; 955 pp->hour = cd.hour; 956 pp->minute = cd.minute; 957 pp->second = cd.second; 958 pp->nsec = 0; 959 pp->leap = LEAP_NOWARNING; 960 #ifdef DEBUG 961 if (debug > 1) { 962 printf("GPS TOW: %ld\n", tow); 963 printf("GPS WN: %d\n", wn); 964 printf("GPS UTC-GPS Offset: %d\n", GPS_UTC_Offset); 965 printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%09ld %02d/%02d/%04d ", 966 up->unit, mb(0) & 0xff, event, pp->hour, pp->minute, pp->second, 967 pp->nsec, cd.month, cd.monthday, pp->year); 968 } 969 #endif 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 memcpy(buf+p,rbufp->recv_space.X_recv_buffer, rbufp->recv_length); 1253 p += rbufp->recv_length; 1254 1255 if(buf[p-2] == '\r' && buf[p-1] == '\n') { 1256 buf[p-2] = '\0'; 1257 record_clock_stats(&peer->srcadr, buf); 1258 1259 p = 0; 1260 praecis_msg = 0; 1261 1262 if (HW_poll(pp) < 0) 1263 refclock_report(peer, CEVNT_FAULT); 1264 1265 } 1266 } 1267 1268 static void 1269 palisade_io ( 1270 struct recvbuf *rbufp 1271 ) 1272 { 1273 /* 1274 * Initialize pointers and read the timecode and timestamp. 1275 */ 1276 struct palisade_unit *up; 1277 struct refclockproc *pp; 1278 struct peer *peer; 1279 1280 char * c, * d; 1281 1282 peer = rbufp->recv_peer; 1283 pp = peer->procptr; 1284 up = pp->unitptr; 1285 1286 if(up->type == CLK_PRAECIS) { 1287 if(praecis_msg) { 1288 praecis_parse(rbufp,peer); 1289 return; 1290 } 1291 } 1292 1293 c = (char *) &rbufp->recv_space; 1294 d = c + rbufp->recv_length; 1295 1296 while (c != d) { 1297 1298 /* Build time packet */ 1299 switch (up->rpt_status) { 1300 1301 case TSIP_PARSED_DLE_1: 1302 switch (*c) 1303 { 1304 case 0: 1305 case DLE: 1306 case ETX: 1307 up->rpt_status = TSIP_PARSED_EMPTY; 1308 break; 1309 1310 default: 1311 up->rpt_status = TSIP_PARSED_DATA; 1312 /* save packet ID */ 1313 up->rpt_buf[0] = *c; 1314 break; 1315 } 1316 break; 1317 1318 case TSIP_PARSED_DATA: 1319 if (*c == DLE) 1320 up->rpt_status = TSIP_PARSED_DLE_2; 1321 else 1322 mb(up->rpt_cnt++) = *c; 1323 break; 1324 1325 case TSIP_PARSED_DLE_2: 1326 if (*c == DLE) { 1327 up->rpt_status = TSIP_PARSED_DATA; 1328 mb(up->rpt_cnt++) = 1329 *c; 1330 } 1331 else if (*c == ETX) 1332 up->rpt_status = TSIP_PARSED_FULL; 1333 else { 1334 /* error: start new report packet */ 1335 up->rpt_status = TSIP_PARSED_DLE_1; 1336 up->rpt_buf[0] = *c; 1337 } 1338 break; 1339 1340 case TSIP_PARSED_FULL: 1341 case TSIP_PARSED_EMPTY: 1342 default: 1343 if ( *c != DLE) 1344 up->rpt_status = TSIP_PARSED_EMPTY; 1345 else 1346 up->rpt_status = TSIP_PARSED_DLE_1; 1347 break; 1348 } 1349 1350 c++; 1351 1352 if (up->rpt_status == TSIP_PARSED_DLE_1) { 1353 up->rpt_cnt = 0; 1354 if (pp->sloppyclockflag & CLK_FLAG2) 1355 /* stamp it */ 1356 get_systime(&pp->lastrec); 1357 } 1358 else if (up->rpt_status == TSIP_PARSED_EMPTY) 1359 up->rpt_cnt = 0; 1360 1361 else if (up->rpt_cnt > BMAX) 1362 up->rpt_status =TSIP_PARSED_EMPTY; 1363 1364 if (up->rpt_status == TSIP_PARSED_FULL) 1365 palisade_receive(peer); 1366 1367 } /* while chars in buffer */ 1368 } 1369 1370 1371 /* 1372 * Trigger the Palisade's event input, which is driven off the RTS 1373 * 1374 * Take a system time stamp to match the GPS time stamp. 1375 * 1376 */ 1377 long 1378 HW_poll ( 1379 struct refclockproc * pp /* pointer to unit structure */ 1380 ) 1381 { 1382 int x; /* state before & after RTS set */ 1383 struct palisade_unit *up; 1384 struct packettx tx; 1385 1386 up = pp->unitptr; 1387 1388 if (up->type == CLK_ACE) { 1389 /* Poll by sending a 0x21 command */ 1390 tx.size = 0; 1391 tx.data = (u_char *) emalloc(100); 1392 sendcmd (&tx, 0x21); 1393 sendetx (&tx, pp->io.fd); 1394 free(tx.data); 1395 } else { 1396 1397 /* read the current status, so we put things back right */ 1398 if (ioctl(pp->io.fd, TIOCMGET, &x) < 0) { 1399 DPRINTF(1, ("Palisade HW_poll: unit %d: GET %m\n", 1400 up->unit)); 1401 msyslog(LOG_ERR, "Palisade(%d) HW_poll: ioctl(fd,GET): %m", 1402 up->unit); 1403 return -1; 1404 } 1405 1406 x |= TIOCM_RTS; /* turn on RTS */ 1407 1408 /* Edge trigger */ 1409 if (up->type == CLK_ACUTIME) 1410 write (pp->io.fd, "", 1); 1411 1412 if (ioctl(pp->io.fd, TIOCMSET, &x) < 0) { 1413 #ifdef DEBUG 1414 if (debug) 1415 printf("Palisade HW_poll: unit %d: SET \n", up->unit); 1416 #endif 1417 msyslog(LOG_ERR, 1418 "Palisade(%d) HW_poll: ioctl(fd, SET, RTS_on): %m", 1419 up->unit); 1420 return -1; 1421 } 1422 1423 x &= ~TIOCM_RTS; /* turn off RTS */ 1424 1425 } /* (up->type != CLK_ACE) */ 1426 1427 /* poll timestamp */ 1428 get_systime(&pp->lastrec); 1429 1430 if (up->type != CLK_ACE) { 1431 if (ioctl(pp->io.fd, TIOCMSET, &x) == -1) { 1432 #ifdef DEBUG 1433 if (debug) 1434 printf("Palisade HW_poll: unit %d: UNSET \n", up->unit); 1435 #endif 1436 msyslog(LOG_ERR, 1437 "Palisade(%d) HW_poll: ioctl(fd, UNSET, RTS_off): %m", 1438 up->unit); 1439 return -1; 1440 } 1441 } 1442 1443 return 0; 1444 } 1445 1446 /* 1447 * copy/swap a big-endian palisade double into a host double 1448 */ 1449 static double 1450 getdbl ( 1451 u_char *bp 1452 ) 1453 { 1454 #ifdef WORDS_BIGENDIAN 1455 double out; 1456 1457 memcpy(&out, bp, sizeof(out)); 1458 return out; 1459 #else 1460 union { 1461 u_char ch[8]; 1462 u_int32 u32[2]; 1463 } ui; 1464 1465 union { 1466 double out; 1467 u_int32 u32[2]; 1468 } uo; 1469 1470 memcpy(ui.ch, bp, sizeof(ui.ch)); 1471 /* least-significant 32 bits of double from swapped bp[4] to bp[7] */ 1472 uo.u32[0] = ntohl(ui.u32[1]); 1473 /* most-significant 32 bits from swapped bp[0] to bp[3] */ 1474 uo.u32[1] = ntohl(ui.u32[0]); 1475 1476 return uo.out; 1477 #endif 1478 } 1479 1480 /* 1481 * copy/swap a big-endian palisade short into a host short 1482 */ 1483 static short 1484 getint ( 1485 u_char *bp 1486 ) 1487 { 1488 u_short us; 1489 1490 memcpy(&us, bp, sizeof(us)); 1491 return (short)ntohs(us); 1492 } 1493 1494 /* 1495 * copy/swap a big-endian palisade 32-bit int into a host 32-bit int 1496 */ 1497 static int32 1498 getlong( 1499 u_char *bp 1500 ) 1501 { 1502 u_int32 u32; 1503 1504 memcpy(&u32, bp, sizeof(u32)); 1505 return (int32)(u_int32)ntohl(u32); 1506 } 1507 1508 /* 1509 * copy/swap a big-endian 32-bit single-precision floating point into a host 32-bit int 1510 */ 1511 static int32 1512 getsingle( 1513 u_char *bp 1514 ) 1515 { 1516 u_int32 mantissa; 1517 int8_t exponent; 1518 uint8_t sign, exp_field; 1519 int32 res; 1520 1521 memcpy(&mantissa, bp, sizeof(mantissa)); 1522 mantissa = ((u_int32)ntohl(mantissa) & 0x7FFFFF) | 0x800000; 1523 exp_field = ((uint8_t)bp[0] << 1) + ((uint8_t)bp[1] >> 7); 1524 exponent = (int8_t)exp_field - 127; 1525 sign = ((uint8_t)bp[0] >> 7); 1526 if (exponent > 23) 1527 res = (int32)(mantissa << (exponent - 23)); 1528 else 1529 res = (int32)(mantissa >> (23 - exponent)); 1530 return sign ? -res : res; 1531 } 1532 1533 #else /* REFCLOCK && CLOCK_PALISADE*/ 1534 int refclock_palisade_c_notempty; 1535 #endif 1536