]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ntp/ntpd/refclock_hopfser.c
This commit was generated by cvs2svn to compensate for changes in r172665,
[FreeBSD/FreeBSD.git] / contrib / ntp / ntpd / refclock_hopfser.c
1 /*
2  *
3  * refclock_hopfser.c
4  * - clock driver for hopf serial boards (GPS or DCF77)
5  *
6  * Date: 30.03.2000 Revision: 01.10
7  *
8  * latest source and further information can be found at:
9  * http://www.ATLSoft.de/ntp
10  *
11  */
12
13 #ifdef HAVE_CONFIG_H
14 # include "config.h"
15 #endif
16
17 #if defined(SYS_WINNT)
18 #undef close
19 #define close closesocket
20 #endif
21
22 #if defined(REFCLOCK) && (defined(CLOCK_HOPF_SERIAL))
23
24 #include "ntpd.h"
25 #include "ntp_io.h"
26 #include "ntp_control.h"
27 #include "ntp_refclock.h"
28 #include "ntp_unixtime.h"
29 #include "ntp_stdlib.h"
30
31 #if defined HAVE_SYS_MODEM_H
32 # include <sys/modem.h>
33 # define TIOCMSET MCSETA
34 # define TIOCMGET MCGETA
35 # define TIOCM_RTS MRTS
36 #endif
37
38 #ifdef HAVE_TERMIOS_H
39 # ifdef TERMIOS_NEEDS__SVID3
40 #  define _SVID3
41 # endif
42 # include <termios.h>
43 # ifdef TERMIOS_NEEDS__SVID3
44 #  undef _SVID3
45 # endif
46 #endif
47
48 #ifdef HAVE_SYS_IOCTL_H
49 # include <sys/ioctl.h>
50 #endif
51
52 /*
53  * clock definitions
54  */
55 #define DESCRIPTION     "hopf Elektronik serial clock" /* Long name */
56 #define PRECISION       (-10)   /* precision assumed (about 1 ms) */
57 #define REFID           "hopf\0"        /* reference ID */
58 /*
59  * I/O definitions
60  */
61 #define DEVICE          "/dev/hopfclock%d"      /* device name and unit */
62 #define SPEED232        B9600                   /* uart speed (9600 baud) */
63
64
65 #define STX 0x02
66 #define ETX 0x03
67 #define CR  0x0c
68 #define LF  0x0a
69
70 /* parse states */
71 #define REC_QUEUE_EMPTY       0
72 #define REC_QUEUE_FULL        1
73
74 #define HOPF_OPMODE     0x0C    /* operation mode mask */
75 #define HOPF_INVALID    0x00    /* no time code available */
76 #define HOPF_INTERNAL   0x04    /* internal clock */
77 #define HOPF_RADIO      0x08    /* radio clock */
78 #define HOPF_RADIOHP    0x0C    /* high precision radio clock */
79
80 /*
81  * hopfclock unit control structure.
82  */
83 struct hopfclock_unit {
84         l_fp    laststamp;      /* last receive timestamp */
85         short   unit;           /* NTP refclock unit number */
86         u_long  polled;         /* flag to detect noreplies */
87         char    leap_status;    /* leap second flag */
88         int     rpt_next;
89 };
90
91 /*
92  * Function prototypes
93  */
94
95 static  int     hopfserial_start        P((int, struct peer *));
96 static  void    hopfserial_shutdown     P((int, struct peer *));
97 static  void    hopfserial_receive      P((struct recvbuf *));
98 static  void    hopfserial_poll         P((int, struct peer *));
99 /* static  void hopfserial_io           P((struct recvbuf *)); */
100 /*
101  * Transfer vector
102  */
103 struct refclock refclock_hopfser = {
104         hopfserial_start,       /* start up driver */
105         hopfserial_shutdown,    /* shut down driver */
106         hopfserial_poll,        /* transmit poll message */
107         noentry,                /* not used  */
108         noentry,                /* initialize driver (not used) */
109         noentry,                /* not used */
110         NOFLAGS                 /* not used */
111 };
112
113 /*
114  * hopfserial_start - open the devices and initialize data for processing
115  */
116 static int
117 hopfserial_start (
118         int unit,
119         struct peer *peer
120         )
121 {
122         register struct hopfclock_unit *up;
123         struct refclockproc *pp;
124         int fd;
125         char gpsdev[20];
126
127 #ifdef SYS_WINNT
128         (void) sprintf(gpsdev, "COM%d:", unit);
129 #else
130         (void) sprintf(gpsdev, DEVICE, unit);
131 #endif
132         /* LDISC_STD, LDISC_RAW
133          * Open serial port. Use CLK line discipline, if available.
134          */
135         fd = refclock_open(gpsdev, SPEED232, LDISC_CLK);
136         if (fd <= 0) {
137 #ifdef DEBUG
138                 printf("hopfSerialClock(%d) start: open %s failed\n", unit, gpsdev);
139 #endif
140                 return 0;
141         }
142
143         msyslog(LOG_NOTICE, "hopfSerialClock(%d) fd: %d dev: %s", unit, fd,
144                 gpsdev);
145
146         /*
147          * Allocate and initialize unit structure
148          */
149         up = (struct hopfclock_unit *) emalloc(sizeof(struct hopfclock_unit));
150
151         if (!(up)) {
152                 msyslog(LOG_ERR, "hopfSerialClock(%d) emalloc: %m",unit);
153 #ifdef DEBUG
154                 printf("hopfSerialClock(%d) emalloc\n",unit);
155 #endif
156                 (void) close(fd);
157                 return (0);
158         }
159
160         memset((char *)up, 0, sizeof(struct hopfclock_unit));
161         pp = peer->procptr;
162         pp->unitptr = (caddr_t)up;
163         pp->io.clock_recv = hopfserial_receive;
164         pp->io.srcclock = (caddr_t)peer;
165         pp->io.datalen = 0;
166         pp->io.fd = fd;
167         if (!io_addclock(&pp->io)) {
168 #ifdef DEBUG
169                 printf("hopfSerialClock(%d) io_addclock\n",unit);
170 #endif
171                 (void) close(fd);
172                 free(up);
173                 return (0);
174         }
175
176         /*
177          * Initialize miscellaneous variables
178          */
179         pp->clockdesc = DESCRIPTION;
180         peer->precision = PRECISION;
181         peer->burst = NSTAGE;
182         memcpy((char *)&pp->refid, REFID, 4);
183
184         up->leap_status = 0;
185         up->unit = (short) unit;
186
187         return (1);
188 }
189
190
191 /*
192  * hopfserial_shutdown - shut down the clock
193  */
194 static void
195 hopfserial_shutdown (
196         int unit,
197         struct peer *peer
198         )
199 {
200         register struct hopfclock_unit *up;
201         struct refclockproc *pp;
202
203         pp = peer->procptr;
204         up = (struct hopfclock_unit *)pp->unitptr;
205         io_closeclock(&pp->io);
206         free(up);
207 }
208
209
210
211 /*
212  * hopfserial_receive - receive data from the serial interface
213  */
214
215 static void
216 hopfserial_receive (
217         struct recvbuf *rbufp
218         )
219 {
220         struct hopfclock_unit *up;
221         struct refclockproc *pp;
222         struct peer *peer;
223
224         int             synch;  /* synchhronization indicator */
225         int             DoW;    /* Dow */
226
227         int     day, month;     /* ddd conversion */
228
229         /*
230          * Initialize pointers and read the timecode and timestamp.
231          */
232         peer = (struct peer *)rbufp->recv_srcclock;
233         pp = peer->procptr;
234         up = (struct hopfclock_unit *)pp->unitptr;
235
236         if (up->rpt_next == 0 )
237                 return;
238
239
240         up->rpt_next = 0; /* wait until next poll interval occur */
241
242         pp->lencode = (u_short)refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &pp->lastrec);
243
244         if (pp->lencode  == 0)
245                 return;
246
247         sscanf(pp->a_lastcode,
248 #if 1
249                "%1x%1x%2d%2d%2d%2d%2d%2d",   /* ...cr,lf */
250 #else
251                "%*c%1x%1x%2d%2d%2d%2d%2d%2d", /* stx...cr,lf,etx */
252 #endif
253                &synch,
254                &DoW,
255                &pp->hour,
256                &pp->minute,
257                &pp->second,
258                &day,
259                &month,
260                &pp->year);
261
262
263         /*
264           Validate received values at least enough to prevent internal
265           array-bounds problems, etc.
266         */
267         if((pp->hour < 0) || (pp->hour > 23) ||
268            (pp->minute < 0) || (pp->minute > 59) ||
269            (pp->second < 0) || (pp->second > 60) /*Allow for leap seconds.*/ ||
270            (day < 1) || (day > 31) ||
271            (month < 1) || (month > 12) ||
272            (pp->year < 0) || (pp->year > 99)) {
273                 /* Data out of range. */
274                 refclock_report(peer, CEVNT_BADREPLY);
275                 return;
276         }
277         /*
278           some preparations
279         */
280         pp->day    = ymd2yd(pp->year,month,day);
281         pp->leap=0;
282
283         /* Year-2000 check! */
284         /* wrap 2-digit date into 4-digit */
285
286         if(pp->year < YEAR_PIVOT) { pp->year += 100; }          /* < 98 */
287         pp->year += 1900;
288
289         /* preparation for timecode ntpq rl command ! */
290
291 #if 0
292         wsprintf(pp->a_lastcode,
293                  "STATUS: %1X%1X, DATE: %02d.%02d.%04d  TIME: %02d:%02d:%02d",
294                  synch,
295                  DoW,
296                  day,
297                  month,
298                  pp->year,
299                  pp->hour,
300                  pp->minute,
301                  pp->second);
302
303         pp->lencode = strlen(pp->a_lastcode);
304         if ((synch && 0xc) == 0 ){  /* time ok? */
305                 refclock_report(peer, CEVNT_BADTIME);
306                 pp->leap = LEAP_NOTINSYNC;
307                 return;
308         }
309 #endif
310         /*
311          * If clock has no valid status then report error and exit
312          */
313         if ((synch & HOPF_OPMODE) == HOPF_INVALID ){  /* time ok? */
314                 refclock_report(peer, CEVNT_BADTIME);
315                 pp->leap = LEAP_NOTINSYNC;
316                 return;
317         }
318
319         /*
320          * Test if time is running on internal quarz
321          * if CLK_FLAG1 is set, sychronize even if no radio operation
322          */
323
324         if ((synch & HOPF_OPMODE) == HOPF_INTERNAL){
325                 if ((pp->sloppyclockflag & CLK_FLAG1) == 0) {
326                         refclock_report(peer, CEVNT_BADTIME);
327                         pp->leap = LEAP_NOTINSYNC;
328                         return;
329                 }
330         }
331
332
333         if (!refclock_process(pp)) {
334                 refclock_report(peer, CEVNT_BADTIME);
335                 return;
336         }
337         pp->lastref = pp->lastrec;
338         refclock_receive(peer);
339
340 #if 0
341         msyslog(LOG_ERR, " D:%x  D:%d D:%d",synch,pp->minute,pp->second);
342 #endif
343
344         record_clock_stats(&peer->srcadr, pp->a_lastcode);
345
346         return;
347 }
348
349
350 /*
351  * hopfserial_poll - called by the transmit procedure
352  *
353  */
354 static void
355 hopfserial_poll (
356         int unit,
357         struct peer *peer
358         )
359 {
360         register struct hopfclock_unit *up;
361         struct refclockproc *pp;
362         pp = peer->procptr;
363
364         up = (struct hopfclock_unit *)pp->unitptr;
365
366         pp->polls++;
367         up->rpt_next = 1;
368
369 #if 0
370         record_clock_stats(&peer->srcadr, pp->a_lastcode);
371 #endif
372
373         return;
374 }
375
376 #else
377 int refclock_hopfser_bs;
378 #endif /* REFCLOCK */