Skip to content

Commit 4f57cac

Browse files
glikelyJiri Kosina
authored andcommitted
HID: input: Fix devices that return multiple bytes in battery report
Some devices, particularly the 3DConnexion Spacemouse wireless 3D controllers, return more than just the battery capacity in the battery report. The Spacemouse devices return an additional byte with a device specific field. However, hidinput_query_battery_capacity() only requests a 2 byte transfer. When a spacemouse is connected via USB (direct wire, no wireless dongle) and it returns a 3 byte report instead of the assumed 2 byte battery report the larger transfer confuses and frightens the USB subsystem which chooses to ignore the transfer. Then after 2 seconds assume the device has stopped responding and reset it. This can be reproduced easily by using a wired connection with a wireless spacemouse. The Spacemouse will enter a loop of resetting every 2 seconds which can be observed in dmesg. This patch solves the problem by increasing the transfer request to 4 bytes instead of 2. The fix isn't particularly elegant, but it is simple and safe to backport to stable kernels. A further patch will follow to more elegantly handle battery reports that contain additional data. Signed-off-by: Grant Likely <[email protected]> Cc: Darren Hart <[email protected]> Cc: Jiri Kosina <[email protected]> Cc: Benjamin Tissoires <[email protected]> Cc: [email protected] Tested-by: Darren Hart <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent 1ad273d commit 4f57cac

File tree

1 file changed

+3
-3
lines changed

1 file changed

+3
-3
lines changed

drivers/hid/hid-input.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -350,13 +350,13 @@ static int hidinput_query_battery_capacity(struct hid_device *dev)
350350
u8 *buf;
351351
int ret;
352352

353-
buf = kmalloc(2, GFP_KERNEL);
353+
buf = kmalloc(4, GFP_KERNEL);
354354
if (!buf)
355355
return -ENOMEM;
356356

357-
ret = hid_hw_raw_request(dev, dev->battery_report_id, buf, 2,
357+
ret = hid_hw_raw_request(dev, dev->battery_report_id, buf, 4,
358358
dev->battery_report_type, HID_REQ_GET_REPORT);
359-
if (ret != 2) {
359+
if (ret < 2) {
360360
kfree(buf);
361361
return -ENODATA;
362362
}

0 commit comments

Comments
 (0)