xref: /freebsd/contrib/ntp/ntpd/refclock_palisade.c (revision 5129159789cc9d7bc514e4546b88e3427695002d)
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 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 #ifdef HAVE_CONFIG_H
56 #include "config.h"
57 #endif
58 
59 #if defined(REFCLOCK) && (defined(PALISADE) || defined(CLOCK_PALISADE))
60 
61 #include "refclock_palisade.h"
62 /* Table to get from month to day of the year */
63 const int days_of_year [12] = {
64 	0,  31,  59,  90, 120, 151, 181, 212, 243, 273, 304, 334
65 };
66 
67 #ifdef DEBUG
68 const char * Tracking_Status[15][15] = {
69         	{ "Doing Fixes\0" }, { "Good 1SV\0" }, { "Approx. 1SV\0" },
70         	{"Need Time\0" }, { "Need INIT\0" }, { "PDOP too High\0" },
71         	{ "Bad 1SV\0" }, { "0SV Usable\0" }, { "1SV Usable\0" },
72         	{ "2SV Usable\0" }, { "3SV Usable\0" }, { "No Integrity\0" },
73         	{ "Diff Corr\0" }, { "Overdet Clock\0" }, { "Invalid\0" } };
74 #endif
75 
76 /*
77  * Transfer vector
78  */
79 struct refclock refclock_palisade = {
80 	palisade_start,		/* start up driver */
81 	palisade_shutdown,	/* shut down driver */
82 	palisade_poll,		/* transmit poll message */
83 	noentry,		/* not used  */
84 	noentry,		/* initialize driver (not used) */
85 	noentry,		/* not used */
86 	NOFLAGS			/* not used */
87 };
88 
89 
90 /*
91  * palisade_start - open the devices and initialize data for processing
92  */
93 static int
94 palisade_start (
95 #ifdef PALISADE
96 	unit, peer
97 	)
98 	int unit;
99 	struct peer *peer;
100 #else /* ANSI */
101 	int unit,
102 	struct peer *peer
103 	)
104 #endif
105 {
106 	struct palisade_unit *up;
107 	struct refclockproc *pp;
108 	int fd;
109 	char gpsdev[20];
110 
111 	struct termios tio;
112 #ifdef SYS_WINNT
113 	(void) sprintf(gpsdev, "COM%d:", unit);
114 #else
115 	(void) sprintf(gpsdev, DEVICE, unit);
116 #endif
117 	/*
118 	 * Open serial port.
119 	 */
120 #if defined PALISADE
121 	 fd = open(gpsdev, O_RDWR
122 #ifdef O_NONBLOCK
123                   | O_NONBLOCK
124 #endif
125                   );
126 #else /* NTP 4.x */
127 	fd = refclock_open(gpsdev, SPEED232, LDISC_RAW);
128 #endif
129 	if (fd <= 0) {
130 #ifdef DEBUG
131 		printf("Palisade(%d) start: open %s failed\n", unit, gpsdev);
132 #endif
133 		return 0;
134 	}
135 
136 	msyslog(LOG_NOTICE, "Palisade(%d) fd: %d dev: %s", unit, fd,
137 		gpsdev);
138 
139 #if defined PALISADE
140         tio.c_cflag = (CS8|CLOCAL|CREAD|PARENB|PARODD);
141         tio.c_iflag = (IGNBRK);
142         tio.c_oflag = (0);
143         tio.c_lflag = (0);
144 
145         if (cfsetispeed(&tio, SPEED232) == -1) {
146                 msyslog(LOG_ERR,"Palisade(%d) cfsetispeed(fd, &tio): %m",unit);
147 #ifdef DEBUG
148                 printf("Palisade(%d) cfsetispeed(fd, &tio)\n",unit);
149 #endif
150                 return 0;
151         }
152         if (cfsetospeed(&tio, SPEED232) == -1) {
153 #ifdef DEBUG
154                 printf("Palisade(%d) cfsetospeed(fd, &tio)\n",unit);
155 #endif
156                 msyslog(LOG_ERR,"Palisade(%d) cfsetospeed(fd, &tio): %m",unit);
157                 return 0;
158         }
159 #else /* NTP 4.x */
160         if (tcgetattr(fd, &tio) < 0) {
161                 msyslog(LOG_ERR,
162 			"Palisade(%d) tcgetattr(fd, &tio): %m",unit);
163 #ifdef DEBUG
164                 printf("Palisade(%d) tcgetattr(fd, &tio)\n",unit);
165 #endif
166                 return (0);
167         }
168 
169         tio.c_cflag |= (PARENB|PARODD);
170         tio.c_iflag &= ~ICRNL;
171 #endif /*  NTP 4.x */
172 
173 	if (tcsetattr(fd, TCSANOW, &tio) == -1) {
174                 msyslog(LOG_ERR, "Palisade(%d) tcsetattr(fd, &tio): %m",unit);
175 #ifdef DEBUG
176                 printf("Palisade(%d) tcsetattr(fd, &tio)\n",unit);
177 #endif
178                 return 0;
179         }
180 
181 	/*
182 	 * Allocate and initialize unit structure
183 	 */
184 	up = (struct palisade_unit *) emalloc(sizeof(struct palisade_unit));
185 
186 	if (!(up)) {
187                 msyslog(LOG_ERR, "Palisade(%d) emalloc: %m",unit);
188 #ifdef DEBUG
189                 printf("Palisade(%d) emalloc\n",unit);
190 #endif
191 		(void) close(fd);
192 		return (0);
193 	}
194 
195 	memset((char *)up, 0, sizeof(struct palisade_unit));
196 
197 	pp = peer->procptr;
198 	pp->io.clock_recv = palisade_io;
199 	pp->io.srcclock = (caddr_t)peer;
200 	pp->io.datalen = 0;
201 	pp->io.fd = fd;
202 	if (!io_addclock(&pp->io)) {
203 #ifdef DEBUG
204                 printf("Palisade(%d) io_addclock\n",unit);
205 #endif
206 		(void) close(fd);
207 		free(up);
208 		return (0);
209 	}
210 
211 	/*
212 	 * Initialize miscellaneous variables
213 	 */
214 	pp->unitptr = (caddr_t)up;
215 	pp->clockdesc = DESCRIPTION;
216 
217 	peer->precision = PRECISION;
218 	peer->sstclktype = CTL_SST_TS_UHF;
219 	peer->minpoll = TRMB_MINPOLL;
220 	peer->maxpoll = TRMB_MAXPOLL;
221 	memcpy((char *)&pp->refid, REFID, 4);
222 
223 	up->leap_status = 0;
224 	up->unit = (short) unit;
225 	up->rpt_status = TSIP_PARSED_EMPTY;
226     	up->rpt_cnt = 0;
227 
228 	return 1;
229 }
230 
231 
232 /*
233  * palisade_shutdown - shut down the clock
234  */
235 static void
236 palisade_shutdown (
237 #ifdef PALISADE
238 	unit, peer
239 	)
240 	int unit;
241 	struct peer *peer;
242 #else /* ANSI */
243 	int unit,
244 	struct peer *peer
245 	)
246 #endif
247 {
248 	struct palisade_unit *up;
249 	struct refclockproc *pp;
250 	pp = peer->procptr;
251 	up = (struct palisade_unit *)pp->unitptr;
252 	io_closeclock(&pp->io);
253 	free(up);
254 }
255 
256 
257 
258 /*
259  * unpack_date - get day and year from date
260  */
261 int
262 day_of_year (
263 #ifdef PALISADE
264 	dt
265 	)
266 	char * dt;
267 #else
268 	char * dt
269 	)
270 #endif
271 {
272 	int day, mon, year;
273 
274 	mon = dt[1];
275        /* Check month is inside array bounds */
276        if ((mon < 1) || (mon > 12))
277 		return -1;
278 
279 	day = dt[0] + days_of_year[mon - 1];
280 	year = getint((u_char *) (dt + 2));
281 
282 	if ( !(year % 4) && ((year % 100) ||
283 		(!(year % 100) && !(year%400)))
284 			&&(mon > 2))
285 			day ++; /* leap year and March or later */
286 
287 	return day;
288 }
289 
290 
291 /*
292  * TSIP_decode - decode the TSIP data packets
293  */
294 int
295 TSIP_decode (
296 #ifdef PALISADE
297 	peer
298 	)
299 	struct peer *peer;
300 #else
301 	struct peer *peer
302 	)
303 #endif
304 {
305 	int st;
306 	long   secint;
307 	double secs;
308 	double secfrac;
309 	unsigned short event = 0;
310 
311 	struct palisade_unit *up;
312 	struct refclockproc *pp;
313 
314 	pp = peer->procptr;
315 	up = (struct palisade_unit *)pp->unitptr;
316 
317 	/*
318 	 * Check the time packet, decode its contents.
319 	 * If the timecode has invalid length or is not in
320 	 * proper format, declare bad format and exit.
321 	 */
322 
323 	if ((up->rpt_buf[0] == (char) 0x41) ||
324 		(up->rpt_buf[0] == (char) 0x46) ||
325 		(up->rpt_buf[0] == (char) 0x54) ||
326 		(up->rpt_buf[0] == (char) 0x4B) ||
327 		(up->rpt_buf[0] == (char) 0x6D)) {
328 
329 	/* standard time packet - GPS time and GPS week number */
330 #ifdef DEBUG
331 			printf("Palisade Port B packets detected. Connect to Port A\n");
332 #endif
333 
334 		return 0;
335 	}
336 
337 	if (up->rpt_buf[0] == (char) 0x8f) {
338 	/*
339 	 * Superpackets
340 	 */
341 	   event = (unsigned short) (getint((u_char *) &mb(1)) & 0xffff);
342 	   if (!((pp->sloppyclockflag & CLK_FLAG2) || event))
343 		/* Ignore Packet */
344 			return 0;
345 
346 	   switch (mb(0) & 0xff) {
347 	     int GPS_UTC_Offset;
348 	     case PACKET_8F0B:
349 
350 		if (up->polled <= 0)
351 			return 0;
352 
353 		if (up->rpt_cnt != LENCODE_8F0B)  /* check length */
354 			break;
355 
356 #ifdef DEBUG
357 if (debug > 1) {
358 		int ts;
359 		double lat, lon, alt;
360 		lat = getdbl((u_char *) &mb(42)) * R2D;
361 		lon = getdbl((u_char *) &mb(50)) * R2D;
362 		alt = getdbl((u_char *) &mb(58));
363 
364   		printf("TSIP_decode: unit %d: Latitude: %03.4f Longitude: %03.4f Alt: %05.2f m\n",
365 				up->unit, lat,lon,alt);
366   		printf("TSIP_decode: unit %d: Sats:", up->unit);
367 		for (st = 66, ts = 0; st <= 73; st++) if (mb(st)) {
368 			if (mb(st) > 0) ts++;
369 			printf(" %02d", mb(st));
370 		}
371 		printf(" : Tracking %d\n", ts);
372 	}
373 #endif
374 
375 		GPS_UTC_Offset = getint((u_char *) &mb(16));
376 		if (GPS_UTC_Offset == 0) { /* Check UTC offset */
377 #ifdef DEBUG
378 			 printf("TSIP_decode: UTC Offset Unknown\n");
379 #endif
380 			break;
381 		}
382 
383 		secs = getdbl((u_char *) &mb(3));
384 		secint = (long) secs;
385 		secfrac = secs - secint; /* 0.0 <= secfrac < 1.0 */
386 
387 		pp->usec = (long) (secfrac * 1000000);
388 
389 		secint %= 86400;    /* Only care about today */
390 		pp->hour = secint / 3600;
391 		secint %= 3600;
392 		pp->minute = secint / 60;
393 		secint %= 60;
394 		pp->second = secint % 60;
395 
396 		if ((pp->day = day_of_year(&mb(11))) < 0) break;
397 
398 		pp->year = getint((u_char *) &mb(13));
399 
400 #ifdef DEBUG
401 	if (debug > 1)
402 		printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%06ld %02d/%02d/%04d UTC %02d\n",
403  			up->unit, mb(0) & 0xff, event, pp->hour, pp->minute,
404 			pp->second, pp->usec, mb(12), mb(11), pp->year, GPS_UTC_Offset);
405 #endif
406 		/* Only use this packet when no
407 		 * 8F-AD's are being received
408 		 */
409 
410 		if (up->leap_status) {
411 			up->leap_status = 0;
412 			return 0;
413 		}
414 
415 		return 2;
416 		break;
417 
418 	  case PACKET_NTP:
419 		/* Palisade-NTP Packet */
420 
421 		if (up->rpt_cnt != LENCODE_NTP) /* check length */
422 			break;
423 
424 		up->leap_status = mb(19);
425 
426 		if (up->polled  <= 0)
427 			return 0;
428 
429 		/* Check Tracking Status */
430 		st = mb(18);
431 		if (st < 0 || st > 14) st = 14;
432 		if ((st >= 2 && st <= 7) || st == 11 || st == 12) {
433 #ifdef DEBUG
434 		 printf("TSIP_decode: Not Tracking Sats : %s\n",
435 				*Tracking_Status[st]);
436 #endif
437 			refclock_report(peer, CEVNT_BADTIME);
438 			up->polled = -1;
439 			return 0;
440 			break;
441 		}
442 
443 		if (up->leap_status & PALISADE_LEAP_PENDING) {
444 			if (up->leap_status & PALISADE_UTC_TIME)
445 				pp->leap = LEAP_ADDSECOND;
446 			else
447 				pp->leap = LEAP_DELSECOND;
448 		}
449 		else if (up->leap_status)
450 			pp->leap = LEAP_NOWARNING;
451 
452 		else {  /* UTC flag is not set:
453 			 * Receiver may have been reset, and lost
454 			 * its UTC almanac data */
455 			pp->leap = LEAP_NOTINSYNC;
456 #ifdef DEBUG
457 			 printf("TSIP_decode: UTC Almanac unavailable: %d\n",
458 				mb(19));
459 #endif
460 			refclock_report(peer, CEVNT_BADTIME);
461 			up->polled = -1;
462 			return 0;
463 		}
464 
465 		pp->usec = (long) (getdbl((u_char *) &mb(3)) * 1000000);
466 
467 		if ((pp->day = day_of_year(&mb(14))) < 0)
468 			break;
469 		pp->year = getint((u_char *) &mb(16));
470 		pp->hour = mb(11);
471 		pp->minute = mb(12);
472 		pp->second = mb(13);
473 
474 #ifdef DEBUG
475 	if (debug > 1)
476 printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%06ld %02d/%02d/%04d UTC %02x %s\n",
477  			up->unit, mb(0) & 0xff, event, pp->hour, pp->minute,
478 			pp->second, pp->usec, mb(15), mb(14), pp->year,
479 			mb(19), *Tracking_Status[st]);
480 #endif
481 		return 1;
482 		break;
483 
484 	  default:
485 		/* Ignore Packet */
486 		return 0;
487 	  } /* switch */
488 	}/* if 8F packets */
489 
490 	refclock_report(peer, CEVNT_BADREPLY);
491 	up->polled = -1;
492 #ifdef DEBUG
493 	printf("TSIP_decode: unit %d: bad packet %02x-%02x event %d len %d\n",
494 		   up->unit, up->rpt_buf[0] & 0xff, mb(0) & 0xff,
495 			event, up->rpt_cnt);
496 #endif
497 	return 0;
498 }
499 
500 /*
501  * palisade__receive - receive data from the serial interface
502  */
503 
504 static void
505 palisade_receive (
506 #ifdef PALISADE
507 	peer
508 	)
509 	struct peer * peer;
510 #else /* ANSI */
511 	struct peer * peer
512 	)
513 #endif
514 {
515 	struct palisade_unit *up;
516 	struct refclockproc *pp;
517 
518 	/*
519 	 * Initialize pointers and read the timecode and timestamp.
520 	 */
521 	pp = peer->procptr;
522 	up = (struct palisade_unit *)pp->unitptr;
523 
524 	if (! TSIP_decode(peer)) return;
525 
526 	if (up->polled <= 0)
527 	    return;   /* no poll pending, already received or timeout */
528 
529 	up->polled = 0;  /* Poll reply received */
530 	pp->lencode = 0; /* clear time code */
531 #ifdef DEBUG
532 	if (debug)
533 		printf(
534 	"palisade_receive: unit %d: %4d %03d %02d:%02d:%02d.%06ld\n",
535 			up->unit, pp->year, pp->day, pp->hour, pp->minute,
536 			pp->second, pp->usec);
537 #endif
538 
539 	/*
540 	 * Process the sample
541 	 * Generate timecode: YYYY DoY HH:MM:SS.microsec
542 	 * report and process
543 	 */
544 
545 	(void) sprintf(pp->a_lastcode,"%4d %03d %02d:%02d:%02d.%06ld",
546 		   pp->year,pp->day,pp->hour,pp->minute, pp->second,pp->usec);
547 	pp->lencode = 24;
548 
549 #ifdef PALISADE
550     	pp->lasttime = current_time;
551 #endif
552 	if (!refclock_process(pp
553 #ifdef PALISADE
554 		, PALISADE_SAMPLES, PALISADE_SAMPLES * 3 / 5
555 #endif
556 		)) {
557 		refclock_report(peer, CEVNT_BADTIME);
558 
559 #ifdef DEBUG
560 		printf("palisade_receive: unit %d: refclock_process failed!\n",
561 			up->unit);
562 #endif
563 		return;
564 	}
565 
566 	record_clock_stats(&peer->srcadr, pp->a_lastcode);
567 
568 #ifdef DEBUG
569 	if (debug)
570 	    printf("palisade_receive: unit %d: %s\n",
571 		   up->unit, prettydate(&pp->lastrec));
572 #endif
573 
574 	refclock_receive(peer
575 #ifdef PALISADE
576 		, &pp->offset, 0, pp->dispersion,
577               &pp->lastrec, &pp->lastrec, pp->leap
578 #endif
579 		);
580 }
581 
582 
583 /*
584  * palisade_poll - called by the transmit procedure
585  *
586  */
587 static void
588 palisade_poll (
589 #ifdef PALISADE
590 	unit, peer
591 	)
592 	int unit;
593 	struct peer *peer;
594 #else
595 	int unit,
596 	struct peer *peer
597 	)
598 #endif
599 {
600 	struct palisade_unit *up;
601 	struct refclockproc *pp;
602 
603 	pp = peer->procptr;
604 	up = (struct palisade_unit *)pp->unitptr;
605 
606 	pp->polls++;
607 	if (up->polled > 0) /* last reply never arrived or error */
608 	    refclock_report(peer, CEVNT_TIMEOUT);
609 
610 	up->polled = 2; /* synchronous packet + 1 event */
611 
612 #ifdef DEBUG
613 	if (debug)
614 	    printf("palisade_poll: unit %d: polling %s\n", unit,
615 		   (pp->sloppyclockflag & CLK_FLAG2) ?
616 			"synchronous packet" : "event");
617 #endif
618 
619 	if (pp->sloppyclockflag & CLK_FLAG2)
620 	    return;  /* using synchronous packet input */
621 
622 	if (HW_poll(pp) < 0)
623 	    refclock_report(peer, CEVNT_FAULT);
624 }
625 
626 
627 static void
628 palisade_io (
629 #ifdef PALISADE
630 	rbufp
631 	)
632 	struct recvbuf *rbufp;
633 #else /* ANSI */
634 	struct recvbuf *rbufp
635 	)
636 #endif
637 {
638 	/*
639 	 * Initialize pointers and read the timecode and timestamp.
640 	 */
641 	struct palisade_unit *up;
642 	struct refclockproc *pp;
643 	struct peer *peer;
644 
645 	char * c, * d;
646 
647 	peer = (struct peer *)rbufp->recv_srcclock;
648 	pp = peer->procptr;
649 	up = (struct palisade_unit *)pp->unitptr;
650 
651 	c = (char *) &rbufp->recv_space;
652 	d = c + rbufp->recv_length;
653 
654 	while (c != d) {
655 
656 		/* Build time packet */
657 		switch (up->rpt_status) {
658 
659 		    case TSIP_PARSED_DLE_1:
660 			switch (*c)
661 			{
662 			    case 0:
663 			    case DLE:
664 			    case ETX:
665 				up->rpt_status = TSIP_PARSED_EMPTY;
666 				break;
667 
668 			    default:
669 				up->rpt_status = TSIP_PARSED_DATA;
670 				/* save packet ID */
671 				up->rpt_buf[0] = *c;
672 				break;
673 			}
674 			break;
675 
676 		    case TSIP_PARSED_DATA:
677 			if (*c == DLE)
678 			    up->rpt_status = TSIP_PARSED_DLE_2;
679 			else
680 			    mb(up->rpt_cnt++) = *c;
681 			break;
682 
683 		    case TSIP_PARSED_DLE_2:
684 			if (*c == DLE) {
685 				up->rpt_status = TSIP_PARSED_DATA;
686 				mb(up->rpt_cnt++) =
687 						*c;
688 			}
689 			else if (*c == ETX)
690 				    up->rpt_status = TSIP_PARSED_FULL;
691 			else 	{
692                         	/* error: start new report packet */
693 				up->rpt_status = TSIP_PARSED_DLE_1;
694 				up->rpt_buf[0] = *c;
695 			}
696 			break;
697 
698 		    case TSIP_PARSED_FULL:
699 		    case TSIP_PARSED_EMPTY:
700 		    default:
701 		        if ( *c != DLE)
702                           up->rpt_status = TSIP_PARSED_EMPTY;
703                 else
704                           up->rpt_status = TSIP_PARSED_DLE_1;
705                         break;
706 		}
707 
708 		c++;
709 
710 		if (up->rpt_status == TSIP_PARSED_DLE_1) {
711 		    up->rpt_cnt = 0;
712 			if (pp->sloppyclockflag & CLK_FLAG2)
713                 		/* stamp it */
714                        	get_systime(&pp->lastrec);
715 		}
716 		else if (up->rpt_status == TSIP_PARSED_EMPTY)
717 		    	up->rpt_cnt = 0;
718 
719 		else if (up->rpt_cnt > BMAX)
720 			up->rpt_status =TSIP_PARSED_EMPTY;
721 
722 		if (up->rpt_status == TSIP_PARSED_FULL)
723 			palisade_receive(peer);
724 
725 	} /* while chars in buffer */
726 }
727 
728 
729 /*
730  * Trigger the Palisade's event input, which is driven off the RTS
731  *
732  * Take a system time stamp to match the GPS time stamp.
733  *
734  */
735 long
736 HW_poll (
737 #ifdef PALISADE
738 	pp 	/* pointer to unit structure */
739 	)
740 	struct refclockproc * pp;	/* pointer to unit structure */
741 #else
742 	struct refclockproc * pp 	/* pointer to unit structure */
743 	)
744 #endif
745 {
746 	int x;	/* state before & after RTS set */
747 	struct palisade_unit *up;
748 
749 	up = (struct palisade_unit *) pp->unitptr;
750 
751 	/* read the current status, so we put things back right */
752 	if (ioctl(pp->io.fd, TIOCMGET, &x) < 0) {
753 #ifdef DEBUG
754 	if (debug)
755 	    printf("Palisade HW_poll: unit %d: GET %s\n", up->unit, strerror(errno));
756 #endif
757 		msyslog(LOG_ERR, "Palisade(%d) HW_poll: ioctl(fd,GET): %m",
758 			up->unit);
759 		return -1;
760 	}
761 
762 	x |= TIOCM_RTS;        /* turn on RTS  */
763 
764 	/* Edge trigger */
765 	if (ioctl(pp->io.fd, TIOCMSET, &x) < 0) {
766 #ifdef DEBUG
767 	if (debug)
768 	    printf("Palisade HW_poll: unit %d: SET \n", up->unit);
769 #endif
770 		msyslog(LOG_ERR,
771 			"Palisade(%d) HW_poll: ioctl(fd, SET, RTS_on): %m",
772 			up->unit);
773 		return -1;
774 	}
775 
776 	x &= ~TIOCM_RTS;        /* turn off RTS  */
777 
778 	/* poll timestamp */
779 	get_systime(&pp->lastrec);
780 
781 	if (ioctl(pp->io.fd, TIOCMSET, &x) == -1) {
782 #ifdef DEBUG
783 	if (debug)
784 	    printf("Palisade HW_poll: unit %d: UNSET \n", up->unit);
785 #endif
786 		msyslog(LOG_ERR,
787 			"Palisade(%d) HW_poll: ioctl(fd, UNSET, RTS_off): %m",
788 			up->unit);
789 		return -1;
790 	}
791 
792 	return 0;
793 }
794 
795 #if 0 /* unused */
796 /*
797  * this 'casts' a character array into a float
798  */
799 float
800 getfloat (
801 #ifdef PALISADE
802 	bp
803 	)
804 	u_char *bp;
805 #else
806 	u_char *bp
807 	)
808 #endif
809 {
810 	float sval;
811 #ifdef WORDS_BIGENDIAN
812 	((char *) &sval)[0] = *bp++;
813 	((char *) &sval)[1] = *bp++;
814 	((char *) &sval)[2] = *bp++;
815 	((char *) &sval)[3] = *bp++;
816 #else
817 	((char *) &sval)[3] = *bp++;
818 	((char *) &sval)[2] = *bp++;
819 	((char *) &sval)[1] = *bp++;
820 	((char *) &sval)[0] = *bp;
821 #endif  /* ! XNTP_BIG_ENDIAN */
822 	return sval;
823 }
824 #endif
825 
826 /*
827  * this 'casts' a character array into a double
828  */
829 double
830 getdbl (
831 #ifdef PALISADE
832 	bp
833 	)
834 	u_char *bp;
835 #else
836 	u_char *bp
837 	)
838 #endif
839 {
840 	double dval;
841 #ifdef WORDS_BIGENDIAN
842 	((char *) &dval)[0] = *bp++;
843 	((char *) &dval)[1] = *bp++;
844 	((char *) &dval)[2] = *bp++;
845 	((char *) &dval)[3] = *bp++;
846 	((char *) &dval)[4] = *bp++;
847 	((char *) &dval)[5] = *bp++;
848 	((char *) &dval)[6] = *bp++;
849 	((char *) &dval)[7] = *bp;
850 #else
851 	((char *) &dval)[7] = *bp++;
852 	((char *) &dval)[6] = *bp++;
853 	((char *) &dval)[5] = *bp++;
854 	((char *) &dval)[4] = *bp++;
855 	((char *) &dval)[3] = *bp++;
856 	((char *) &dval)[2] = *bp++;
857 	((char *) &dval)[1] = *bp++;
858 	((char *) &dval)[0] = *bp;
859 #endif  /* ! XNTP_BIG_ENDIAN */
860 	return dval;
861 }
862 
863 /*
864  * cast a 16 bit character array into a short (16 bit) int
865  */
866 short
867 getint (
868 #ifdef PALISADE
869 	bp
870 	)
871 	u_char *bp;
872 #else
873 	u_char *bp
874 	)
875 #endif
876 {
877 return (short) (bp[1] + (bp[0] << 8));
878 }
879 
880 #endif /* REFCLOCK */
881