Skip to content

Handle HID OUT reports with no report ID #7806

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 7 additions & 10 deletions ports/atmel-samd/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -104,24 +104,21 @@ else
CFLAGS += -DNDEBUG

# Do a default shrink for small builds, including all SAMD21 builds.
ifeq ($(CIRCUITPY_FULL_BUILD),0)
SHRINK_BUILD = 1
else
ifeq ($(CHIP_FAMILY), samd21)
SHRINK_BUILD = 1
endif
endif

# -finline-limit can shrink the image size.
# -finline-limit=80 or so is similar to not having it on.
# There is no simple default value, though.
ifeq ($(SHRINK_BUILD), 1)
ifeq ($(CIRCUITPY_FULL_BUILD),0)
CFLAGS += -finline-limit=45
else
ifeq ($(CHIP_FAMILY), samd21)
# max-inline-insns-auto increases the size of SAMD51 builds.
CFLAGS += -finline-limit=45 --param max-inline-insns-auto=110
endif
endif

# We used to do this but it seems to not reduce space any more, at least in gcc 11.
# Leave it here, commented out, just for reference.
# --param inline-unit-growth=15 --param max-inline-insns-auto=20
# --param inline-unit-growth=15

ifdef CFLAGS_BOARD
CFLAGS += $(CFLAGS_BOARD)
Expand Down
44 changes: 30 additions & 14 deletions shared-module/usb_hid/Device.c
Original file line number Diff line number Diff line change
Expand Up @@ -293,24 +293,40 @@ uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t
// Callback invoked when we receive Set_Report request through control endpoint
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) {
(void)itf;
if (report_type == HID_REPORT_TYPE_INVALID) {
report_id = buffer[0];
buffer++;
bufsize--;

usb_hid_device_obj_t *hid_device = NULL;
size_t id_idx;

if (report_id == 0 && report_type == HID_REPORT_TYPE_INVALID) {
// This could be a report with a non-zero report ID in the first byte, or
// it could be for report ID 0.
// Heuristic: see if there's a device with report ID 0, and if its report length matches
// the size of the incoming buffer. In that case, assume the first byte is not the report ID,
// but is data. Otherwise use the first byte as the report id.
if (usb_hid_get_device_with_report_id(0, &hid_device, &id_idx) &&
hid_device &&
hid_device->out_report_buffers[id_idx] &&
hid_device->out_report_lengths[id_idx] == bufsize) {
// Use as is, with report_id 0.
} else {
// No matching report ID 0, so use the first byte as the report ID.
report_id = buffer[0];
buffer++;
bufsize--;
}
} else if (report_type != HID_REPORT_TYPE_OUTPUT && report_type != HID_REPORT_TYPE_FEATURE) {
return;
}

usb_hid_device_obj_t *hid_device;
size_t id_idx;
// Find device with this report id, and get the report id index.
if (usb_hid_get_device_with_report_id(report_id, &hid_device, &id_idx)) {
// report_id might be changed due to parsing above, so test again.
if ((report_id == 0 && report_type == HID_REPORT_TYPE_INVALID) ||
// Fetch the matching device if we don't already have the report_id 0 device.
(usb_hid_get_device_with_report_id(report_id, &hid_device, &id_idx) &&
hid_device &&
hid_device->out_report_buffers[id_idx] &&
hid_device->out_report_lengths[id_idx] == bufsize)) {
// If a report of the correct size has been read, save it in the proper OUT report buffer.
if (hid_device &&
hid_device->out_report_buffers[id_idx] &&
hid_device->out_report_lengths[id_idx] >= bufsize) {
memcpy(hid_device->out_report_buffers[id_idx], buffer, bufsize);
hid_device->out_report_buffers_updated[id_idx] = true;
}
memcpy(hid_device->out_report_buffers[id_idx], buffer, bufsize);
hid_device->out_report_buffers_updated[id_idx] = true;
}
}