udcf.c revision 1.24
1/*	$OpenBSD: udcf.c,v 1.24 2006/12/10 14:39:05 mbalmer Exp $ */
2
3/*
4 * Copyright (c) 2006 Marc Balmer <mbalmer@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/param.h>
20#include <sys/systm.h>
21#include <sys/kernel.h>
22#include <sys/conf.h>
23#include <sys/file.h>
24#include <sys/select.h>
25#include <sys/proc.h>
26#include <sys/vnode.h>
27#include <sys/device.h>
28#include <sys/poll.h>
29#include <sys/time.h>
30#include <sys/sensors.h>
31
32#include <dev/usb/usb.h>
33#include <dev/usb/usbdi.h>
34#include <dev/usb/usbdi_util.h>
35#include <dev/usb/usbdevs.h>
36
37#ifdef UDCF_DEBUG
38#define DPRINTFN(n, x)	do { if (udcfdebug > (n)) printf x; } while (0)
39int udcfdebug = 0;
40#else
41#define DPRINTFN(n, x)
42#endif
43#define DPRINTF(x)	DPRINTFN(0, x)
44
45#define UDCF_READ_REQ	0xc0
46#define UDCF_READ_IDX	0x1f
47
48#define UDCF_CTRL_REQ	0x40
49#define UDCF_CTRL_IDX	0x33
50#define UDCF_CTRL_VAL	0x98
51
52#define DPERIOD1	((long) 5 * 60)		/* degrade OK -> WARN */
53#define DPERIOD2	((long) 15 * 60)	/* degrade WARN -> CRIT */
54
55/* max. skew of received time diff vs. measured time diff in percent. */
56#define MAX_SKEW	5
57
58#define CLOCK_DCF77	0
59#define CLOCK_HBG	1
60
61static const char	*clockname[2] = {
62	"DCF77",
63	"HBG" };
64
65struct udcf_softc {
66	USBBASEDEVICE		sc_dev;		/* base device */
67	usbd_device_handle	sc_udev;	/* USB device */
68	usbd_interface_handle	sc_iface;	/* data interface */
69	u_char			sc_dying;	/* disconnecting */
70
71	struct timeout		sc_to;
72	struct usb_task		sc_task;
73
74	struct timeout		sc_bv_to;	/* bit-value detect */
75	struct timeout		sc_db_to;	/* debounce */
76	struct timeout		sc_mg_to;	/* minute-gap detect */
77	struct timeout		sc_sl_to;	/* signal-loss detect */
78	struct timeout		sc_it_to;	/* invalidate time */
79	struct timeout		sc_ct_to;	/* detect clock type */
80	struct usb_task		sc_bv_task;
81	struct usb_task		sc_mg_task;
82	struct usb_task		sc_sl_task;
83	struct usb_task		sc_it_task;
84	struct usb_task		sc_ct_task;
85
86	usb_device_request_t	sc_req;
87
88	int			sc_clocktype;	/* DCF77 or HBG */
89	int			sc_sync;	/* 1 during sync */
90	u_int64_t		sc_mask;	/* 64 bit mask */
91	u_int64_t		sc_tbits;	/* Time bits */
92	int			sc_minute;
93	int			sc_level;
94	time_t			sc_last_mg;
95
96	time_t			sc_current;	/* current time */
97	time_t			sc_next;	/* time to become valid next */
98	time_t			sc_last;
99	int			sc_nrecv;	/* consecutive valid times */
100	struct timeval		sc_last_tv;	/* uptime of last valid time */
101	struct sensor		sc_sensor;
102#ifdef UDCF_DEBUG
103	struct sensor		sc_skew;	/* recv vs local skew */
104#endif
105};
106
107/*
108 * timeouts being used in hz:
109 * t_bv		bit value detection (150ms)
110 * t_ct		detect clocktype (250ms)
111 * t_sync	sync (950ms)
112 * t_mg		minute gap detection (1500ms)
113 * t_mgsync	resync after a minute gap (450ms)
114 * t_sl		detect signal loss (3sec)
115 * t_wait	wait (5sec)
116 * t_warn	degrade sensor status to warning (5min)
117 * t_crit	degrade sensor status to critical (15min)
118 */
119static int t_bv, t_ct, t_sync, t_mg, t_sl, t_mgsync, t_wait, t_warn, t_crit;
120
121void	udcf_intr(void *);
122void	udcf_probe(void *);
123
124void	udcf_bv_intr(void *);
125void	udcf_mg_intr(void *);
126void	udcf_sl_intr(void *);
127void	udcf_it_intr(void *);
128void	udcf_ct_intr(void *);
129void	udcf_bv_probe(void *);
130void	udcf_mg_probe(void *);
131void	udcf_sl_probe(void *);
132void	udcf_it_probe(void *);
133void	udcf_ct_probe(void *);
134
135USB_DECLARE_DRIVER(udcf);
136
137USB_MATCH(udcf)
138{
139	USB_MATCH_START(udcf, uaa);
140
141	if (uaa->iface != NULL)
142		return (UMATCH_NONE);
143
144	return uaa->vendor == USB_VENDOR_GUDE &&
145	    uaa->product == USB_PRODUCT_GUDE_DCF ?
146	    UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
147}
148
149USB_ATTACH(udcf)
150{
151	USB_ATTACH_START(udcf, sc, uaa);
152	usbd_device_handle		 dev = uaa->device;
153	usbd_interface_handle		 iface;
154	struct timeval			 t;
155	char				*devinfop;
156	usb_interface_descriptor_t	*id;
157	usbd_status			 err;
158	usb_device_request_t		 req;
159	uWord				 result;
160	int				 actlen;
161
162	if ((err = usbd_set_config_index(dev, 0, 1))) {
163		DPRINTF(("\n%s: failed to set configuration, err=%s\n",
164		    USBDEVNAME(sc->sc_dev), usbd_errstr(err)));
165		goto fishy;
166	}
167
168	if ((err = usbd_device2interface_handle(dev, 0, &iface))) {
169		DPRINTF(("\n%s: failed to get interface, err=%s\n",
170		    USBDEVNAME(sc->sc_dev), usbd_errstr(err)));
171		goto fishy;
172	}
173
174	devinfop = usbd_devinfo_alloc(dev, 0);
175	USB_ATTACH_SETUP;
176	printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfop);
177	usbd_devinfo_free(devinfop);
178
179	id = usbd_get_interface_descriptor(iface);
180
181	sc->sc_udev = dev;
182	sc->sc_iface = iface;
183
184	sc->sc_clocktype = -1;
185	sc->sc_level = 0;
186	sc->sc_minute = 0;
187	sc->sc_last_mg = 0L;
188
189	sc->sc_sync = 1;
190
191	sc->sc_current = 0L;
192	sc->sc_next = 0L;
193	sc->sc_nrecv = 0;
194	sc->sc_last = 0L;
195	sc->sc_last_tv.tv_sec = 0L;
196
197	strlcpy(sc->sc_sensor.device, USBDEVNAME(sc->sc_dev),
198	    sizeof(sc->sc_sensor.device));
199	sc->sc_sensor.type = SENSOR_TIMEDELTA;
200	sc->sc_sensor.status = SENSOR_S_UNKNOWN;
201	sc->sc_sensor.value = 0LL;
202	sc->sc_sensor.flags = 0;
203	strlcpy(sc->sc_sensor.desc, "Unknown", sizeof(sc->sc_sensor.desc));
204	sensor_add(&sc->sc_sensor);
205#ifdef UDCF_DEBUG
206	strlcpy(sc->sc_skew.device, USBDEVNAME(sc->sc_dev),
207	    sizeof(sc->sc_skew.device));
208	sc->sc_skew.type = SENSOR_TIMEDELTA;
209	sc->sc_skew.status = SENSOR_S_UNKNOWN;
210	sc->sc_skew.value = 0LL;
211	sc->sc_skew.flags = 0;
212	strlcpy(sc->sc_skew.desc, "local clock skew",
213	    sizeof(sc->sc_skew.desc));
214	sensor_add(&sc->sc_skew);
215#endif
216	/* Prepare the USB request to probe the value */
217	sc->sc_req.bmRequestType = UDCF_READ_REQ;
218	sc->sc_req.bRequest = 1;
219	USETW(sc->sc_req.wValue, 0);
220	USETW(sc->sc_req.wIndex, UDCF_READ_IDX);
221	USETW(sc->sc_req.wLength, 1);
222
223	req.bmRequestType = UDCF_CTRL_REQ;
224	req.bRequest = 0;
225	USETW(req.wValue, 0);
226	USETW(req.wIndex, 0);
227	USETW(req.wLength, 0);
228	if ((err = usbd_do_request_flags(sc->sc_udev, &req, &result,
229	    USBD_SHORT_XFER_OK, &actlen, USBD_DEFAULT_TIMEOUT))) {
230		DPRINTF(("failed to turn on power for receiver\n"));
231		goto fishy;
232	}
233
234	req.bmRequestType = UDCF_CTRL_REQ;
235	req.bRequest = 0;
236	USETW(req.wValue, UDCF_CTRL_VAL);
237	USETW(req.wIndex, UDCF_CTRL_IDX);
238	USETW(req.wLength, 0);
239	if ((err = usbd_do_request_flags(sc->sc_udev, &req, &result,
240	    USBD_SHORT_XFER_OK, &actlen, USBD_DEFAULT_TIMEOUT))) {
241		DPRINTF(("failed to turn on receiver\n"));
242		goto fishy;
243	}
244
245	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
246	    USBDEV(sc->sc_dev));
247
248	usb_init_task(&sc->sc_task, udcf_probe, sc);
249	usb_init_task(&sc->sc_bv_task, udcf_bv_probe, sc);
250	usb_init_task(&sc->sc_mg_task, udcf_mg_probe, sc);
251	usb_init_task(&sc->sc_sl_task, udcf_sl_probe, sc);
252	usb_init_task(&sc->sc_it_task, udcf_it_probe, sc);
253	usb_init_task(&sc->sc_ct_task, udcf_ct_probe, sc);
254
255	timeout_set(&sc->sc_to, udcf_intr, sc);
256	timeout_set(&sc->sc_bv_to, udcf_bv_intr, sc);
257	timeout_set(&sc->sc_mg_to, udcf_mg_intr, sc);
258	timeout_set(&sc->sc_sl_to, udcf_sl_intr, sc);
259	timeout_set(&sc->sc_it_to, udcf_it_intr, sc);
260	timeout_set(&sc->sc_ct_to, udcf_ct_intr, sc);
261
262	/* convert timevals to hz */
263	t.tv_sec = 0L;
264	t.tv_usec = 150000L;
265	t_bv = tvtohz(&t);
266
267	t.tv_usec = 450000L;
268	t_mgsync = tvtohz(&t);
269
270	t.tv_usec = 950000L;
271	t_sync = tvtohz(&t);
272
273	t.tv_sec = 1L;
274	t.tv_usec = 500000L;
275	t_mg = tvtohz(&t);
276
277	t.tv_sec = 3L;
278	t.tv_usec = 0L;
279	t_sl = tvtohz(&t);
280
281	t.tv_sec = 5L;
282	t_wait = tvtohz(&t);
283
284	t.tv_sec = DPERIOD1;
285	t_warn = tvtohz(&t);
286
287	t.tv_sec = DPERIOD2;
288	t_crit = tvtohz(&t);
289
290	t.tv_sec = 0L;
291	t.tv_usec = 250000L;
292	t_ct = tvtohz(&t);
293
294	/* Give the receiver some slack to stabilize */
295	timeout_add(&sc->sc_to, t_wait);
296
297	/* Detect signal loss */
298	timeout_add(&sc->sc_sl_to, t_wait + t_sl);
299
300	DPRINTF(("synchronizing\n"));
301	USB_ATTACH_SUCCESS_RETURN;
302
303fishy:
304	DPRINTF(("udcf_attach failed\n"));
305	sc->sc_dying = 1;
306	USB_ATTACH_ERROR_RETURN;
307}
308
309USB_DETACH(udcf)
310{
311	struct udcf_softc	*sc = (struct udcf_softc *)self;
312
313	sc->sc_dying = 1;
314
315	timeout_del(&sc->sc_to);
316	timeout_del(&sc->sc_bv_to);
317	timeout_del(&sc->sc_mg_to);
318	timeout_del(&sc->sc_sl_to);
319	timeout_del(&sc->sc_it_to);
320	timeout_del(&sc->sc_ct_to);
321
322	/* Unregister the clock with the kernel */
323	sensor_del(&sc->sc_sensor);
324#ifdef UDCF_DEBUG
325	sensor_del(&sc->sc_skew);
326#endif
327	usb_rem_task(sc->sc_udev, &sc->sc_task);
328	usb_rem_task(sc->sc_udev, &sc->sc_bv_task);
329	usb_rem_task(sc->sc_udev, &sc->sc_mg_task);
330	usb_rem_task(sc->sc_udev, &sc->sc_sl_task);
331	usb_rem_task(sc->sc_udev, &sc->sc_it_task);
332	usb_rem_task(sc->sc_udev, &sc->sc_ct_task);
333
334	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
335	    USBDEV(sc->sc_dev));
336	return (0);
337}
338
339/* udcf_intr runs in an interrupt context */
340void
341udcf_intr(void *xsc)
342{
343	struct udcf_softc *sc = xsc;
344	usb_add_task(sc->sc_udev, &sc->sc_task);
345}
346
347/* bit value detection */
348void
349udcf_bv_intr(void *xsc)
350{
351	struct udcf_softc *sc = xsc;
352	usb_add_task(sc->sc_udev, &sc->sc_bv_task);
353}
354
355/* minute gap detection */
356void
357udcf_mg_intr(void *xsc)
358{
359	struct udcf_softc *sc = xsc;
360	usb_add_task(sc->sc_udev, &sc->sc_mg_task);
361}
362
363/* signal loss detection */
364void
365udcf_sl_intr(void *xsc)
366{
367	struct udcf_softc *sc = xsc;
368	usb_add_task(sc->sc_udev, &sc->sc_sl_task);
369}
370
371/* degrade the sensor */
372void
373udcf_it_intr(void *xsc)
374{
375	struct udcf_softc *sc = xsc;
376	usb_add_task(sc->sc_udev, &sc->sc_it_task);
377}
378
379/* detect the clock type (DCF77 or HBG) */
380void
381udcf_ct_intr(void *xsc)
382{
383	struct udcf_softc *sc = xsc;
384	usb_add_task(sc->sc_udev, &sc->sc_ct_task);
385}
386
387/*
388 * udcf_probe runs in a process context.  If bit 0 is set, the transmitter
389 * emits at full power.  During the low-power emission we decode a zero bit.
390 */
391void
392udcf_probe(void *xsc)
393{
394	struct udcf_softc	*sc = xsc;
395	struct timespec		 now;
396	unsigned char		 data;
397	int			 actlen;
398
399	if (sc->sc_dying)
400		return;
401
402	if (usbd_do_request_flags(sc->sc_udev, &sc->sc_req, &data,
403	    USBD_SHORT_XFER_OK, &actlen, USBD_DEFAULT_TIMEOUT))
404		/* This happens if we pull the receiver */
405		return;
406
407	if (data & 0x01) {
408		sc->sc_level = 1;
409		timeout_add(&sc->sc_to, 1);
410		return;
411	}
412
413	if (sc->sc_level == 0)
414		return;
415
416	/* Begin of a second */
417	sc->sc_level = 0;
418	if (sc->sc_minute == 1) {
419		if (sc->sc_sync) {
420			DPRINTF(("synchronized, collecting bits\n"));
421			sc->sc_sync = 0;
422			if (sc->sc_sensor.status == SENSOR_S_UNKNOWN)
423				sc->sc_clocktype = -1;
424		} else {
425			/* provide the timedelta */
426			microtime(&sc->sc_sensor.tv);
427			nanotime(&now);
428			sc->sc_current = sc->sc_next;
429			sc->sc_sensor.value = (int64_t)(now.tv_sec -
430			    sc->sc_current) * 1000000000LL + now.tv_nsec;
431
432			/* set the clocktype and make sensor valid */
433			if (sc->sc_sensor.status == SENSOR_S_UNKNOWN) {
434				strlcpy(sc->sc_sensor.desc, sc->sc_clocktype ?
435				    clockname[CLOCK_HBG] :
436				    clockname[CLOCK_DCF77],
437				    sizeof(sc->sc_sensor.desc));
438			}
439			sc->sc_sensor.status = SENSOR_S_OK;
440
441			/*
442			 * if no valid time information is received
443			 * during the next 5 minutes, the sensor state
444			 * will be degraded to SENSOR_S_WARN
445			 */
446			timeout_add(&sc->sc_it_to, t_warn);
447		}
448		sc->sc_minute = 0;
449	}
450
451	timeout_add(&sc->sc_to, t_sync);	/* resync in 950 ms */
452
453	/* No clock and bit detection during sync */
454	if (!sc->sc_sync) {
455		/* detect bit value */
456		timeout_add(&sc->sc_bv_to, t_bv);
457
458		/* detect clocktype */
459		if (sc->sc_clocktype == -1)
460			timeout_add(&sc->sc_ct_to, t_ct);
461	}
462	timeout_add(&sc->sc_mg_to, t_mg);	/* detect minute gap */
463	timeout_add(&sc->sc_sl_to, t_sl);	/* detect signal loss */
464}
465
466/* detect the bit value */
467void
468udcf_bv_probe(void *xsc)
469{
470	struct udcf_softc	*sc = xsc;
471	int			 actlen;
472	unsigned char		 data;
473
474	if (sc->sc_dying)
475		return;
476
477	if (usbd_do_request_flags(sc->sc_udev, &sc->sc_req, &data,
478	    USBD_SHORT_XFER_OK, &actlen, USBD_DEFAULT_TIMEOUT)) {
479		/* This happens if we pull the receiver */
480		DPRINTF(("bit detection failed\n"));
481		return;
482	}
483
484	DPRINTFN(1, (data & 0x01 ? "0" : "1"));
485	if (!(data & 0x01))
486		sc->sc_tbits |= sc->sc_mask;
487	sc->sc_mask <<= 1;
488}
489
490/* detect the minute gap */
491void
492udcf_mg_probe(void *xsc)
493{
494	struct udcf_softc	*sc = xsc;
495
496	struct clock_ymdhms	 ymdhm;
497	struct timeval		 monotime;
498	int			 tdiff_recv, tdiff_local;
499	int			 skew;
500	int			 minute_bits, hour_bits, day_bits;
501	int			 month_bits, year_bits, wday;
502	int			 p1, p2, p3;
503	int			 p1_bit, p2_bit, p3_bit;
504	int			 r_bit, a1_bit, a2_bit, z1_bit, z2_bit;
505	int			 s_bit, m_bit;
506
507	u_int32_t		 parity = 0x6996;
508
509	if (sc->sc_sync) {
510		sc->sc_minute = 1;
511		goto cleanbits;
512	}
513
514	if (time_second - sc->sc_last_mg < 57) {
515		DPRINTF(("\nunexpected gap, resync\n"));
516		sc->sc_sync = sc->sc_minute = 1;
517		goto cleanbits;
518	}
519
520	/* Extract bits w/o parity */
521	m_bit = sc->sc_tbits & 1;
522	r_bit = sc->sc_tbits >> 15 & 1;
523	a1_bit = sc->sc_tbits >> 16 & 1;
524	z1_bit = sc->sc_tbits >> 17 & 1;
525	z2_bit = sc->sc_tbits >> 18 & 1;
526	a2_bit = sc->sc_tbits >> 19 & 1;
527	s_bit = sc->sc_tbits >> 20 & 1;
528	p1_bit = sc->sc_tbits >> 28 & 1;
529	p2_bit = sc->sc_tbits >> 35 & 1;
530	p3_bit = sc->sc_tbits >> 58 & 1;
531
532	minute_bits = sc->sc_tbits >> 21 & 0x7f;
533	hour_bits = sc->sc_tbits >> 29 & 0x3f;
534	day_bits = sc->sc_tbits >> 36 & 0x3f;
535	wday = (sc->sc_tbits >> 42) & 0x07;
536	month_bits = sc->sc_tbits >> 45 & 0x1f;
537	year_bits = sc->sc_tbits >> 50 & 0xff;
538
539	/* Validate time information */
540	p1 = (parity >> (minute_bits & 0x0f) & 1) ^
541	    (parity >> (minute_bits >> 4) & 1);
542
543	p2 = (parity >> (hour_bits & 0x0f) & 1) ^
544	    (parity >> (hour_bits >> 4) & 1);
545
546	p3 = (parity >> (day_bits & 0x0f) & 1) ^
547	    (parity >> (day_bits >> 4) & 1) ^
548	    ((parity >> wday) & 1) ^ (parity >> (month_bits & 0x0f) & 1) ^
549	    (parity >> (month_bits >> 4) & 1) ^
550	    (parity >> (year_bits & 0x0f) & 1) ^
551	    (parity >> (year_bits >> 4) & 1);
552
553	if (m_bit == 0 && s_bit == 1 && p1 == p1_bit && p2 == p2_bit &&
554	    p3 == p3_bit && (z1_bit ^ z2_bit)) {
555
556		/* Decode time */
557		if ((ymdhm.dt_year = 2000 + FROMBCD(year_bits)) > 2037) {
558			DPRINTF(("year out of range, resync\n"));
559			sc->sc_sync = 1;
560			goto cleanbits;
561		}
562		ymdhm.dt_min = FROMBCD(minute_bits);
563		ymdhm.dt_hour = FROMBCD(hour_bits);
564		ymdhm.dt_day = FROMBCD(day_bits);
565		ymdhm.dt_mon = FROMBCD(month_bits);
566		ymdhm.dt_sec = 0;
567
568		sc->sc_next = clock_ymdhms_to_secs(&ymdhm);
569		getmicrouptime(&monotime);
570
571		/* convert to coordinated universal time */
572		sc->sc_next -= z1_bit ? 7200 : 3600;
573
574		DPRINTF(("\n%02d.%02d.%04d %02d:%02d:00 %s",
575		    ymdhm.dt_day, ymdhm.dt_mon, ymdhm.dt_year,
576		    ymdhm.dt_hour, ymdhm.dt_min, z1_bit ? "CEST" : "CET"));
577		DPRINTF((r_bit ? ", call bit" : ""));
578		DPRINTF((a1_bit ? ", dst chg ann." : ""));
579		DPRINTF((a2_bit ? ", leap sec ann." : ""));
580		DPRINTF(("\n"));
581
582		if (sc->sc_last) {
583			tdiff_recv = sc->sc_next - sc->sc_last;
584			tdiff_local = monotime.tv_sec - sc->sc_last_tv.tv_sec;
585			skew = abs(tdiff_local - tdiff_recv);
586#ifdef UDCF_DEBUG
587			if (sc->sc_skew.status == SENSOR_S_UNKNOWN)
588				sc->sc_skew.status = SENSOR_S_CRIT;
589			sc->sc_skew.value = skew * 1000000000LL;
590			getmicrotime(&sc->sc_skew.tv);
591#endif
592			DPRINTF(("local = %d, recv = %d, skew = %d\n",
593			    tdiff_local, tdiff_recv, skew));
594
595			if (skew && skew * 100LL / tdiff_local > MAX_SKEW) {
596				DPRINTF(("skew out of tolerated range\n"));
597				goto cleanbits;
598			} else {
599				if (sc->sc_nrecv < 2) {
600					sc->sc_nrecv++;
601					DPRINTF(("got frame %d\n",
602					    sc->sc_nrecv));
603				} else {
604					DPRINTF(("data is valid\n"));
605					sc->sc_minute = 1;
606				}
607			}
608		} else {
609			DPRINTF(("received the first frame\n"));
610			sc->sc_nrecv = 1;
611		}
612
613		/* record the time received and when it was received */
614		sc->sc_last = sc->sc_next;
615		sc->sc_last_tv.tv_sec = monotime.tv_sec;
616	} else {
617		DPRINTF(("\nparity error, resync\n"));
618		sc->sc_sync = 1;
619	}
620
621cleanbits:
622	timeout_add(&sc->sc_to, t_mgsync);	/* re-sync in 450 ms */
623	sc->sc_last_mg = time_second;
624	sc->sc_tbits = 0LL;
625	sc->sc_mask = 1LL;
626}
627
628/* detect signal loss */
629void
630udcf_sl_probe(void *xsc)
631{
632	struct udcf_softc *sc = xsc;
633
634	if (sc->sc_dying)
635		return;
636
637	DPRINTF(("no signal\n"));
638	sc->sc_sync = 1;
639	timeout_add(&sc->sc_to, t_wait);
640	timeout_add(&sc->sc_sl_to, t_wait + t_sl);
641}
642
643/* invalidate timedelta */
644void
645udcf_it_probe(void *xsc)
646{
647	struct udcf_softc *sc = xsc;
648
649	if (sc->sc_dying)
650		return;
651
652	DPRINTF(("\ndegrading sensor state\n"));
653
654	if (sc->sc_sensor.status == SENSOR_S_OK) {
655		sc->sc_sensor.status = SENSOR_S_WARN;
656		/*
657		 * further degrade in 15 minutes if we dont receive any new
658		 * time information
659		 */
660		timeout_add(&sc->sc_it_to, t_crit);
661	} else {
662		sc->sc_sensor.status = SENSOR_S_CRIT;
663		sc->sc_nrecv = 0;
664	}
665}
666
667/* detect clock type */
668void
669udcf_ct_probe(void *xsc)
670{
671	struct udcf_softc	*sc = xsc;
672	int			 actlen;
673	unsigned char		 data;
674
675	if (sc->sc_dying)
676		return;
677
678	if (usbd_do_request_flags(sc->sc_udev, &sc->sc_req, &data,
679	    USBD_SHORT_XFER_OK, &actlen, USBD_DEFAULT_TIMEOUT)) {
680		/* This happens if we pull the receiver */
681		DPRINTF(("clocktype detection failed\n"));
682		return;
683	}
684
685	sc->sc_clocktype = data & 0x01 ? 0 : 1;
686	DPRINTF(("\nclocktype is %s\n", sc->sc_clocktype ?
687		clockname[CLOCK_HBG] : clockname[CLOCK_DCF77]));
688}
689
690int
691udcf_activate(device_ptr_t self, enum devact act)
692{
693	struct udcf_softc *sc = (struct udcf_softc *)self;
694
695	switch (act) {
696	case DVACT_ACTIVATE:
697		break;
698	case DVACT_DEACTIVATE:
699		sc->sc_dying = 1;
700		break;
701	}
702	return (0);
703}
704