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