diff options
Diffstat (limited to 'sys/dev/iicbus/iichid.c')
-rw-r--r-- | sys/dev/iicbus/iichid.c | 23 |
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); } |