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