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