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 * [email protected]
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: [email protected]
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 ([email protected])
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
sendcmd(struct packettx * buffer,int c)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
sendsupercmd(struct packettx * buffer,int c1,int c2)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
sendbyte(struct packettx * buffer,int b)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
sendint(struct packettx * buffer,int a)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
sendetx(struct packettx * buffer,int fd)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
init_thunderbolt(int fd)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
init_acutime(int fd)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
init_resolution(int fd)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
palisade_start(int unit,struct peer * peer)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
308 snprintf(gpsdev, sizeof(gpsdev), DEVICE, unit);
309
310 /*
311 * Open serial port.
312 */
313 u_int speed;
314 speed = (CLK_TYPE(peer) == CLK_COPERNICUS) ? SPEED232COP : SPEED232;
315 fd = refclock_open(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
palisade_shutdown(int unit,struct peer * peer)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
get_u8(const char * cp)463 get_u8(
464 const char *cp)
465 {
466 return ((const u_char*)cp)[0];
467 }
468
469 static inline uint16_t
get_u16(const char * cp)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
decode_date(struct refclockproc * pp,const char * cp)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
TSIP_decode(struct peer * peer)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 TCivilDate cd;
945 TGpsDatum wd;
946 l_fp ugo; /* UTC-GPS offset, negative number */
947 ugo.Ul_i.Xl_i = (int32_t)-GPS_UTC_Offset;
948 ugo.l_uf = 0;
949 wd = gpscal_from_gpsweek((wn % 1024), (int32_t)tow, ugo);
950 gpscal_to_calendar(&cd, &wd);
951 pp->year = cd.year;
952 pp->day = cd.yearday;
953 pp->hour = cd.hour;
954 pp->minute = cd.minute;
955 pp->second = cd.second;
956 pp->nsec = 0;
957 pp->leap = LEAP_NOWARNING;
958 #ifdef DEBUG
959 if (debug > 1) {
960 printf("GPS TOW: %ld\n", tow);
961 printf("GPS WN: %d\n", wn);
962 printf("GPS UTC-GPS Offset: %d\n", GPS_UTC_Offset);
963 printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%09ld %02d/%02d/%04d ",
964 up->unit, mb(0) & 0xff, event, pp->hour, pp->minute, pp->second,
965 pp->nsec, cd.month, cd.monthday, pp->year);
966 }
967 #endif
968 return 1;
969 }
970
971 /* Health Status for Acutime Receiver */
972 else if ((up->rpt_buf[0] == PACKET_46) & (up->type == CLK_ACUTIME)) {
973 #ifdef DEBUG
974 if (debug > 1)
975 /* Status Codes */
976 switch (mb(0)) {
977 case 0x00:
978 printf ("Doing Position Fixes\n");
979 break;
980 case 0x01:
981 printf ("Do not have GPS time yet\n");
982 break;
983 case 0x03:
984 printf ("PDOP is too high\n");
985 break;
986 case 0x08:
987 printf ("No usable satellites\n");
988 break;
989 case 0x09:
990 printf ("Only 1 usable satellite\n");
991 break;
992 case 0x0A:
993 printf ("Only 2 usable satellites\n");
994 break;
995 case 0x0B:
996 printf ("Only 3 usable satellites\n");
997 break;
998 case 0x0C:
999 printf("The Chosen satellite is unusable\n");
1000 break;
1001 }
1002 #endif
1003 /* Error Codes */
1004 if (mb(1) != 0) {
1005
1006 refclock_report(peer, CEVNT_BADTIME);
1007 up->polled = -1;
1008 #ifdef DEBUG
1009 if (debug > 1) {
1010 if (mb(1) & 0x01)
1011 printf ("Signal Processor Error, reset unit.\n");
1012 if (mb(1) & 0x02)
1013 printf ("Alignment error, channel or chip 1, reset unit.\n");
1014 if (mb(1) & 0x03)
1015 printf ("Alignment error, channel or chip 2, reset unit.\n");
1016 if (mb(1) & 0x04)
1017 printf ("Antenna feed line fault (open or short)\n");
1018 if (mb(1) & 0x05)
1019 printf ("Excessive reference frequency error, refer to packet 0x2D and packet 0x4D documentation for further information\n");
1020 }
1021 #endif
1022
1023 return 0;
1024 }
1025 }
1026
1027 /* Health Status for Copernicus II Receiver */
1028 else if ((up->rpt_buf[0] == PACKET_46) && (up->type == CLK_COPERNICUS)) {
1029 #ifdef DEBUG
1030 if (debug > 1)
1031 /* Status Codes */
1032 switch (mb(0)) {
1033 case 0x00:
1034 printf ("Doing Position Fixes\n");
1035 break;
1036 case 0x01:
1037 printf ("Do not have GPS time yet\n");
1038 break;
1039 case 0x03:
1040 printf ("PDOP is too high\n");
1041 break;
1042 case 0x04:
1043 printf("The Chosen satellite is unusable\n");
1044 break;
1045 case 0x08:
1046 printf ("No usable satellites\n");
1047 break;
1048 case 0x09:
1049 printf ("Only 1 usable satellite\n");
1050 break;
1051 case 0x0A:
1052 printf ("Only 2 usable satellites\n");
1053 break;
1054 case 0x0B:
1055 printf ("Only 3 usable satellites\n");
1056 break;
1057 }
1058 #endif
1059 /* Error Codes */
1060 if ((mb(1) & 0x3E) != 0) { /* Don't regard bits 0 and 6 as errors */
1061 refclock_report(peer, CEVNT_BADTIME);
1062 up->polled = -1;
1063 #ifdef DEBUG
1064 if (debug > 1) {
1065 if ((mb(1) & 0x18) == 0x08)
1066 printf ("Antenna feed line fault (open)\n");
1067 if ((mb(1) & 0x18) == 0x18)
1068 printf ("Antenna feed line fault (short)\n");
1069 }
1070 #endif
1071 }
1072 return 0;
1073 }
1074
1075 /* Other packets output by ACE III & Copernicus II Receivers, dropped silently */
1076 else if (((up->rpt_buf[0] == (char) 0x4A) ||
1077 (up->rpt_buf[0] == (char) 0x4B) ||
1078 (up->rpt_buf[0] == (char) 0x56) ||
1079 (up->rpt_buf[0] == (char) 0x5F) ||
1080 (up->rpt_buf[0] == (char) 0x6D) ||
1081 (up->rpt_buf[0] == (char) 0x82) ||
1082 (up->rpt_buf[0] == (char) 0x84)) &&
1083 ((up->type == CLK_ACE) || (up->type == CLK_COPERNICUS))) {
1084 #ifdef DEBUG
1085 if ((debug > 1) && (up->type == CLK_ACE))
1086 printf("TSIP_decode: Packet 0x%2x seen in ACE III mode\n", (up->rpt_buf[0] & 0XFF));
1087 if ((debug > 1) && (up->type == CLK_COPERNICUS))
1088 printf("TSIP_decode: Packet 0x%2x seen in Copernicus II mode\n", (up->rpt_buf[0] & 0XFF));
1089 #endif
1090 return 0;
1091 }
1092
1093 else if (up->rpt_buf[0] == 0x54)
1094 return 0;
1095
1096 else if (up->rpt_buf[0] == PACKET_6D) {
1097 #ifdef DEBUG
1098 int sats;
1099
1100 if ((mb(0) & 0x01) && (mb(0) & 0x02))
1101 printf("2d Fix Dimension\n");
1102 if (mb(0) & 0x04)
1103 printf("3d Fix Dimension\n");
1104
1105 if (mb(0) & 0x08)
1106 printf("Fix Mode is MANUAL\n");
1107 else
1108 printf("Fix Mode is AUTO\n");
1109
1110 sats = mb(0) & 0xF0;
1111 sats = sats >> 4;
1112 printf("Tracking %d Satellites\n", sats);
1113 #endif
1114 return 0;
1115 } /* else if not super packet */
1116 refclock_report(peer, CEVNT_BADREPLY);
1117 up->polled = -1;
1118 #ifdef DEBUG
1119 printf("TSIP_decode: unit %d: bad packet %02x-%02x event %d len %d\n",
1120 up->unit, up->rpt_buf[0] & 0xff, mb(0) & 0xff,
1121 event, up->rpt_cnt);
1122 #endif
1123 return 0;
1124 }
1125
1126 /*
1127 * palisade__receive - receive data from the serial interface
1128 */
1129
1130 static void
palisade_receive(struct peer * peer)1131 palisade_receive (
1132 struct peer * peer
1133 )
1134 {
1135 struct palisade_unit *up;
1136 struct refclockproc *pp;
1137
1138 /*
1139 * Initialize pointers and read the timecode and timestamp.
1140 */
1141 pp = peer->procptr;
1142 up = pp->unitptr;
1143
1144 if (! TSIP_decode(peer)) return;
1145
1146 if (up->polled <= 0)
1147 return; /* no poll pending, already received or timeout */
1148
1149 up->polled = 0; /* Poll reply received */
1150 pp->lencode = 0; /* clear time code */
1151 #ifdef DEBUG
1152 if (debug)
1153 printf(
1154 "palisade_receive: unit %d: %4d %03d %02d:%02d:%02d.%09ld\n",
1155 up->unit, pp->year, pp->day, pp->hour, pp->minute,
1156 pp->second, pp->nsec);
1157 #endif
1158
1159 /*
1160 * Process the sample
1161 * Generate timecode: YYYY DoY HH:MM:SS.microsec
1162 * report and process
1163 */
1164
1165 snprintf(pp->a_lastcode, sizeof(pp->a_lastcode),
1166 "%4d %03d %02d:%02d:%02d.%09ld",
1167 pp->year, pp->day,
1168 pp->hour,pp->minute, pp->second, pp->nsec);
1169 pp->lencode = 24;
1170
1171 if (!refclock_process(pp)) {
1172 refclock_report(peer, CEVNT_BADTIME);
1173
1174 #ifdef DEBUG
1175 printf("palisade_receive: unit %d: refclock_process failed!\n",
1176 up->unit);
1177 #endif
1178 return;
1179 }
1180
1181 record_clock_stats(&peer->srcadr, pp->a_lastcode);
1182
1183 #ifdef DEBUG
1184 if (debug)
1185 printf("palisade_receive: unit %d: %s\n",
1186 up->unit, prettydate(&pp->lastrec));
1187 #endif
1188 pp->lastref = pp->lastrec;
1189 refclock_receive(peer);
1190 }
1191
1192
1193 /*
1194 * palisade_poll - called by the transmit procedure
1195 *
1196 */
1197 static void
palisade_poll(int unit,struct peer * peer)1198 palisade_poll (
1199 int unit,
1200 struct peer *peer
1201 )
1202 {
1203 struct palisade_unit *up;
1204 struct refclockproc *pp;
1205
1206 pp = peer->procptr;
1207 up = pp->unitptr;
1208
1209 pp->polls++;
1210 if (up->polled > 0) /* last reply never arrived or error */
1211 refclock_report(peer, CEVNT_TIMEOUT);
1212
1213 up->polled = 2; /* synchronous packet + 1 event */
1214
1215 #ifdef DEBUG
1216 if (debug)
1217 printf("palisade_poll: unit %d: polling %s\n", unit,
1218 (pp->sloppyclockflag & CLK_FLAG2) ?
1219 "synchronous packet" : "event");
1220 #endif
1221
1222 if (pp->sloppyclockflag & CLK_FLAG2)
1223 return; /* using synchronous packet input */
1224
1225 if(up->type == CLK_PRAECIS) {
1226 if(write(peer->procptr->io.fd,"SPSTAT\r\n",8) < 0)
1227 msyslog(LOG_ERR, "Palisade(%d) write: %m:",unit);
1228 else {
1229 praecis_msg = 1;
1230 return;
1231 }
1232 }
1233
1234 if (HW_poll(pp) < 0)
1235 refclock_report(peer, CEVNT_FAULT);
1236 }
1237
1238 static void
praecis_parse(struct recvbuf * rbufp,struct peer * peer)1239 praecis_parse (
1240 struct recvbuf *rbufp,
1241 struct peer *peer
1242 )
1243 {
1244 static char buf[100];
1245 static int p = 0;
1246 struct refclockproc *pp;
1247
1248 pp = peer->procptr;
1249
1250 memcpy(buf+p,rbufp->recv_space.X_recv_buffer, rbufp->recv_length);
1251 p += rbufp->recv_length;
1252
1253 if(buf[p-2] == '\r' && buf[p-1] == '\n') {
1254 buf[p-2] = '\0';
1255 record_clock_stats(&peer->srcadr, buf);
1256
1257 p = 0;
1258 praecis_msg = 0;
1259
1260 if (HW_poll(pp) < 0)
1261 refclock_report(peer, CEVNT_FAULT);
1262
1263 }
1264 }
1265
1266 static void
palisade_io(struct recvbuf * rbufp)1267 palisade_io (
1268 struct recvbuf *rbufp
1269 )
1270 {
1271 /*
1272 * Initialize pointers and read the timecode and timestamp.
1273 */
1274 struct palisade_unit *up;
1275 struct refclockproc *pp;
1276 struct peer *peer;
1277
1278 char * c, * d;
1279
1280 peer = rbufp->recv_peer;
1281 pp = peer->procptr;
1282 up = pp->unitptr;
1283
1284 if(up->type == CLK_PRAECIS) {
1285 if(praecis_msg) {
1286 praecis_parse(rbufp,peer);
1287 return;
1288 }
1289 }
1290
1291 c = (char *) &rbufp->recv_space;
1292 d = c + rbufp->recv_length;
1293
1294 while (c != d) {
1295
1296 /* Build time packet */
1297 switch (up->rpt_status) {
1298
1299 case TSIP_PARSED_DLE_1:
1300 switch (*c)
1301 {
1302 case 0:
1303 case DLE:
1304 case ETX:
1305 up->rpt_status = TSIP_PARSED_EMPTY;
1306 break;
1307
1308 default:
1309 up->rpt_status = TSIP_PARSED_DATA;
1310 /* save packet ID */
1311 up->rpt_buf[0] = *c;
1312 break;
1313 }
1314 break;
1315
1316 case TSIP_PARSED_DATA:
1317 if (*c == DLE)
1318 up->rpt_status = TSIP_PARSED_DLE_2;
1319 else
1320 mb(up->rpt_cnt++) = *c;
1321 break;
1322
1323 case TSIP_PARSED_DLE_2:
1324 if (*c == DLE) {
1325 up->rpt_status = TSIP_PARSED_DATA;
1326 mb(up->rpt_cnt++) =
1327 *c;
1328 }
1329 else if (*c == ETX)
1330 up->rpt_status = TSIP_PARSED_FULL;
1331 else {
1332 /* error: start new report packet */
1333 up->rpt_status = TSIP_PARSED_DLE_1;
1334 up->rpt_buf[0] = *c;
1335 }
1336 break;
1337
1338 case TSIP_PARSED_FULL:
1339 case TSIP_PARSED_EMPTY:
1340 default:
1341 if ( *c != DLE)
1342 up->rpt_status = TSIP_PARSED_EMPTY;
1343 else
1344 up->rpt_status = TSIP_PARSED_DLE_1;
1345 break;
1346 }
1347
1348 c++;
1349
1350 if (up->rpt_status == TSIP_PARSED_DLE_1) {
1351 up->rpt_cnt = 0;
1352 if (pp->sloppyclockflag & CLK_FLAG2)
1353 /* stamp it */
1354 get_systime(&pp->lastrec);
1355 }
1356 else if (up->rpt_status == TSIP_PARSED_EMPTY)
1357 up->rpt_cnt = 0;
1358
1359 else if (up->rpt_cnt > BMAX)
1360 up->rpt_status =TSIP_PARSED_EMPTY;
1361
1362 if (up->rpt_status == TSIP_PARSED_FULL)
1363 palisade_receive(peer);
1364
1365 } /* while chars in buffer */
1366 }
1367
1368
1369 /*
1370 * Trigger the Palisade's event input, which is driven off the RTS
1371 *
1372 * Take a system time stamp to match the GPS time stamp.
1373 *
1374 */
1375 long
HW_poll(struct refclockproc * pp)1376 HW_poll (
1377 struct refclockproc * pp /* pointer to unit structure */
1378 )
1379 {
1380 int x; /* state before & after RTS set */
1381 struct palisade_unit *up;
1382 struct packettx tx;
1383
1384 up = pp->unitptr;
1385
1386 if (up->type == CLK_ACE) {
1387 /* Poll by sending a 0x21 command */
1388 tx.size = 0;
1389 tx.data = (u_char *) emalloc(100);
1390 sendcmd (&tx, 0x21);
1391 sendetx (&tx, pp->io.fd);
1392 free(tx.data);
1393 } else {
1394
1395 /* read the current status, so we put things back right */
1396 if (ioctl(pp->io.fd, TIOCMGET, &x) < 0) {
1397 DPRINTF(1, ("Palisade HW_poll: unit %d: GET %m\n",
1398 up->unit));
1399 msyslog(LOG_ERR, "Palisade(%d) HW_poll: ioctl(fd,GET): %m",
1400 up->unit);
1401 return -1;
1402 }
1403
1404 x |= TIOCM_RTS; /* turn on RTS */
1405
1406 /* Edge trigger */
1407 if (up->type == CLK_ACUTIME)
1408 write (pp->io.fd, "", 1);
1409
1410 if (ioctl(pp->io.fd, TIOCMSET, &x) < 0) {
1411 #ifdef DEBUG
1412 if (debug)
1413 printf("Palisade HW_poll: unit %d: SET \n", up->unit);
1414 #endif
1415 msyslog(LOG_ERR,
1416 "Palisade(%d) HW_poll: ioctl(fd, SET, RTS_on): %m",
1417 up->unit);
1418 return -1;
1419 }
1420
1421 x &= ~TIOCM_RTS; /* turn off RTS */
1422
1423 } /* (up->type != CLK_ACE) */
1424
1425 /* poll timestamp */
1426 get_systime(&pp->lastrec);
1427
1428 if (up->type != CLK_ACE) {
1429 if (ioctl(pp->io.fd, TIOCMSET, &x) == -1) {
1430 #ifdef DEBUG
1431 if (debug)
1432 printf("Palisade HW_poll: unit %d: UNSET \n", up->unit);
1433 #endif
1434 msyslog(LOG_ERR,
1435 "Palisade(%d) HW_poll: ioctl(fd, UNSET, RTS_off): %m",
1436 up->unit);
1437 return -1;
1438 }
1439 }
1440
1441 return 0;
1442 }
1443
1444 /*
1445 * copy/swap a big-endian palisade double into a host double
1446 */
1447 static double
getdbl(u_char * bp)1448 getdbl (
1449 u_char *bp
1450 )
1451 {
1452 #ifdef WORDS_BIGENDIAN
1453 double out;
1454
1455 memcpy(&out, bp, sizeof(out));
1456 return out;
1457 #else
1458 union {
1459 u_char ch[8];
1460 u_int32 u32[2];
1461 } ui;
1462
1463 union {
1464 double out;
1465 u_int32 u32[2];
1466 } uo;
1467
1468 memcpy(ui.ch, bp, sizeof(ui.ch));
1469 /* least-significant 32 bits of double from swapped bp[4] to bp[7] */
1470 uo.u32[0] = ntohl(ui.u32[1]);
1471 /* most-significant 32 bits from swapped bp[0] to bp[3] */
1472 uo.u32[1] = ntohl(ui.u32[0]);
1473
1474 return uo.out;
1475 #endif
1476 }
1477
1478 /*
1479 * copy/swap a big-endian palisade short into a host short
1480 */
1481 static short
getint(u_char * bp)1482 getint (
1483 u_char *bp
1484 )
1485 {
1486 u_short us;
1487
1488 memcpy(&us, bp, sizeof(us));
1489 return (short)ntohs(us);
1490 }
1491
1492 /*
1493 * copy/swap a big-endian palisade 32-bit int into a host 32-bit int
1494 */
1495 static int32
getlong(u_char * bp)1496 getlong(
1497 u_char *bp
1498 )
1499 {
1500 u_int32 u32;
1501
1502 memcpy(&u32, bp, sizeof(u32));
1503 return (int32)(u_int32)ntohl(u32);
1504 }
1505
1506 /*
1507 * copy/swap a big-endian 32-bit single-precision floating point into a host 32-bit int
1508 */
1509 static int32
getsingle(u_char * bp)1510 getsingle(
1511 u_char *bp
1512 )
1513 {
1514 u_int32 mantissa;
1515 int8_t exponent;
1516 uint8_t sign, exp_field;
1517 int32 res;
1518
1519 memcpy(&mantissa, bp, sizeof(mantissa));
1520 mantissa = ((u_int32)ntohl(mantissa) & 0x7FFFFF) | 0x800000;
1521 exp_field = ((uint8_t)bp[0] << 1) + ((uint8_t)bp[1] >> 7);
1522 exponent = (int8_t)exp_field - 127;
1523 sign = ((uint8_t)bp[0] >> 7);
1524 if (exponent > 23)
1525 res = (int32)(mantissa << (exponent - 23));
1526 else
1527 res = (int32)(mantissa >> (23 - exponent));
1528 return sign ? -res : res;
1529 }
1530
1531 #else /* REFCLOCK && CLOCK_PALISADE*/
1532 int refclock_palisade_c_notempty;
1533 #endif
1534