summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjung <jung@openbsd.org>2015-07-15 08:39:11 +0000
committerjung <jung@openbsd.org>2015-07-15 08:39:11 +0000
commitdd214550654af93b9843fde5495ceae6bd85901b (patch)
treeb07663523856af3930def12724df7dd05d70af30
parentfix NULL-deref when SSH1 reenabled (diff)
downloadwireguard-openbsd-dd214550654af93b9843fde5495ceae6bd85901b.tar.xz
wireguard-openbsd-dd214550654af93b9843fde5495ceae6bd85901b.zip
add support for newer PCsensor TEMPerHUM thermo- and hygrometers:
TEMPerHUM1V1.2 tested by Raf Czlonka via bugs@ and TEMPerHUM1V1.0 tested by myself earlier version tested by sasano, input from mpi@ and deraadt ok mpi@
-rw-r--r--share/man/man4/ugold.432
-rw-r--r--share/man/man4/usb.46
-rw-r--r--sys/dev/usb/ugold.c188
3 files changed, 199 insertions, 27 deletions
diff --git a/share/man/man4/ugold.4 b/share/man/man4/ugold.4
index 22e8193a5e1..291962bf1ec 100644
--- a/share/man/man4/ugold.4
+++ b/share/man/man4/ugold.4
@@ -1,7 +1,8 @@
-.\" $OpenBSD: ugold.4,v 1.1 2013/09/06 08:39:39 mpi Exp $
+.\" $OpenBSD: ugold.4,v 1.2 2015/07/15 08:39:11 jung Exp $
.\"
.\" Copyright (c) 2013 Takayoshi SASANO <sasano@openbsd.org>
.\" Copyright (c) 2013 Martin Pieuchot <mpi@openbsd.org>
+.\" Copyright (c) 2015 Joerg Jung <jung@openbsd.org>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
@@ -15,24 +16,26 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: September 6 2013 $
+.Dd $Mdocdate: July 15 2015 $
.Dt UGOLD 4
.Os
.Sh NAME
.Nm ugold
-.Nd TEMPer gold HID thermometer
+.Nd TEMPer gold HID thermometer and hygrometer
.Sh SYNOPSIS
.Cd "ugold* at uhidev?"
.Sh DESCRIPTION
The
.Nm
-driver provides support for pcsensors TEMPer gold devices.
+driver provides support for PCsensors TEMPer gold devices.
The following devices are supported by the
.Nm
driver:
-.Bl -column "RDing TEMPer1V1.2" "1 Temperature" -offset indent
+.Bl -column "RDing TEMPerHUM1V1.0" "1 Temperature" -offset indent
.It Em "Device" Ta Em "Sensors"
.It Li "RDing TEMPer1V1.2" Ta "1 Temperature"
+.It Li "RDing TEMPerHUM1V1.0" Ta "1 Temperature and 1 Humidity"
+.It Li "RDing TEMPerHUM1V1.2" Ta "1 Temperature and 1 Humidity"
.El
.Pp
The driver possesses a collection of sensor values which are
@@ -44,3 +47,22 @@ interface.
.Xr uhidev 4 ,
.Xr sensorsd 8 ,
.Xr sysctl 8
+.Sh HISTORY
+The
+.Nm
+driver first appeared in
+.Ox 5.5 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+driver was written by
+.An Takayoshi SASANO Aq Mt uaa@openbsd.org
+and
+.An Martin Pieuchot Aq Mt mpi@openbsd.org .
+.Pp
+TEMPerHUM support was added by
+.An Joerg Jung Aq Mt jung@openbsd.org .
+.Sh CAVEATS
+Linearization and temperature compensation for the humidity values of the
+TEMPerHUM1V1.0 is not implemented.
diff --git a/share/man/man4/usb.4 b/share/man/man4/usb.4
index 8101080d872..94f9fcd09ea 100644
--- a/share/man/man4/usb.4
+++ b/share/man/man4/usb.4
@@ -1,4 +1,4 @@
-.\" $OpenBSD: usb.4,v 1.167 2015/05/04 14:30:06 jmc Exp $
+.\" $OpenBSD: usb.4,v 1.168 2015/07/15 08:39:11 jung Exp $
.\" $NetBSD: usb.4,v 1.15 1999/07/29 14:20:32 augustss Exp $
.\"
.\" Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -28,7 +28,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd $Mdocdate: May 4 2015 $
+.Dd $Mdocdate: July 15 2015 $
.Dt USB 4
.Os
.Sh NAME
@@ -284,7 +284,7 @@ USB generic device support
.It Xr ugl 4
Genesys Logic based host-to-host adapters
.It Xr ugold 4
-TEMPer gold HID thermometer
+TEMPer gold HID thermometer and hygrometer
.It Xr uow 4
Maxim/Dallas DS2490 USB 1-Wire adapter
.It Xr upl 4
diff --git a/sys/dev/usb/ugold.c b/sys/dev/usb/ugold.c
index 21c55b0a428..9f4ab2d72bf 100644
--- a/sys/dev/usb/ugold.c
+++ b/sys/dev/usb/ugold.c
@@ -1,8 +1,9 @@
-/* $OpenBSD: ugold.c,v 1.7 2014/12/11 18:39:27 mpi Exp $ */
+/* $OpenBSD: ugold.c,v 1.8 2015/07/15 08:39:11 jung Exp $ */
/*
* Copyright (c) 2013 Takayoshi SASANO <sasano@openbsd.org>
* Copyright (c) 2013 Martin Pieuchot <mpi@openbsd.org>
+ * Copyright (c) 2015 Joerg Jung <jung@openbsd.org>
*
* 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
+ * humidity sensors
+ */
#include <sys/param.h>
#include <sys/systm.h>
@@ -36,14 +40,18 @@
#define UGOLD_INNER 0
#define UGOLD_OUTER 1
+#define UGOLD_HUM 1
#define UGOLD_MAX_SENSORS 2
#define UGOLD_CMD_DATA 0x80
#define UGOLD_CMD_INIT 0x82
+#define UGOLD_TYPE_SI7005 1
+#define UGOLD_TYPE_SI7006 2
+
/*
- * This driver only uses two of the three known commands for the
- * TEMPerV1.2 device.
+ * This driver uses three known commands for the TEMPer and TEMPerHUM
+ * devices.
*
* The first byte of the answer corresponds to the command and the
* second one seems to be the size (in bytes) of the answer.
@@ -53,21 +61,20 @@
* is why most of the time the last n bytes of the answers are the
* same.
*
- * The third command below seems to generate two answers with a
+ * The type command below seems to generate two answers with a
* string corresponding to the device, for example:
* 'TEMPer1F' and '1.1Per1F' (here Per1F is repeated).
*/
static uint8_t cmd_data[8] = { 0x01, 0x80, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00 };
static uint8_t cmd_init[8] = { 0x01, 0x82, 0x77, 0x01, 0x00, 0x00, 0x00, 0x00 };
-#if 0
static uint8_t cmd_type[8] = { 0x01, 0x86, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00 };
-#endif
struct ugold_softc {
struct uhidev sc_hdev;
struct usbd_device *sc_udev;
int sc_num_sensors;
+ int sc_type;
struct ksensor sc_sensor[UGOLD_MAX_SENSORS];
struct ksensordev sc_sensordev;
@@ -76,13 +83,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_si700x_intr(struct uhidev *, void *, u_int);
void ugold_refresh(void *);
int ugold_issue_cmd(struct ugold_softc *, uint8_t *, int);
@@ -132,9 +141,19 @@ ugold_attach(struct device *parent, struct device *self, void *aux)
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_si700x_intr;
+ break;
+ default:
+ printf(", unknown product\n");
+ return;
+ }
uhidev_get_report_desc(uha->parent, &desc, &size);
repid = uha->reportid;
@@ -150,13 +169,29 @@ ugold_attach(struct device *parent, struct device *self, void *aux)
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_INNER].type = SENSOR_TEMP;
+ strlcpy(sc->sc_sensor[UGOLD_INNER].desc, "inner",
+ sizeof(sc->sc_sensor[UGOLD_INNER].desc));
+ sc->sc_sensor[UGOLD_OUTER].type = SENSOR_TEMP;
+ strlcpy(sc->sc_sensor[UGOLD_OUTER].desc, "outer",
+ sizeof(sc->sc_sensor[UGOLD_OUTER].desc));
+ break;
+ case USB_PRODUCT_MICRODIA_TEMPERHUM:
+ /* 1 temperature and 1 humidity sensor */
+ sc->sc_sensor[UGOLD_INNER].type = SENSOR_TEMP;
+ strlcpy(sc->sc_sensor[UGOLD_INNER].desc, "inner",
+ sizeof(sc->sc_sensor[UGOLD_INNER].desc));
+ sc->sc_sensor[UGOLD_HUM].type = SENSOR_HUMIDITY;
+ strlcpy(sc->sc_sensor[UGOLD_HUM].desc, "RH",
+ sizeof(sc->sc_sensor[UGOLD_HUM].desc));
+ break;
+ default:
+ printf(", unknown product\n");
+ return;
+ }
/* 0.1Hz */
sc->sc_sensortask = sensor_task_register(sc, ugold_refresh, 6);
@@ -192,12 +227,12 @@ ugold_detach(struct device *self, int flags)
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;
@@ -237,6 +272,115 @@ ugold_intr(struct uhidev *addr, void *ibuf, u_int len)
}
break;
default:
+ if (!sc->sc_type) {
+ sc->sc_type = -1; /* ignore type */
+ break;
+ }
+ printf("%s: unknown command 0x%02x\n",
+ sc->sc_hdev.sc_dev.dv_xname, buf[0]);
+ }
+}
+
+static int
+ugold_si700x_temp(int type, uint8_t msb, uint8_t lsb)
+{
+ int temp = msb * 256 + lsb;
+
+ switch (type) { /* convert to mdegC */
+ case UGOLD_TYPE_SI7005: /* 14bit 32 codes per degC 0x0000 = -50 degC */
+ temp = (((temp & 0x3fff) * 1000) / 32) - 50000;
+ break;
+ case UGOLD_TYPE_SI7006: /* 14bit and status bit */
+ temp = (((temp & ~3) * 21965) / 8192) - 46850;
+ break;
+ default:
+ temp = 0;
+ }
+ return temp;
+}
+
+static int
+ugold_si700x_rhum(int type, uint8_t msb, uint8_t lsb, int temp)
+{
+ int rhum = msb * 256 + lsb;
+
+ switch (type) { /* convert to m%RH */
+ case UGOLD_TYPE_SI7005: /* 12bit 16 codes per %RH 0x0000 = -24 %RH */
+ rhum = (((rhum & 0x0fff) * 1000) / 16) - 24000;
+#if 0 /* todo: linearization and temperature compensation */
+ rhum -= -0.00393 * rhum * rhum + 0.4008 * rhum - 4.7844;
+ rhum += (temp - 30) * (0.00237 * rhum + 0.1973);
+#endif
+ break;
+ case UGOLD_TYPE_SI7006: /* 14bit and status bit */
+ rhum = (((rhum & ~3) * 15625) / 8192) - 6000;
+ break;
+ default:
+ rhum = 0;
+ }
+
+ /* limit the humidity to valid values */
+ if (rhum < 0)
+ rhum = 0;
+ else if (rhum > 100000)
+ rhum = 100000;
+ return rhum;
+}
+
+static void
+ugold_si700x_type(struct ugold_softc *sc, uint8_t *buf, u_int len)
+{
+ if (memcmp(buf, "TEMPerHu", len) == 0)
+ return; /* skip equal first half of the answer */
+
+ printf("%s: %d sensor%s type ", sc->sc_hdev.sc_dev.dv_xname,
+ sc->sc_num_sensors, (sc->sc_num_sensors == 1) ? "" : "s");
+
+ if (memcmp(buf, "mM12V1.0", len) == 0) {
+ sc->sc_type = UGOLD_TYPE_SI7005;
+ printf("si7005 (temperature and humidity)\n");
+ } else if (memcmp(buf, "mM12V1.2", len) == 0) {
+ sc->sc_type = UGOLD_TYPE_SI7006;
+ printf("si7006 (temperature and humidity)\n");
+ } else
+ printf("unknown\n");
+}
+
+void
+ugold_si700x_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]);
+ }
+ 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_si700x_temp(sc->sc_type, buf[2], buf[3]);
+ sc->sc_sensor[UGOLD_INNER].value = (temp * 1000) + 273150000;
+ sc->sc_sensor[UGOLD_INNER].flags &= ~SENSOR_FINVALID;
+ rhum = ugold_si700x_rhum(sc->sc_type, buf[4], buf[5], temp);
+ sc->sc_sensor[UGOLD_HUM].value = rhum;
+ sc->sc_sensor[UGOLD_HUM].flags &= ~SENSOR_FINVALID;
+ break;
+ default:
+ if (!sc->sc_type) { /* type command returns arbitrary string */
+ ugold_si700x_type(sc, buf, len);
+ break;
+ }
printf("%s: unknown command 0x%02x\n",
sc->sc_hdev.sc_dev.dv_xname, buf[0]);
}
@@ -248,8 +392,14 @@ ugold_refresh(void *arg)
struct ugold_softc *sc = arg;
int i;
- if (sc->sc_num_sensors == 0)
+ if (!sc->sc_num_sensors) {
ugold_issue_cmd(sc, cmd_init, sizeof(cmd_init));
+ return;
+ }
+ if (!sc->sc_type) {
+ ugold_issue_cmd(sc, cmd_type, sizeof(cmd_type));
+ return;
+ }
if (ugold_issue_cmd(sc, cmd_data, sizeof(cmd_data))) {
for (i = 0; i < sc->sc_num_sensors; i++)