PageRenderTime 59ms CodeModel.GetById 14ms app.highlight 39ms RepoModel.GetById 1ms app.codeStats 0ms

/contrib/ntp/ntpd/refclock_hopfser.c

https://bitbucket.org/freebsd/freebsd-head/
C | 381 lines | 249 code | 61 blank | 71 comment | 26 complexity | c0db03e08e20fe744d99bb6a519b7158 MD5 | raw file
  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
 50extern 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 */
 86struct 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
 98static	int	hopfserial_start	P((int, struct peer *));
 99static	void	hopfserial_shutdown	P((int, struct peer *));
100static	void	hopfserial_receive	P((struct recvbuf *));
101static	void	hopfserial_poll		P((int, struct peer *));
102/* static  void hopfserial_io		P((struct recvbuf *)); */
103/*
104 * Transfer vector
105 */
106struct 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 */
119static int
120hopfserial_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#ifdef SYS_WINNT
131	(void) sprintf(gpsdev, "COM%d:", unit);
132#else
133	(void) sprintf(gpsdev, DEVICE, unit);
134#endif
135	/* LDISC_STD, LDISC_RAW
136	 * Open serial port. Use CLK line discipline, if available.
137	 */
138	fd = refclock_open(gpsdev, SPEED232, LDISC_CLK);
139	if (fd <= 0) {
140#ifdef DEBUG
141		printf("hopfSerialClock(%d) start: open %s failed\n", unit, gpsdev);
142#endif
143		return 0;
144	}
145
146	msyslog(LOG_NOTICE, "hopfSerialClock(%d) fd: %d dev: %s", unit, fd,
147		gpsdev);
148
149	/*
150	 * Allocate and initialize unit structure
151	 */
152	up = (struct hopfclock_unit *) emalloc(sizeof(struct hopfclock_unit));
153
154	if (!(up)) {
155                msyslog(LOG_ERR, "hopfSerialClock(%d) emalloc: %m",unit);
156#ifdef DEBUG
157                printf("hopfSerialClock(%d) emalloc\n",unit);
158#endif
159		(void) close(fd);
160		return (0);
161	}
162
163	memset((char *)up, 0, sizeof(struct hopfclock_unit));
164	pp = peer->procptr;
165	pp->unitptr = (caddr_t)up;
166	pp->io.clock_recv = hopfserial_receive;
167	pp->io.srcclock = (caddr_t)peer;
168	pp->io.datalen = 0;
169	pp->io.fd = fd;
170	if (!io_addclock(&pp->io)) {
171#ifdef DEBUG
172                printf("hopfSerialClock(%d) io_addclock\n",unit);
173#endif
174		(void) close(fd);
175		free(up);
176		return (0);
177	}
178
179	/*
180	 * Initialize miscellaneous variables
181	 */
182	pp->clockdesc = DESCRIPTION;
183	peer->precision = PRECISION;
184	peer->burst = NSTAGE;
185	memcpy((char *)&pp->refid, REFID, 4);
186
187	up->leap_status = 0;
188	up->unit = (short) unit;
189
190	return (1);
191}
192
193
194/*
195 * hopfserial_shutdown - shut down the clock
196 */
197static void
198hopfserial_shutdown (
199	int unit,
200	struct peer *peer
201	)
202{
203	register struct hopfclock_unit *up;
204	struct refclockproc *pp;
205
206	pp = peer->procptr;
207	up = (struct hopfclock_unit *)pp->unitptr;
208	io_closeclock(&pp->io);
209	free(up);
210}
211
212
213
214/*
215 * hopfserial_receive - receive data from the serial interface
216 */
217
218static void
219hopfserial_receive (
220	struct recvbuf *rbufp
221	)
222{
223	struct hopfclock_unit *up;
224	struct refclockproc *pp;
225	struct peer *peer;
226
227	int		synch;	/* synchhronization indicator */
228	int		DoW;	/* Dow */
229
230	int	day, month;	/* ddd conversion */
231
232	/*
233	 * Initialize pointers and read the timecode and timestamp.
234	 */
235	peer = (struct peer *)rbufp->recv_srcclock;
236	pp = peer->procptr;
237	up = (struct hopfclock_unit *)pp->unitptr;
238
239	if (up->rpt_next == 0 )
240		return;
241
242
243	up->rpt_next = 0; /* wait until next poll interval occur */
244
245	pp->lencode = (u_short)refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &pp->lastrec);
246
247	if (pp->lencode  == 0)
248		return;
249
250	sscanf(pp->a_lastcode,
251#if 1
252	       "%1x%1x%2d%2d%2d%2d%2d%2d",   /* ...cr,lf */
253#else
254	       "%*c%1x%1x%2d%2d%2d%2d%2d%2d", /* stx...cr,lf,etx */
255#endif
256	       &synch,
257	       &DoW,
258	       &pp->hour,
259	       &pp->minute,
260	       &pp->second,
261	       &day,
262	       &month,
263	       &pp->year);
264
265
266	/*
267	  Validate received values at least enough to prevent internal
268	  array-bounds problems, etc.
269	*/
270	if((pp->hour < 0) || (pp->hour > 23) ||
271	   (pp->minute < 0) || (pp->minute > 59) ||
272	   (pp->second < 0) || (pp->second > 60) /*Allow for leap seconds.*/ ||
273	   (day < 1) || (day > 31) ||
274	   (month < 1) || (month > 12) ||
275	   (pp->year < 0) || (pp->year > 99)) {
276		/* Data out of range. */
277		refclock_report(peer, CEVNT_BADREPLY);
278		return;
279	}
280	/*
281	  some preparations
282	*/
283	pp->day    = ymd2yd(pp->year,month,day);
284	pp->leap=0;
285
286	/* Year-2000 check! */
287	/* wrap 2-digit date into 4-digit */
288
289	if(pp->year < YEAR_PIVOT) { pp->year += 100; }		/* < 98 */
290	pp->year += 1900;
291
292	/* preparation for timecode ntpq rl command ! */
293
294#if 0
295	wsprintf(pp->a_lastcode,
296		 "STATUS: %1X%1X, DATE: %02d.%02d.%04d  TIME: %02d:%02d:%02d",
297		 synch,
298		 DoW,
299		 day,
300		 month,
301		 pp->year,
302		 pp->hour,
303		 pp->minute,
304		 pp->second);
305
306	pp->lencode = strlen(pp->a_lastcode);
307	if ((synch && 0xc) == 0 ){  /* time ok? */
308		refclock_report(peer, CEVNT_BADTIME);
309		pp->leap = LEAP_NOTINSYNC;
310		return;
311	}
312#endif
313	/*
314	 * If clock has no valid status then report error and exit
315	 */
316	if ((synch & HOPF_OPMODE) == HOPF_INVALID ){  /* time ok? */
317		refclock_report(peer, CEVNT_BADTIME);
318		pp->leap = LEAP_NOTINSYNC;
319		return;
320	}
321
322	/*
323	 * Test if time is running on internal quarz
324	 * if CLK_FLAG1 is set, sychronize even if no radio operation
325	 */
326
327	if ((synch & HOPF_OPMODE) == HOPF_INTERNAL){
328		if ((pp->sloppyclockflag & CLK_FLAG1) == 0) {
329			refclock_report(peer, CEVNT_BADTIME);
330			pp->leap = LEAP_NOTINSYNC;
331			return;
332		}
333	}
334
335
336	if (!refclock_process(pp)) {
337		refclock_report(peer, CEVNT_BADTIME);
338		return;
339	}
340	pp->lastref = pp->lastrec;
341	refclock_receive(peer);
342
343#if 0
344	msyslog(LOG_ERR, " D:%x  D:%d D:%d",synch,pp->minute,pp->second);
345#endif
346
347	record_clock_stats(&peer->srcadr, pp->a_lastcode);
348
349	return;
350}
351
352
353/*
354 * hopfserial_poll - called by the transmit procedure
355 *
356 */
357static void
358hopfserial_poll (
359	int unit,
360	struct peer *peer
361	)
362{
363	register struct hopfclock_unit *up;
364	struct refclockproc *pp;
365	pp = peer->procptr;
366
367	up = (struct hopfclock_unit *)pp->unitptr;
368
369	pp->polls++;
370	up->rpt_next = 1;
371
372#if 0
373	record_clock_stats(&peer->srcadr, pp->a_lastcode);
374#endif
375
376	return;
377}
378
379#else
380int refclock_hopfser_bs;
381#endif /* REFCLOCK */