On Tue, Jun 30, 2015 at 11:23:07AM +0100, Raf Czlonka wrote:
> On Tue, Jun 30, 2015 at 09:40:14AM BST, Joerg Jung wrote:
> > On Mon, Jun 29, 2015 at 09:50:19PM +0100, Raf Czlonka wrote:
> > > >Synopsis:        uthum(4) - TEMPerHUM sensors not available through 
> > > >sysctl(8)
> > > >Category:        system kernel
> > > >Environment:
> > >   System      : OpenBSD 5.8
> > >   Details     : OpenBSD 5.8-beta (GENERIC) #952: Thu Jun 25 21:33:40 MDT 
> > > 2015
> > >                    
> > > [email protected]:/usr/src/sys/arch/i386/compile/GENERIC
> > > 
> > >   Architecture: OpenBSD.i386
> > >   Machine     : i386
> > > >Description:
> > >     Recently, I have acquired a USB temperature and humidity sensor
> > >     - TEMPerHUM. I had picked this one since it is listed as one of
> > >     devices supported by the uthum(4) driver, which itself is actually
> > >     named after the device in question, so it seems.
> > > 
> > >     However, neither the temperature nor humidity sensors are available
> > >     through the sysctl(8) interface.
> > 
> > Your device is not detected/attached to uthum(4).
> > 
> > Because, currently uthum(4) only supports
> > idVendor:idProduct=0x0c45:0x7401 (LM75) based devices.
> > 
> > Your *newer* device 0x0c45:0x7402 (AFAIK Si7005 chip) really is an
> > (unsupported) ugold(4) variant.
> 
> I did check the ugold(4) man page but since the driver only supports
> one device, and I wanted a hygrometer as well, I went with a uthum(4)
> supported one... or so I thought.
> 
> > I bought a similar device and prepared a diff a while ago for ugold(4).
> > Once I find some time I will polish the diff and post it here for 
> > testing.
> 
> I'll keep an eye out.

Can you try the diff below please? Building kernel with this should make
your device working, attaching as ugold(4) and providing the hygrometer
values as well.

Thanks,
Regards,
Joerg


Index: sys/dev/usb/ugold.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/ugold.c,v
retrieving revision 1.7
diff -u -p -r1.7 ugold.c
--- sys/dev/usb/ugold.c 11 Dec 2014 18:39:27 -0000      1.7
+++ sys/dev/usb/ugold.c 4 Jul 2015 15:04:54 -0000
@@ -3,6 +3,7 @@
 /*
  * Copyright (c) 2013 Takayoshi SASANO <[email protected]>
  * Copyright (c) 2013 Martin Pieuchot <[email protected]>
+ * Copyright (c) 2015 Joerg Jung <[email protected]>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -17,7 +18,10 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* Driver for Microdia's HID base TEMPer Temperature sensor */
+/*
+ * Driver for Microdia's HID base TEMPer and TEMPerHUM temperature and
+ * humididty sensors
+ */
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -34,8 +38,10 @@
 #include <dev/usb/uhidev.h>
 #include <dev/usb/hid.h>
 
-#define UGOLD_INNER            0
-#define UGOLD_OUTER            1
+#define UGOLD_TEMPER_INNER     0
+#define UGOLD_TEMPER_OUTER     1
+#define UGOLD_TEMPERHUM_TEMP   0
+#define UGOLD_TEMPERHUM_HUM    1
 #define UGOLD_MAX_SENSORS      2
 
 #define UGOLD_CMD_DATA         0x80
