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