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