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