@@ -76,13 +82,15 @@ struct ugold_softc {
 
 const struct usb_devno ugold_devs[] = {
        { USB_VENDOR_MICRODIA, USB_PRODUCT_MICRODIA_TEMPER },
+       { USB_VENDOR_MICRODIA, USB_PRODUCT_MICRODIA_TEMPERHUM },
 };
 
 int    ugold_match(struct device *, void *, void *);
 void   ugold_attach(struct device *, struct device *, void *);
 int    ugold_detach(struct device *, int);
 
-void   ugold_intr(struct uhidev *, void *, u_int);
+void   ugold_ds75_intr(struct uhidev *, void *, u_int);
+void   ugold_si7005_intr(struct uhidev *, void *, u_int);
 void   ugold_refresh(void *);
 
 int    ugold_issue_cmd(struct ugold_softc *, uint8_t *, int);
@@ -132,9 +140,16 @@ ugold_attach(struct device *parent, stru
        void *desc;
 
        sc->sc_udev = uha->parent->sc_udev;
-       sc->sc_hdev.sc_intr = ugold_intr;
        sc->sc_hdev.sc_parent = uha->parent;
        sc->sc_hdev.sc_report_id = uha->reportid;
+       switch (uha->uaa->product) {
+       case USB_PRODUCT_MICRODIA_TEMPER:
+               sc->sc_hdev.sc_intr = ugold_ds75_intr;
+               break;
+       case USB_PRODUCT_MICRODIA_TEMPERHUM:
+               sc->sc_hdev.sc_intr = ugold_si7005_intr;
+               break;
+       }
 
        uhidev_get_report_desc(uha->parent, &desc, &size);
        repid = uha->reportid;
@@ -150,13 +165,26 @@ ugold_attach(struct device *parent, stru
        strlcpy(sc->sc_sensordev.xname, sc->sc_hdev.sc_dev.dv_xname,
            sizeof(sc->sc_sensordev.xname));
 
-       sc->sc_sensor[UGOLD_OUTER].type = SENSOR_TEMP;
-       strlcpy(sc->sc_sensor[UGOLD_OUTER].desc, "outer",
-           sizeof(sc->sc_sensor[UGOLD_OUTER].desc));
-
-       sc->sc_sensor[UGOLD_INNER].type = SENSOR_TEMP;
-       strlcpy(sc->sc_sensor[UGOLD_INNER].desc, "inner",
-           sizeof(sc->sc_sensor[UGOLD_INNER].desc));
+       switch (uha->uaa->product) {
+       case USB_PRODUCT_MICRODIA_TEMPER:
+               /* 2 temperature sensors */
+               sc->sc_sensor[UGOLD_TEMPER_INNER].type = SENSOR_TEMP;
+               strlcpy(sc->sc_sensor[UGOLD_TEMPER_INNER].desc, "inner",
+                   sizeof(sc->sc_sensor[UGOLD_TEMPER_INNER].desc));
+               sc->sc_sensor[UGOLD_TEMPER_OUTER].type = SENSOR_TEMP;
+               strlcpy(sc->sc_sensor[UGOLD_TEMPER_OUTER].desc, "outer",
+                   sizeof(sc->sc_sensor[UGOLD_TEMPER_OUTER].desc));
+               break;
+       case USB_PRODUCT_MICRODIA_TEMPERHUM:
+               /* 1 temperature and 1 humidity sensor */
+               sc->sc_sensor[UGOLD_TEMPERHUM_TEMP].type = SENSOR_TEMP;
+               strlcpy(sc->sc_sensor[UGOLD_TEMPERHUM_TEMP].desc, "inner",
+                   sizeof(sc->sc_sensor[UGOLD_TEMPERHUM_TEMP].desc));
+               sc->sc_sensor[UGOLD_TEMPERHUM_HUM].type = SENSOR_HUMIDITY;
+               strlcpy(sc->sc_sensor[UGOLD_TEMPERHUM_HUM].desc, "RH",
+                   sizeof(sc->sc_sensor[UGOLD_TEMPERHUM_HUM].desc));
+               break;
+       }
 
        /* 0.1Hz */
        sc->sc_sensortask = sensor_task_register(sc, ugold_refresh, 6);
@@ -192,12 +220,12 @@ ugold_detach(struct device *self, int fl
 static int
 ugold_ds75_temp(uint8_t msb, uint8_t lsb)
 {
-       /* DS75: 12bit precision mode : 0.0625 degrees Celsius ticks */
+       /* DS75 12bit precision mode: 0.0625 degrees Celsius ticks */
        return (((msb * 100) + ((lsb >> 4) * 25 / 4)) * 10000) + 273150000;
 }
 
 void
-ugold_intr(struct uhidev *addr, void *ibuf, u_int len)
+ugold_ds75_intr(struct uhidev *addr, void *ibuf, u_int len)
 {
        struct ugold_softc *sc = (struct ugold_softc *)addr;
        uint8_t *buf = ibuf;
@@ -223,18 +251,96 @@ ugold_intr(struct uhidev *addr, void *ib
                switch (buf[1]) {
                case 4:
                        temp = ugold_ds75_temp(buf[4], buf[5]);
-                       sc->sc_sensor[UGOLD_OUTER].value = temp;
-                       sc->sc_sensor[UGOLD_OUTER].flags &= ~SENSOR_FINVALID;
+                       sc->sc_sensor[UGOLD_TEMPER_OUTER].value = temp;
+                       sc->sc_sensor[UGOLD_TEMPER_OUTER].flags &= 
~SENSOR_FINVALID;
                        /* FALLTHROUGH */
                case 2:
                        temp = ugold_ds75_temp(buf[2], buf[3]);
-                       sc->sc_sensor[UGOLD_INNER].value = temp;
-                       sc->sc_sensor[UGOLD_INNER].flags &= ~SENSOR_FINVALID;
+                       sc->sc_sensor[UGOLD_TEMPER_INNER].value = temp;
+                       sc->sc_sensor[UGOLD_TEMPER_INNER].flags &= 
~SENSOR_FINVALID;
                        break;
                default:
                        printf("%s: invalid data length (%d bytes)\n",
                                sc->sc_hdev.sc_dev.dv_xname, buf[1]);
                }
+               break;
+       default:
+               printf("%s: unknown command 0x%02x\n",
+                   sc->sc_hdev.sc_dev.dv_xname, buf[0]);
+       }
+}
+
+static int
+ugold_si7005_temp(uint8_t msb, uint8_t lsb)
+{
+       int temp = (msb * 256 + lsb); /* 14bit si7005 (data sheet sec 5.1.2) */
+
+       /* convert to mdegC: 32 codes per degC with 0x0000 = -50 degC */
+       return ((temp * 1000) / 32) - (50 * 1000);
+}
+
+static int
+ugold_si7005_rhum(uint8_t msb, uint8_t lsb, int temp)
+{
+       int rhc, rhl, rht, hum = (msb * 256 + lsb); /* 12bit si7005 (data sheet 
sec 5.1.1) */
+
+       /* convert to m%RH: 16 codes per %RH, with 0x0000 = -24%RH */
+       rhc = ((hum * 1000) / 16) - (24 * 1000);
+
+       /* linearization with coefficients a0 a1 a2 (data sheet sec 4.3) */
+#define UGOLD_SI7005_SC        16384    /* scalar */
+#define UGOLD_SI7005_A0        (-78388) /* -4.7844  * scalar */
+#define UGOLD_SI7005_A1        6567     /*  0.4008  * scalar */
+#define UGOLD_SI7005_A2        (-64)    /* -0.00393 * scalar */
+       rhl = (rhc * UGOLD_SI7005_SC - (rhc * rhc * UGOLD_SI7005_A2)/1000 - 
+           rhc * UGOLD_SI7005_A1 - UGOLD_SI7005_A0 * 1000) / UGOLD_SI7005_SC;
+
+       /* temperature compensation with coefficients q0 q1 (data sheet sec 
4.4) */
+#define UGOLD_SI7005_Q0        3233     /*  0.1973  * scalar */
+#define UGOLD_SI7005_Q1        39       /*  0.00237 * scalar */
+       rht = (rhl * UGOLD_SI7005_SC + (temp - 30000) *
+           ((rhl * UGOLD_SI7005_Q1) / 1000 + UGOLD_SI7005_Q0)) / 
UGOLD_SI7005_SC;
+
+       /* limit the humidity to valid values */
+       if (rht < 0)
+               rht = 0;
+       else if (rht > 100000)
+               rht = 100000;
+        return rht;
+}
+
+void
+ugold_si7005_intr(struct uhidev *addr, void *ibuf, u_int len)
+{
+       struct ugold_softc *sc = (struct ugold_softc *)addr;
+       uint8_t *buf = ibuf;
+       int i, temp, rhum;
+
+       switch (buf[0]) {
+       case UGOLD_CMD_INIT:
+               if (sc->sc_num_sensors)
+                       break;
+
+               sc->sc_num_sensors = min(buf[1], UGOLD_MAX_SENSORS) /* XXX */;
+
+               for (i = 0; i < sc->sc_num_sensors; i++) {
+                       sc->sc_sensor[i].flags |= SENSOR_FINVALID;
+                       sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
+               }
+               printf("%s: %d sensor%s type si7005 (temperature and 
humidity)\n",
+                   sc->sc_hdev.sc_dev.dv_xname, sc->sc_num_sensors,
+                   (sc->sc_num_sensors == 1) ? "" : "s");
+               break;
+       case UGOLD_CMD_DATA:
+               if (buf[1] != 4)
+                       printf("%s: invalid data length (%d bytes)\n",
+                           sc->sc_hdev.sc_dev.dv_xname, buf[1]);
+               temp = ugold_si7005_temp(buf[2], buf[3]);
+               sc->sc_sensor[UGOLD_TEMPERHUM_TEMP].value = (temp * 1000) + 
273150000;
+               sc->sc_sensor[UGOLD_TEMPERHUM_TEMP].flags &= ~SENSOR_FINVALID;
+               rhum = ugold_si7005_rhum(buf[4], buf[5], temp);
+               sc->sc_sensor[UGOLD_TEMPERHUM_HUM].value = rhum;
+               sc->sc_sensor[UGOLD_TEMPERHUM_HUM].flags &= ~SENSOR_FINVALID;
                break;
        default:
                printf("%s: unknown command 0x%02x\n",
Index: sys/dev/usb/usbdevs
===================================================================
RCS file: /cvs/src/sys/dev/usb/usbdevs,v
retrieving revision 1.652
diff -u -p -r1.652 usbdevs
--- sys/dev/usb/usbdevs 24 Jun 2015 11:31:04 -0000      1.652
+++ sys/dev/usb/usbdevs 4 Jul 2015 15:04:56 -0000
@@ -2965,6 +2965,7 @@ product MSI BLUETOOTH_3           0xa97a  Bluetoot
 product MICRODIA YUREX         0x1010  YUREX
 product MICRODIA CAM_1         0x62c0  CAM_1
 product MICRODIA TEMPER                0x7401  TEMPer sensor
+product MICRODIA TEMPERHUM     0x7402  TEMPerHUM sensor
 
 /* Micronet Communications products */
 product MICRONET SP128AR       0x0003  SP128AR EtherFast
Index: sys/dev/usb/usbdevs.h
===================================================================
RCS file: /cvs/src/sys/dev/usb/usbdevs.h,v
retrieving revision 1.664
diff -u -p -r1.664 usbdevs.h
--- sys/dev/usb/usbdevs.h       24 Jun 2015 11:31:49 -0000      1.664
+++ sys/dev/usb/usbdevs.h       4 Jul 2015 15:04:57 -0000
@@ -1,4 +1,4 @@
-/*     $OpenBSD: usbdevs.h,v 1.664 2015/06/24 11:31:49 mpi Exp $       */
+/*     $OpenBSD$       */
 
 /*
  * THIS FILE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
@@ -2972,6 +2972,7 @@
 #define        USB_PRODUCT_MICRODIA_YUREX      0x1010          /* YUREX */
 #define        USB_PRODUCT_MICRODIA_CAM_1      0x62c0          /* CAM_1 */
 #define        USB_PRODUCT_MICRODIA_TEMPER     0x7401          /* TEMPer 
sensor */
+#define        USB_PRODUCT_MICRODIA_TEMPERHUM  0x7402          /* TEMPerHUM 
sensor */
 
 /* Micronet Communications products */
 #define        USB_PRODUCT_MICRONET_SP128AR    0x0003          /* SP128AR 
EtherFast */
Index: sys/dev/usb/usbdevs_data.h
===================================================================
RCS file: /cvs/src/sys/dev/usb/usbdevs_data.h,v
retrieving revision 1.658
diff -u -p -r1.658 usbdevs_data.h
--- sys/dev/usb/usbdevs_data.h  24 Jun 2015 11:31:49 -0000      1.658
+++ sys/dev/usb/usbdevs_data.h  4 Jul 2015 15:04:58 -0000
@@ -1,4 +1,4 @@
-/*     $OpenBSD: usbdevs_data.h,v 1.658 2015/06/24 11:31:49 mpi Exp $  */
+/*     $OpenBSD$       */
 
 /*
  * THIS FILE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
@@ -7152,6 +7152,10 @@ const struct usb_known_product usb_known
        {
            USB_VENDOR_MICRODIA, USB_PRODUCT_MICRODIA_TEMPER,
            "TEMPer sensor",
+       },
+       {
+           USB_VENDOR_MICRODIA, USB_PRODUCT_MICRODIA_TEMPERHUM,
+           "TEMPerHUM sensor",
        },
        {
            USB_VENDOR_MICRONET, USB_PRODUCT_MICRONET_SP128AR,

Reply via email to