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