aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-usb/build.rs8
-rw-r--r--embassy-usb/src/builder.rs44
-rw-r--r--embassy-usb/src/class/cdc_acm.rs53
-rw-r--r--embassy-usb/src/class/cdc_ncm/mod.rs63
-rw-r--r--embassy-usb/src/class/hid.rs36
-rw-r--r--embassy-usb/src/class/midi.rs16
-rw-r--r--embassy-usb/src/control.rs2
-rw-r--r--embassy-usb/src/descriptor.rs34
-rw-r--r--embassy-usb/src/descriptor_reader.rs6
-rw-r--r--embassy-usb/src/lib.rs54
-rw-r--r--embassy-usb/src/msos.rs2
-rw-r--r--embassy-usb/src/types.rs4
12 files changed, 156 insertions, 166 deletions
diff --git a/embassy-usb/build.rs b/embassy-usb/build.rs
index 33d32f7d3..5e3bec485 100644
--- a/embassy-usb/build.rs
+++ b/embassy-usb/build.rs
@@ -70,9 +70,11 @@ fn main() {
70 70
71 // envvars take priority. 71 // envvars take priority.
72 if !cfg.seen_env { 72 if !cfg.seen_env {
73 if cfg.seen_feature { 73 assert!(
74 panic!("multiple values set for feature {}: {} and {}", name, cfg.value, value); 74 !cfg.seen_feature,
75 } 75 "multiple values set for feature {}: {} and {}",
76 name, cfg.value, value
77 );
76 78
77 cfg.value = value; 79 cfg.value = value;
78 cfg.seen_feature = true; 80 cfg.seen_feature = true;
diff --git a/embassy-usb/src/builder.rs b/embassy-usb/src/builder.rs
index 6b68bcd7b..b4ddccd71 100644
--- a/embassy-usb/src/builder.rs
+++ b/embassy-usb/src/builder.rs
@@ -1,17 +1,17 @@
1use heapless::Vec; 1use heapless::Vec;
2 2
3use crate::config::*; 3use crate::config::MAX_HANDLER_COUNT;
4use crate::descriptor::{BosWriter, DescriptorWriter}; 4use crate::descriptor::{BosWriter, DescriptorWriter};
5use crate::driver::{Driver, Endpoint, EndpointType}; 5use crate::driver::{Driver, Endpoint, EndpointType};
6#[cfg(feature = "msos-descriptor")] 6#[cfg(feature = "msos-descriptor")]
7use crate::msos::{DeviceLevelDescriptor, FunctionLevelDescriptor, MsOsDescriptorWriter}; 7use crate::msos::{DeviceLevelDescriptor, FunctionLevelDescriptor, MsOsDescriptorWriter};
8use crate::types::*; 8use crate::types::{InterfaceNumber, StringIndex};
9use crate::{Handler, Interface, UsbDevice, MAX_INTERFACE_COUNT, STRING_INDEX_CUSTOM_START}; 9use crate::{Handler, Interface, UsbDevice, MAX_INTERFACE_COUNT, STRING_INDEX_CUSTOM_START};
10 10
11#[derive(Debug, Copy, Clone)] 11#[derive(Debug, Copy, Clone)]
12#[cfg_attr(feature = "defmt", derive(defmt::Format))] 12#[cfg_attr(feature = "defmt", derive(defmt::Format))]
13#[non_exhaustive] 13#[non_exhaustive]
14/// Configuration used when creating [UsbDevice]. 14/// Configuration used when creating [`UsbDevice`].
15pub struct Config<'a> { 15pub struct Config<'a> {
16 pub(crate) vendor_id: u16, 16 pub(crate) vendor_id: u16,
17 pub(crate) product_id: u16, 17 pub(crate) product_id: u16,
@@ -99,7 +99,7 @@ pub struct Config<'a> {
99 99
100impl<'a> Config<'a> { 100impl<'a> Config<'a> {
101 /// Create default configuration with the provided vid and pid values. 101 /// Create default configuration with the provided vid and pid values.
102 pub fn new(vid: u16, pid: u16) -> Self { 102 pub const fn new(vid: u16, pid: u16) -> Self {
103 Self { 103 Self {
104 device_class: 0x00, 104 device_class: 0x00,
105 device_sub_class: 0x00, 105 device_sub_class: 0x00,
@@ -159,9 +159,10 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
159 panic!("if composite_with_iads is set, you must set device_class = 0xEF, device_sub_class = 0x02, device_protocol = 0x01"); 159 panic!("if composite_with_iads is set, you must set device_class = 0xEF, device_sub_class = 0x02, device_protocol = 0x01");
160 } 160 }
161 161
162 if config.max_power > 500 { 162 assert!(
163 panic!("The maximum allowed value for `max_power` is 500mA"); 163 config.max_power <= 500,
164 } 164 "The maximum allowed value for `max_power` is 500mA"
165 );
165 166
166 match config.max_packet_size_0 { 167 match config.max_packet_size_0 {
167 8 | 16 | 32 | 64 => {} 168 8 | 16 | 32 | 64 => {}
@@ -260,12 +261,11 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
260 /// The Handler is called on some USB bus events, and to handle all control requests not already 261 /// The Handler is called on some USB bus events, and to handle all control requests not already
261 /// handled by the USB stack. 262 /// handled by the USB stack.
262 pub fn handler(&mut self, handler: &'d mut dyn Handler) { 263 pub fn handler(&mut self, handler: &'d mut dyn Handler) {
263 if self.handlers.push(handler).is_err() { 264 assert!(
264 panic!( 265 self.handlers.push(handler).is_ok(),
265 "embassy-usb: handler list full. Increase the `max_handler_count` compile-time setting. Current value: {}", 266 "embassy-usb: handler list full. Increase the `max_handler_count` compile-time setting. Current value: {}",
266 MAX_HANDLER_COUNT 267 MAX_HANDLER_COUNT
267 ) 268 );
268 }
269 } 269 }
270 270
271 /// Allocates a new string index. 271 /// Allocates a new string index.
@@ -332,12 +332,10 @@ impl<'a, 'd, D: Driver<'d>> FunctionBuilder<'a, 'd, D> {
332 num_alt_settings: 0, 332 num_alt_settings: 0,
333 }; 333 };
334 334
335 if self.builder.interfaces.push(iface).is_err() { 335 assert!(self.builder.interfaces.push(iface).is_ok(),
336 panic!( 336 "embassy-usb: interface list full. Increase the `max_interface_count` compile-time setting. Current value: {}",
337 "embassy-usb: interface list full. Increase the `max_interface_count` compile-time setting. Current value: {}", 337 MAX_INTERFACE_COUNT
338 MAX_INTERFACE_COUNT 338 );
339 )
340 }
341 339
342 InterfaceBuilder { 340 InterfaceBuilder {
343 builder: self.builder, 341 builder: self.builder,
@@ -371,7 +369,7 @@ pub struct InterfaceBuilder<'a, 'd, D: Driver<'d>> {
371 369
372impl<'a, 'd, D: Driver<'d>> InterfaceBuilder<'a, 'd, D> { 370impl<'a, 'd, D: Driver<'d>> InterfaceBuilder<'a, 'd, D> {
373 /// Get the interface number. 371 /// Get the interface number.
374 pub fn interface_number(&self) -> InterfaceNumber { 372 pub const fn interface_number(&self) -> InterfaceNumber {
375 self.interface_number 373 self.interface_number
376 } 374 }
377 375
@@ -422,12 +420,12 @@ pub struct InterfaceAltBuilder<'a, 'd, D: Driver<'d>> {
422 420
423impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> { 421impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
424 /// Get the interface number. 422 /// Get the interface number.
425 pub fn interface_number(&self) -> InterfaceNumber { 423 pub const fn interface_number(&self) -> InterfaceNumber {
426 self.interface_number 424 self.interface_number
427 } 425 }
428 426
429 /// Get the alternate setting number. 427 /// Get the alternate setting number.
430 pub fn alt_setting_number(&self) -> u8 { 428 pub const fn alt_setting_number(&self) -> u8 {
431 self.alt_setting_number 429 self.alt_setting_number
432 } 430 }
433 431
@@ -436,7 +434,7 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
436 /// Descriptors are written in the order builder functions are called. Note that some 434 /// Descriptors are written in the order builder functions are called. Note that some
437 /// classes care about the order. 435 /// classes care about the order.
438 pub fn descriptor(&mut self, descriptor_type: u8, descriptor: &[u8]) { 436 pub fn descriptor(&mut self, descriptor_type: u8, descriptor: &[u8]) {
439 self.builder.config_descriptor.write(descriptor_type, descriptor) 437 self.builder.config_descriptor.write(descriptor_type, descriptor);
440 } 438 }
441 439
442 fn endpoint_in(&mut self, ep_type: EndpointType, max_packet_size: u16, interval_ms: u8) -> D::EndpointIn { 440 fn endpoint_in(&mut self, ep_type: EndpointType, max_packet_size: u16, interval_ms: u8) -> D::EndpointIn {
diff --git a/embassy-usb/src/class/cdc_acm.rs b/embassy-usb/src/class/cdc_acm.rs
index 0c708464d..f1066d2f2 100644
--- a/embassy-usb/src/class/cdc_acm.rs
+++ b/embassy-usb/src/class/cdc_acm.rs
@@ -11,7 +11,7 @@ use embassy_sync::waitqueue::WakerRegistration;
11 11
12use crate::control::{self, InResponse, OutResponse, Recipient, Request, RequestType}; 12use crate::control::{self, InResponse, OutResponse, Recipient, Request, RequestType};
13use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut}; 13use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut};
14use crate::types::*; 14use crate::types::InterfaceNumber;
15use crate::{Builder, Handler}; 15use crate::{Builder, Handler};
16 16
17/// This should be used as `device_class` when building the `UsbDevice`. 17/// This should be used as `device_class` when building the `UsbDevice`.
@@ -39,12 +39,18 @@ pub struct State<'a> {
39 shared: ControlShared, 39 shared: ControlShared,
40} 40}
41 41
42impl<'a> Default for State<'a> {
43 fn default() -> Self {
44 Self::new()
45 }
46}
47
42impl<'a> State<'a> { 48impl<'a> State<'a> {
43 /// Create a new `State`. 49 /// Create a new `State`.
44 pub fn new() -> Self { 50 pub fn new() -> Self {
45 Self { 51 Self {
46 control: MaybeUninit::uninit(), 52 control: MaybeUninit::uninit(),
47 shared: Default::default(), 53 shared: ControlShared::default(),
48 } 54 }
49 } 55 }
50} 56}
@@ -55,9 +61,9 @@ impl<'a> State<'a> {
55/// writing USB packets with no intermediate buffers, but it will not act like a stream-like serial 61/// writing USB packets with no intermediate buffers, but it will not act like a stream-like serial
56/// port. The following constraints must be followed if you use this class directly: 62/// port. The following constraints must be followed if you use this class directly:
57/// 63///
58/// - `read_packet` must be called with a buffer large enough to hold max_packet_size bytes. 64/// - `read_packet` must be called with a buffer large enough to hold `max_packet_size` bytes.
59/// - `write_packet` must not be called with a buffer larger than max_packet_size bytes. 65/// - `write_packet` must not be called with a buffer larger than `max_packet_size` bytes.
60/// - If you write a packet that is exactly max_packet_size bytes long, it won't be processed by the 66/// - If you write a packet that is exactly `max_packet_size` bytes long, it won't be processed by the
61/// host operating system until a subsequent shorter packet is sent. A zero-length packet (ZLP) 67/// host operating system until a subsequent shorter packet is sent. A zero-length packet (ZLP)
62/// can be sent if there is no other data to send. This is because USB bulk transactions must be 68/// can be sent if there is no other data to send. This is because USB bulk transactions must be
63/// terminated with a short packet, even if the bulk endpoint is used for stream-like data. 69/// terminated with a short packet, even if the bulk endpoint is used for stream-like data.
@@ -103,17 +109,16 @@ impl Default for ControlShared {
103 109
104impl ControlShared { 110impl ControlShared {
105 async fn changed(&self) { 111 async fn changed(&self) {
106 poll_fn(|cx| match self.changed.load(Ordering::Relaxed) { 112 poll_fn(|cx| {
107 true => { 113 if self.changed.load(Ordering::Relaxed) {
108 self.changed.store(false, Ordering::Relaxed); 114 self.changed.store(false, Ordering::Relaxed);
109 Poll::Ready(()) 115 Poll::Ready(())
110 } 116 } else {
111 false => {
112 self.waker.borrow_mut().register(cx.waker()); 117 self.waker.borrow_mut().register(cx.waker());
113 Poll::Pending 118 Poll::Pending
114 } 119 }
115 }) 120 })
116 .await 121 .await;
117 } 122 }
118} 123}
119 124
@@ -192,7 +197,7 @@ impl<'d> Handler for Control<'d> {
192 // REQ_GET_ENCAPSULATED_COMMAND is not really supported - it will be rejected below. 197 // REQ_GET_ENCAPSULATED_COMMAND is not really supported - it will be rejected below.
193 REQ_GET_LINE_CODING if req.length == 7 => { 198 REQ_GET_LINE_CODING if req.length == 7 => {
194 debug!("Sending line coding"); 199 debug!("Sending line coding");
195 let coding = self.shared().line_coding.lock(|x| x.get()); 200 let coding = self.shared().line_coding.lock(Cell::get);
196 assert!(buf.len() >= 7); 201 assert!(buf.len() >= 7);
197 buf[0..4].copy_from_slice(&coding.data_rate.to_le_bytes()); 202 buf[0..4].copy_from_slice(&coding.data_rate.to_le_bytes());
198 buf[4] = coding.stop_bits as u8; 203 buf[4] = coding.stop_bits as u8;
@@ -206,8 +211,8 @@ impl<'d> Handler for Control<'d> {
206} 211}
207 212
208impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> { 213impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> {
209 /// Creates a new CdcAcmClass with the provided UsbBus and max_packet_size in bytes. For 214 /// Creates a new CdcAcmClass with the provided UsbBus and `max_packet_size` in bytes. For
210 /// full-speed devices, max_packet_size has to be one of 8, 16, 32 or 64. 215 /// full-speed devices, `max_packet_size` has to be one of 8, 16, 32 or 64.
211 pub fn new(builder: &mut Builder<'d, D>, state: &'d mut State<'d>, max_packet_size: u16) -> Self { 216 pub fn new(builder: &mut Builder<'d, D>, state: &'d mut State<'d>, max_packet_size: u16) -> Self {
212 assert!(builder.control_buf_len() >= 7); 217 assert!(builder.control_buf_len() >= 7);
213 218
@@ -242,7 +247,7 @@ impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> {
242 &[ 247 &[
243 CDC_TYPE_UNION, // bDescriptorSubtype 248 CDC_TYPE_UNION, // bDescriptorSubtype
244 comm_if.into(), // bControlInterface 249 comm_if.into(), // bControlInterface
245 data_if.into(), // bSubordinateInterface 250 data_if, // bSubordinateInterface
246 ], 251 ],
247 ); 252 );
248 253
@@ -283,7 +288,7 @@ impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> {
283 /// Gets the current line coding. The line coding contains information that's mainly relevant 288 /// Gets the current line coding. The line coding contains information that's mainly relevant
284 /// for USB to UART serial port emulators, and can be ignored if not relevant. 289 /// for USB to UART serial port emulators, and can be ignored if not relevant.
285 pub fn line_coding(&self) -> LineCoding { 290 pub fn line_coding(&self) -> LineCoding {
286 self.control.line_coding.lock(|x| x.get()) 291 self.control.line_coding.lock(Cell::get)
287 } 292 }
288 293
289 /// Gets the DTR (data terminal ready) state 294 /// Gets the DTR (data terminal ready) state
@@ -308,7 +313,7 @@ impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> {
308 313
309 /// Waits for the USB host to enable this interface 314 /// Waits for the USB host to enable this interface
310 pub async fn wait_connection(&mut self) { 315 pub async fn wait_connection(&mut self) {
311 self.read_ep.wait_enabled().await 316 self.read_ep.wait_enabled().await;
312 } 317 }
313 318
314 /// Split the class into a sender and receiver. 319 /// Split the class into a sender and receiver.
@@ -356,7 +361,7 @@ pub struct ControlChanged<'d> {
356impl<'d> ControlChanged<'d> { 361impl<'d> ControlChanged<'d> {
357 /// Return a future for when the control settings change 362 /// Return a future for when the control settings change
358 pub async fn control_changed(&self) { 363 pub async fn control_changed(&self) {
359 self.control.changed().await 364 self.control.changed().await;
360 } 365 }
361} 366}
362 367
@@ -378,7 +383,7 @@ impl<'d, D: Driver<'d>> Sender<'d, D> {
378 /// Gets the current line coding. The line coding contains information that's mainly relevant 383 /// Gets the current line coding. The line coding contains information that's mainly relevant
379 /// for USB to UART serial port emulators, and can be ignored if not relevant. 384 /// for USB to UART serial port emulators, and can be ignored if not relevant.
380 pub fn line_coding(&self) -> LineCoding { 385 pub fn line_coding(&self) -> LineCoding {
381 self.control.line_coding.lock(|x| x.get()) 386 self.control.line_coding.lock(Cell::get)
382 } 387 }
383 388
384 /// Gets the DTR (data terminal ready) state 389 /// Gets the DTR (data terminal ready) state
@@ -398,7 +403,7 @@ impl<'d, D: Driver<'d>> Sender<'d, D> {
398 403
399 /// Waits for the USB host to enable this interface 404 /// Waits for the USB host to enable this interface
400 pub async fn wait_connection(&mut self) { 405 pub async fn wait_connection(&mut self) {
401 self.write_ep.wait_enabled().await 406 self.write_ep.wait_enabled().await;
402 } 407 }
403} 408}
404 409
@@ -420,7 +425,7 @@ impl<'d, D: Driver<'d>> Receiver<'d, D> {
420 /// Gets the current line coding. The line coding contains information that's mainly relevant 425 /// Gets the current line coding. The line coding contains information that's mainly relevant
421 /// for USB to UART serial port emulators, and can be ignored if not relevant. 426 /// for USB to UART serial port emulators, and can be ignored if not relevant.
422 pub fn line_coding(&self) -> LineCoding { 427 pub fn line_coding(&self) -> LineCoding {
423 self.control.line_coding.lock(|x| x.get()) 428 self.control.line_coding.lock(Cell::get)
424 } 429 }
425 430
426 /// Gets the DTR (data terminal ready) state 431 /// Gets the DTR (data terminal ready) state
@@ -440,7 +445,7 @@ impl<'d, D: Driver<'d>> Receiver<'d, D> {
440 445
441 /// Waits for the USB host to enable this interface 446 /// Waits for the USB host to enable this interface
442 pub async fn wait_connection(&mut self) { 447 pub async fn wait_connection(&mut self) {
443 self.read_ep.wait_enabled().await 448 self.read_ep.wait_enabled().await;
444 } 449 }
445} 450}
446 451
@@ -514,17 +519,17 @@ impl LineCoding {
514 } 519 }
515 520
516 /// Gets the number of data bits for UART communication. 521 /// Gets the number of data bits for UART communication.
517 pub fn data_bits(&self) -> u8 { 522 pub const fn data_bits(&self) -> u8 {
518 self.data_bits 523 self.data_bits
519 } 524 }
520 525
521 /// Gets the parity type for UART communication. 526 /// Gets the parity type for UART communication.
522 pub fn parity_type(&self) -> ParityType { 527 pub const fn parity_type(&self) -> ParityType {
523 self.parity_type 528 self.parity_type
524 } 529 }
525 530
526 /// Gets the data rate in bits per second for UART communication. 531 /// Gets the data rate in bits per second for UART communication.
527 pub fn data_rate(&self) -> u32 { 532 pub const fn data_rate(&self) -> u32 {
528 self.data_rate 533 self.data_rate
529 } 534 }
530} 535}
diff --git a/embassy-usb/src/class/cdc_ncm/mod.rs b/embassy-usb/src/class/cdc_ncm/mod.rs
index 830e9b768..bea9dac27 100644
--- a/embassy-usb/src/class/cdc_ncm/mod.rs
+++ b/embassy-usb/src/class/cdc_ncm/mod.rs
@@ -16,10 +16,11 @@
16 16
17use core::intrinsics::copy_nonoverlapping; 17use core::intrinsics::copy_nonoverlapping;
18use core::mem::{size_of, MaybeUninit}; 18use core::mem::{size_of, MaybeUninit};
19use core::ptr::addr_of;
19 20
20use crate::control::{self, InResponse, OutResponse, Recipient, Request, RequestType}; 21use crate::control::{self, InResponse, OutResponse, Recipient, Request, RequestType};
21use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut}; 22use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut};
22use crate::types::*; 23use crate::types::{InterfaceNumber, StringIndex};
23use crate::{Builder, Handler}; 24use crate::{Builder, Handler};
24 25
25pub mod embassy_net; 26pub mod embassy_net;
@@ -62,9 +63,9 @@ const REQ_SET_NTB_INPUT_SIZE: u8 = 0x86;
62//const NOTIF_POLL_INTERVAL: u8 = 20; 63//const NOTIF_POLL_INTERVAL: u8 = 20;
63 64
64const NTB_MAX_SIZE: usize = 2048; 65const NTB_MAX_SIZE: usize = 2048;
65const SIG_NTH: u32 = 0x484d434e; 66const SIG_NTH: u32 = 0x484d_434e;
66const SIG_NDP_NO_FCS: u32 = 0x304d434e; 67const SIG_NDP_NO_FCS: u32 = 0x304d_434e;
67const SIG_NDP_WITH_FCS: u32 = 0x314d434e; 68const SIG_NDP_WITH_FCS: u32 = 0x314d_434e;
68 69
69const ALTERNATE_SETTING_DISABLED: u8 = 0x00; 70const ALTERNATE_SETTING_DISABLED: u8 = 0x00;
70const ALTERNATE_SETTING_ENABLED: u8 = 0x01; 71const ALTERNATE_SETTING_ENABLED: u8 = 0x01;
@@ -111,7 +112,7 @@ struct NtbParametersDir {
111 112
112fn byteify<T>(buf: &mut [u8], data: T) -> &[u8] { 113fn byteify<T>(buf: &mut [u8], data: T) -> &[u8] {
113 let len = size_of::<T>(); 114 let len = size_of::<T>();
114 unsafe { copy_nonoverlapping(&data as *const _ as *const u8, buf.as_mut_ptr(), len) } 115 unsafe { copy_nonoverlapping(addr_of!(data).cast(), buf.as_mut_ptr(), len) }
115 &buf[..len] 116 &buf[..len]
116} 117}
117 118
@@ -121,27 +122,28 @@ pub struct State<'a> {
121 shared: ControlShared, 122 shared: ControlShared,
122} 123}
123 124
125impl<'a> Default for State<'a> {
126 fn default() -> Self {
127 Self::new()
128 }
129}
130
124impl<'a> State<'a> { 131impl<'a> State<'a> {
125 /// Create a new `State`. 132 /// Create a new `State`.
126 pub fn new() -> Self { 133 pub fn new() -> Self {
127 Self { 134 Self {
128 control: MaybeUninit::uninit(), 135 control: MaybeUninit::uninit(),
129 shared: Default::default(), 136 shared: ControlShared::default(),
130 } 137 }
131 } 138 }
132} 139}
133 140
134/// Shared data between Control and CdcAcmClass 141/// Shared data between Control and `CdcAcmClass`
142#[derive(Default)]
135struct ControlShared { 143struct ControlShared {
136 mac_addr: [u8; 6], 144 mac_addr: [u8; 6],
137} 145}
138 146
139impl Default for ControlShared {
140 fn default() -> Self {
141 ControlShared { mac_addr: [0; 6] }
142 }
143}
144
145struct Control<'a> { 147struct Control<'a> {
146 mac_addr_string: StringIndex, 148 mac_addr_string: StringIndex,
147 shared: &'a ControlShared, 149 shared: &'a ControlShared,
@@ -377,12 +379,12 @@ impl<'d, D: Driver<'d>> Sender<'d, D> {
377 /// 379 ///
378 /// This waits until the packet is successfully stored in the CDC-NCM endpoint buffers. 380 /// This waits until the packet is successfully stored in the CDC-NCM endpoint buffers.
379 pub async fn write_packet(&mut self, data: &[u8]) -> Result<(), EndpointError> { 381 pub async fn write_packet(&mut self, data: &[u8]) -> Result<(), EndpointError> {
380 let seq = self.seq;
381 self.seq = self.seq.wrapping_add(1);
382
383 const OUT_HEADER_LEN: usize = 28; 382 const OUT_HEADER_LEN: usize = 28;
384 const ABS_MAX_PACKET_SIZE: usize = 512; 383 const ABS_MAX_PACKET_SIZE: usize = 512;
385 384
385 let seq = self.seq;
386 self.seq = self.seq.wrapping_add(1);
387
386 let header = NtbOutHeader { 388 let header = NtbOutHeader {
387 nth_sig: SIG_NTH, 389 nth_sig: SIG_NTH,
388 nth_len: 0x0c, 390 nth_len: 0x0c,
@@ -416,7 +418,7 @@ impl<'d, D: Driver<'d>> Sender<'d, D> {
416 self.write_ep.write(&buf[..self.max_packet_size]).await?; 418 self.write_ep.write(&buf[..self.max_packet_size]).await?;
417 419
418 for chunk in d2.chunks(self.max_packet_size) { 420 for chunk in d2.chunks(self.max_packet_size) {
419 self.write_ep.write(&chunk).await?; 421 self.write_ep.write(chunk).await?;
420 } 422 }
421 423
422 // Send ZLP if needed. 424 // Send ZLP if needed.
@@ -459,12 +461,9 @@ impl<'d, D: Driver<'d>> Receiver<'d, D> {
459 let ntb = &ntb[..pos]; 461 let ntb = &ntb[..pos];
460 462
461 // Process NTB header (NTH) 463 // Process NTB header (NTH)
462 let nth = match ntb.get(..12) { 464 let Some(nth) = ntb.get(..12) else {
463 Some(x) => x, 465 warn!("Received too short NTB");
464 None => { 466 continue;
465 warn!("Received too short NTB");
466 continue;
467 }
468 }; 467 };
469 let sig = u32::from_le_bytes(nth[0..4].try_into().unwrap()); 468 let sig = u32::from_le_bytes(nth[0..4].try_into().unwrap());
470 if sig != SIG_NTH { 469 if sig != SIG_NTH {
@@ -474,12 +473,9 @@ impl<'d, D: Driver<'d>> Receiver<'d, D> {
474 let ndp_idx = u16::from_le_bytes(nth[10..12].try_into().unwrap()) as usize; 473 let ndp_idx = u16::from_le_bytes(nth[10..12].try_into().unwrap()) as usize;
475 474
476 // Process NTB Datagram Pointer (NDP) 475 // Process NTB Datagram Pointer (NDP)
477 let ndp = match ntb.get(ndp_idx..ndp_idx + 12) { 476 let Some(ndp) = ntb.get(ndp_idx..ndp_idx + 12) else {
478 Some(x) => x, 477 warn!("NTH has an NDP pointer out of range.");
479 None => { 478 continue;
480 warn!("NTH has an NDP pointer out of range.");
481 continue;
482 }
483 }; 479 };
484 let sig = u32::from_le_bytes(ndp[0..4].try_into().unwrap()); 480 let sig = u32::from_le_bytes(ndp[0..4].try_into().unwrap());
485 if sig != SIG_NDP_NO_FCS && sig != SIG_NDP_WITH_FCS { 481 if sig != SIG_NDP_NO_FCS && sig != SIG_NDP_WITH_FCS {
@@ -495,12 +491,9 @@ impl<'d, D: Driver<'d>> Receiver<'d, D> {
495 } 491 }
496 492
497 // Process actual datagram, finally. 493 // Process actual datagram, finally.
498 let datagram = match ntb.get(datagram_index..datagram_index + datagram_len) { 494 let Some(datagram) = ntb.get(datagram_index..datagram_index + datagram_len) else {
499 Some(x) => x, 495 warn!("NDP has a datagram pointer out of range.");
500 None => { 496 continue;
501 warn!("NDP has a datagram pointer out of range.");
502 continue;
503 }
504 }; 497 };
505 buf[..datagram_len].copy_from_slice(datagram); 498 buf[..datagram_len].copy_from_slice(datagram);
506 499
diff --git a/embassy-usb/src/class/hid.rs b/embassy-usb/src/class/hid.rs
index 889d66ec5..0000b5b2b 100644
--- a/embassy-usb/src/class/hid.rs
+++ b/embassy-usb/src/class/hid.rs
@@ -63,7 +63,7 @@ pub enum ReportId {
63} 63}
64 64
65impl ReportId { 65impl ReportId {
66 fn try_from(value: u16) -> Result<Self, ()> { 66 const fn try_from(value: u16) -> Result<Self, ()> {
67 match value >> 8 { 67 match value >> 8 {
68 1 => Ok(ReportId::In(value as u8)), 68 1 => Ok(ReportId::In(value as u8)),
69 2 => Ok(ReportId::Out(value as u8)), 69 2 => Ok(ReportId::Out(value as u8)),
@@ -79,9 +79,15 @@ pub struct State<'d> {
79 out_report_offset: AtomicUsize, 79 out_report_offset: AtomicUsize,
80} 80}
81 81
82impl<'d> Default for State<'d> {
83 fn default() -> Self {
84 Self::new()
85 }
86}
87
82impl<'d> State<'d> { 88impl<'d> State<'d> {
83 /// Create a new `State`. 89 /// Create a new `State`.
84 pub fn new() -> Self { 90 pub const fn new() -> Self {
85 State { 91 State {
86 control: MaybeUninit::uninit(), 92 control: MaybeUninit::uninit(),
87 out_report_offset: AtomicUsize::new(0), 93 out_report_offset: AtomicUsize::new(0),
@@ -148,7 +154,7 @@ fn build<'d, D: Driver<'d>>(
148} 154}
149 155
150impl<'d, D: Driver<'d>, const READ_N: usize, const WRITE_N: usize> HidReaderWriter<'d, D, READ_N, WRITE_N> { 156impl<'d, D: Driver<'d>, const READ_N: usize, const WRITE_N: usize> HidReaderWriter<'d, D, READ_N, WRITE_N> {
151 /// Creates a new HidReaderWriter. 157 /// Creates a new `HidReaderWriter`.
152 /// 158 ///
153 /// This will allocate one IN and one OUT endpoints. If you only need writing (sending) 159 /// This will allocate one IN and one OUT endpoints. If you only need writing (sending)
154 /// HID reports, consider using [`HidWriter::new`] instead, which allocates an IN endpoint only. 160 /// HID reports, consider using [`HidWriter::new`] instead, which allocates an IN endpoint only.
@@ -171,7 +177,7 @@ impl<'d, D: Driver<'d>, const READ_N: usize, const WRITE_N: usize> HidReaderWrit
171 } 177 }
172 178
173 /// Waits for both IN and OUT endpoints to be enabled. 179 /// Waits for both IN and OUT endpoints to be enabled.
174 pub async fn ready(&mut self) -> () { 180 pub async fn ready(&mut self) {
175 self.reader.ready().await; 181 self.reader.ready().await;
176 self.writer.ready().await; 182 self.writer.ready().await;
177 } 183 }
@@ -224,7 +230,7 @@ pub enum ReadError {
224 230
225impl From<EndpointError> for ReadError { 231impl From<EndpointError> for ReadError {
226 fn from(val: EndpointError) -> Self { 232 fn from(val: EndpointError) -> Self {
227 use EndpointError::*; 233 use EndpointError::{BufferOverflow, Disabled};
228 match val { 234 match val {
229 BufferOverflow => ReadError::BufferOverflow, 235 BufferOverflow => ReadError::BufferOverflow,
230 Disabled => ReadError::Disabled, 236 Disabled => ReadError::Disabled,
@@ -251,17 +257,16 @@ impl<'d, D: Driver<'d>, const N: usize> HidWriter<'d, D, N> {
251 } 257 }
252 258
253 /// Waits for the interrupt in endpoint to be enabled. 259 /// Waits for the interrupt in endpoint to be enabled.
254 pub async fn ready(&mut self) -> () { 260 pub async fn ready(&mut self) {
255 self.ep_in.wait_enabled().await 261 self.ep_in.wait_enabled().await;
256 } 262 }
257 263
258 /// Writes an input report by serializing the given report structure. 264 /// Writes an input report by serializing the given report structure.
259 #[cfg(feature = "usbd-hid")] 265 #[cfg(feature = "usbd-hid")]
260 pub async fn write_serialize<IR: AsInputReport>(&mut self, r: &IR) -> Result<(), EndpointError> { 266 pub async fn write_serialize<IR: AsInputReport>(&mut self, r: &IR) -> Result<(), EndpointError> {
261 let mut buf: [u8; N] = [0; N]; 267 let mut buf: [u8; N] = [0; N];
262 let size = match serialize(&mut buf, r) { 268 let Ok(size) = serialize(&mut buf, r) else {
263 Ok(size) => size, 269 return Err(EndpointError::BufferOverflow);
264 Err(_) => return Err(EndpointError::BufferOverflow),
265 }; 270 };
266 self.write(&buf[0..size]).await 271 self.write(&buf[0..size]).await
267 } 272 }
@@ -286,8 +291,8 @@ impl<'d, D: Driver<'d>, const N: usize> HidWriter<'d, D, N> {
286 291
287impl<'d, D: Driver<'d>, const N: usize> HidReader<'d, D, N> { 292impl<'d, D: Driver<'d>, const N: usize> HidReader<'d, D, N> {
288 /// Waits for the interrupt out endpoint to be enabled. 293 /// Waits for the interrupt out endpoint to be enabled.
289 pub async fn ready(&mut self) -> () { 294 pub async fn ready(&mut self) {
290 self.ep_out.wait_enabled().await 295 self.ep_out.wait_enabled().await;
291 } 296 }
292 297
293 /// Delivers output reports from the Interrupt Out pipe to `handler`. 298 /// Delivers output reports from the Interrupt Out pipe to `handler`.
@@ -344,9 +349,8 @@ impl<'d, D: Driver<'d>, const N: usize> HidReader<'d, D, N> {
344 if size < max_packet_size || total == N { 349 if size < max_packet_size || total == N {
345 self.offset.store(0, Ordering::Release); 350 self.offset.store(0, Ordering::Release);
346 break; 351 break;
347 } else {
348 self.offset.store(total, Ordering::Release);
349 } 352 }
353 self.offset.store(total, Ordering::Release);
350 } 354 }
351 Err(err) => { 355 Err(err) => {
352 self.offset.store(0, Ordering::Release); 356 self.offset.store(0, Ordering::Release);
@@ -466,7 +470,7 @@ impl<'d> Handler for Control<'d> {
466 HID_REQ_SET_IDLE => { 470 HID_REQ_SET_IDLE => {
467 if let Some(handler) = self.request_handler { 471 if let Some(handler) = self.request_handler {
468 let id = req.value as u8; 472 let id = req.value as u8;
469 let id = (id != 0).then(|| ReportId::In(id)); 473 let id = (id != 0).then_some(ReportId::In(id));
470 let dur = u32::from(req.value >> 8); 474 let dur = u32::from(req.value >> 8);
471 let dur = if dur == 0 { u32::MAX } else { 4 * dur }; 475 let dur = if dur == 0 { u32::MAX } else { 4 * dur };
472 handler.set_idle_ms(id, dur); 476 handler.set_idle_ms(id, dur);
@@ -522,7 +526,7 @@ impl<'d> Handler for Control<'d> {
522 HID_REQ_GET_IDLE => { 526 HID_REQ_GET_IDLE => {
523 if let Some(handler) = self.request_handler { 527 if let Some(handler) = self.request_handler {
524 let id = req.value as u8; 528 let id = req.value as u8;
525 let id = (id != 0).then(|| ReportId::In(id)); 529 let id = (id != 0).then_some(ReportId::In(id));
526 if let Some(dur) = handler.get_idle_ms(id) { 530 if let Some(dur) = handler.get_idle_ms(id) {
527 let dur = u8::try_from(dur / 4).unwrap_or(0); 531 let dur = u8::try_from(dur / 4).unwrap_or(0);
528 buf[0] = dur; 532 buf[0] = dur;
diff --git a/embassy-usb/src/class/midi.rs b/embassy-usb/src/class/midi.rs
index c5cf8d876..52a96f278 100644
--- a/embassy-usb/src/class/midi.rs
+++ b/embassy-usb/src/class/midi.rs
@@ -27,9 +27,9 @@ const MIDI_OUT_SIZE: u8 = 0x09;
27/// writing USB packets with no intermediate buffers, but it will not act like a stream-like port. 27/// writing USB packets with no intermediate buffers, but it will not act like a stream-like port.
28/// The following constraints must be followed if you use this class directly: 28/// The following constraints must be followed if you use this class directly:
29/// 29///
30/// - `read_packet` must be called with a buffer large enough to hold max_packet_size bytes. 30/// - `read_packet` must be called with a buffer large enough to hold `max_packet_size` bytes.
31/// - `write_packet` must not be called with a buffer larger than max_packet_size bytes. 31/// - `write_packet` must not be called with a buffer larger than `max_packet_size` bytes.
32/// - If you write a packet that is exactly max_packet_size bytes long, it won't be processed by the 32/// - If you write a packet that is exactly `max_packet_size` bytes long, it won't be processed by the
33/// host operating system until a subsequent shorter packet is sent. A zero-length packet (ZLP) 33/// host operating system until a subsequent shorter packet is sent. A zero-length packet (ZLP)
34/// can be sent if there is no other data to send. This is because USB bulk transactions must be 34/// can be sent if there is no other data to send. This is because USB bulk transactions must be
35/// terminated with a short packet, even if the bulk endpoint is used for stream-like data. 35/// terminated with a short packet, even if the bulk endpoint is used for stream-like data.
@@ -39,8 +39,8 @@ pub struct MidiClass<'d, D: Driver<'d>> {
39} 39}
40 40
41impl<'d, D: Driver<'d>> MidiClass<'d, D> { 41impl<'d, D: Driver<'d>> MidiClass<'d, D> {
42 /// Creates a new MidiClass with the provided UsbBus, number of input and output jacks and max_packet_size in bytes. 42 /// Creates a new `MidiClass` with the provided UsbBus, number of input and output jacks and `max_packet_size` in bytes.
43 /// For full-speed devices, max_packet_size has to be one of 8, 16, 32 or 64. 43 /// For full-speed devices, `max_packet_size` has to be one of 8, 16, 32 or 64.
44 pub fn new(builder: &mut Builder<'d, D>, n_in_jacks: u8, n_out_jacks: u8, max_packet_size: u16) -> Self { 44 pub fn new(builder: &mut Builder<'d, D>, n_in_jacks: u8, n_out_jacks: u8, max_packet_size: u16) -> Self {
45 let mut func = builder.function(USB_AUDIO_CLASS, USB_AUDIOCONTROL_SUBCLASS, PROTOCOL_NONE); 45 let mut func = builder.function(USB_AUDIO_CLASS, USB_AUDIOCONTROL_SUBCLASS, PROTOCOL_NONE);
46 46
@@ -160,7 +160,7 @@ impl<'d, D: Driver<'d>> MidiClass<'d, D> {
160 160
161 /// Waits for the USB host to enable this interface 161 /// Waits for the USB host to enable this interface
162 pub async fn wait_connection(&mut self) { 162 pub async fn wait_connection(&mut self) {
163 self.read_ep.wait_enabled().await 163 self.read_ep.wait_enabled().await;
164 } 164 }
165 165
166 /// Split the class into a sender and receiver. 166 /// Split the class into a sender and receiver.
@@ -197,7 +197,7 @@ impl<'d, D: Driver<'d>> Sender<'d, D> {
197 197
198 /// Waits for the USB host to enable this interface 198 /// Waits for the USB host to enable this interface
199 pub async fn wait_connection(&mut self) { 199 pub async fn wait_connection(&mut self) {
200 self.write_ep.wait_enabled().await 200 self.write_ep.wait_enabled().await;
201 } 201 }
202} 202}
203 203
@@ -222,6 +222,6 @@ impl<'d, D: Driver<'d>> Receiver<'d, D> {
222 222
223 /// Waits for the USB host to enable this interface 223 /// Waits for the USB host to enable this interface
224 pub async fn wait_connection(&mut self) { 224 pub async fn wait_connection(&mut self) {
225 self.read_ep.wait_enabled().await 225 self.read_ep.wait_enabled().await;
226 } 226 }
227} 227}
diff --git a/embassy-usb/src/control.rs b/embassy-usb/src/control.rs
index ceccfd85b..79f736309 100644
--- a/embassy-usb/src/control.rs
+++ b/embassy-usb/src/control.rs
@@ -120,7 +120,7 @@ impl Request {
120 } 120 }
121 121
122 /// Gets the descriptor type and index from the value field of a GET_DESCRIPTOR request. 122 /// Gets the descriptor type and index from the value field of a GET_DESCRIPTOR request.
123 pub fn descriptor_type_index(&self) -> (u8, u8) { 123 pub const fn descriptor_type_index(&self) -> (u8, u8) {
124 ((self.value >> 8) as u8, self.value as u8) 124 ((self.value >> 8) as u8, self.value as u8)
125 } 125 }
126} 126}
diff --git a/embassy-usb/src/descriptor.rs b/embassy-usb/src/descriptor.rs
index ae38e26ca..fa83ef583 100644
--- a/embassy-usb/src/descriptor.rs
+++ b/embassy-usb/src/descriptor.rs
@@ -2,7 +2,7 @@
2 2
3use crate::builder::Config; 3use crate::builder::Config;
4use crate::driver::EndpointInfo; 4use crate::driver::EndpointInfo;
5use crate::types::*; 5use crate::types::{InterfaceNumber, StringIndex};
6use crate::CONFIGURATION_VALUE; 6use crate::CONFIGURATION_VALUE;
7 7
8/// Standard descriptor types 8/// Standard descriptor types
@@ -59,7 +59,7 @@ impl<'a> DescriptorWriter<'a> {
59 } 59 }
60 60
61 /// Gets the current position in the buffer, i.e. the number of bytes written so far. 61 /// Gets the current position in the buffer, i.e. the number of bytes written so far.
62 pub fn position(&self) -> usize { 62 pub const fn position(&self) -> usize {
63 self.position 63 self.position
64 } 64 }
65 65
@@ -67,9 +67,10 @@ impl<'a> DescriptorWriter<'a> {
67 pub fn write(&mut self, descriptor_type: u8, descriptor: &[u8]) { 67 pub fn write(&mut self, descriptor_type: u8, descriptor: &[u8]) {
68 let length = descriptor.len(); 68 let length = descriptor.len();
69 69
70 if (self.position + 2 + length) > self.buf.len() || (length + 2) > 255 { 70 assert!(
71 panic!("Descriptor buffer full"); 71 (self.position + 2 + length) <= self.buf.len() && (length + 2) <= 255,
72 } 72 "Descriptor buffer full"
73 );
73 74
74 self.buf[self.position] = (length + 2) as u8; 75 self.buf[self.position] = (length + 2) as u8;
75 self.buf[self.position + 1] = descriptor_type; 76 self.buf[self.position + 1] = descriptor_type;
@@ -102,7 +103,7 @@ impl<'a> DescriptorWriter<'a> {
102 config.serial_number.map_or(0, |_| 3), // iSerialNumber 103 config.serial_number.map_or(0, |_| 3), // iSerialNumber
103 1, // bNumConfigurations 104 1, // bNumConfigurations
104 ], 105 ],
105 ) 106 );
106 } 107 }
107 108
108 pub(crate) fn configuration(&mut self, config: &Config) { 109 pub(crate) fn configuration(&mut self, config: &Config) {
@@ -120,7 +121,7 @@ impl<'a> DescriptorWriter<'a> {
120 | if config.supports_remote_wakeup { 0x20 } else { 0x00 }, // bmAttributes 121 | if config.supports_remote_wakeup { 0x20 } else { 0x00 }, // bmAttributes
121 (config.max_power / 2) as u8, // bMaxPower 122 (config.max_power / 2) as u8, // bMaxPower
122 ], 123 ],
123 ) 124 );
124 } 125 }
125 126
126 #[allow(unused)] 127 #[allow(unused)]
@@ -248,9 +249,7 @@ impl<'a> DescriptorWriter<'a> {
248 pub(crate) fn string(&mut self, string: &str) { 249 pub(crate) fn string(&mut self, string: &str) {
249 let mut pos = self.position; 250 let mut pos = self.position;
250 251
251 if pos + 2 > self.buf.len() { 252 assert!(pos + 2 <= self.buf.len(), "Descriptor buffer full");
252 panic!("Descriptor buffer full");
253 }
254 253
255 self.buf[pos] = 0; // length placeholder 254 self.buf[pos] = 0; // length placeholder
256 self.buf[pos + 1] = descriptor_type::STRING; 255 self.buf[pos + 1] = descriptor_type::STRING;
@@ -258,9 +257,7 @@ impl<'a> DescriptorWriter<'a> {
258 pos += 2; 257 pos += 2;
259 258
260 for c in string.encode_utf16() { 259 for c in string.encode_utf16() {
261 if pos >= self.buf.len() { 260 assert!(pos < self.buf.len(), "Descriptor buffer full");
262 panic!("Descriptor buffer full");
263 }
264 261
265 self.buf[pos..pos + 2].copy_from_slice(&c.to_le_bytes()); 262 self.buf[pos..pos + 2].copy_from_slice(&c.to_le_bytes());
266 pos += 2; 263 pos += 2;
@@ -279,9 +276,9 @@ pub struct BosWriter<'a> {
279} 276}
280 277
281impl<'a> BosWriter<'a> { 278impl<'a> BosWriter<'a> {
282 pub(crate) fn new(writer: DescriptorWriter<'a>) -> Self { 279 pub(crate) const fn new(writer: DescriptorWriter<'a>) -> Self {
283 Self { 280 Self {
284 writer: writer, 281 writer,
285 num_caps_mark: None, 282 num_caps_mark: None,
286 } 283 }
287 } 284 }
@@ -314,9 +311,10 @@ impl<'a> BosWriter<'a> {
314 let mut start = self.writer.position; 311 let mut start = self.writer.position;
315 let blen = data.len(); 312 let blen = data.len();
316 313
317 if (start + blen + 3) > self.writer.buf.len() || (blen + 3) > 255 { 314 assert!(
318 panic!("Descriptor buffer full"); 315 (start + blen + 3) <= self.writer.buf.len() && (blen + 3) <= 255,
319 } 316 "Descriptor buffer full"
317 );
320 318
321 self.writer.buf[start] = (blen + 3) as u8; 319 self.writer.buf[start] = (blen + 3) as u8;
322 self.writer.buf[start + 1] = descriptor_type::CAPABILITY; 320 self.writer.buf[start + 1] = descriptor_type::CAPABILITY;
diff --git a/embassy-usb/src/descriptor_reader.rs b/embassy-usb/src/descriptor_reader.rs
index 05adcce60..abb4b379e 100644
--- a/embassy-usb/src/descriptor_reader.rs
+++ b/embassy-usb/src/descriptor_reader.rs
@@ -11,11 +11,11 @@ pub struct Reader<'a> {
11} 11}
12 12
13impl<'a> Reader<'a> { 13impl<'a> Reader<'a> {
14 pub fn new(data: &'a [u8]) -> Self { 14 pub const fn new(data: &'a [u8]) -> Self {
15 Self { data } 15 Self { data }
16 } 16 }
17 17
18 pub fn eof(&self) -> bool { 18 pub const fn eof(&self) -> bool {
19 self.data.is_empty() 19 self.data.is_empty()
20 } 20 }
21 21
@@ -102,7 +102,7 @@ pub fn foreach_endpoint(data: &[u8], mut f: impl FnMut(EndpointInfo)) -> Result<
102 } 102 }
103 descriptor_type::ENDPOINT => { 103 descriptor_type::ENDPOINT => {
104 ep.ep_address = EndpointAddress::from(r.read_u8()?); 104 ep.ep_address = EndpointAddress::from(r.read_u8()?);
105 f(ep) 105 f(ep);
106 } 106 }
107 _ => {} 107 _ => {}
108 } 108 }
diff --git a/embassy-usb/src/lib.rs b/embassy-usb/src/lib.rs
index 1180b9b66..88d88cad7 100644
--- a/embassy-usb/src/lib.rs
+++ b/embassy-usb/src/lib.rs
@@ -24,12 +24,12 @@ use embassy_futures::select::{select, Either};
24use heapless::Vec; 24use heapless::Vec;
25 25
26pub use crate::builder::{Builder, Config, FunctionBuilder, InterfaceAltBuilder, InterfaceBuilder}; 26pub use crate::builder::{Builder, Config, FunctionBuilder, InterfaceAltBuilder, InterfaceBuilder};
27use crate::config::*; 27use crate::config::{MAX_HANDLER_COUNT, MAX_INTERFACE_COUNT};
28use crate::control::*; 28use crate::control::{InResponse, OutResponse, Recipient, Request, RequestType};
29use crate::descriptor::*; 29use crate::descriptor::{descriptor_type, lang_id};
30use crate::descriptor_reader::foreach_endpoint; 30use crate::descriptor_reader::foreach_endpoint;
31use crate::driver::{Bus, ControlPipe, Direction, Driver, EndpointAddress, Event}; 31use crate::driver::{Bus, ControlPipe, Direction, Driver, EndpointAddress, Event};
32use crate::types::*; 32use crate::types::{InterfaceNumber, StringIndex};
33 33
34/// The global state of the USB device. 34/// The global state of the USB device.
35/// 35///
@@ -294,7 +294,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
294 /// After dropping the future, [`UsbDevice::disable()`] should be called 294 /// After dropping the future, [`UsbDevice::disable()`] should be called
295 /// before calling any other `UsbDevice` methods to fully reset the 295 /// before calling any other `UsbDevice` methods to fully reset the
296 /// peripheral. 296 /// peripheral.
297 pub async fn run_until_suspend(&mut self) -> () { 297 pub async fn run_until_suspend(&mut self) {
298 while !self.inner.suspended { 298 while !self.inner.suspended {
299 let control_fut = self.control.setup(); 299 let control_fut = self.control.setup();
300 let bus_fut = self.inner.bus.poll(); 300 let bus_fut = self.inner.bus.poll();
@@ -364,6 +364,8 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
364 } 364 }
365 365
366 async fn handle_control_in(&mut self, req: Request) { 366 async fn handle_control_in(&mut self, req: Request) {
367 const DEVICE_DESCRIPTOR_LEN: usize = 18;
368
367 let mut resp_length = req.length as usize; 369 let mut resp_length = req.length as usize;
368 let max_packet_size = self.control.max_packet_size(); 370 let max_packet_size = self.control.max_packet_size();
369 371
@@ -371,19 +373,15 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
371 // The host doesn't know our EP0 max packet size yet, and might assume 373 // The host doesn't know our EP0 max packet size yet, and might assume
372 // a full-length packet is a short packet, thinking we're done sending data. 374 // a full-length packet is a short packet, thinking we're done sending data.
373 // See https://github.com/hathach/tinyusb/issues/184 375 // See https://github.com/hathach/tinyusb/issues/184
374 const DEVICE_DESCRIPTOR_LEN: usize = 18; 376 if self.inner.address == 0 && max_packet_size < DEVICE_DESCRIPTOR_LEN && max_packet_size < resp_length {
375 if self.inner.address == 0
376 && max_packet_size < DEVICE_DESCRIPTOR_LEN
377 && (max_packet_size as usize) < resp_length
378 {
379 trace!("received control req while not addressed: capping response to 1 packet."); 377 trace!("received control req while not addressed: capping response to 1 packet.");
380 resp_length = max_packet_size; 378 resp_length = max_packet_size;
381 } 379 }
382 380
383 match self.inner.handle_control_in(req, &mut self.control_buf) { 381 match self.inner.handle_control_in(req, self.control_buf) {
384 InResponse::Accepted(data) => { 382 InResponse::Accepted(data) => {
385 let len = data.len().min(resp_length); 383 let len = data.len().min(resp_length);
386 let need_zlp = len != resp_length && (len % usize::from(max_packet_size)) == 0; 384 let need_zlp = len != resp_length && (len % max_packet_size) == 0;
387 385
388 let chunks = data[0..len] 386 let chunks = data[0..len]
389 .chunks(max_packet_size) 387 .chunks(max_packet_size)
@@ -435,7 +433,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
435 self.control.accept_set_address(self.inner.address).await; 433 self.control.accept_set_address(self.inner.address).await;
436 self.inner.set_address_pending = false; 434 self.inner.set_address_pending = false;
437 } else { 435 } else {
438 self.control.accept().await 436 self.control.accept().await;
439 } 437 }
440 } 438 }
441 OutResponse::Rejected => self.control.reject().await, 439 OutResponse::Rejected => self.control.reject().await,
@@ -548,9 +546,8 @@ impl<'d, D: Driver<'d>> Inner<'d, D> {
548 546
549 OutResponse::Accepted 547 OutResponse::Accepted
550 } 548 }
551 (Request::SET_CONFIGURATION, CONFIGURATION_NONE_U16) => match self.device_state { 549 (Request::SET_CONFIGURATION, CONFIGURATION_NONE_U16) => {
552 UsbDeviceState::Default => OutResponse::Accepted, 550 if self.device_state != UsbDeviceState::Default {
553 _ => {
554 debug!("SET_CONFIGURATION: unconfigured"); 551 debug!("SET_CONFIGURATION: unconfigured");
555 self.device_state = UsbDeviceState::Addressed; 552 self.device_state = UsbDeviceState::Addressed;
556 553
@@ -564,17 +561,15 @@ impl<'d, D: Driver<'d>> Inner<'d, D> {
564 for h in &mut self.handlers { 561 for h in &mut self.handlers {
565 h.configured(false); 562 h.configured(false);
566 } 563 }
567
568 OutResponse::Accepted
569 } 564 }
570 }, 565 OutResponse::Accepted
566 }
571 _ => OutResponse::Rejected, 567 _ => OutResponse::Rejected,
572 }, 568 },
573 (RequestType::Standard, Recipient::Interface) => { 569 (RequestType::Standard, Recipient::Interface) => {
574 let iface_num = InterfaceNumber::new(req.index as _); 570 let iface_num = InterfaceNumber::new(req.index as _);
575 let iface = match self.interfaces.get_mut(iface_num.0 as usize) { 571 let Some(iface) = self.interfaces.get_mut(iface_num.0 as usize) else {
576 Some(iface) => iface, 572 return OutResponse::Rejected;
577 None => return OutResponse::Rejected,
578 }; 573 };
579 574
580 match req.request { 575 match req.request {
@@ -650,9 +645,8 @@ impl<'d, D: Driver<'d>> Inner<'d, D> {
650 _ => InResponse::Rejected, 645 _ => InResponse::Rejected,
651 }, 646 },
652 (RequestType::Standard, Recipient::Interface) => { 647 (RequestType::Standard, Recipient::Interface) => {
653 let iface = match self.interfaces.get_mut(req.index as usize) { 648 let Some(iface) = self.interfaces.get_mut(req.index as usize) else {
654 Some(iface) => iface, 649 return InResponse::Rejected;
655 None => return InResponse::Rejected,
656 }; 650 };
657 651
658 match req.request { 652 match req.request {
@@ -706,7 +700,7 @@ impl<'d, D: Driver<'d>> Inner<'d, D> {
706 } 700 }
707 701
708 fn handle_control_in_delegated<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> { 702 fn handle_control_in_delegated<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> {
709 unsafe fn extend_lifetime<'x, 'y>(r: InResponse<'x>) -> InResponse<'y> { 703 unsafe fn extend_lifetime<'y>(r: InResponse<'_>) -> InResponse<'y> {
710 core::mem::transmute(r) 704 core::mem::transmute(r)
711 } 705 }
712 706
@@ -756,16 +750,12 @@ impl<'d, D: Driver<'d>> Inner<'d, D> {
756 }; 750 };
757 751
758 if let Some(s) = s { 752 if let Some(s) = s {
759 if buf.len() < 2 { 753 assert!(buf.len() >= 2, "control buffer too small");
760 panic!("control buffer too small");
761 }
762 754
763 buf[1] = descriptor_type::STRING; 755 buf[1] = descriptor_type::STRING;
764 let mut pos = 2; 756 let mut pos = 2;
765 for c in s.encode_utf16() { 757 for c in s.encode_utf16() {
766 if pos + 2 >= buf.len() { 758 assert!(pos + 2 < buf.len(), "control buffer too small");
767 panic!("control buffer too small");
768 }
769 759
770 buf[pos..pos + 2].copy_from_slice(&c.to_le_bytes()); 760 buf[pos..pos + 2].copy_from_slice(&c.to_le_bytes());
771 pos += 2; 761 pos += 2;
diff --git a/embassy-usb/src/msos.rs b/embassy-usb/src/msos.rs
index 847338e5f..13d5d7c4b 100644
--- a/embassy-usb/src/msos.rs
+++ b/embassy-usb/src/msos.rs
@@ -6,7 +6,7 @@
6 6
7use core::mem::size_of; 7use core::mem::size_of;
8 8
9use super::{capability_type, BosWriter}; 9use crate::descriptor::{capability_type, BosWriter};
10use crate::types::InterfaceNumber; 10use crate::types::InterfaceNumber;
11 11
12/// A serialized Microsoft OS 2.0 Descriptor set. 12/// A serialized Microsoft OS 2.0 Descriptor set.
diff --git a/embassy-usb/src/types.rs b/embassy-usb/src/types.rs
index c7a47f7e4..cb9fe2576 100644
--- a/embassy-usb/src/types.rs
+++ b/embassy-usb/src/types.rs
@@ -7,7 +7,7 @@
7pub struct InterfaceNumber(pub u8); 7pub struct InterfaceNumber(pub u8);
8 8
9impl InterfaceNumber { 9impl InterfaceNumber {
10 pub(crate) fn new(index: u8) -> InterfaceNumber { 10 pub(crate) const fn new(index: u8) -> InterfaceNumber {
11 InterfaceNumber(index) 11 InterfaceNumber(index)
12 } 12 }
13} 13}
@@ -25,7 +25,7 @@ impl From<InterfaceNumber> for u8 {
25pub struct StringIndex(pub u8); 25pub struct StringIndex(pub u8);
26 26
27impl StringIndex { 27impl StringIndex {
28 pub(crate) fn new(index: u8) -> StringIndex { 28 pub(crate) const fn new(index: u8) -> StringIndex {
29 StringIndex(index) 29 StringIndex(index)
30 } 30 }
31} 31}