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