diff options
| -rw-r--r-- | embassy-usb-hid/src/lib.rs | 77 | ||||
| -rw-r--r-- | examples/nrf/src/bin/usb_hid_keyboard.rs | 15 | ||||
| -rw-r--r-- | examples/nrf/src/bin/usb_hid_mouse.rs | 18 |
3 files changed, 49 insertions, 61 deletions
diff --git a/embassy-usb-hid/src/lib.rs b/embassy-usb-hid/src/lib.rs index 1035c2792..abcd6b5d9 100644 --- a/embassy-usb-hid/src/lib.rs +++ b/embassy-usb-hid/src/lib.rs | |||
| @@ -41,6 +41,24 @@ const HID_REQ_SET_REPORT: u8 = 0x09; | |||
| 41 | const HID_REQ_GET_PROTOCOL: u8 = 0x03; | 41 | const HID_REQ_GET_PROTOCOL: u8 = 0x03; |
| 42 | const HID_REQ_SET_PROTOCOL: u8 = 0x0b; | 42 | const HID_REQ_SET_PROTOCOL: u8 = 0x0b; |
| 43 | 43 | ||
| 44 | pub struct Config<'d> { | ||
| 45 | /// HID report descriptor. | ||
| 46 | pub report_descriptor: &'d [u8], | ||
| 47 | |||
| 48 | /// Handler for control requests. | ||
| 49 | pub request_handler: Option<&'d dyn RequestHandler>, | ||
| 50 | |||
| 51 | /// Configures how frequently the host should poll for reading/writing HID reports. | ||
| 52 | /// | ||
| 53 | /// A lower value means better throughput & latency, at the expense | ||
| 54 | /// of CPU on the device & bandwidth on the bus. A value of 10 is reasonable for | ||
| 55 | /// high performance uses, and a value of 255 is good for best-effort usecases. | ||
| 56 | pub poll_ms: u8, | ||
| 57 | |||
| 58 | /// Max packet size for both the IN and OUT endpoints. | ||
| 59 | pub max_packet_size: u16, | ||
| 60 | } | ||
| 61 | |||
| 44 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | 62 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
| 45 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 63 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 46 | pub enum ReportId { | 64 | pub enum ReportId { |
| @@ -82,23 +100,20 @@ pub struct HidReaderWriter<'d, D: Driver<'d>, const READ_N: usize, const WRITE_N | |||
| 82 | fn build<'d, D: Driver<'d>>( | 100 | fn build<'d, D: Driver<'d>>( |
| 83 | builder: &mut UsbDeviceBuilder<'d, D>, | 101 | builder: &mut UsbDeviceBuilder<'d, D>, |
| 84 | state: &'d mut State<'d>, | 102 | state: &'d mut State<'d>, |
| 85 | report_descriptor: &'static [u8], | 103 | config: Config<'d>, |
| 86 | request_handler: Option<&'d dyn RequestHandler>, | ||
| 87 | poll_ms: u8, | ||
| 88 | max_packet_size: u16, | ||
| 89 | with_out_endpoint: bool, | 104 | with_out_endpoint: bool, |
| 90 | ) -> (Option<D::EndpointOut>, D::EndpointIn, &'d AtomicUsize) { | 105 | ) -> (Option<D::EndpointOut>, D::EndpointIn, &'d AtomicUsize) { |
| 91 | let control = state.control.write(Control::new( | 106 | let control = state.control.write(Control::new( |
| 92 | report_descriptor, | 107 | config.report_descriptor, |
| 93 | request_handler, | 108 | config.request_handler, |
| 94 | &state.out_report_offset, | 109 | &state.out_report_offset, |
| 95 | )); | 110 | )); |
| 96 | 111 | ||
| 97 | let len = report_descriptor.len(); | 112 | let len = config.report_descriptor.len(); |
| 98 | let if_num = builder.alloc_interface_with_handler(control); | 113 | let if_num = builder.alloc_interface_with_handler(control); |
| 99 | let ep_in = builder.alloc_interrupt_endpoint_in(max_packet_size, poll_ms); | 114 | let ep_in = builder.alloc_interrupt_endpoint_in(config.max_packet_size, config.poll_ms); |
| 100 | let ep_out = if with_out_endpoint { | 115 | let ep_out = if with_out_endpoint { |
| 101 | Some(builder.alloc_interrupt_endpoint_out(max_packet_size, poll_ms)) | 116 | Some(builder.alloc_interrupt_endpoint_out(config.max_packet_size, config.poll_ms)) |
| 102 | } else { | 117 | } else { |
| 103 | None | 118 | None |
| 104 | }; | 119 | }; |
| @@ -145,27 +160,12 @@ impl<'d, D: Driver<'d>, const READ_N: usize, const WRITE_N: usize> | |||
| 145 | /// This will allocate one IN and one OUT endpoints. If you only need writing (sending) | 160 | /// This will allocate one IN and one OUT endpoints. If you only need writing (sending) |
| 146 | /// HID reports, consider using [`HidWriter::new`] instead, which allocates an IN endpoint only. | 161 | /// HID reports, consider using [`HidWriter::new`] instead, which allocates an IN endpoint only. |
| 147 | /// | 162 | /// |
| 148 | /// poll_ms configures how frequently the host should poll for reading/writing | ||
| 149 | /// HID reports. A lower value means better throughput & latency, at the expense | ||
| 150 | /// of CPU on the device & bandwidth on the bus. A value of 10 is reasonable for | ||
| 151 | /// high performance uses, and a value of 255 is good for best-effort usecases. | ||
| 152 | pub fn new( | 163 | pub fn new( |
| 153 | builder: &mut UsbDeviceBuilder<'d, D>, | 164 | builder: &mut UsbDeviceBuilder<'d, D>, |
| 154 | state: &'d mut State<'d>, | 165 | state: &'d mut State<'d>, |
| 155 | report_descriptor: &'static [u8], | 166 | config: Config<'d>, |
| 156 | request_handler: Option<&'d dyn RequestHandler>, | ||
| 157 | poll_ms: u8, | ||
| 158 | max_packet_size: u16, | ||
| 159 | ) -> Self { | 167 | ) -> Self { |
| 160 | let (ep_out, ep_in, offset) = build( | 168 | let (ep_out, ep_in, offset) = build(builder, state, config, true); |
| 161 | builder, | ||
| 162 | state, | ||
| 163 | report_descriptor, | ||
| 164 | request_handler, | ||
| 165 | poll_ms, | ||
| 166 | max_packet_size, | ||
| 167 | true, | ||
| 168 | ); | ||
| 169 | 169 | ||
| 170 | Self { | 170 | Self { |
| 171 | reader: HidReader { | 171 | reader: HidReader { |
| @@ -249,20 +249,9 @@ impl<'d, D: Driver<'d>, const N: usize> HidWriter<'d, D, N> { | |||
| 249 | pub fn new( | 249 | pub fn new( |
| 250 | builder: &mut UsbDeviceBuilder<'d, D>, | 250 | builder: &mut UsbDeviceBuilder<'d, D>, |
| 251 | state: &'d mut State<'d>, | 251 | state: &'d mut State<'d>, |
| 252 | report_descriptor: &'static [u8], | 252 | config: Config<'d>, |
| 253 | request_handler: Option<&'d dyn RequestHandler>, | ||
| 254 | poll_ms: u8, | ||
| 255 | max_packet_size: u16, | ||
| 256 | ) -> Self { | 253 | ) -> Self { |
| 257 | let (ep_out, ep_in, _offset) = build( | 254 | let (ep_out, ep_in, _offset) = build(builder, state, config, false); |
| 258 | builder, | ||
| 259 | state, | ||
| 260 | report_descriptor, | ||
| 261 | request_handler, | ||
| 262 | poll_ms, | ||
| 263 | max_packet_size, | ||
| 264 | false, | ||
| 265 | ); | ||
| 266 | 255 | ||
| 267 | assert!(ep_out.is_none()); | 256 | assert!(ep_out.is_none()); |
| 268 | 257 | ||
| @@ -422,17 +411,17 @@ pub trait RequestHandler { | |||
| 422 | } | 411 | } |
| 423 | 412 | ||
| 424 | struct Control<'d> { | 413 | struct Control<'d> { |
| 425 | report_descriptor: &'static [u8], | 414 | report_descriptor: &'d [u8], |
| 426 | request_handler: Option<&'d dyn RequestHandler>, | 415 | request_handler: Option<&'d dyn RequestHandler>, |
| 427 | out_report_offset: &'d AtomicUsize, | 416 | out_report_offset: &'d AtomicUsize, |
| 428 | hid_descriptor: [u8; 9], | 417 | hid_descriptor: [u8; 9], |
| 429 | } | 418 | } |
| 430 | 419 | ||
| 431 | impl<'a> Control<'a> { | 420 | impl<'d> Control<'d> { |
| 432 | fn new( | 421 | fn new( |
| 433 | report_descriptor: &'static [u8], | 422 | report_descriptor: &'d [u8], |
| 434 | request_handler: Option<&'a dyn RequestHandler>, | 423 | request_handler: Option<&'d dyn RequestHandler>, |
| 435 | out_report_offset: &'a AtomicUsize, | 424 | out_report_offset: &'d AtomicUsize, |
| 436 | ) -> Self { | 425 | ) -> Self { |
| 437 | Control { | 426 | Control { |
| 438 | report_descriptor, | 427 | report_descriptor, |
diff --git a/examples/nrf/src/bin/usb_hid_keyboard.rs b/examples/nrf/src/bin/usb_hid_keyboard.rs index 4ed49d375..a2d78b08e 100644 --- a/examples/nrf/src/bin/usb_hid_keyboard.rs +++ b/examples/nrf/src/bin/usb_hid_keyboard.rs | |||
| @@ -88,14 +88,13 @@ async fn main(_spawner: Spawner, p: Peripherals) { | |||
| 88 | ); | 88 | ); |
| 89 | 89 | ||
| 90 | // Create classes on the builder. | 90 | // Create classes on the builder. |
| 91 | let hid = HidReaderWriter::<_, 1, 8>::new( | 91 | let config = embassy_usb_hid::Config { |
| 92 | &mut builder, | 92 | report_descriptor: KeyboardReport::desc(), |
| 93 | &mut state, | 93 | request_handler: Some(&request_handler), |
| 94 | KeyboardReport::desc(), | 94 | poll_ms: 60, |
| 95 | Some(&request_handler), | 95 | max_packet_size: 64, |
| 96 | 60, | 96 | }; |
| 97 | 64, | 97 | let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config); |
| 98 | ); | ||
| 99 | 98 | ||
| 100 | // Build the builder. | 99 | // Build the builder. |
| 101 | let mut usb = builder.build(); | 100 | let mut usb = builder.build(); |
diff --git a/examples/nrf/src/bin/usb_hid_mouse.rs b/examples/nrf/src/bin/usb_hid_mouse.rs index bbdced745..1e98dd1ae 100644 --- a/examples/nrf/src/bin/usb_hid_mouse.rs +++ b/examples/nrf/src/bin/usb_hid_mouse.rs | |||
| @@ -52,7 +52,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { | |||
| 52 | let mut control_buf = [0; 16]; | 52 | let mut control_buf = [0; 16]; |
| 53 | let request_handler = MyRequestHandler {}; | 53 | let request_handler = MyRequestHandler {}; |
| 54 | 54 | ||
| 55 | let mut control = State::new(); | 55 | let mut state = State::new(); |
| 56 | 56 | ||
| 57 | let mut builder = UsbDeviceBuilder::new( | 57 | let mut builder = UsbDeviceBuilder::new( |
| 58 | driver, | 58 | driver, |
| @@ -65,14 +65,14 @@ async fn main(_spawner: Spawner, p: Peripherals) { | |||
| 65 | ); | 65 | ); |
| 66 | 66 | ||
| 67 | // Create classes on the builder. | 67 | // Create classes on the builder. |
| 68 | let mut writer = HidWriter::<_, 5>::new( | 68 | let config = embassy_usb_hid::Config { |
| 69 | &mut builder, | 69 | report_descriptor: MouseReport::desc(), |
| 70 | &mut control, | 70 | request_handler: Some(&request_handler), |
| 71 | MouseReport::desc(), | 71 | poll_ms: 60, |
| 72 | Some(&request_handler), | 72 | max_packet_size: 8, |
| 73 | 60, | 73 | }; |
| 74 | 8, | 74 | |
| 75 | ); | 75 | let mut writer = HidWriter::<_, 5>::new(&mut builder, &mut state, config); |
| 76 | 76 | ||
| 77 | // Build the builder. | 77 | // Build the builder. |
| 78 | let mut usb = builder.build(); | 78 | let mut usb = builder.build(); |
