xref: /freebsd/contrib/ntp/ntpd/refclock_dumbclock.c (revision c0b746e5e8d9479f05b3749cbf1f73b8928719bd)
1c0b746e5SOllivier Robert /*
2c0b746e5SOllivier Robert  * refclock_dumbclock - clock driver for a unknown time distribution system
3c0b746e5SOllivier Robert  * that only provides hh:mm:ss (in local time, yet!).
4c0b746e5SOllivier Robert  */
5c0b746e5SOllivier Robert 
6c0b746e5SOllivier Robert /*
7c0b746e5SOllivier Robert  * Must interpolate back to local time.  Very annoying.
8c0b746e5SOllivier Robert  */
9c0b746e5SOllivier Robert #define GET_LOCALTIME
10c0b746e5SOllivier Robert 
11c0b746e5SOllivier Robert #ifdef HAVE_CONFIG_H
12c0b746e5SOllivier Robert #include <config.h>
13c0b746e5SOllivier Robert #endif
14c0b746e5SOllivier Robert 
15c0b746e5SOllivier Robert #if defined(REFCLOCK) && defined(CLOCK_DUMBCLOCK)
16c0b746e5SOllivier Robert 
17c0b746e5SOllivier Robert #include <stdio.h>
18c0b746e5SOllivier Robert #include <ctype.h>
19c0b746e5SOllivier Robert #include <sys/time.h>
20c0b746e5SOllivier Robert #include <time.h>
21c0b746e5SOllivier Robert 
22c0b746e5SOllivier Robert #include "ntpd.h"
23c0b746e5SOllivier Robert #include "ntp_io.h"
24c0b746e5SOllivier Robert #include "ntp_refclock.h"
25c0b746e5SOllivier Robert #include "ntp_calendar.h"
26c0b746e5SOllivier Robert #include "ntp_stdlib.h"
27c0b746e5SOllivier Robert 
28c0b746e5SOllivier Robert /*
29c0b746e5SOllivier Robert  * This driver supports a generic dumb clock that only outputs hh:mm:ss,
30c0b746e5SOllivier Robert  * in local time, no less.
31c0b746e5SOllivier Robert  *
32c0b746e5SOllivier Robert  * Input format:
33c0b746e5SOllivier Robert  *
34c0b746e5SOllivier Robert  *      hh:mm:ss   <cr>
35c0b746e5SOllivier Robert  *
36c0b746e5SOllivier Robert  * hh:mm:ss -- what you'd expect, with a 24 hour clock.  (Heck, that's the only
37c0b746e5SOllivier Robert  * way it could get stupider.)  We take time on the <cr>.
38c0b746e5SOllivier Robert  *
39c0b746e5SOllivier Robert  * The original source of this module was the WWVB module.
40c0b746e5SOllivier Robert  */
41c0b746e5SOllivier Robert 
42c0b746e5SOllivier Robert /*
43c0b746e5SOllivier Robert  * Interface definitions
44c0b746e5SOllivier Robert  */
45c0b746e5SOllivier Robert #define	DEVICE		"/dev/dumbclock%d" /* device name and unit */
46c0b746e5SOllivier Robert #define	SPEED232	B9600	/* uart speed (9600 baud) */
47c0b746e5SOllivier Robert #define	PRECISION	(-13)	/* precision assumed (about 100 us) */
48c0b746e5SOllivier Robert #define	REFID		"dumbclock"	/* reference ID */
49c0b746e5SOllivier Robert #define	DESCRIPTION	"Dumb clock" /* WRU */
50c0b746e5SOllivier Robert 
51c0b746e5SOllivier Robert 
52c0b746e5SOllivier Robert /*
53c0b746e5SOllivier Robert  * Insanity check.  Since the time is local, we need to make sure that during midnight
54c0b746e5SOllivier Robert  * transitions, we can convert back to Unix time.  If the conversion results in some number
55c0b746e5SOllivier Robert  * worse than this number of seconds away, assume the next day and retry.
56c0b746e5SOllivier Robert  */
57c0b746e5SOllivier Robert #define INSANE_SECONDS 3600
58c0b746e5SOllivier Robert 
59c0b746e5SOllivier Robert /*
60c0b746e5SOllivier Robert  * Dumb clock control structure
61c0b746e5SOllivier Robert  */
62c0b746e5SOllivier Robert struct dumbclock_unit {
63c0b746e5SOllivier Robert 	u_char	  tcswitch;		     /* timecode switch */
64c0b746e5SOllivier Robert 	l_fp	  laststamp;		     /* last receive timestamp */
65c0b746e5SOllivier Robert 	u_char	  lasthour;		     /* last hour (for monitor) */
66c0b746e5SOllivier Robert 	u_char	  linect;		     /* count ignored lines (for monitor */
67c0b746e5SOllivier Robert         struct tm ymd;			     /* struct tm for y/m/d only */
68c0b746e5SOllivier Robert };
69c0b746e5SOllivier Robert 
70c0b746e5SOllivier Robert /*
71c0b746e5SOllivier Robert  * Function prototypes
72c0b746e5SOllivier Robert  */
73c0b746e5SOllivier Robert static	int	dumbclock_start		P((int, struct peer *));
74c0b746e5SOllivier Robert static	void	dumbclock_shutdown	P((int, struct peer *));
75c0b746e5SOllivier Robert static	void	dumbclock_receive	P((struct recvbuf *));
76c0b746e5SOllivier Robert #if 0
77c0b746e5SOllivier Robert static	void	dumbclock_poll		P((int, struct peer *));
78c0b746e5SOllivier Robert #endif
79c0b746e5SOllivier Robert 
80c0b746e5SOllivier Robert /*
81c0b746e5SOllivier Robert  * Transfer vector
82c0b746e5SOllivier Robert  */
83c0b746e5SOllivier Robert struct	refclock refclock_dumbclock = {
84c0b746e5SOllivier Robert 	dumbclock_start,		     /* start up driver */
85c0b746e5SOllivier Robert 	dumbclock_shutdown,		     /* shut down driver */
86c0b746e5SOllivier Robert 	noentry,			     /* poll the driver -- a nice fabrication */
87c0b746e5SOllivier Robert 	noentry,			     /* not used */
88c0b746e5SOllivier Robert 	noentry,			     /* not used */
89c0b746e5SOllivier Robert 	noentry,			     /* not used */
90c0b746e5SOllivier Robert 	NOFLAGS				     /* not used */
91c0b746e5SOllivier Robert };
92c0b746e5SOllivier Robert 
93c0b746e5SOllivier Robert 
94c0b746e5SOllivier Robert /*
95c0b746e5SOllivier Robert  * dumbclock_start - open the devices and initialize data for processing
96c0b746e5SOllivier Robert  */
97c0b746e5SOllivier Robert static int
98c0b746e5SOllivier Robert dumbclock_start(
99c0b746e5SOllivier Robert 	int unit,
100c0b746e5SOllivier Robert 	struct peer *peer
101c0b746e5SOllivier Robert 	)
102c0b746e5SOllivier Robert {
103c0b746e5SOllivier Robert 	register struct dumbclock_unit *up;
104c0b746e5SOllivier Robert 	struct refclockproc *pp;
105c0b746e5SOllivier Robert 	int fd;
106c0b746e5SOllivier Robert 	char device[20];
107c0b746e5SOllivier Robert 	struct tm *tm_time_p;
108c0b746e5SOllivier Robert 	time_t     now;
109c0b746e5SOllivier Robert 
110c0b746e5SOllivier Robert 	/*
111c0b746e5SOllivier Robert 	 * Open serial port. Don't bother with CLK line discipline, since
112c0b746e5SOllivier Robert 	 * it's not available.
113c0b746e5SOllivier Robert 	 */
114c0b746e5SOllivier Robert 	(void)sprintf(device, DEVICE, unit);
115c0b746e5SOllivier Robert #ifdef DEBUG
116c0b746e5SOllivier Robert 	if (debug)
117c0b746e5SOllivier Robert 		printf ("starting Dumbclock with device %s\n",device);
118c0b746e5SOllivier Robert #endif
119c0b746e5SOllivier Robert 	if (!(fd = refclock_open(device, SPEED232, 0)))
120c0b746e5SOllivier Robert 		return (0);
121c0b746e5SOllivier Robert 
122c0b746e5SOllivier Robert 	/*
123c0b746e5SOllivier Robert 	 * Allocate and initialize unit structure
124c0b746e5SOllivier Robert 	 */
125c0b746e5SOllivier Robert 	if (!(up = (struct dumbclock_unit *)
126c0b746e5SOllivier Robert 	      emalloc(sizeof(struct dumbclock_unit)))) {
127c0b746e5SOllivier Robert 		(void) close(fd);
128c0b746e5SOllivier Robert 		return (0);
129c0b746e5SOllivier Robert 	}
130c0b746e5SOllivier Robert 	memset((char *)up, 0, sizeof(struct dumbclock_unit));
131c0b746e5SOllivier Robert 	pp = peer->procptr;
132c0b746e5SOllivier Robert 	pp->unitptr = (caddr_t)up;
133c0b746e5SOllivier Robert 	pp->io.clock_recv = dumbclock_receive;
134c0b746e5SOllivier Robert 	pp->io.srcclock = (caddr_t)peer;
135c0b746e5SOllivier Robert 	pp->io.datalen = 0;
136c0b746e5SOllivier Robert 	pp->io.fd = fd;
137c0b746e5SOllivier Robert 	if (!io_addclock(&pp->io)) {
138c0b746e5SOllivier Robert 		(void) close(fd);
139c0b746e5SOllivier Robert 		free(up);
140c0b746e5SOllivier Robert 		return (0);
141c0b746e5SOllivier Robert 	}
142c0b746e5SOllivier Robert 
143c0b746e5SOllivier Robert 
144c0b746e5SOllivier Robert 	time(&now);
145c0b746e5SOllivier Robert #ifdef GET_LOCALTIME
146c0b746e5SOllivier Robert 	tm_time_p = localtime(&now);
147c0b746e5SOllivier Robert #else
148c0b746e5SOllivier Robert 	tm_time_p = gmtime(&now);
149c0b746e5SOllivier Robert #endif
150c0b746e5SOllivier Robert 	if (tm_time_p)
151c0b746e5SOllivier Robert 	{
152c0b746e5SOllivier Robert 	    up->ymd = *tm_time_p;
153c0b746e5SOllivier Robert 	}
154c0b746e5SOllivier Robert 	else
155c0b746e5SOllivier Robert 	{
156c0b746e5SOllivier Robert 	    return 0;
157c0b746e5SOllivier Robert 	}
158c0b746e5SOllivier Robert 
159c0b746e5SOllivier Robert 	/*
160c0b746e5SOllivier Robert 	 * Initialize miscellaneous variables
161c0b746e5SOllivier Robert 	 */
162c0b746e5SOllivier Robert 	peer->precision = PRECISION;
163c0b746e5SOllivier Robert 	pp->clockdesc = DESCRIPTION;
164c0b746e5SOllivier Robert 	memcpy((char *)&pp->refid, REFID, 4);
165c0b746e5SOllivier Robert 	return (1);
166c0b746e5SOllivier Robert }
167c0b746e5SOllivier Robert 
168c0b746e5SOllivier Robert 
169c0b746e5SOllivier Robert /*
170c0b746e5SOllivier Robert  * dumbclock_shutdown - shut down the clock
171c0b746e5SOllivier Robert  */
172c0b746e5SOllivier Robert static void
173c0b746e5SOllivier Robert dumbclock_shutdown(
174c0b746e5SOllivier Robert 	int unit,
175c0b746e5SOllivier Robert 	struct peer *peer
176c0b746e5SOllivier Robert 	)
177c0b746e5SOllivier Robert {
178c0b746e5SOllivier Robert 	register struct dumbclock_unit *up;
179c0b746e5SOllivier Robert 	struct refclockproc *pp;
180c0b746e5SOllivier Robert 
181c0b746e5SOllivier Robert 	pp = peer->procptr;
182c0b746e5SOllivier Robert 	up = (struct dumbclock_unit *)pp->unitptr;
183c0b746e5SOllivier Robert 	io_closeclock(&pp->io);
184c0b746e5SOllivier Robert 	free(up);
185c0b746e5SOllivier Robert }
186c0b746e5SOllivier Robert 
187c0b746e5SOllivier Robert 
188c0b746e5SOllivier Robert /*
189c0b746e5SOllivier Robert  * dumbclock_receive - receive data from the serial interface
190c0b746e5SOllivier Robert  */
191c0b746e5SOllivier Robert static void
192c0b746e5SOllivier Robert dumbclock_receive(
193c0b746e5SOllivier Robert 	struct recvbuf *rbufp
194c0b746e5SOllivier Robert 	)
195c0b746e5SOllivier Robert {
196c0b746e5SOllivier Robert 	struct dumbclock_unit *up;
197c0b746e5SOllivier Robert 	struct refclockproc *pp;
198c0b746e5SOllivier Robert 	struct peer *peer;
199c0b746e5SOllivier Robert 
200c0b746e5SOllivier Robert 	l_fp	     trtmp;	/* arrival timestamp */
201c0b746e5SOllivier Robert 	int          hours;	/* hour-of-day */
202c0b746e5SOllivier Robert 	int	     minutes;	/* minutes-past-the-hour */
203c0b746e5SOllivier Robert 	int          seconds;	/* seconds */
204c0b746e5SOllivier Robert 	int	     temp;	/* int temp */
205c0b746e5SOllivier Robert 	int          got_good;	/* got a good time flag */
206c0b746e5SOllivier Robert 
207c0b746e5SOllivier Robert 	/*
208c0b746e5SOllivier Robert 	 * Initialize pointers and read the timecode and timestamp
209c0b746e5SOllivier Robert 	 */
210c0b746e5SOllivier Robert 	peer = (struct peer *)rbufp->recv_srcclock;
211c0b746e5SOllivier Robert 	pp = peer->procptr;
212c0b746e5SOllivier Robert 	up = (struct dumbclock_unit *)pp->unitptr;
213c0b746e5SOllivier Robert 	temp = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &trtmp);
214c0b746e5SOllivier Robert 
215c0b746e5SOllivier Robert 	if (temp == 0) {
216c0b746e5SOllivier Robert 		if (up->tcswitch == 0) {
217c0b746e5SOllivier Robert 			up->tcswitch = 1;
218c0b746e5SOllivier Robert 			up->laststamp = trtmp;
219c0b746e5SOllivier Robert 		} else
220c0b746e5SOllivier Robert 		    up->tcswitch = 0;
221c0b746e5SOllivier Robert 		return;
222c0b746e5SOllivier Robert 	}
223c0b746e5SOllivier Robert 	pp->lencode = temp;
224c0b746e5SOllivier Robert 	pp->lastrec = up->laststamp;
225c0b746e5SOllivier Robert 	up->laststamp = trtmp;
226c0b746e5SOllivier Robert 	up->tcswitch = 1;
227c0b746e5SOllivier Robert 
228c0b746e5SOllivier Robert #ifdef DEBUG
229c0b746e5SOllivier Robert 	if (debug)
230c0b746e5SOllivier Robert 		printf("dumbclock: timecode %d %s\n",
231c0b746e5SOllivier Robert 		       pp->lencode, pp->a_lastcode);
232c0b746e5SOllivier Robert #endif
233c0b746e5SOllivier Robert 
234c0b746e5SOllivier Robert 	/*
235c0b746e5SOllivier Robert 	 * We get down to business. Check the timecode format...
236c0b746e5SOllivier Robert 	 */
237c0b746e5SOllivier Robert 	pp->msec = 0;
238c0b746e5SOllivier Robert 	got_good=0;
239c0b746e5SOllivier Robert 	if (sscanf(pp->a_lastcode,"%02d:%02d:%02d",
240c0b746e5SOllivier Robert 		   &hours,&minutes,&seconds) == 3)
241c0b746e5SOllivier Robert 	{
242c0b746e5SOllivier Robert 	    struct tm *gmtp;
243c0b746e5SOllivier Robert 	    struct tm *lt_p;
244c0b746e5SOllivier Robert 	    time_t     asserted_time;	     /* the SPM time based on the composite time+date */
245c0b746e5SOllivier Robert 	    struct tm  asserted_tm;	     /* the struct tm of the same */
246c0b746e5SOllivier Robert 	    int        adjyear;
247c0b746e5SOllivier Robert 	    int        adjmon;
248c0b746e5SOllivier Robert 	    int        reality_delta;
249c0b746e5SOllivier Robert 	    time_t     now;
250c0b746e5SOllivier Robert 
251c0b746e5SOllivier Robert 
252c0b746e5SOllivier Robert 	    /*
253c0b746e5SOllivier Robert 	     * Convert to GMT for sites that distribute localtime.  This
254c0b746e5SOllivier Robert              * means we have to figure out what day it is.  Easier said
255c0b746e5SOllivier Robert 	     * than done...
256c0b746e5SOllivier Robert 	     */
257c0b746e5SOllivier Robert 
258c0b746e5SOllivier Robert 	    asserted_tm.tm_year  = up->ymd.tm_year;
259c0b746e5SOllivier Robert 	    asserted_tm.tm_mon   = up->ymd.tm_mon;
260c0b746e5SOllivier Robert 	    asserted_tm.tm_mday  = up->ymd.tm_mday;
261c0b746e5SOllivier Robert 	    asserted_tm.tm_hour  = hours;
262c0b746e5SOllivier Robert 	    asserted_tm.tm_min   = minutes;
263c0b746e5SOllivier Robert 	    asserted_tm.tm_sec   = seconds;
264c0b746e5SOllivier Robert 	    asserted_tm.tm_isdst = -1;
265c0b746e5SOllivier Robert 
266c0b746e5SOllivier Robert #ifdef GET_LOCALTIME
267c0b746e5SOllivier Robert 	    asserted_time = mktime (&asserted_tm);
268c0b746e5SOllivier Robert 	    time(&now);
269c0b746e5SOllivier Robert #else
270c0b746e5SOllivier Robert #include "GMT unsupported for dumbclock!"
271c0b746e5SOllivier Robert #endif
272c0b746e5SOllivier Robert 	    reality_delta = asserted_time - now;
273c0b746e5SOllivier Robert 
274c0b746e5SOllivier Robert 	    /*
275c0b746e5SOllivier Robert 	     * We assume that if the time is grossly wrong, it's because we got the
276c0b746e5SOllivier Robert 	     * year/month/day wrong.
277c0b746e5SOllivier Robert 	     */
278c0b746e5SOllivier Robert 	    if (reality_delta > INSANE_SECONDS)
279c0b746e5SOllivier Robert 	    {
280c0b746e5SOllivier Robert 		asserted_time -= SECSPERDAY; /* local clock behind real time */
281c0b746e5SOllivier Robert 	    }
282c0b746e5SOllivier Robert 	    else if (-reality_delta > INSANE_SECONDS)
283c0b746e5SOllivier Robert 	    {
284c0b746e5SOllivier Robert 		asserted_time += SECSPERDAY; /* local clock ahead of real time */
285c0b746e5SOllivier Robert 	    }
286c0b746e5SOllivier Robert 	    lt_p = localtime(&asserted_time);
287c0b746e5SOllivier Robert 	    if (lt_p)
288c0b746e5SOllivier Robert 	    {
289c0b746e5SOllivier Robert 		up->ymd = *lt_p;
290c0b746e5SOllivier Robert 	    }
291c0b746e5SOllivier Robert 	    else
292c0b746e5SOllivier Robert 	    {
293c0b746e5SOllivier Robert 		refclock_report (peer, CEVNT_FAULT);
294c0b746e5SOllivier Robert 		return;
295c0b746e5SOllivier Robert 	    }
296c0b746e5SOllivier Robert 
297c0b746e5SOllivier Robert 	    if ((gmtp = gmtime (&asserted_time)) == NULL)
298c0b746e5SOllivier Robert 	    {
299c0b746e5SOllivier Robert 		refclock_report (peer, CEVNT_FAULT);
300c0b746e5SOllivier Robert 		return;
301c0b746e5SOllivier Robert 	    }
302c0b746e5SOllivier Robert 	    adjyear = gmtp->tm_year+1900;
303c0b746e5SOllivier Robert 	    adjmon  = gmtp->tm_mon+1;
304c0b746e5SOllivier Robert 	    pp->day = ymd2yd (adjyear, adjmon, gmtp->tm_mday);
305c0b746e5SOllivier Robert 	    pp->hour   = gmtp->tm_hour;
306c0b746e5SOllivier Robert 	    pp->minute = gmtp->tm_min;
307c0b746e5SOllivier Robert 	    pp->second = gmtp->tm_sec;
308c0b746e5SOllivier Robert #ifdef DEBUG
309c0b746e5SOllivier Robert 	    if (debug)
310c0b746e5SOllivier Robert 		printf ("time is %04d/%02d/%02d %02d:%02d:%02d UTC\n",
311c0b746e5SOllivier Robert 			adjyear,adjmon,gmtp->tm_mday,pp->hour,pp->minute,
312c0b746e5SOllivier Robert 			pp->second);
313c0b746e5SOllivier Robert #endif
314c0b746e5SOllivier Robert 
315c0b746e5SOllivier Robert 	    got_good=1;
316c0b746e5SOllivier Robert 	}
317c0b746e5SOllivier Robert 
318c0b746e5SOllivier Robert 	if (!got_good)
319c0b746e5SOllivier Robert 	{
320c0b746e5SOllivier Robert 	    if (up->linect > 0)
321c0b746e5SOllivier Robert 	    	up->linect--;
322c0b746e5SOllivier Robert 	    else
323c0b746e5SOllivier Robert 	    	refclock_report(peer, CEVNT_BADREPLY);
324c0b746e5SOllivier Robert 	    return;
325c0b746e5SOllivier Robert 	}
326c0b746e5SOllivier Robert 
327c0b746e5SOllivier Robert 	/*
328c0b746e5SOllivier Robert 	 * Process the new sample in the median filter and determine the
329c0b746e5SOllivier Robert 	 * timecode timestamp.
330c0b746e5SOllivier Robert 	 */
331c0b746e5SOllivier Robert 	if (!refclock_process(pp)) {
332c0b746e5SOllivier Robert 		refclock_report(peer, CEVNT_BADTIME);
333c0b746e5SOllivier Robert 		return;
334c0b746e5SOllivier Robert 	}
335c0b746e5SOllivier Robert 	record_clock_stats(&peer->srcadr, pp->a_lastcode);
336c0b746e5SOllivier Robert 	refclock_receive(peer);
337c0b746e5SOllivier Robert 	up->lasthour = pp->hour;
338c0b746e5SOllivier Robert }
339c0b746e5SOllivier Robert 
340c0b746e5SOllivier Robert #if 0
341c0b746e5SOllivier Robert /*
342c0b746e5SOllivier Robert  * dumbclock_poll - called by the transmit procedure
343c0b746e5SOllivier Robert  */
344c0b746e5SOllivier Robert static void
345c0b746e5SOllivier Robert dumbclock_poll(
346c0b746e5SOllivier Robert 	int unit,
347c0b746e5SOllivier Robert 	struct peer *peer
348c0b746e5SOllivier Robert 	)
349c0b746e5SOllivier Robert {
350c0b746e5SOllivier Robert 	register struct dumbclock_unit *up;
351c0b746e5SOllivier Robert 	struct refclockproc *pp;
352c0b746e5SOllivier Robert 	char pollchar;
353c0b746e5SOllivier Robert 
354c0b746e5SOllivier Robert 	/*
355c0b746e5SOllivier Robert 	 * Time to poll the clock. The Chrono-log clock is supposed to
356c0b746e5SOllivier Robert 	 * respond to a 'T' by returning a timecode in the format(s)
357c0b746e5SOllivier Robert 	 * specified above.  Ours does (can?) not, but this seems to be
358c0b746e5SOllivier Robert 	 * an installation-specific problem.  This code is dyked out,
359c0b746e5SOllivier Robert 	 * but may be re-enabled if anyone ever finds a Chrono-log that
360c0b746e5SOllivier Robert 	 * actually listens to this command.
361c0b746e5SOllivier Robert 	 */
362c0b746e5SOllivier Robert #if 0
363c0b746e5SOllivier Robert 	pp = peer->procptr;
364c0b746e5SOllivier Robert 	up = (struct dumbclock_unit *)pp->unitptr;
365c0b746e5SOllivier Robert 	if (peer->reach == 0)
366c0b746e5SOllivier Robert 		refclock_report(peer, CEVNT_TIMEOUT);
367c0b746e5SOllivier Robert 	if (up->linect > 0)
368c0b746e5SOllivier Robert 		pollchar = 'R';
369c0b746e5SOllivier Robert 	else
370c0b746e5SOllivier Robert 		pollchar = 'T';
371c0b746e5SOllivier Robert 	if (write(pp->io.fd, &pollchar, 1) != 1)
372c0b746e5SOllivier Robert 		refclock_report(peer, CEVNT_FAULT);
373c0b746e5SOllivier Robert 	else
374c0b746e5SOllivier Robert 		pp->polls++;
375c0b746e5SOllivier Robert #endif
376c0b746e5SOllivier Robert }
377c0b746e5SOllivier Robert #endif
378c0b746e5SOllivier Robert 
379c0b746e5SOllivier Robert #else
380c0b746e5SOllivier Robert int refclock_dumbclock_bs;
381c0b746e5SOllivier Robert #endif /* REFCLOCK */
382