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