Skip to content

Commit d289329

Browse files
committed
Handle HID OUT reports with no report ID
1 parent 31f46f2 commit d289329

File tree

1 file changed

+30
-14
lines changed

1 file changed

+30
-14
lines changed

shared-module/usb_hid/Device.c

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -293,24 +293,40 @@ uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t
293293
// Callback invoked when we receive Set_Report request through control endpoint
294294
void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const *buffer, uint16_t bufsize) {
295295
(void)itf;
296-
if (report_type == HID_REPORT_TYPE_INVALID) {
297-
report_id = buffer[0];
298-
buffer++;
299-
bufsize--;
296+
297+
usb_hid_device_obj_t *hid_device = NULL;
298+
size_t id_idx;
299+
300+
if (report_id == 0 && report_type == HID_REPORT_TYPE_INVALID) {
301+
// This could be a report with a non-zero report ID in the first byte, or
302+
// it could be for report ID 0.
303+
// Heuristic: see if there's a device with report ID 0, and if its report length matches
304+
// the size of the incoming buffer. In that case, assume the first byte is not the report ID,
305+
// but is data. Otherwise use the first byte as the report id.
306+
if (usb_hid_get_device_with_report_id(0, &hid_device, &id_idx) &&
307+
hid_device &&
308+
hid_device->out_report_buffers[id_idx] &&
309+
hid_device->out_report_lengths[id_idx] == bufsize) {
310+
// Use as is, with report_id 0.
311+
} else {
312+
// No matching report ID 0, so use the first byte as the report ID.
313+
report_id = buffer[0];
314+
buffer++;
315+
bufsize--;
316+
}
300317
} else if (report_type != HID_REPORT_TYPE_OUTPUT && report_type != HID_REPORT_TYPE_FEATURE) {
301318
return;
302319
}
303320

304-
usb_hid_device_obj_t *hid_device;
305-
size_t id_idx;
306-
// Find device with this report id, and get the report id index.
307-
if (usb_hid_get_device_with_report_id(report_id, &hid_device, &id_idx)) {
321+
// report_id might be changed due to parsing above, so test again.
322+
if ((report_id == 0 && report_type == HID_REPORT_TYPE_INVALID) ||
323+
// Fetch the matching device if we don't already have the report_id 0 device.
324+
(usb_hid_get_device_with_report_id(report_id, &hid_device, &id_idx) &&
325+
hid_device &&
326+
hid_device->out_report_buffers[id_idx] &&
327+
hid_device->out_report_lengths[id_idx] == bufsize)) {
308328
// If a report of the correct size has been read, save it in the proper OUT report buffer.
309-
if (hid_device &&
310-
hid_device->out_report_buffers[id_idx] &&
311-
hid_device->out_report_lengths[id_idx] >= bufsize) {
312-
memcpy(hid_device->out_report_buffers[id_idx], buffer, bufsize);
313-
hid_device->out_report_buffers_updated[id_idx] = true;
314-
}
329+
memcpy(hid_device->out_report_buffers[id_idx], buffer, bufsize);
330+
hid_device->out_report_buffers_updated[id_idx] = true;
315331
}
316332
}

0 commit comments

Comments
 (0)