aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/iicbus/iichid.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/iicbus/iichid.c')
-rw-r--r--sys/dev/iicbus/iichid.c23
1 files changed, 13 insertions, 10 deletions
diff --git a/sys/dev/iicbus/iichid.c b/sys/dev/iicbus/iichid.c
index 3f1d7a0cefba..5ca3f1b84e48 100644
--- a/sys/dev/iicbus/iichid.c
+++ b/sys/dev/iicbus/iichid.c
@@ -540,7 +540,7 @@ iichid_sampling_task(void *context, int pending)
error = iichid_cmd_read(sc, sc->intr_buf, sc->intr_bufsize, &actual);
if (error == 0) {
if (actual > 0) {
- sc->intr_handler(sc->intr_ctx, sc->intr_buf + 2, actual);
+ sc->intr_handler(sc->intr_ctx, sc->intr_buf + 2, actual - 2);
sc->missing_samples = 0;
if (sc->dup_size != actual ||
memcmp(sc->dup_buf, sc->intr_buf, actual) != 0) {
@@ -607,7 +607,7 @@ iichid_intr(void *context)
if (sc->power_on && sc->open) {
if (actual != 0)
sc->intr_handler(sc->intr_ctx, sc->intr_buf + 2,
- actual);
+ actual - 2);
else
DPRINTF(sc, "no data received\n");
}
@@ -816,12 +816,13 @@ iichid_intr_setup(device_t dev, device_t child __unused, hid_intr_t intr,
sc = device_get_softc(dev);
/*
- * Do not rely just on wMaxInputLength, as some devices (which?)
- * may set it to a wrong length. Also find the longest input report
- * in report descriptor, and add two for the length field.
+ * Start with wMaxInputLength to follow HID-over-I2C specs. Than if
+ * semi-HID device like ietp(4) requested changing of input buffer
+ * size with report descriptor overloading, find the longest input
+ * report in the descriptor, and add two for the length field.
*/
- rdesc->rdsize = 2 +
- MAX(rdesc->isize, le16toh(sc->desc.wMaxInputLength));
+ rdesc->rdsize = rdesc->rdsize == 0 ?
+ le16toh(sc->desc.wMaxInputLength) - 2 : rdesc->isize;
/* Write and get/set_report sizes are limited by I2C-HID protocol. */
rdesc->grsize = rdesc->srsize = IICHID_SIZE_MAX;
rdesc->wrsize = IICHID_SIZE_MAX;
@@ -831,7 +832,7 @@ iichid_intr_setup(device_t dev, device_t child __unused, hid_intr_t intr,
sc->intr_handler = intr;
sc->intr_ctx = context;
- sc->intr_bufsize = rdesc->rdsize;
+ sc->intr_bufsize = rdesc->rdsize + 2;
sc->intr_buf = realloc(sc->intr_buf, sc->intr_bufsize,
M_DEVBUF, M_WAITOK | M_ZERO);
#ifdef IICHID_SAMPLING
@@ -861,7 +862,8 @@ iichid_intr_start(device_t dev, device_t child __unused)
sc = device_get_softc(dev);
DPRINTF(sc, "iichid device open\n");
- iichid_set_power_state(sc, IICHID_PS_ON, IICHID_PS_NULL);
+ if (!sc->open)
+ iichid_set_power_state(sc, IICHID_PS_ON, IICHID_PS_NULL);
return (0);
}
@@ -1092,7 +1094,8 @@ iichid_probe(device_t dev)
}
if (le16toh(sc->desc.wHIDDescLength) != 30 ||
- le16toh(sc->desc.bcdVersion) != 0x100) {
+ le16toh(sc->desc.bcdVersion) != 0x100 ||
+ le16toh(sc->desc.wMaxInputLength) < 2) {
DPRINTF(sc, "HID descriptor is broken\n");
return (ENXIO);
}