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