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