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