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