diff --git a/shared-bindings/usb_hid/Device.c b/shared-bindings/usb_hid/Device.c index 66c9c01ad6e..aa8af56a185 100644 --- a/shared-bindings/usb_hid/Device.c +++ b/shared-bindings/usb_hid/Device.c @@ -156,6 +156,10 @@ static mp_obj_t usb_hid_device_make_new(const mp_obj_type_t *type, size_t n_args //| The ``report`` itself will be discarded, to prevent unwanted extraneous characters, //| mouse clicks, etc. //| +//| If the host has put the interface in boot protocol, the boot device sends its report +//| without a report ID, and `send_report()` on any other device discards the report, +//| because the host reads only the boot device. +//| //| Note: Host operating systems allow enabling and disabling specific devices //| and kinds of devices to do wakeup. //| The defaults are different for different operating systems. diff --git a/shared-bindings/usb_hid/__init__.c b/shared-bindings/usb_hid/__init__.c index 47f7f03c493..1bedaf3edf0 100644 --- a/shared-bindings/usb_hid/__init__.c +++ b/shared-bindings/usb_hid/__init__.c @@ -25,6 +25,10 @@ //| the `devices` tuple is **replaced** when ``code.py`` starts with a single-element tuple //| containing a `Device` that describes the boot device chosen (keyboard or mouse). //| The request for a boot device overrides any other HID devices. +//| +//| If the host requests a boot device after ``code.py`` has started, `devices` is not replaced. +//| The boot device then sends reports in the boot format, with no report ID, and +//| `Device.send_report()` on any other device does nothing, because the host ignores it. //| """ //| //| diff --git a/shared-module/usb_hid/Device.c b/shared-module/usb_hid/Device.c index 42f5790123e..ffdda7377dd 100644 --- a/shared-module/usb_hid/Device.c +++ b/shared-module/usb_hid/Device.c @@ -130,6 +130,19 @@ void common_hal_usb_hid_device_send_report(usb_hid_device_obj_t *self, uint8_t * mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("USB busy")); } + if (tud_hid_get_protocol() == HID_PROTOCOL_BOOT) { + // In boot protocol the host reads the fixed boot report, which carries no report ID, + // and ignores every device other than the boot device. + uint8_t boot_device = usb_hid_boot_device(); + if (self->usage_page == HID_USAGE_PAGE_DESKTOP && + ((boot_device == 1 && self->usage == HID_USAGE_DESKTOP_KEYBOARD) || + (boot_device == 2 && self->usage == HID_USAGE_DESKTOP_MOUSE))) { + report_id = 0; + } else { + return; + } + } + if (!tud_hid_report(report_id, report, len)) { mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("USB error")); }