root/dev/usb/udcf.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. udcf_match
  2. udcf_attach
  3. udcf_detach
  4. udcf_intr
  5. udcf_bv_intr
  6. udcf_mg_intr
  7. udcf_sl_intr
  8. udcf_it_intr
  9. udcf_ct_intr
  10. udcf_probe
  11. udcf_bv_probe
  12. udcf_mg_probe
  13. udcf_sl_probe
  14. udcf_it_probe
  15. udcf_ct_probe
  16. udcf_activate

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

/* [<][>][^][v][top][bottom][index][help] */