Skip to content

Commit a5e5e03

Browse files
dtorJiri Kosina
authored andcommitted
HID: i2c-hid: fix GET/SET_REPORT for unnumbered reports
Internally kernel prepends all report buffers, for both numbered and unnumbered reports, with report ID, therefore to properly handle unnumbered reports we should prepend it ourselves. For the same reason we should skip the first byte of the buffer when calling i2c_hid_set_or_send_report() which then will take care of properly formatting the transfer buffer based on its separate report ID argument along with report payload. [jkosina@suse.cz: finalize trimmed sentence in changelog as spotted by Benjamin] Fixes: 9b5a9ae ("HID: i2c-hid: implement ll_driver transport-layer callbacks") Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> Tested-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
1 parent cf5b2fb commit a5e5e03

1 file changed

Lines changed: 24 additions & 8 deletions

File tree

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

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,17 @@ static int i2c_hid_get_raw_report(struct hid_device *hid,
614614
if (report_type == HID_OUTPUT_REPORT)
615615
return -EINVAL;
616616

617+
/*
618+
* In case of unnumbered reports the response from the device will
619+
* not have the report ID that the upper layers expect, so we need
620+
* to stash it the buffer ourselves and adjust the data size.
621+
*/
622+
if (!report_number) {
623+
buf[0] = 0;
624+
buf++;
625+
count--;
626+
}
627+
617628
/* +2 bytes to include the size of the reply in the query buffer */
618629
ask_count = min(count + 2, (size_t)ihid->bufsize);
619630

@@ -635,6 +646,9 @@ static int i2c_hid_get_raw_report(struct hid_device *hid,
635646
count = min(count, ret_count - 2);
636647
memcpy(buf, ihid->rawbuf + 2, count);
637648

649+
if (!report_number)
650+
count++;
651+
638652
return count;
639653
}
640654

@@ -651,17 +665,19 @@ static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf,
651665

652666
mutex_lock(&ihid->reset_lock);
653667

654-
if (report_id) {
655-
buf++;
656-
count--;
657-
}
658-
668+
/*
669+
* Note that both numbered and unnumbered reports passed here
670+
* are supposed to have report ID stored in the 1st byte of the
671+
* buffer, so we strip it off unconditionally before passing payload
672+
* to i2c_hid_set_or_send_report which takes care of encoding
673+
* everything properly.
674+
*/
659675
ret = i2c_hid_set_or_send_report(client,
660676
report_type == HID_FEATURE_REPORT ? 0x03 : 0x02,
661-
report_id, buf, count, use_data);
677+
report_id, buf + 1, count - 1, use_data);
662678

663-
if (report_id && ret >= 0)
664-
ret++; /* add report_id to the number of transfered bytes */
679+
if (ret >= 0)
680+
ret++; /* add report_id to the number of transferred bytes */
665681

666682
mutex_unlock(&ihid->reset_lock);
667683

0 commit comments

Comments
 (0)