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