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