aboutsummaryrefslogtreecommitdiff
path: root/embassy-usb
diff options
context:
space:
mode:
authormatteo <email>2025-09-23 20:08:11 +0200
committermatteo <email>2025-09-23 20:08:11 +0200
commitd72e8d9af921bfd5ddc25a17933e16b2132386b8 (patch)
tree5ac016298f640684f0590432bcbcdff997cee78f /embassy-usb
parent10397e9f3c4a224c38caa81f1f1d72c0aa96fcdf (diff)
add usb subclass boot and usb protocol mouse and keyboard
Diffstat (limited to 'embassy-usb')
-rw-r--r--embassy-usb/src/class/hid.rs95
1 files changed, 90 insertions, 5 deletions
diff --git a/embassy-usb/src/class/hid.rs b/embassy-usb/src/class/hid.rs
index c8875435f..b9830baeb 100644
--- a/embassy-usb/src/class/hid.rs
+++ b/embassy-usb/src/class/hid.rs
@@ -17,8 +17,13 @@ use crate::types::InterfaceNumber;
17use crate::{Builder, Handler}; 17use crate::{Builder, Handler};
18 18
19const USB_CLASS_HID: u8 = 0x03; 19const USB_CLASS_HID: u8 = 0x03;
20const USB_SUBCLASS_NONE: u8 = 0x00; 20
21const USB_SUBCLASS_REPORT_ONLY: u8 = 0x00;
22const USB_SUBCLASS_BOOT_OR_REPORT: u8 = 0x01;
23
21const USB_PROTOCOL_NONE: u8 = 0x00; 24const USB_PROTOCOL_NONE: u8 = 0x00;
25const USB_PROTOCOL_KEYBOARD: u8 = 0x01;
26const USB_PROTOCOL_MOUSE: u8 = 0x02;
22 27
23// HID 28// HID
24const HID_DESC_DESCTYPE_HID: u8 = 0x21; 29const HID_DESC_DESCTYPE_HID: u8 = 0x21;
@@ -132,13 +137,15 @@ fn build<'d, D: Driver<'d>>(
132 state: &'d mut State<'d>, 137 state: &'d mut State<'d>,
133 config: Config<'d>, 138 config: Config<'d>,
134 with_out_endpoint: bool, 139 with_out_endpoint: bool,
140 usb_subclass: u8,
141 usb_protocol: u8,
135) -> (Option<D::EndpointOut>, D::EndpointIn, &'d AtomicUsize) { 142) -> (Option<D::EndpointOut>, D::EndpointIn, &'d AtomicUsize) {
136 let len = config.report_descriptor.len(); 143 let len = config.report_descriptor.len();
137 144
138 let mut func = builder.function(USB_CLASS_HID, USB_SUBCLASS_NONE, USB_PROTOCOL_NONE); 145 let mut func = builder.function(USB_CLASS_HID, usb_subclass, usb_protocol);
139 let mut iface = func.interface(); 146 let mut iface = func.interface();
140 let if_num = iface.interface_number(); 147 let if_num = iface.interface_number();
141 let mut alt = iface.alt_setting(USB_CLASS_HID, USB_SUBCLASS_NONE, USB_PROTOCOL_NONE, None); 148 let mut alt = iface.alt_setting(USB_CLASS_HID, usb_subclass, usb_protocol, None);
142 149
143 // HID descriptor 150 // HID descriptor
144 alt.descriptor( 151 alt.descriptor(
@@ -186,7 +193,42 @@ impl<'d, D: Driver<'d>, const READ_N: usize, const WRITE_N: usize> HidReaderWrit
186 /// HID reports, consider using [`HidWriter::new`] instead, which allocates an IN endpoint only. 193 /// HID reports, consider using [`HidWriter::new`] instead, which allocates an IN endpoint only.
187 /// 194 ///
188 pub fn new(builder: &mut Builder<'d, D>, state: &'d mut State<'d>, config: Config<'d>) -> Self { 195 pub fn new(builder: &mut Builder<'d, D>, state: &'d mut State<'d>, config: Config<'d>) -> Self {
189 let (ep_out, ep_in, offset) = build(builder, state, config, true); 196 HidReaderWriter::_new(builder, state, config, USB_SUBCLASS_REPORT_ONLY, USB_PROTOCOL_NONE)
197 }
198
199 /// Creates a new `HidReaderWriter` for a HID Mouse, with support for the BOOT protocol mode.
200 ///
201 /// This will allocate one IN and one OUT endpoints. If you only need writing (sending)
202 /// HID reports, consider using [`HidWriter::new`] instead, which allocates an IN endpoint only.
203 ///
204 pub fn new_mouse(builder: &mut Builder<'d, D>, state: &'d mut State<'d>, config: Config<'d>) -> Self {
205 HidReaderWriter::_new(builder, state, config, USB_SUBCLASS_BOOT_OR_REPORT, USB_PROTOCOL_MOUSE)
206 }
207
208 /// Creates a new `HidReaderWriter` for a HID Keyboard, with support for the BOOT protocol mode.
209 ///
210 /// This will allocate one IN and one OUT endpoints. If you only need writing (sending)
211 /// HID reports, consider using [`HidWriter::new`] instead, which allocates an IN endpoint only.
212 ///
213 pub fn new_keyboard(builder: &mut Builder<'d, D>, state: &'d mut State<'d>, config: Config<'d>) -> Self {
214 HidReaderWriter::_new(
215 builder,
216 state,
217 config,
218 USB_SUBCLASS_BOOT_OR_REPORT,
219 USB_PROTOCOL_KEYBOARD,
220 )
221 }
222
223 /// Private helper function to create a new `HidReaderWriter`.
224 fn _new(
225 builder: &mut Builder<'d, D>,
226 state: &'d mut State<'d>,
227 config: Config<'d>,
228 usb_subclass: u8,
229 usb_protocol: u8,
230 ) -> Self {
231 let (ep_out, ep_in, offset) = build(builder, state, config, true, usb_subclass, usb_protocol);
190 232
191 Self { 233 Self {
192 reader: HidReader { 234 reader: HidReader {
@@ -275,7 +317,50 @@ impl<'d, D: Driver<'d>, const N: usize> HidWriter<'d, D, N> {
275 /// of CPU on the device & bandwidth on the bus. A value of 10 is reasonable for 317 /// of CPU on the device & bandwidth on the bus. A value of 10 is reasonable for
276 /// high performance uses, and a value of 255 is good for best-effort usecases. 318 /// high performance uses, and a value of 255 is good for best-effort usecases.
277 pub fn new(builder: &mut Builder<'d, D>, state: &'d mut State<'d>, config: Config<'d>) -> Self { 319 pub fn new(builder: &mut Builder<'d, D>, state: &'d mut State<'d>, config: Config<'d>) -> Self {
278 let (ep_out, ep_in, _offset) = build(builder, state, config, false); 320 HidWriter::_new(builder, state, config, USB_SUBCLASS_REPORT_ONLY, USB_PROTOCOL_NONE)
321 }
322
323 /// Creates a new `HidWriter` for a HID Mouse, with support for the BOOT protocol mode.
324 ///
325 /// This will allocate one IN endpoint only, so the host won't be able to send
326 /// reports to us. If you need that, consider using [`HidReaderWriter::new`] instead.
327 ///
328 /// poll_ms configures how frequently the host should poll for reading/writing
329 /// HID reports. A lower value means better throughput & latency, at the expense
330 /// of CPU on the device & bandwidth on the bus. A value of 10 is reasonable for
331 /// high performance uses, and a value of 255 is good for best-effort usecases.
332 pub fn new_mouse(builder: &mut Builder<'d, D>, state: &'d mut State<'d>, config: Config<'d>) -> Self {
333 HidWriter::_new(builder, state, config, USB_SUBCLASS_BOOT_OR_REPORT, USB_PROTOCOL_MOUSE)
334 }
335
336 /// Creates a new `HidWriter` for a HID Keyboard, with support for the BOOT protocol mode.
337 ///
338 /// This will allocate one IN endpoint only, so the host won't be able to send
339 /// reports to us. If you need that, consider using [`HidReaderWriter::new`] instead.
340 ///
341 /// poll_ms configures how frequently the host should poll for reading/writing
342 /// HID reports. A lower value means better throughput & latency, at the expense
343 /// of CPU on the device & bandwidth on the bus. A value of 10 is reasonable for
344 /// high performance uses, and a value of 255 is good for best-effort usecases.
345 pub fn new_keyboard(builder: &mut Builder<'d, D>, state: &'d mut State<'d>, config: Config<'d>) -> Self {
346 HidWriter::_new(
347 builder,
348 state,
349 config,
350 USB_SUBCLASS_BOOT_OR_REPORT,
351 USB_PROTOCOL_KEYBOARD,
352 )
353 }
354
355 /// Private helper function to create a new `HidWriter`.
356 pub fn _new(
357 builder: &mut Builder<'d, D>,
358 state: &'d mut State<'d>,
359 config: Config<'d>,
360 usb_subclass: u8,
361 usb_protocol: u8,
362 ) -> Self {
363 let (ep_out, ep_in, _offset) = build(builder, state, config, false, usb_subclass, usb_protocol);
279 364
280 assert!(ep_out.is_none()); 365 assert!(ep_out.is_none());
281 366