From a4231932a2a00640a018620b5f4d38fd20919ef1 Mon Sep 17 00:00:00 2001 From: Adamaq01 Date: Sun, 12 Jan 2025 02:27:55 +0100 Subject: [PATCH] embassy-usb: add string descriptor support for hid class --- embassy-usb/src/class/hid.rs | 16 ++++++++++++++-- examples/nrf52840/src/bin/usb_hid_keyboard.rs | 1 + examples/nrf52840/src/bin/usb_hid_mouse.rs | 1 + examples/rp/src/bin/usb_hid_keyboard.rs | 1 + examples/rp/src/bin/usb_hid_mouse.rs | 1 + examples/rp23/src/bin/usb_hid_keyboard.rs | 1 + examples/stm32f4/src/bin/usb_hid_keyboard.rs | 1 + examples/stm32f4/src/bin/usb_hid_mouse.rs | 1 + examples/stm32l5/src/bin/usb_hid_mouse.rs | 1 + 9 files changed, 22 insertions(+), 2 deletions(-) diff --git a/embassy-usb/src/class/hid.rs b/embassy-usb/src/class/hid.rs index 6d9e0aceda..4fc14369fc 100644 --- a/embassy-usb/src/class/hid.rs +++ b/embassy-usb/src/class/hid.rs @@ -11,7 +11,7 @@ use usbd_hid::descriptor::AsInputReport; use crate::control::{InResponse, OutResponse, Recipient, Request, RequestType}; use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut}; -use crate::types::InterfaceNumber; +use crate::types::{InterfaceNumber, StringIndex}; use crate::{Builder, Handler}; const USB_CLASS_HID: u8 = 0x03; @@ -36,6 +36,9 @@ pub struct Config<'d> { /// HID report descriptor. pub report_descriptor: &'d [u8], + /// Optional string descriptor for the HID interface. + pub string_descriptor: Option<&'d str>, + /// Handler for control requests. pub request_handler: Option<&'d mut dyn RequestHandler>, @@ -112,7 +115,8 @@ fn build<'d, D: Driver<'d>>( let mut func = builder.function(USB_CLASS_HID, USB_SUBCLASS_NONE, USB_PROTOCOL_NONE); let mut iface = func.interface(); let if_num = iface.interface_number(); - let mut alt = iface.alt_setting(USB_CLASS_HID, USB_SUBCLASS_NONE, USB_PROTOCOL_NONE, None); + let string_index = config.string_descriptor.map(|_| iface.string()); + let mut alt = iface.alt_setting(USB_CLASS_HID, USB_SUBCLASS_NONE, USB_PROTOCOL_NONE, string_index); // HID descriptor alt.descriptor( @@ -145,6 +149,7 @@ fn build<'d, D: Driver<'d>>( let control = state.control.write(Control::new( if_num, config.report_descriptor, + string_index.zip(config.string_descriptor), config.request_handler, &state.out_report_offset, )); @@ -411,6 +416,7 @@ pub trait RequestHandler { struct Control<'d> { if_num: InterfaceNumber, report_descriptor: &'d [u8], + string_descriptor: Option<(StringIndex, &'d str)>, request_handler: Option<&'d mut dyn RequestHandler>, out_report_offset: &'d AtomicUsize, hid_descriptor: [u8; 9], @@ -420,12 +426,14 @@ impl<'d> Control<'d> { fn new( if_num: InterfaceNumber, report_descriptor: &'d [u8], + string_descriptor: Option<(StringIndex, &'d str)>, request_handler: Option<&'d mut dyn RequestHandler>, out_report_offset: &'d AtomicUsize, ) -> Self { Control { if_num, report_descriptor, + string_descriptor, request_handler, out_report_offset, hid_descriptor: [ @@ -549,4 +557,8 @@ impl<'d> Handler for Control<'d> { _ => None, } } + + fn get_string(&mut self, index: StringIndex, _lang_id: u16) -> Option<&str> { + self.string_descriptor.and_then(|(idx, s)| (index == idx).then_some(s)) + } } diff --git a/examples/nrf52840/src/bin/usb_hid_keyboard.rs b/examples/nrf52840/src/bin/usb_hid_keyboard.rs index 5a9dc90a21..507ac97997 100644 --- a/examples/nrf52840/src/bin/usb_hid_keyboard.rs +++ b/examples/nrf52840/src/bin/usb_hid_keyboard.rs @@ -71,6 +71,7 @@ async fn main(_spawner: Spawner) { // Create classes on the builder. let config = embassy_usb::class::hid::Config { report_descriptor: KeyboardReport::desc(), + string_descriptor: None, request_handler: None, poll_ms: 60, max_packet_size: 64, diff --git a/examples/nrf52840/src/bin/usb_hid_mouse.rs b/examples/nrf52840/src/bin/usb_hid_mouse.rs index 80cda70e31..b760fddf10 100644 --- a/examples/nrf52840/src/bin/usb_hid_mouse.rs +++ b/examples/nrf52840/src/bin/usb_hid_mouse.rs @@ -60,6 +60,7 @@ async fn main(_spawner: Spawner) { // Create classes on the builder. let config = embassy_usb::class::hid::Config { report_descriptor: MouseReport::desc(), + string_descriptor: None, request_handler: Some(&mut request_handler), poll_ms: 60, max_packet_size: 8, diff --git a/examples/rp/src/bin/usb_hid_keyboard.rs b/examples/rp/src/bin/usb_hid_keyboard.rs index a7cb322d80..b8172f9a2e 100644 --- a/examples/rp/src/bin/usb_hid_keyboard.rs +++ b/examples/rp/src/bin/usb_hid_keyboard.rs @@ -60,6 +60,7 @@ async fn main(_spawner: Spawner) { // Create classes on the builder. let config = embassy_usb::class::hid::Config { report_descriptor: KeyboardReport::desc(), + string_descriptor: None, request_handler: None, poll_ms: 60, max_packet_size: 64, diff --git a/examples/rp/src/bin/usb_hid_mouse.rs b/examples/rp/src/bin/usb_hid_mouse.rs index 5ee6509100..088507bec4 100644 --- a/examples/rp/src/bin/usb_hid_mouse.rs +++ b/examples/rp/src/bin/usb_hid_mouse.rs @@ -62,6 +62,7 @@ async fn main(_spawner: Spawner) { // Create classes on the builder. let config = embassy_usb::class::hid::Config { report_descriptor: MouseReport::desc(), + string_descriptor: None, request_handler: None, poll_ms: 60, max_packet_size: 64, diff --git a/examples/rp23/src/bin/usb_hid_keyboard.rs b/examples/rp23/src/bin/usb_hid_keyboard.rs index ec1e88746e..03f3c74acb 100644 --- a/examples/rp23/src/bin/usb_hid_keyboard.rs +++ b/examples/rp23/src/bin/usb_hid_keyboard.rs @@ -65,6 +65,7 @@ async fn main(_spawner: Spawner) { // Create classes on the builder. let config = embassy_usb::class::hid::Config { report_descriptor: KeyboardReport::desc(), + string_descriptor: None, request_handler: None, poll_ms: 60, max_packet_size: 64, diff --git a/examples/stm32f4/src/bin/usb_hid_keyboard.rs b/examples/stm32f4/src/bin/usb_hid_keyboard.rs index d6b4a9bc94..db24e52671 100644 --- a/examples/stm32f4/src/bin/usb_hid_keyboard.rs +++ b/examples/stm32f4/src/bin/usb_hid_keyboard.rs @@ -98,6 +98,7 @@ async fn main(_spawner: Spawner) { // Create classes on the builder. let config = embassy_usb::class::hid::Config { report_descriptor: KeyboardReport::desc(), + string_descriptor: None, request_handler: None, poll_ms: 60, max_packet_size: 8, diff --git a/examples/stm32f4/src/bin/usb_hid_mouse.rs b/examples/stm32f4/src/bin/usb_hid_mouse.rs index badb65e986..66d8522672 100644 --- a/examples/stm32f4/src/bin/usb_hid_mouse.rs +++ b/examples/stm32f4/src/bin/usb_hid_mouse.rs @@ -88,6 +88,7 @@ async fn main(_spawner: Spawner) { // Create classes on the builder. let config = embassy_usb::class::hid::Config { report_descriptor: MouseReport::desc(), + string_descriptor: None, request_handler: Some(&mut request_handler), poll_ms: 60, max_packet_size: 8, diff --git a/examples/stm32l5/src/bin/usb_hid_mouse.rs b/examples/stm32l5/src/bin/usb_hid_mouse.rs index 3f8c52b825..9a8ec03720 100644 --- a/examples/stm32l5/src/bin/usb_hid_mouse.rs +++ b/examples/stm32l5/src/bin/usb_hid_mouse.rs @@ -70,6 +70,7 @@ async fn main(_spawner: Spawner) { // Create classes on the builder. let config = embassy_usb::class::hid::Config { report_descriptor: MouseReport::desc(), + string_descriptor: None, request_handler: Some(&mut request_handler), poll_ms: 60, max_packet_size: 8,