udcf.c revision 1.7
1/* $OpenBSD: udcf.c,v 1.7 2006/05/27 18:22:04 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/clock_subr.h> 33#include <dev/usb/usb.h> 34#include <dev/usb/usbdi.h> 35#include <dev/usb/usbdi_util.h> 36#include <dev/usb/usbdevs.h> 37 38#ifdef UDCF_DEBUG 39#define DPRINTFN(n, x) do { if (udcfdebug > (n)) printf x; } while (0) 40int udcfdebug = 0; 41#else 42#define DPRINTFN(n, x) 43#endif 44#define DPRINTF(x) DPRINTFN(0, x) 45 46#define UDCF_READ_REQ 0xc0 47#define UDCF_READ_IDX 0x1f 48 49#define UDCF_CTRL_REQ 0x40 50#define UDCF_CTRL_IDX 0x33 51#define UDCF_CTRL_VAL 0x98 52 53#define DPERIOD ((long) 15 * 60) /* degrade period, 15 min */ 54 55#define CLOCK_DCF77 0 56#define CLOCK_HBG 1 57 58static const char *clockname[2] = { 59 "DCF77", 60 "HBG" }; 61 62struct udcf_softc { 63 USBBASEDEVICE sc_dev; /* base device */ 64 usbd_device_handle sc_udev; /* USB device */ 65 usbd_interface_handle sc_iface; /* data interface */ 66 u_char sc_dying; /* disconnecting */ 67 68 struct timeout sc_to; 69 struct usb_task sc_task; 70 71 struct timeout sc_bv_to; /* bit-value detect */ 72 struct timeout sc_db_to; /* debounce */ 73 struct timeout sc_mg_to; /* minute-gap detect */ 74 struct timeout sc_sl_to; /* signal-loss detect */ 75 struct timeout sc_it_to; /* invalidate time */ 76 struct timeout sc_ct_to; /* detect clock type */ 77 struct usb_task sc_bv_task; 78 struct usb_task sc_mg_task; 79 struct usb_task sc_sl_task; 80 struct usb_task sc_it_task; 81 struct usb_task sc_ct_task; 82 83 usb_device_request_t sc_req; 84 85 int sc_clocktype; /* DCF77 or HBG */ 86 int sc_sync; /* 1 during sync to DCF77 */ 87 u_int64_t sc_mask; /* 64 bit mask */ 88 u_int64_t sc_tbits; /* Time bits */ 89 int sc_minute; 90 int sc_level; 91 time_t sc_last_mg; 92 93 time_t sc_current; /* current time information */ 94 time_t sc_next; /* time to become valid next */ 95 96 struct sensor sc_sensor; 97}; 98 99static int t1, t2, t3, t4, t5, t6, t7, t8; /* timeouts in hz */ 100static int t9; 101 102void udcf_intr(void *); 103void udcf_probe(void *); 104 105void udcf_bv_intr(void *); 106void udcf_mg_intr(void *); 107void udcf_sl_intr(void *); 108void udcf_it_intr(void *); 109void udcf_ct_intr(void *); 110void udcf_bv_probe(void *); 111void udcf_mg_probe(void *); 112void udcf_sl_probe(void *); 113void udcf_it_probe(void *); 114void udcf_ct_probe(void *); 115 116USB_DECLARE_DRIVER(udcf); 117 118USB_MATCH(udcf) 119{ 120 USB_MATCH_START(udcf, uaa); 121 122 if (uaa->iface != NULL) 123 return (UMATCH_NONE); 124 125 return uaa->vendor == USB_VENDOR_GUDE && 126 uaa->product == USB_PRODUCT_GUDE_DCF ? 127 UMATCH_VENDOR_PRODUCT : UMATCH_NONE; 128} 129 130USB_ATTACH(udcf) 131{ 132 USB_ATTACH_START(udcf, sc, uaa); 133 usbd_device_handle dev = uaa->device; 134 usbd_interface_handle iface; 135 struct timeval t; 136 char *devinfop; 137 usb_interface_descriptor_t *id; 138#ifdef UDCF_DEBUG 139 char *devname = USBDEVNAME(sc->sc_dev); 140#endif 141 usbd_status err; 142 usb_device_request_t req; 143 uWord result; 144 int actlen; 145 146 if ((err = usbd_set_config_index(dev, 0, 1))) { 147 DPRINTF(("\n%s: failed to set configuration, err=%s\n", 148 devname, usbd_errstr(err))); 149 goto fishy; 150 } 151 152 if ((err = usbd_device2interface_handle(dev, 0, &iface))) { 153 DPRINTF(("\n%s: failed to get interface, err=%s\n", 154 devname, usbd_errstr(err))); 155 goto fishy; 156 } 157 158 devinfop = usbd_devinfo_alloc(dev, 0); 159 USB_ATTACH_SETUP; 160 printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfop); 161 usbd_devinfo_free(devinfop); 162 163 id = usbd_get_interface_descriptor(iface); 164 165 sc->sc_udev = dev; 166 sc->sc_iface = iface; 167 168 sc->sc_clocktype = -1; 169 sc->sc_level = 0; 170 sc->sc_minute = 0; 171 sc->sc_last_mg = 0L; 172 173 sc->sc_sync = 1; 174 175 sc->sc_current = 0L; 176 sc->sc_next = 0L; 177 178 strlcpy(sc->sc_sensor.device, USBDEVNAME(sc->sc_dev), 179 sizeof(sc->sc_sensor.device)); 180 sc->sc_sensor.type = SENSOR_TIMEDELTA; 181 sc->sc_sensor.status = SENSOR_S_UNKNOWN; 182 sc->sc_sensor.flags = SENSOR_FINVALID; 183 sensor_add(&sc->sc_sensor); 184 185 /* Prepare the USB request to probe the value */ 186 187 sc->sc_req.bmRequestType = UDCF_READ_REQ; 188 sc->sc_req.bRequest = 1; 189 USETW(sc->sc_req.wValue, 0); 190 USETW(sc->sc_req.wIndex, UDCF_READ_IDX); 191 USETW(sc->sc_req.wLength, 1); 192 193 req.bmRequestType = UDCF_CTRL_REQ; 194 req.bRequest = 0; 195 USETW(req.wValue, 0); 196 USETW(req.wIndex, 0); 197 USETW(req.wLength, 0); 198 if ((err = usbd_do_request_flags(sc->sc_udev, &req, &result, 199 USBD_SHORT_XFER_OK, &actlen, USBD_DEFAULT_TIMEOUT))) { 200 DPRINTF(("failed to turn on power for receiver\n")); 201 goto fishy; 202 } 203 204 req.bmRequestType = UDCF_CTRL_REQ; 205 req.bRequest = 0; 206 USETW(req.wValue, UDCF_CTRL_VAL); 207 USETW(req.wIndex, UDCF_CTRL_IDX); 208 USETW(req.wLength, 0); 209 if ((err = usbd_do_request_flags(sc->sc_udev, &req, &result, 210 USBD_SHORT_XFER_OK, &actlen, USBD_DEFAULT_TIMEOUT))) { 211 DPRINTF(("failed to turn on receiver\n")); 212 goto fishy; 213 } 214 215 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, 216 USBDEV(sc->sc_dev)); 217 218 usb_init_task(&sc->sc_task, udcf_probe, sc); 219 usb_init_task(&sc->sc_bv_task, udcf_bv_probe, sc); 220 usb_init_task(&sc->sc_mg_task, udcf_mg_probe, sc); 221 usb_init_task(&sc->sc_sl_task, udcf_sl_probe, sc); 222 usb_init_task(&sc->sc_it_task, udcf_it_probe, sc); 223 usb_init_task(&sc->sc_ct_task, udcf_ct_probe, sc); 224 225 timeout_set(&sc->sc_to, udcf_intr, sc); 226 timeout_set(&sc->sc_bv_to, udcf_bv_intr, sc); 227 timeout_set(&sc->sc_mg_to, udcf_mg_intr, sc); 228 timeout_set(&sc->sc_sl_to, udcf_sl_intr, sc); 229 timeout_set(&sc->sc_it_to, udcf_it_intr, sc); 230 timeout_set(&sc->sc_ct_to, udcf_ct_intr, sc); 231 232 /* convert timevals to hz */ 233 234 t.tv_sec = 0L; 235 t.tv_usec = 150000L; 236 t1 = tvtohz(&t); 237 238 t.tv_usec = 450000L; 239 t4 = tvtohz(&t); 240 241 t.tv_usec = 900000L; 242 t7 = tvtohz(&t); 243 244 t.tv_sec = 1L; 245 t.tv_usec = 500000L; 246 t2 = tvtohz(&t); 247 248 t.tv_sec = 3L; 249 t.tv_usec = 0L; 250 t3 = tvtohz(&t); 251 252 t.tv_sec = 5L; 253 t5 = tvtohz(&t); 254 255 t.tv_sec = 8L; 256 t6 = tvtohz(&t); 257 258 t.tv_sec = DPERIOD; 259 t8 = tvtohz(&t); 260 261 t.tv_sec = 0L; 262 t.tv_usec = 250000L; 263 t9 = tvtohz(&t); 264 265 /* Give the receiver some slack to stabilize */ 266 timeout_add(&sc->sc_to, t3); 267 268 /* Detect signal loss in 5 sec */ 269 timeout_add(&sc->sc_sl_to, t5); 270 271 DPRINTF(("synchronizing\n")); 272 USB_ATTACH_SUCCESS_RETURN; 273 274fishy: 275 DPRINTF(("udcf_attach failed\n")); 276 sc->sc_dying = 1; 277 USB_ATTACH_ERROR_RETURN; 278} 279 280USB_DETACH(udcf) 281{ 282 struct udcf_softc *sc = (struct udcf_softc *)self; 283 284 sc->sc_dying = 1; 285 286 timeout_del(&sc->sc_to); 287 timeout_del(&sc->sc_bv_to); 288 timeout_del(&sc->sc_mg_to); 289 timeout_del(&sc->sc_sl_to); 290 timeout_del(&sc->sc_it_to); 291 timeout_del(&sc->sc_ct_to); 292 293 /* Unregister the clock with the kernel */ 294 295 if (sc->sc_sensor.status != SENSOR_S_UNKNOWN) 296 sensor_del(&sc->sc_sensor); 297 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 usb_rem_task(sc->sc_udev, &sc->sc_it_task); 303 usb_rem_task(sc->sc_udev, &sc->sc_ct_task); 304 305 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, 306 USBDEV(sc->sc_dev)); 307 return (0); 308} 309 310/* udcf_intr runs in an interrupt context */ 311 312void 313udcf_intr(void *xsc) 314{ 315 struct udcf_softc *sc = xsc; 316 usb_add_task(sc->sc_udev, &sc->sc_task); 317} 318 319/* bit value detection */ 320 321void 322udcf_bv_intr(void *xsc) 323{ 324 struct udcf_softc *sc = xsc; 325 usb_add_task(sc->sc_udev, &sc->sc_bv_task); 326} 327 328/* minute gap detection */ 329 330void 331udcf_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 339void 340udcf_sl_intr(void *xsc) 341{ 342 struct udcf_softc *sc = xsc; 343 usb_add_task(sc->sc_udev, &sc->sc_sl_task); 344} 345 346/* degrade the sensor if no new time received for >= DPERIOD seconds. */ 347 348void 349udcf_it_intr(void *xsc) 350{ 351 struct udcf_softc *sc = xsc; 352 usb_add_task(sc->sc_udev, &sc->sc_it_task); 353} 354 355/* detect the cloc type (DCF77 or HBG) */ 356 357void 358udcf_ct_intr(void *xsc) 359{ 360 struct udcf_softc *sc = xsc; 361 usb_add_task(sc->sc_udev, &sc->sc_ct_task); 362} 363 364/* 365 * udcf_probe runs in a process context. If Bit 0 is set, the transmitter 366 * emits at full power. During the low-power emission we decode a zero bit. 367 */ 368 369void 370udcf_probe(void *xsc) 371{ 372 struct udcf_softc *sc = xsc; 373 struct timespec now; 374 unsigned char data; 375 int actlen; 376 377 if (sc->sc_dying) 378 return; 379 380 if (usbd_do_request_flags(sc->sc_udev, &sc->sc_req, &data, 381 USBD_SHORT_XFER_OK, &actlen, USBD_DEFAULT_TIMEOUT)) 382 /* This happens if we pull the receiver */ 383 return; 384 385 if (data & 0x01) { 386 sc->sc_level = 1; 387 timeout_add(&sc->sc_to, 1); 388 } else if (sc->sc_level == 1) { /* Begin of a second */ 389 sc->sc_level = 0; 390 if (sc->sc_minute == 1) { 391 if (sc->sc_sync) { 392 DPRINTF(("synchronized, collecting bits\n")); 393 sc->sc_sync = 0; 394 if (sc->sc_sensor.status == SENSOR_S_UNKNOWN) 395 sc->sc_clocktype = -1; 396 } else { 397 /* provide the time delta */ 398 399 microtime(&sc->sc_sensor.tv); 400 nanotime(&now); 401 sc->sc_current = sc->sc_next; 402 sc->sc_sensor.value = 403 (now.tv_sec - sc->sc_current) 404 * 1000000000 + now.tv_nsec; 405 406 /* set the clocktype and make sensor valid */ 407 408 if (sc->sc_sensor.status == SENSOR_S_UNKNOWN) { 409 strlcpy(sc->sc_sensor.desc, 410 sc->sc_clocktype ? 411 clockname[CLOCK_HBG] : 412 clockname[CLOCK_DCF77], 413 sizeof(sc->sc_sensor.desc)); 414 DPRINTF(("add timedelta sensor for %s\n", 415 sc->sc_sensor.desc)); 416 sc->sc_sensor.flags &= 417 ~SENSOR_FINVALID; 418 } 419 sc->sc_sensor.status = SENSOR_S_OK; 420 421 timeout_del(&sc->sc_it_to); 422 } 423 sc->sc_tbits = 0LL; 424 sc->sc_mask = 1LL; 425 sc->sc_minute = 0; 426 } 427 428 timeout_add(&sc->sc_to, t7); /* Begin resync in 900 ms */ 429 430 /* No clock and bit detection during sync */ 431 if (!sc->sc_sync) { 432 timeout_add(&sc->sc_bv_to, t1); /* bit in 150 ms */ 433 434 /* detect clocktype in 250 ms if not known yet */ 435 436 if (sc->sc_clocktype == -1) 437 timeout_add(&sc->sc_ct_to, t9); 438 } 439 timeout_add(&sc->sc_mg_to, t2); /* minute gap in 1500 ms */ 440 timeout_add(&sc->sc_sl_to, t3); /* signal loss in 3 sec */ 441 } 442} 443 444/* detect the bit value */ 445 446void 447udcf_bv_probe(void *xsc) 448{ 449 struct udcf_softc *sc = xsc; 450 int actlen; 451 unsigned char data; 452 453 if (sc->sc_dying) 454 return; 455 456 if (usbd_do_request_flags(sc->sc_udev, &sc->sc_req, &data, 457 USBD_SHORT_XFER_OK, &actlen, USBD_DEFAULT_TIMEOUT)) { 458 /* This happens if we pull the receiver */ 459 DPRINTF(("bit detection failed\n")); 460 return; 461 } 462 463 DPRINTF((data & 0x01 ? "0" : "1")); 464 if (!(data & 0x01)) 465 sc->sc_tbits |= sc->sc_mask; 466 sc->sc_mask <<= 1; 467} 468 469/* detect the minute gap */ 470 471void 472udcf_mg_probe(void *xsc) 473{ 474 struct udcf_softc *sc = xsc; 475 476 struct clock_ymdhms ymdhm; 477 int minute_bits, hour_bits, day_bits; 478 int month_bits, year_bits, wday; 479 int p1, p2, p3; 480 int p1_bit, p2_bit, p3_bit; 481 int r_bit, a1_bit, a2_bit, z1_bit, z2_bit; 482 int s_bit, m_bit; 483 484 u_int32_t parity = 0x6996; 485 486 if (sc->sc_sync) { 487 timeout_add(&sc->sc_to, t4); /* re-sync in 450 ms */ 488 sc->sc_minute = 1; 489 sc->sc_last_mg = time_second; 490 } else { 491 if (time_second - sc->sc_last_mg < 57) { 492 DPRINTF(("unexpected gap, resync\n")); 493 sc->sc_sync = 1; 494 if (sc->sc_sensor.status == SENSOR_S_OK) { 495 sc->sc_sensor.status = SENSOR_S_WARN; 496 timeout_add(&sc->sc_it_to, t8); 497 } 498 timeout_add(&sc->sc_to, t5); 499 timeout_add(&sc->sc_sl_to, t6); 500 sc->sc_last_mg = 0; 501 } else { 502 /* Extract bits w/o parity */ 503 504 m_bit = sc->sc_tbits & 1; 505 r_bit = sc->sc_tbits >> 15 & 1; 506 a1_bit = sc->sc_tbits >> 16 & 1; 507 z1_bit = sc->sc_tbits >> 17 & 1; 508 z2_bit = sc->sc_tbits >> 18 & 1; 509 a2_bit = sc->sc_tbits >> 19 & 1; 510 s_bit = sc->sc_tbits >> 20 & 1; 511 p1_bit = sc->sc_tbits >> 28 & 1; 512 p2_bit = sc->sc_tbits >> 35 & 1; 513 p3_bit = sc->sc_tbits >> 58 & 1; 514 515 minute_bits = sc->sc_tbits >> 21 & 0x7f; 516 hour_bits = sc->sc_tbits >> 29 & 0x3f; 517 day_bits = sc->sc_tbits >> 36 & 0x3f; 518 wday = (sc->sc_tbits >> 42) & 0x07; 519 month_bits = sc->sc_tbits >> 45 & 0x1f; 520 year_bits = sc->sc_tbits >> 50 & 0xff; 521 522 /* Validate time information */ 523 524 p1 = (parity >> (minute_bits & 0x0f) & 1) ^ 525 (parity >> (minute_bits >> 4) & 1); 526 527 p2 = (parity >> (hour_bits & 0x0f) & 1) ^ 528 (parity >> (hour_bits >> 4) & 1); 529 530 p3 = (parity >> (day_bits & 0x0f) & 1) ^ 531 (parity >> (day_bits >> 4) & 1) ^ 532 ((parity >> wday) & 1) ^ 533 (parity >> (month_bits & 0x0f) & 1) ^ 534 (parity >> (month_bits >> 4) & 1) ^ 535 (parity >> (year_bits & 0x0f) & 1) ^ 536 (parity >> (year_bits >> 4) & 1); 537 538 if (m_bit == 0 && s_bit == 1 && 539 p1 == p1_bit && p2 == p2_bit && 540 p3 == p3_bit && 541 (z1_bit ^ z2_bit)) { 542 543 /* Decode valid time */ 544 545 ymdhm.dt_min = FROMBCD(minute_bits); 546 ymdhm.dt_hour = FROMBCD(hour_bits); 547 ymdhm.dt_day = FROMBCD(day_bits); 548 ymdhm.dt_mon = FROMBCD(month_bits); 549 ymdhm.dt_year = 2000 + FROMBCD(year_bits); 550 ymdhm.dt_sec = 0; 551 552 sc->sc_next = clock_ymdhms_to_secs(&ymdhm); 553 554 /* convert to coordinated universal time */ 555 556 sc->sc_next -= z1_bit ? 7200 : 3600; 557 558 DPRINTF(("\n%02d.%02d.%04d %02d:%02d:00 %s", 559 ymdhm.dt_day, ymdhm.dt_mon + 1, 560 ymdhm.dt_year, ymdhm.dt_hour, 561 ymdhm.dt_min, z1_bit ? "CEST" : "CET")); 562 DPRINTF((r_bit ? ", reserve antenna" : "")); 563 DPRINTF((a1_bit ? ", dst chg ann." : "")); 564 DPRINTF((a2_bit ? ", leap sec ann." : "")); 565 DPRINTF(("\n")); 566 } else { 567 DPRINTF(("parity error, resync\n")); 568 569 if (sc->sc_sensor.status == SENSOR_S_OK) { 570 sc->sc_sensor.status = SENSOR_S_WARN; 571 timeout_add(&sc->sc_it_to, t8); 572 } 573 sc->sc_sync = 1; 574 } 575 timeout_add(&sc->sc_to, t4); /* re-sync in 450 ms */ 576 sc->sc_minute = 1; 577 sc->sc_last_mg = time_second; 578 } 579 } 580} 581 582/* detect signal loss */ 583 584void 585udcf_sl_probe(void *xsc) 586{ 587 struct udcf_softc *sc = xsc; 588 589 if (sc->sc_dying) 590 return; 591 592 DPRINTF(("no signal\n")); 593 sc->sc_sync = 1; 594 if (sc->sc_sensor.status == SENSOR_S_OK) { 595 sc->sc_sensor.status = SENSOR_S_WARN; 596 timeout_add(&sc->sc_it_to, t8); 597 } 598 timeout_add(&sc->sc_to, t5); 599 timeout_add(&sc->sc_sl_to, t6); 600} 601 602/* invalidate time delta */ 603 604void 605udcf_it_probe(void *xsc) 606{ 607 struct udcf_softc *sc = xsc; 608 609 if (sc->sc_dying) 610 return; 611 612 DPRINTF(("\ndegrading sensor to state critical")); 613 614 sc->sc_sensor.status = SENSOR_S_CRIT; 615} 616 617/* detect clock type */ 618 619void 620udcf_ct_probe(void *xsc) 621{ 622 struct udcf_softc *sc = xsc; 623 int actlen; 624 unsigned char data; 625 626 if (sc->sc_dying) 627 return; 628 629 if (usbd_do_request_flags(sc->sc_udev, &sc->sc_req, &data, 630 USBD_SHORT_XFER_OK, &actlen, USBD_DEFAULT_TIMEOUT)) { 631 /* This happens if we pull the receiver */ 632 DPRINTF(("clocktype detection failed\n")); 633 return; 634 } 635 636 sc->sc_clocktype = data & 0x01 ? 0 : 1; 637 DPRINTF(("\nclocktype is %s\n", sc->sc_clocktype ? 638 clockname[CLOCK_HBG] : clockname[CLOCK_DCF77])); 639} 640 641int 642udcf_activate(device_ptr_t self, enum devact act) 643{ 644 struct udcf_softc *sc = (struct udcf_softc *)self; 645 646 switch (act) { 647 case DVACT_ACTIVATE: 648 return (EOPNOTSUPP); 649 650 case DVACT_DEACTIVATE: 651 sc->sc_dying = 1; 652 break; 653 } 654 return (0); 655} 656