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