1 /* $NetBSD: refclock_palisade.c,v 1.10 2024/08/18 20:47:18 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
sendcmd(struct packettx * buffer,int c)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
sendsupercmd(struct packettx * buffer,int c1,int c2)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
sendbyte(struct packettx * buffer,int b)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
sendint(struct packettx * buffer,int a)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
sendetx(struct packettx * buffer,int fd)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
init_thunderbolt(int fd)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
init_acutime(int fd)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
init_resolution(int fd)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
palisade_start(int unit,struct peer * peer)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(&peer->srcadr, 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
palisade_shutdown(int unit,struct peer * peer)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
get_u8(const char * cp)465 get_u8(
466 const char *cp)
467 {
468 return ((const u_char*)cp)[0];
469 }
470
471 static inline uint16_t
get_u16(const char * cp)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
decode_date(struct refclockproc * pp,const char * cp)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
TSIP_decode(struct peer * peer)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
palisade_receive(struct peer * peer)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
palisade_poll(int unit,struct peer * peer)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
praecis_parse(struct recvbuf * rbufp,struct peer * peer)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 if ((size_t)(p + rbufp->recv_length) >= sizeof buf) {
1255 struct palisade_unit *up;
1256 up = pp->unitptr;
1257
1258 /*
1259 * We COULD see if there is a \r\n in the incoming
1260 * buffer before it overflows, and then process the
1261 * current line.
1262 *
1263 * Similarly, if we already have a hunk of data that
1264 * we're now flushing, that will cause the line of
1265 * data we're in the process of collecting to be garbage.
1266 *
1267 * Since we now check for this overflow and log when it
1268 * happens, we're now in a better place to easily see
1269 * what's going on and perhaps better choices can be made.
1270 */
1271
1272 /* Do we need to log the size of the overflow? */
1273 msyslog(LOG_ERR, "Palisade(%d) praecis_parse(): input buffer overflow",
1274 up->unit);
1275
1276 p = 0;
1277 praecis_msg = 0;
1278
1279 refclock_report(peer, CEVNT_BADREPLY);
1280
1281 return;
1282 }
1283
1284 memcpy(buf+p, rbufp->recv_buffer, rbufp->recv_length);
1285 p += rbufp->recv_length;
1286
1287 if ( p >= 2
1288 && buf[p-2] == '\r'
1289 && buf[p-1] == '\n') {
1290 buf[p-2] = '\0';
1291 record_clock_stats(&peer->srcadr, buf);
1292
1293 p = 0;
1294 praecis_msg = 0;
1295
1296 if (HW_poll(pp) < 0) {
1297 refclock_report(peer, CEVNT_FAULT);
1298 }
1299 }
1300 return;
1301 }
1302
1303 static void
palisade_io(struct recvbuf * rbufp)1304 palisade_io (
1305 struct recvbuf *rbufp
1306 )
1307 {
1308 /*
1309 * Initialize pointers and read the timecode and timestamp.
1310 */
1311 struct palisade_unit *up;
1312 struct refclockproc *pp;
1313 struct peer *peer;
1314
1315 char * c, * d;
1316
1317 peer = rbufp->recv_peer;
1318 pp = peer->procptr;
1319 up = pp->unitptr;
1320
1321 if(up->type == CLK_PRAECIS) {
1322 if(praecis_msg) {
1323 praecis_parse(rbufp,peer);
1324 return;
1325 }
1326 }
1327
1328 c = (char *) &rbufp->recv_space;
1329 d = c + rbufp->recv_length;
1330
1331 while (c != d) {
1332
1333 /* Build time packet */
1334 switch (up->rpt_status) {
1335
1336 case TSIP_PARSED_DLE_1:
1337 switch (*c)
1338 {
1339 case 0:
1340 case DLE:
1341 case ETX:
1342 up->rpt_status = TSIP_PARSED_EMPTY;
1343 break;
1344
1345 default:
1346 up->rpt_status = TSIP_PARSED_DATA;
1347 /* save packet ID */
1348 up->rpt_buf[0] = *c;
1349 break;
1350 }
1351 break;
1352
1353 case TSIP_PARSED_DATA:
1354 if (*c == DLE)
1355 up->rpt_status = TSIP_PARSED_DLE_2;
1356 else
1357 mb(up->rpt_cnt++) = *c;
1358 break;
1359
1360 case TSIP_PARSED_DLE_2:
1361 if (*c == DLE) {
1362 up->rpt_status = TSIP_PARSED_DATA;
1363 mb(up->rpt_cnt++) =
1364 *c;
1365 }
1366 else if (*c == ETX)
1367 up->rpt_status = TSIP_PARSED_FULL;
1368 else {
1369 /* error: start new report packet */
1370 up->rpt_status = TSIP_PARSED_DLE_1;
1371 up->rpt_buf[0] = *c;
1372 }
1373 break;
1374
1375 case TSIP_PARSED_FULL:
1376 case TSIP_PARSED_EMPTY:
1377 default:
1378 if ( *c != DLE)
1379 up->rpt_status = TSIP_PARSED_EMPTY;
1380 else
1381 up->rpt_status = TSIP_PARSED_DLE_1;
1382 break;
1383 }
1384
1385 c++;
1386
1387 if (up->rpt_status == TSIP_PARSED_DLE_1) {
1388 up->rpt_cnt = 0;
1389 if (pp->sloppyclockflag & CLK_FLAG2)
1390 /* stamp it */
1391 get_systime(&pp->lastrec);
1392 }
1393 else if (up->rpt_status == TSIP_PARSED_EMPTY)
1394 up->rpt_cnt = 0;
1395
1396 else if (up->rpt_cnt > BMAX)
1397 up->rpt_status =TSIP_PARSED_EMPTY;
1398
1399 if (up->rpt_status == TSIP_PARSED_FULL)
1400 palisade_receive(peer);
1401
1402 } /* while chars in buffer */
1403 }
1404
1405
1406 /*
1407 * Trigger the Palisade's event input, which is driven off the RTS
1408 *
1409 * Take a system time stamp to match the GPS time stamp.
1410 *
1411 */
1412 long
HW_poll(struct refclockproc * pp)1413 HW_poll (
1414 struct refclockproc * pp /* pointer to unit structure */
1415 )
1416 {
1417 int x; /* state before & after RTS set */
1418 struct palisade_unit *up;
1419 struct packettx tx;
1420
1421 up = pp->unitptr;
1422
1423 if (up->type == CLK_ACE) {
1424 /* Poll by sending a 0x21 command */
1425 tx.size = 0;
1426 tx.data = (u_char *) emalloc(100);
1427 sendcmd (&tx, 0x21);
1428 sendetx (&tx, pp->io.fd);
1429 free(tx.data);
1430 } else {
1431
1432 /* read the current status, so we put things back right */
1433 if (ioctl(pp->io.fd, TIOCMGET, &x) < 0) {
1434 DPRINTF(1, ("Palisade HW_poll: unit %d: GET %m\n",
1435 up->unit));
1436 msyslog(LOG_ERR, "Palisade(%d) HW_poll: ioctl(fd,GET): %m",
1437 up->unit);
1438 return -1;
1439 }
1440
1441 x |= TIOCM_RTS; /* turn on RTS */
1442
1443 /* Edge trigger */
1444 if (up->type == CLK_ACUTIME)
1445 if (write (pp->io.fd, "", 1) != 1)
1446 msyslog(LOG_WARNING,
1447 "Palisade(%d) HW_poll: failed to send trigger: %m",
1448 up->unit);
1449
1450 if (ioctl(pp->io.fd, TIOCMSET, &x) < 0) {
1451 #ifdef DEBUG
1452 if (debug)
1453 printf("Palisade HW_poll: unit %d: SET \n", up->unit);
1454 #endif
1455 msyslog(LOG_ERR,
1456 "Palisade(%d) HW_poll: ioctl(fd, SET, RTS_on): %m",
1457 up->unit);
1458 return -1;
1459 }
1460
1461 x &= ~TIOCM_RTS; /* turn off RTS */
1462
1463 } /* (up->type != CLK_ACE) */
1464
1465 /* poll timestamp */
1466 get_systime(&pp->lastrec);
1467
1468 if (up->type != CLK_ACE) {
1469 if (ioctl(pp->io.fd, TIOCMSET, &x) == -1) {
1470 #ifdef DEBUG
1471 if (debug)
1472 printf("Palisade HW_poll: unit %d: UNSET \n", up->unit);
1473 #endif
1474 msyslog(LOG_ERR,
1475 "Palisade(%d) HW_poll: ioctl(fd, UNSET, RTS_off): %m",
1476 up->unit);
1477 return -1;
1478 }
1479 }
1480
1481 return 0;
1482 }
1483
1484 /*
1485 * copy/swap a big-endian palisade double into a host double
1486 */
1487 static double
getdbl(u_char * bp)1488 getdbl (
1489 u_char *bp
1490 )
1491 {
1492 #ifdef WORDS_BIGENDIAN
1493 double out;
1494
1495 memcpy(&out, bp, sizeof(out));
1496 return out;
1497 #else
1498 union {
1499 u_char ch[8];
1500 u_int32 u32[2];
1501 } ui;
1502
1503 union {
1504 double out;
1505 u_int32 u32[2];
1506 } uo;
1507
1508 memcpy(ui.ch, bp, sizeof(ui.ch));
1509 /* least-significant 32 bits of double from swapped bp[4] to bp[7] */
1510 uo.u32[0] = ntohl(ui.u32[1]);
1511 /* most-significant 32 bits from swapped bp[0] to bp[3] */
1512 uo.u32[1] = ntohl(ui.u32[0]);
1513
1514 return uo.out;
1515 #endif
1516 }
1517
1518 /*
1519 * copy/swap a big-endian palisade short into a host short
1520 */
1521 static short
getint(u_char * bp)1522 getint (
1523 u_char *bp
1524 )
1525 {
1526 u_short us;
1527
1528 memcpy(&us, bp, sizeof(us));
1529 return (short)ntohs(us);
1530 }
1531
1532 /*
1533 * copy/swap a big-endian palisade 32-bit int into a host 32-bit int
1534 */
1535 static int32
getlong(u_char * bp)1536 getlong(
1537 u_char *bp
1538 )
1539 {
1540 u_int32 u32;
1541
1542 memcpy(&u32, bp, sizeof(u32));
1543 return (int32)(u_int32)ntohl(u32);
1544 }
1545
1546 /*
1547 * copy/swap a big-endian 32-bit single-precision floating point into a host 32-bit int
1548 */
1549 static int32
getsingle(u_char * bp)1550 getsingle(
1551 u_char *bp
1552 )
1553 {
1554 u_int32 mantissa;
1555 int8_t exponent;
1556 uint8_t sign, exp_field;
1557 int32 res;
1558
1559 memcpy(&mantissa, bp, sizeof(mantissa));
1560 mantissa = ((u_int32)ntohl(mantissa) & 0x7FFFFF) | 0x800000;
1561 exp_field = ((uint8_t)bp[0] << 1) + ((uint8_t)bp[1] >> 7);
1562 exponent = (int8_t)exp_field - 127;
1563 sign = ((uint8_t)bp[0] >> 7);
1564 if (exponent > 23)
1565 res = (int32)(mantissa << (exponent - 23));
1566 else
1567 res = (int32)(mantissa >> (23 - exponent));
1568 return sign ? -res : res;
1569 }
1570
1571 #else /* REFCLOCK && CLOCK_PALISADE*/
1572 NONEMPTY_TRANSLATION_UNIT
1573 #endif
1574