aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/iicbus
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/iicbus')
-rw-r--r--sys/dev/iicbus/iicbb.c7
-rw-r--r--sys/dev/iicbus/iichid.c30
2 files changed, 23 insertions, 14 deletions
diff --git a/sys/dev/iicbus/iicbb.c b/sys/dev/iicbus/iicbb.c
index c344bda930b0..5f6423135f46 100644
--- a/sys/dev/iicbus/iicbb.c
+++ b/sys/dev/iicbus/iicbb.c
@@ -331,7 +331,7 @@ iicbb_getack(device_t dev)
{
struct iicbb_softc *sc = device_get_softc(dev);
int noack, err;
- int t;
+ int t = 0;
/* Release SDA so that the slave can drive it. */
err = iicbb_clockin(dev, 1);
@@ -341,12 +341,13 @@ iicbb_getack(device_t dev)
}
/* Sample SDA until ACK (low) or udelay runs out. */
- for (t = 0; t < sc->udelay; t++) {
+ do {
noack = I2C_GETSDA(dev);
if (!noack)
break;
DELAY(1);
- }
+ t++;
+ } while(t < sc->udelay);
DELAY(sc->udelay - t);
iicbb_clockout(dev);
diff --git a/sys/dev/iicbus/iichid.c b/sys/dev/iicbus/iichid.c
index 3f1d7a0cefba..430066bd8f52 100644
--- a/sys/dev/iicbus/iichid.c
+++ b/sys/dev/iicbus/iichid.c
@@ -271,6 +271,8 @@ static int
iichid_cmd_read(struct iichid_softc* sc, void *buf, iichid_size_t maxlen,
iichid_size_t *actual_len)
{
+ int error;
+
/*
* 6.1.3 - Retrieval of Input Reports
* DEVICE returns the length (2 Bytes) and the entire Input Report.
@@ -280,7 +282,10 @@ iichid_cmd_read(struct iichid_softc* sc, void *buf, iichid_size_t maxlen,
struct iic_msg msgs[] = {
{ sc->addr, IIC_M_RD, maxlen, buf },
};
- int error;
+
+ if (!sc->reset_acked) {
+ msgs[0].len = 2;
+ }
error = iicbus_transfer(sc->dev, msgs, nitems(msgs));
if (error != 0)
@@ -540,7 +545,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 +612,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 +821,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 +837,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 +867,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 +1099,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);
}