Skip to content

Commit af93a16

Browse files
jwrdegoedeJiri Kosina
authored andcommitted
HID: i2c-hid: Move i2c_hid_finish_hwreset() to after reading the report-descriptor
A recent bug made me look at Microsoft's i2c-hid docs again and I noticed the following: """ 4. Issue a RESET (Host Initiated Reset) to the Device. 5. Retrieve report descriptor from the device. Note: Steps 4 and 5 may be done in parallel to optimize for time on I²C. Since report descriptors are (a) static and (b) quite long, Windows 8 may issue a request for 5 while it is waiting for a response from the device on 4. """ Which made me think that maybe on some touchpads the reset ack is delayed till after the report descriptor is read ? Testing a T-BAO Tbook Air 12.5 with a 0911:5288 (SIPODEV SP1064?) touchpad, for which the I2C_HID_QUIRK_NO_IRQ_AFTER_RESET quirk was first introduced, shows that reading the report descriptor before waiting for the reset helps with the missing reset IRQ. Now the reset does get acked properly, but the ack sometimes still does not happen unfortunately. Still moving the wait for ack to after reading the report-descriptor, is probably a good idea, both to make i2c-hid's behavior closer to Windows as well as to speed up probing i2c-hid devices. While at it drop the dbg_hid() for a malloc failure, malloc failures already get logged extensively by malloc itself. Link: https://bugzilla.redhat.com/show_bug.cgi?id=2247751 Signed-off-by: Hans de Goede <[email protected]> Reviewed-by: Douglas Anderson <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent aa69d69 commit af93a16

File tree

1 file changed

+19
-10
lines changed

1 file changed

+19
-10
lines changed

drivers/hid/i2c-hid/i2c-hid-core.c

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -725,11 +725,10 @@ static int i2c_hid_parse(struct hid_device *hid)
725725
struct i2c_client *client = hid->driver_data;
726726
struct i2c_hid *ihid = i2c_get_clientdata(client);
727727
struct i2c_hid_desc *hdesc = &ihid->hdesc;
728+
char *rdesc = NULL, *use_override = NULL;
728729
unsigned int rsize;
729-
char *rdesc;
730730
int ret;
731731
int tries = 3;
732-
char *use_override;
733732

734733
i2c_hid_dbg(ihid, "entering %s\n", __func__);
735734

@@ -739,18 +738,15 @@ static int i2c_hid_parse(struct hid_device *hid)
739738
return -EINVAL;
740739
}
741740

741+
mutex_lock(&ihid->reset_lock);
742742
do {
743-
mutex_lock(&ihid->reset_lock);
744743
ret = i2c_hid_start_hwreset(ihid);
745-
if (ret == 0)
746-
ret = i2c_hid_finish_hwreset(ihid);
747-
mutex_unlock(&ihid->reset_lock);
748744
if (ret)
749745
msleep(1000);
750746
} while (tries-- > 0 && ret);
751747

752748
if (ret)
753-
return ret;
749+
goto abort_reset;
754750

755751
use_override = i2c_hid_get_dmi_hid_report_desc_override(client->name,
756752
&rsize);
@@ -762,8 +758,8 @@ static int i2c_hid_parse(struct hid_device *hid)
762758
rdesc = kzalloc(rsize, GFP_KERNEL);
763759

764760
if (!rdesc) {
765-
dbg_hid("couldn't allocate rdesc memory\n");
766-
return -ENOMEM;
761+
ret = -ENOMEM;
762+
goto abort_reset;
767763
}
768764

769765
i2c_hid_dbg(ihid, "asking HID report descriptor\n");
@@ -773,10 +769,23 @@ static int i2c_hid_parse(struct hid_device *hid)
773769
rdesc, rsize);
774770
if (ret) {
775771
hid_err(hid, "reading report descriptor failed\n");
776-
goto out;
772+
goto abort_reset;
777773
}
778774
}
779775

776+
/*
777+
* Windows directly reads the report-descriptor after sending reset
778+
* and then waits for resets completion afterwards. Some touchpads
779+
* actually wait for the report-descriptor to be read before signalling
780+
* reset completion.
781+
*/
782+
ret = i2c_hid_finish_hwreset(ihid);
783+
abort_reset:
784+
clear_bit(I2C_HID_RESET_PENDING, &ihid->flags);
785+
mutex_unlock(&ihid->reset_lock);
786+
if (ret)
787+
goto out;
788+
780789
i2c_hid_dbg(ihid, "Report Descriptor: %*ph\n", rsize, rdesc);
781790

782791
ret = hid_parse_report(hid, rdesc, rsize);

0 commit comments

Comments
 (0)