Report ID of zero is a special case handling ID-less reports and in that case we should omit report ID from the payload being sent to the backend. Without this change UHID_DEV_NUMBERED_{FEATURE,OUTPUT}_REPORTS doesn't represent a semantical difference. Cc: David Rheinsberg <david.rheinsberg@xxxxxxxxx> Cc: Jiri Kosina <jikos@xxxxxxxxxx> Cc: Benjamin Tissoires <benjamin.tissoires@xxxxxxxxxx> Cc: linux-input@xxxxxxxxxxxxxxx Cc: linux-kernel@xxxxxxxxxxxxxxx Cc: linux-usb@xxxxxxxxxxxxxxx Signed-off-by: Andrey Smirnov <andrew.smirnov@xxxxxxxxx> --- drivers/hid/uhid.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c index 2a918aeb0af1..7551120215e8 100644 --- a/drivers/hid/uhid.c +++ b/drivers/hid/uhid.c @@ -273,11 +273,11 @@ static int uhid_hid_get_report(struct hid_device *hid, unsigned char rnum, } static int uhid_hid_set_report(struct hid_device *hid, unsigned char rnum, - const u8 *buf, size_t count, u8 rtype) + u8 *buf, size_t count, u8 rtype) { struct uhid_device *uhid = hid->driver_data; struct uhid_event *ev; - int ret; + int ret, skipped_report_id = 0; if (!READ_ONCE(uhid->running) || count > UHID_DATA_MAX) return -EIO; @@ -286,6 +286,15 @@ static int uhid_hid_set_report(struct hid_device *hid, unsigned char rnum, if (!ev) return -ENOMEM; + /* Byte 0 is the report number. Report data starts at byte 1.*/ + buf[0] = rnum; + if (buf[0] == 0x0) { + /* Don't send the Report ID */ + buf++; + count--; + skipped_report_id = 1; + } + ev->type = UHID_SET_REPORT; ev->u.set_report.rnum = rnum; ev->u.set_report.rtype = rtype; @@ -306,7 +315,7 @@ static int uhid_hid_set_report(struct hid_device *hid, unsigned char rnum, if (uhid->report_buf.u.set_report_reply.err) ret = -EIO; else - ret = count; + ret = count + skipped_report_id; unlock: mutex_unlock(&uhid->report_lock); -- 2.34.1