LCOV - code coverage report
Current view: top level - dev/usb - utrh.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 102 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 7 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: utrh.c,v 1.21 2017/04/08 02:57:25 deraadt Exp $   */
       2             : 
       3             : /*
       4             :  * Copyright (c) 2009 Yojiro UO <yuo@nui.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 DISCAIMS 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             : /* Driver for Strawberry linux USBRH Temerature/Humidity sensor */
      20             : 
      21             : #include <sys/param.h>
      22             : #include <sys/systm.h>
      23             : #include <sys/kernel.h>
      24             : #include <sys/malloc.h>
      25             : #include <sys/device.h>
      26             : #include <sys/conf.h>
      27             : #include <sys/sensors.h>
      28             : 
      29             : #include <dev/usb/usb.h>
      30             : #include <dev/usb/usbhid.h>
      31             : #include <dev/usb/usbdi.h>
      32             : #include <dev/usb/usbdi_util.h>
      33             : #include <dev/usb/usbdevs.h>
      34             : #include <dev/usb/uhidev.h>
      35             : 
      36             : #ifdef UTRH_DEBUG
      37             : #define DPRINTF(x)      do { printf x; } while (0)
      38             : #else
      39             : #define DPRINTF(x)
      40             : #endif
      41             : 
      42             : /* sensors */
      43             : #define UTRH_TEMP               0
      44             : #define UTRH_HUMIDITY           1
      45             : #define UTRH_MAX_SENSORS        2
      46             : 
      47             : struct utrh_softc {
      48             :         struct uhidev            sc_hdev;
      49             :         struct usbd_device      *sc_udev;
      50             : 
      51             :         /* uhidev parameters */
      52             :         size_t                   sc_flen;       /* feature report length */
      53             :         size_t                   sc_ilen;       /* input report length */
      54             :         size_t                   sc_olen;       /* output report length */
      55             : 
      56             :         uint8_t                 *sc_ibuf;
      57             : 
      58             :         /* sensor framework */
      59             :         struct ksensor           sc_sensor[UTRH_MAX_SENSORS];
      60             :         struct ksensordev        sc_sensordev;
      61             :         struct sensor_task      *sc_sensortask;
      62             : 
      63             :         uint8_t                  sc_num_sensors;
      64             : };
      65             : 
      66             : const struct usb_devno utrh_devs[] = {
      67             :         { USB_VENDOR_STRAWBERRYLINUX, USB_PRODUCT_STRAWBERRYLINUX_USBRH},
      68             : };
      69             : 
      70             : int utrh_match(struct device *, void *, void *);
      71             : void utrh_attach(struct device *, struct device *, void *);
      72             : int utrh_detach(struct device *, int);
      73             : 
      74             : int utrh_sht1x_temp(unsigned int);
      75             : int utrh_sht1x_rh(unsigned int, int);
      76             : 
      77             : void utrh_intr(struct uhidev *, void *, u_int);
      78             : void utrh_refresh(void *);
      79             : 
      80             : struct cfdriver utrh_cd = {
      81             :         NULL, "utrh", DV_DULL
      82             : };
      83             : 
      84             : const struct cfattach utrh_ca = {
      85             :         sizeof(struct utrh_softc),
      86             :         utrh_match,
      87             :         utrh_attach,
      88             :         utrh_detach
      89             : };
      90             : 
      91             : int
      92           0 : utrh_match(struct device *parent, void *match, void *aux)
      93             : {
      94           0 :         struct uhidev_attach_arg *uha = aux;
      95             : 
      96           0 :         if (uha->reportid == UHIDEV_CLAIM_ALLREPORTID)
      97           0 :                 return (UMATCH_NONE);
      98             : 
      99           0 :         return (usb_lookup(utrh_devs, uha->uaa->vendor, uha->uaa->product) != NULL ?
     100             :             UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
     101           0 : }
     102             : 
     103             : void
     104           0 : utrh_attach(struct device *parent, struct device *self, void *aux)
     105             : {
     106           0 :         struct utrh_softc *sc = (struct utrh_softc *)self;
     107           0 :         struct usb_attach_arg *uaa = aux;
     108           0 :         struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa;
     109           0 :         struct usbd_device *dev = uha->parent->sc_udev;
     110           0 :         int size, repid, err;
     111           0 :         void *desc;
     112             : 
     113           0 :         sc->sc_udev = dev;
     114           0 :         sc->sc_hdev.sc_intr = utrh_intr;
     115           0 :         sc->sc_hdev.sc_parent = uha->parent;
     116           0 :         sc->sc_hdev.sc_report_id = uha->reportid;
     117           0 :         sc->sc_num_sensors = 0;
     118             : 
     119           0 :         uhidev_get_report_desc(uha->parent, &desc, &size);
     120           0 :         repid = uha->reportid;
     121           0 :         sc->sc_ilen = hid_report_size(desc, size, hid_input, repid);
     122           0 :         sc->sc_olen = hid_report_size(desc, size, hid_output, repid);
     123           0 :         sc->sc_flen = hid_report_size(desc, size, hid_feature, repid);
     124             : 
     125           0 :         err = uhidev_open(&sc->sc_hdev);
     126           0 :         if (err) {
     127           0 :                 printf("utrh_open: uhidev_open %d\n", err);
     128           0 :                 return;
     129             :         }
     130           0 :         sc->sc_ibuf = malloc(sc->sc_ilen, M_USBDEV, M_WAITOK);
     131             : 
     132           0 :         printf("\n");
     133             : 
     134             :         /* attach sensor */
     135           0 :         strlcpy(sc->sc_sensordev.xname, sc->sc_hdev.sc_dev.dv_xname,
     136             :             sizeof(sc->sc_sensordev.xname));
     137             : 
     138           0 :         sc->sc_sensor[UTRH_TEMP].type = SENSOR_TEMP;
     139           0 :         sc->sc_sensor[UTRH_TEMP].flags = SENSOR_FINVALID;
     140             : 
     141           0 :         strlcpy(sc->sc_sensor[UTRH_HUMIDITY].desc, "RH",
     142             :             sizeof(sc->sc_sensor[UTRH_HUMIDITY].desc));
     143           0 :         sc->sc_sensor[UTRH_HUMIDITY].type = SENSOR_HUMIDITY;
     144           0 :         sc->sc_sensor[UTRH_HUMIDITY].flags = SENSOR_FINVALID;
     145             : 
     146           0 :         sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[UTRH_TEMP]);
     147           0 :         sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[UTRH_HUMIDITY]);
     148           0 :         sc->sc_num_sensors = 2;
     149             : 
     150           0 :         if (sc->sc_num_sensors > 0) {
     151           0 :                 sc->sc_sensortask = sensor_task_register(sc, utrh_refresh, 6);
     152           0 :                 if (sc->sc_sensortask == NULL) {
     153           0 :                         printf(", unable to register update task\n");
     154           0 :                         return;
     155             :                 }
     156           0 :                 sensordev_install(&sc->sc_sensordev);
     157           0 :         }
     158             : 
     159             :         DPRINTF(("utrh_attach: complete\n"));
     160           0 : }
     161             : 
     162             : int
     163           0 : utrh_detach(struct device *self, int flags)
     164             : {
     165           0 :         struct utrh_softc *sc = (struct utrh_softc *)self;
     166             :         int i, rv = 0;
     167             : 
     168           0 :         if (sc->sc_num_sensors > 0) {
     169           0 :                 wakeup(&sc->sc_sensortask);
     170           0 :                 sensordev_deinstall(&sc->sc_sensordev);
     171           0 :                 for (i = 0; i < sc->sc_num_sensors; i++)
     172           0 :                         sensor_detach(&sc->sc_sensordev, &sc->sc_sensor[i]);
     173           0 :                 if (sc->sc_sensortask != NULL)
     174           0 :                         sensor_task_unregister(sc->sc_sensortask);
     175             :         }
     176             : 
     177           0 :         if (sc->sc_hdev.sc_state & UHIDEV_OPEN)
     178           0 :                 uhidev_close(&sc->sc_hdev);
     179             : 
     180           0 :         if (sc->sc_ibuf != NULL) {
     181           0 :                 free(sc->sc_ibuf, M_USBDEV, sc->sc_ilen);
     182           0 :                 sc->sc_ibuf = NULL;
     183           0 :         }
     184             : 
     185           0 :         return (rv);
     186             : }
     187             : 
     188             : void
     189           0 : utrh_intr(struct uhidev *addr, void *ibuf, u_int len)
     190             : {
     191           0 :         struct utrh_softc *sc = (struct utrh_softc *)addr;
     192             : 
     193           0 :         if (sc->sc_ibuf == NULL)
     194           0 :                 return;
     195             : 
     196             :         /* receive sensor data */
     197           0 :         memcpy(sc->sc_ibuf, ibuf, len);
     198           0 :         return;
     199           0 : }
     200             : 
     201             : void
     202           0 : utrh_refresh(void *arg)
     203             : {
     204           0 :         struct utrh_softc *sc = arg;
     205             :         unsigned int temp_tick, humidity_tick;
     206             :         int temp, rh;
     207           0 :         uint8_t ledbuf[7];
     208             : 
     209             :         /* turn on LED 1*/
     210           0 :         bzero(ledbuf, sizeof(ledbuf));
     211           0 :         ledbuf[0] = 0x3;
     212           0 :         ledbuf[1] = 0x1;
     213           0 :         if (uhidev_set_report(sc->sc_hdev.sc_parent, UHID_FEATURE_REPORT,
     214           0 :             sc->sc_hdev.sc_report_id, ledbuf, sc->sc_flen) != sc->sc_flen)
     215           0 :                 printf("LED request failed\n");
     216             : 
     217             :         /* issue query */
     218           0 :         uint8_t cmdbuf[] = {0x31, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00};
     219           0 :         if (uhidev_set_report(sc->sc_hdev.sc_parent, UHID_OUTPUT_REPORT,
     220           0 :             sc->sc_hdev.sc_report_id, cmdbuf, sc->sc_olen) != sc->sc_flen)
     221           0 :                 return;
     222             : 
     223             :         /* wait till sensor data are updated, 1s will be enough */
     224           0 :         tsleep(&sc->sc_sensortask, 0, "utrh", (1*hz));
     225             : 
     226             :         /* turn off LED 1 */
     227           0 :         ledbuf[1] = 0x0;
     228           0 :         if (uhidev_set_report(sc->sc_hdev.sc_parent, UHID_FEATURE_REPORT,
     229           0 :             sc->sc_hdev.sc_report_id, ledbuf, sc->sc_flen) != sc->sc_flen)
     230           0 :                 printf("LED request failed\n");
     231             : 
     232           0 :         temp_tick = (sc->sc_ibuf[2] * 256 + sc->sc_ibuf[3]) & 0x3fff;
     233           0 :         humidity_tick = (sc->sc_ibuf[0] * 256 + sc->sc_ibuf[1]) & 0x0fff;
     234             : 
     235           0 :         temp = utrh_sht1x_temp(temp_tick);
     236           0 :         rh = utrh_sht1x_rh(humidity_tick, temp);
     237             : 
     238           0 :         sc->sc_sensor[UTRH_TEMP].value = (temp * 10000) + 273150000;
     239           0 :         sc->sc_sensor[UTRH_TEMP].flags &= ~SENSOR_FINVALID;
     240           0 :         sc->sc_sensor[UTRH_HUMIDITY].value = rh;
     241           0 :         sc->sc_sensor[UTRH_HUMIDITY].flags &= ~SENSOR_FINVALID;
     242           0 : }
     243             : 
     244             : /* return C-degree * 100 value */
     245             : int
     246           0 : utrh_sht1x_temp(unsigned int nticks)
     247             : {
     248           0 :         return (nticks - 4010);
     249             : }
     250             : 
     251             : /* return %RH * 1000 */
     252             : int
     253           0 : utrh_sht1x_rh(unsigned int nticks, int temp)
     254             : {
     255             :         int rh_l, rh;
     256             : 
     257           0 :         rh_l = (-40000 + 405 * nticks) - ((7 * nticks * nticks) / 250);
     258           0 :         rh = ((temp - 2500) * (1 + (nticks >> 7)) + rh_l) / 10;
     259           0 :         return rh;
     260             : }

Generated by: LCOV version 1.13