#6891·embassy

embassy-usb HID: `RequestHandler` cannot restore Report protocol on USB bus reset

Author: techmech-keebCreated Aug 31, 2026Updated Aug 31, 2026

Summary

The HID class delegates protocol-mode state (Boot/Report) to RequestHandler::get_protocol / set_protocol, but the handler is never notified of a USB bus reset.

HID 1.11 Appendix F.3 requires a Boot Keyboard to return on reset to the non-boot protocol described by its Report descriptor, i.e. Report protocol. Section 7.2.6 separately specifies Report protocol as the initialization default.

Consequently, a handler that accepts SET_PROTOCOL(Boot) and stores the selected mode has no trait-level way to restore Report mode on bus reset: after SET_PROTOCOL(Boot) followed by a bus reset, GET_PROTOCOL still reports Boot. The default handler does not expose the problem because it rejects Boot mode and always reports Report mode.

Environment / versions

  • embassy-usb 0.6.0 (crates.io)
  • main at e4b4ba6 (checked 2026-08-31)

Both have the same behavior.

Details

In both versions, Control::reset() only resets out_report_offset:

rust
fn reset(&mut self) {
    self.out_report_offset.store(0, Ordering::Release);
}

It does not notify request_handler, and RequestHandler exposes no USB bus-reset or reinitialization callback.

At the same time, HID_REQ_SET_PROTOCOL and HID_REQ_GET_PROTOCOL are routed to RequestHandler::set_protocol / get_protocol, so for implementations that support switching modes, the authoritative protocol state has to live on the user side.

The in-tree HID keyboard/mouse examples likewise keep the selected mode in an AtomicU8 accessed by their RequestHandler, so this is not specific to one downstream's storage choice.

Reproduction

  1. Implement RequestHandler with protocol state initially HidProtocolMode::Report.
  2. Accept SET_PROTOCOL(Boot) and store Boot.
  3. Trigger a USB bus reset.
  4. Issue GET_PROTOCOL.

The handler sees steps 2 and 4 but gets no notification for step 3, so it still answers Boot.

Expected behavior

A Boot Keyboard implementation that accepts SET_PROTOCOL(Boot) needs a supported way to observe a USB bus reset and restore Report mode: after the reset, GET_PROTOCOL should answer HidProtocolMode::Report, and application code should be able to see the restored mode when producing input reports.

Possible fixes

  1. Add a default no-op USB bus-reset callback to RequestHandler, invoked from Control::reset(). Existing implementations would not be required to add a method, and handlers that own protocol state could restore it there. This preserves the current ownership model, although compliance would still depend on each handler implementing the callback correctly.
  2. Store the authoritative protocol mode in HID State, similarly to the existing shared out_report_offset: Control updates it on SET_PROTOCOL, resets it to Report in reset(), and answers GET_PROTOCOL from it, while a handle/accessor lets application code select the appropriate report format. Bigger change, and it needs a compatibility plan for the existing RequestHandler::get_protocol.

My preference is option 1 because it preserves the current ownership model and does not require changes to existing implementations. I can open a PR implementing it with a regression test if that direction is acceptable.

Context

I hit this while implementing boot-keyboard SET_PROTOCOL support in a keyboard firmware library (RMK). We currently work around it by storing the protocol mode in shared state that a device-level embassy_usb::Handler::reset() clears. This works, but it couples device-level reset handling to state otherwise managed through the per-interface HID RequestHandler.

Related: #6725 discusses the examples starting in Boot mode instead of the Report-mode initialization default. This issue is narrower: even when a handler starts in Report mode, the HID API provides no way to restore that state after a later USB bus reset. The protocol callbacks themselves were introduced in #4691; this issue concerns the missing reset lifecycle for the state managed through them.