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() { // envvars take priority. if !cfg.seen_env { - if cfg.seen_feature { - panic!("multiple values set for feature {}: {} and {}", name, cfg.value, value); - } + assert!( + !cfg.seen_feature, + "multiple values set for feature {}: {} and {}", + name, cfg.value, value + ); cfg.value = value; 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 @@ use heapless::Vec; -use crate::config::*; +use crate::config::MAX_HANDLER_COUNT; use crate::descriptor::{BosWriter, DescriptorWriter}; use crate::driver::{Driver, Endpoint, EndpointType}; #[cfg(feature = "msos-descriptor")] use crate::msos::{DeviceLevelDescriptor, FunctionLevelDescriptor, MsOsDescriptorWriter}; -use crate::types::*; +use crate::types::{InterfaceNumber, StringIndex}; use crate::{Handler, Interface, UsbDevice, MAX_INTERFACE_COUNT, STRING_INDEX_CUSTOM_START}; #[derive(Debug, Copy, Clone)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[non_exhaustive] -/// Configuration used when creating [UsbDevice]. +/// Configuration used when creating [`UsbDevice`]. pub struct Config<'a> { pub(crate) vendor_id: u16, pub(crate) product_id: u16, @@ -99,7 +99,7 @@ pub struct Config<'a> { impl<'a> Config<'a> { /// Create default configuration with the provided vid and pid values. - pub fn new(vid: u16, pid: u16) -> Self { + pub const fn new(vid: u16, pid: u16) -> Self { Self { device_class: 0x00, device_sub_class: 0x00, @@ -159,9 +159,10 @@ impl<'d, D: Driver<'d>> Builder<'d, D> { panic!("if composite_with_iads is set, you must set device_class = 0xEF, device_sub_class = 0x02, device_protocol = 0x01"); } - if config.max_power > 500 { - panic!("The maximum allowed value for `max_power` is 500mA"); - } + assert!( + config.max_power <= 500, + "The maximum allowed value for `max_power` is 500mA" + ); match config.max_packet_size_0 { 8 | 16 | 32 | 64 => {} @@ -260,12 +261,11 @@ impl<'d, D: Driver<'d>> Builder<'d, D> { /// The Handler is called on some USB bus events, and to handle all control requests not already /// handled by the USB stack. pub fn handler(&mut self, handler: &'d mut dyn Handler) { - if self.handlers.push(handler).is_err() { - panic!( - "embassy-usb: handler list full. Increase the `max_handler_count` compile-time setting. Current value: {}", - MAX_HANDLER_COUNT - ) - } + assert!( + self.handlers.push(handler).is_ok(), + "embassy-usb: handler list full. Increase the `max_handler_count` compile-time setting. Current value: {}", + MAX_HANDLER_COUNT + ); } /// Allocates a new string index. @@ -332,12 +332,10 @@ impl<'a, 'd, D: Driver<'d>> FunctionBuilder<'a, 'd, D> { num_alt_settings: 0, }; - if self.builder.interfaces.push(iface).is_err() { - panic!( - "embassy-usb: interface list full. Increase the `max_interface_count` compile-time setting. Current value: {}", - MAX_INTERFACE_COUNT - ) - } + assert!(self.builder.interfaces.push(iface).is_ok(), + "embassy-usb: interface list full. Increase the `max_interface_count` compile-time setting. Current value: {}", + MAX_INTERFACE_COUNT + ); InterfaceBuilder { builder: self.builder, @@ -371,7 +369,7 @@ pub struct InterfaceBuilder<'a, 'd, D: Driver<'d>> { impl<'a, 'd, D: Driver<'d>> InterfaceBuilder<'a, 'd, D> { /// Get the interface number. - pub fn interface_number(&self) -> InterfaceNumber { + pub const fn interface_number(&self) -> InterfaceNumber { self.interface_number } @@ -422,12 +420,12 @@ pub struct InterfaceAltBuilder<'a, 'd, D: Driver<'d>> { impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> { /// Get the interface number. - pub fn interface_number(&self) -> InterfaceNumber { + pub const fn interface_number(&self) -> InterfaceNumber { self.interface_number } /// Get the alternate setting number. - pub fn alt_setting_number(&self) -> u8 { + pub const fn alt_setting_number(&self) -> u8 { self.alt_setting_number } @@ -436,7 +434,7 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> { /// Descriptors are written in the order builder functions are called. Note that some /// classes care about the order. pub fn descriptor(&mut self, descriptor_type: u8, descriptor: &[u8]) { - self.builder.config_descriptor.write(descriptor_type, descriptor) + self.builder.config_descriptor.write(descriptor_type, descriptor); } 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; use crate::control::{self, InResponse, OutResponse, Recipient, Request, RequestType}; use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut}; -use crate::types::*; +use crate::types::InterfaceNumber; use crate::{Builder, Handler}; /// This should be used as `device_class` when building the `UsbDevice`. @@ -39,12 +39,18 @@ pub struct State<'a> { shared: ControlShared, } +impl<'a> Default for State<'a> { + fn default() -> Self { + Self::new() + } +} + impl<'a> State<'a> { /// Create a new `State`. pub fn new() -> Self { Self { control: MaybeUninit::uninit(), - shared: Default::default(), + shared: ControlShared::default(), } } } @@ -55,9 +61,9 @@ impl<'a> State<'a> { /// writing USB packets with no intermediate buffers, but it will not act like a stream-like serial /// port. The following constraints must be followed if you use this class directly: /// -/// - `read_packet` must be called with a buffer large enough to hold max_packet_size bytes. -/// - `write_packet` must not be called with a buffer larger than max_packet_size bytes. -/// - If you write a packet that is exactly max_packet_size bytes long, it won't be processed by the +/// - `read_packet` must be called with a buffer large enough to hold `max_packet_size` bytes. +/// - `write_packet` must not be called with a buffer larger than `max_packet_size` bytes. +/// - If you write a packet that is exactly `max_packet_size` bytes long, it won't be processed by the /// host operating system until a subsequent shorter packet is sent. A zero-length packet (ZLP) /// can be sent if there is no other data to send. This is because USB bulk transactions must be /// terminated with a short packet, even if the bulk endpoint is used for stream-like data. @@ -103,17 +109,16 @@ impl Default for ControlShared { impl ControlShared { async fn changed(&self) { - poll_fn(|cx| match self.changed.load(Ordering::Relaxed) { - true => { + poll_fn(|cx| { + if self.changed.load(Ordering::Relaxed) { self.changed.store(false, Ordering::Relaxed); Poll::Ready(()) - } - false => { + } else { self.waker.borrow_mut().register(cx.waker()); Poll::Pending } }) - .await + .await; } } @@ -192,7 +197,7 @@ impl<'d> Handler for Control<'d> { // REQ_GET_ENCAPSULATED_COMMAND is not really supported - it will be rejected below. REQ_GET_LINE_CODING if req.length == 7 => { debug!("Sending line coding"); - let coding = self.shared().line_coding.lock(|x| x.get()); + let coding = self.shared().line_coding.lock(Cell::get); assert!(buf.len() >= 7); buf[0..4].copy_from_slice(&coding.data_rate.to_le_bytes()); buf[4] = coding.stop_bits as u8; @@ -206,8 +211,8 @@ impl<'d> Handler for Control<'d> { } impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> { - /// Creates a new CdcAcmClass with the provided UsbBus and max_packet_size in bytes. For - /// full-speed devices, max_packet_size has to be one of 8, 16, 32 or 64. + /// Creates a new CdcAcmClass with the provided UsbBus and `max_packet_size` in bytes. For + /// full-speed devices, `max_packet_size` has to be one of 8, 16, 32 or 64. pub fn new(builder: &mut Builder<'d, D>, state: &'d mut State<'d>, max_packet_size: u16) -> Self { assert!(builder.control_buf_len() >= 7); @@ -242,7 +247,7 @@ impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> { &[ CDC_TYPE_UNION, // bDescriptorSubtype comm_if.into(), // bControlInterface - data_if.into(), // bSubordinateInterface + data_if, // bSubordinateInterface ], ); @@ -283,7 +288,7 @@ impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> { /// Gets the current line coding. The line coding contains information that's mainly relevant /// for USB to UART serial port emulators, and can be ignored if not relevant. pub fn line_coding(&self) -> LineCoding { - self.control.line_coding.lock(|x| x.get()) + self.control.line_coding.lock(Cell::get) } /// Gets the DTR (data terminal ready) state @@ -308,7 +313,7 @@ impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> { /// Waits for the USB host to enable this interface pub async fn wait_connection(&mut self) { - self.read_ep.wait_enabled().await + self.read_ep.wait_enabled().await; } /// Split the class into a sender and receiver. @@ -356,7 +361,7 @@ pub struct ControlChanged<'d> { impl<'d> ControlChanged<'d> { /// Return a future for when the control settings change pub async fn control_changed(&self) { - self.control.changed().await + self.control.changed().await; } } @@ -378,7 +383,7 @@ impl<'d, D: Driver<'d>> Sender<'d, D> { /// Gets the current line coding. The line coding contains information that's mainly relevant /// for USB to UART serial port emulators, and can be ignored if not relevant. pub fn line_coding(&self) -> LineCoding { - self.control.line_coding.lock(|x| x.get()) + self.control.line_coding.lock(Cell::get) } /// Gets the DTR (data terminal ready) state @@ -398,7 +403,7 @@ impl<'d, D: Driver<'d>> Sender<'d, D> { /// Waits for the USB host to enable this interface pub async fn wait_connection(&mut self) { - self.write_ep.wait_enabled().await + self.write_ep.wait_enabled().await; } } @@ -420,7 +425,7 @@ impl<'d, D: Driver<'d>> Receiver<'d, D> { /// Gets the current line coding. The line coding contains information that's mainly relevant /// for USB to UART serial port emulators, and can be ignored if not relevant. pub fn line_coding(&self) -> LineCoding { - self.control.line_coding.lock(|x| x.get()) + self.control.line_coding.lock(Cell::get) } /// Gets the DTR (data terminal ready) state @@ -440,7 +445,7 @@ impl<'d, D: Driver<'d>> Receiver<'d, D> { /// Waits for the USB host to enable this interface pub async fn wait_connection(&mut self) { - self.read_ep.wait_enabled().await + self.read_ep.wait_enabled().await; } } @@ -514,17 +519,17 @@ impl LineCoding { } /// Gets the number of data bits for UART communication. - pub fn data_bits(&self) -> u8 { + pub const fn data_bits(&self) -> u8 { self.data_bits } /// Gets the parity type for UART communication. - pub fn parity_type(&self) -> ParityType { + pub const fn parity_type(&self) -> ParityType { self.parity_type } /// Gets the data rate in bits per second for UART communication. - pub fn data_rate(&self) -> u32 { + pub const fn data_rate(&self) -> u32 { self.data_rate } } 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 @@ use core::intrinsics::copy_nonoverlapping; use core::mem::{size_of, MaybeUninit}; +use core::ptr::addr_of; use crate::control::{self, InResponse, OutResponse, Recipient, Request, RequestType}; use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut}; -use crate::types::*; +use crate::types::{InterfaceNumber, StringIndex}; use crate::{Builder, Handler}; pub mod embassy_net; @@ -62,9 +63,9 @@ const REQ_SET_NTB_INPUT_SIZE: u8 = 0x86; //const NOTIF_POLL_INTERVAL: u8 = 20; const NTB_MAX_SIZE: usize = 2048; -const SIG_NTH: u32 = 0x484d434e; -const SIG_NDP_NO_FCS: u32 = 0x304d434e; -const SIG_NDP_WITH_FCS: u32 = 0x314d434e; +const SIG_NTH: u32 = 0x484d_434e; +const SIG_NDP_NO_FCS: u32 = 0x304d_434e; +const SIG_NDP_WITH_FCS: u32 = 0x314d_434e; const ALTERNATE_SETTING_DISABLED: u8 = 0x00; const ALTERNATE_SETTING_ENABLED: u8 = 0x01; @@ -111,7 +112,7 @@ struct NtbParametersDir { fn byteify(buf: &mut [u8], data: T) -> &[u8] { let len = size_of::(); - unsafe { copy_nonoverlapping(&data as *const _ as *const u8, buf.as_mut_ptr(), len) } + unsafe { copy_nonoverlapping(addr_of!(data).cast(), buf.as_mut_ptr(), len) } &buf[..len] } @@ -121,27 +122,28 @@ pub struct State<'a> { shared: ControlShared, } +impl<'a> Default for State<'a> { + fn default() -> Self { + Self::new() + } +} + impl<'a> State<'a> { /// Create a new `State`. pub fn new() -> Self { Self { control: MaybeUninit::uninit(), - shared: Default::default(), + shared: ControlShared::default(), } } } -/// Shared data between Control and CdcAcmClass +/// Shared data between Control and `CdcAcmClass` +#[derive(Default)] struct ControlShared { mac_addr: [u8; 6], } -impl Default for ControlShared { - fn default() -> Self { - ControlShared { mac_addr: [0; 6] } - } -} - struct Control<'a> { mac_addr_string: StringIndex, shared: &'a ControlShared, @@ -377,12 +379,12 @@ impl<'d, D: Driver<'d>> Sender<'d, D> { /// /// This waits until the packet is successfully stored in the CDC-NCM endpoint buffers. pub async fn write_packet(&mut self, data: &[u8]) -> Result<(), EndpointError> { - let seq = self.seq; - self.seq = self.seq.wrapping_add(1); - const OUT_HEADER_LEN: usize = 28; const ABS_MAX_PACKET_SIZE: usize = 512; + let seq = self.seq; + self.seq = self.seq.wrapping_add(1); + let header = NtbOutHeader { nth_sig: SIG_NTH, nth_len: 0x0c, @@ -416,7 +418,7 @@ impl<'d, D: Driver<'d>> Sender<'d, D> { self.write_ep.write(&buf[..self.max_packet_size]).await?; for chunk in d2.chunks(self.max_packet_size) { - self.write_ep.write(&chunk).await?; + self.write_ep.write(chunk).await?; } // Send ZLP if needed. @@ -459,12 +461,9 @@ impl<'d, D: Driver<'d>> Receiver<'d, D> { let ntb = &ntb[..pos]; // Process NTB header (NTH) - let nth = match ntb.get(..12) { - Some(x) => x, - None => { - warn!("Received too short NTB"); - continue; - } + let Some(nth) = ntb.get(..12) else { + warn!("Received too short NTB"); + continue; }; let sig = u32::from_le_bytes(nth[0..4].try_into().unwrap()); if sig != SIG_NTH { @@ -474,12 +473,9 @@ impl<'d, D: Driver<'d>> Receiver<'d, D> { let ndp_idx = u16::from_le_bytes(nth[10..12].try_into().unwrap()) as usize; // Process NTB Datagram Pointer (NDP) - let ndp = match ntb.get(ndp_idx..ndp_idx + 12) { - Some(x) => x, - None => { - warn!("NTH has an NDP pointer out of range."); - continue; - } + let Some(ndp) = ntb.get(ndp_idx..ndp_idx + 12) else { + warn!("NTH has an NDP pointer out of range."); + continue; }; let sig = u32::from_le_bytes(ndp[0..4].try_into().unwrap()); if sig != SIG_NDP_NO_FCS && sig != SIG_NDP_WITH_FCS { @@ -495,12 +491,9 @@ impl<'d, D: Driver<'d>> Receiver<'d, D> { } // Process actual datagram, finally. - let datagram = match ntb.get(datagram_index..datagram_index + datagram_len) { - Some(x) => x, - None => { - warn!("NDP has a datagram pointer out of range."); - continue; - } + let Some(datagram) = ntb.get(datagram_index..datagram_index + datagram_len) else { + warn!("NDP has a datagram pointer out of range."); + continue; }; buf[..datagram_len].copy_from_slice(datagram); 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 { } impl ReportId { - fn try_from(value: u16) -> Result { + const fn try_from(value: u16) -> Result { match value >> 8 { 1 => Ok(ReportId::In(value as u8)), 2 => Ok(ReportId::Out(value as u8)), @@ -79,9 +79,15 @@ pub struct State<'d> { out_report_offset: AtomicUsize, } +impl<'d> Default for State<'d> { + fn default() -> Self { + Self::new() + } +} + impl<'d> State<'d> { /// Create a new `State`. - pub fn new() -> Self { + pub const fn new() -> Self { State { control: MaybeUninit::uninit(), out_report_offset: AtomicUsize::new(0), @@ -148,7 +154,7 @@ fn build<'d, D: Driver<'d>>( } impl<'d, D: Driver<'d>, const READ_N: usize, const WRITE_N: usize> HidReaderWriter<'d, D, READ_N, WRITE_N> { - /// Creates a new HidReaderWriter. + /// Creates a new `HidReaderWriter`. /// /// This will allocate one IN and one OUT endpoints. If you only need writing (sending) /// 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 } /// Waits for both IN and OUT endpoints to be enabled. - pub async fn ready(&mut self) -> () { + pub async fn ready(&mut self) { self.reader.ready().await; self.writer.ready().await; } @@ -224,7 +230,7 @@ pub enum ReadError { impl From for ReadError { fn from(val: EndpointError) -> Self { - use EndpointError::*; + use EndpointError::{BufferOverflow, Disabled}; match val { BufferOverflow => ReadError::BufferOverflow, Disabled => ReadError::Disabled, @@ -251,17 +257,16 @@ impl<'d, D: Driver<'d>, const N: usize> HidWriter<'d, D, N> { } /// Waits for the interrupt in endpoint to be enabled. - pub async fn ready(&mut self) -> () { - self.ep_in.wait_enabled().await + pub async fn ready(&mut self) { + self.ep_in.wait_enabled().await; } /// Writes an input report by serializing the given report structure. #[cfg(feature = "usbd-hid")] pub async fn write_serialize(&mut self, r: &IR) -> Result<(), EndpointError> { let mut buf: [u8; N] = [0; N]; - let size = match serialize(&mut buf, r) { - Ok(size) => size, - Err(_) => return Err(EndpointError::BufferOverflow), + let Ok(size) = serialize(&mut buf, r) else { + return Err(EndpointError::BufferOverflow); }; self.write(&buf[0..size]).await } @@ -286,8 +291,8 @@ impl<'d, D: Driver<'d>, const N: usize> HidWriter<'d, D, N> { impl<'d, D: Driver<'d>, const N: usize> HidReader<'d, D, N> { /// Waits for the interrupt out endpoint to be enabled. - pub async fn ready(&mut self) -> () { - self.ep_out.wait_enabled().await + pub async fn ready(&mut self) { + self.ep_out.wait_enabled().await; } /// 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> { if size < max_packet_size || total == N { self.offset.store(0, Ordering::Release); break; - } else { - self.offset.store(total, Ordering::Release); } + self.offset.store(total, Ordering::Release); } Err(err) => { self.offset.store(0, Ordering::Release); @@ -466,7 +470,7 @@ impl<'d> Handler for Control<'d> { HID_REQ_SET_IDLE => { if let Some(handler) = self.request_handler { let id = req.value as u8; - let id = (id != 0).then(|| ReportId::In(id)); + let id = (id != 0).then_some(ReportId::In(id)); let dur = u32::from(req.value >> 8); let dur = if dur == 0 { u32::MAX } else { 4 * dur }; handler.set_idle_ms(id, dur); @@ -522,7 +526,7 @@ impl<'d> Handler for Control<'d> { HID_REQ_GET_IDLE => { if let Some(handler) = self.request_handler { let id = req.value as u8; - let id = (id != 0).then(|| ReportId::In(id)); + let id = (id != 0).then_some(ReportId::In(id)); if let Some(dur) = handler.get_idle_ms(id) { let dur = u8::try_from(dur / 4).unwrap_or(0); 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; /// writing USB packets with no intermediate buffers, but it will not act like a stream-like port. /// The following constraints must be followed if you use this class directly: /// -/// - `read_packet` must be called with a buffer large enough to hold max_packet_size bytes. -/// - `write_packet` must not be called with a buffer larger than max_packet_size bytes. -/// - If you write a packet that is exactly max_packet_size bytes long, it won't be processed by the +/// - `read_packet` must be called with a buffer large enough to hold `max_packet_size` bytes. +/// - `write_packet` must not be called with a buffer larger than `max_packet_size` bytes. +/// - If you write a packet that is exactly `max_packet_size` bytes long, it won't be processed by the /// host operating system until a subsequent shorter packet is sent. A zero-length packet (ZLP) /// can be sent if there is no other data to send. This is because USB bulk transactions must be /// 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>> { } impl<'d, D: Driver<'d>> MidiClass<'d, D> { - /// Creates a new MidiClass with the provided UsbBus, number of input and output jacks and max_packet_size in bytes. - /// For full-speed devices, max_packet_size has to be one of 8, 16, 32 or 64. + /// Creates a new `MidiClass` with the provided UsbBus, number of input and output jacks and `max_packet_size` in bytes. + /// For full-speed devices, `max_packet_size` has to be one of 8, 16, 32 or 64. pub fn new(builder: &mut Builder<'d, D>, n_in_jacks: u8, n_out_jacks: u8, max_packet_size: u16) -> Self { let mut func = builder.function(USB_AUDIO_CLASS, USB_AUDIOCONTROL_SUBCLASS, PROTOCOL_NONE); @@ -160,7 +160,7 @@ impl<'d, D: Driver<'d>> MidiClass<'d, D> { /// Waits for the USB host to enable this interface pub async fn wait_connection(&mut self) { - self.read_ep.wait_enabled().await + self.read_ep.wait_enabled().await; } /// Split the class into a sender and receiver. @@ -197,7 +197,7 @@ impl<'d, D: Driver<'d>> Sender<'d, D> { /// Waits for the USB host to enable this interface pub async fn wait_connection(&mut self) { - self.write_ep.wait_enabled().await + self.write_ep.wait_enabled().await; } } @@ -222,6 +222,6 @@ impl<'d, D: Driver<'d>> Receiver<'d, D> { /// Waits for the USB host to enable this interface pub async fn wait_connection(&mut self) { - self.read_ep.wait_enabled().await + self.read_ep.wait_enabled().await; } } 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 { } /// Gets the descriptor type and index from the value field of a GET_DESCRIPTOR request. - pub fn descriptor_type_index(&self) -> (u8, u8) { + pub const fn descriptor_type_index(&self) -> (u8, u8) { ((self.value >> 8) as u8, self.value as u8) } } 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 @@ use crate::builder::Config; use crate::driver::EndpointInfo; -use crate::types::*; +use crate::types::{InterfaceNumber, StringIndex}; use crate::CONFIGURATION_VALUE; /// Standard descriptor types @@ -59,7 +59,7 @@ impl<'a> DescriptorWriter<'a> { } /// Gets the current position in the buffer, i.e. the number of bytes written so far. - pub fn position(&self) -> usize { + pub const fn position(&self) -> usize { self.position } @@ -67,9 +67,10 @@ impl<'a> DescriptorWriter<'a> { pub fn write(&mut self, descriptor_type: u8, descriptor: &[u8]) { let length = descriptor.len(); - if (self.position + 2 + length) > self.buf.len() || (length + 2) > 255 { - panic!("Descriptor buffer full"); - } + assert!( + (self.position + 2 + length) <= self.buf.len() && (length + 2) <= 255, + "Descriptor buffer full" + ); self.buf[self.position] = (length + 2) as u8; self.buf[self.position + 1] = descriptor_type; @@ -102,7 +103,7 @@ impl<'a> DescriptorWriter<'a> { config.serial_number.map_or(0, |_| 3), // iSerialNumber 1, // bNumConfigurations ], - ) + ); } pub(crate) fn configuration(&mut self, config: &Config) { @@ -120,7 +121,7 @@ impl<'a> DescriptorWriter<'a> { | if config.supports_remote_wakeup { 0x20 } else { 0x00 }, // bmAttributes (config.max_power / 2) as u8, // bMaxPower ], - ) + ); } #[allow(unused)] @@ -248,9 +249,7 @@ impl<'a> DescriptorWriter<'a> { pub(crate) fn string(&mut self, string: &str) { let mut pos = self.position; - if pos + 2 > self.buf.len() { - panic!("Descriptor buffer full"); - } + assert!(pos + 2 <= self.buf.len(), "Descriptor buffer full"); self.buf[pos] = 0; // length placeholder self.buf[pos + 1] = descriptor_type::STRING; @@ -258,9 +257,7 @@ impl<'a> DescriptorWriter<'a> { pos += 2; for c in string.encode_utf16() { - if pos >= self.buf.len() { - panic!("Descriptor buffer full"); - } + assert!(pos < self.buf.len(), "Descriptor buffer full"); self.buf[pos..pos + 2].copy_from_slice(&c.to_le_bytes()); pos += 2; @@ -279,9 +276,9 @@ pub struct BosWriter<'a> { } impl<'a> BosWriter<'a> { - pub(crate) fn new(writer: DescriptorWriter<'a>) -> Self { + pub(crate) const fn new(writer: DescriptorWriter<'a>) -> Self { Self { - writer: writer, + writer, num_caps_mark: None, } } @@ -314,9 +311,10 @@ impl<'a> BosWriter<'a> { let mut start = self.writer.position; let blen = data.len(); - if (start + blen + 3) > self.writer.buf.len() || (blen + 3) > 255 { - panic!("Descriptor buffer full"); - } + assert!( + (start + blen + 3) <= self.writer.buf.len() && (blen + 3) <= 255, + "Descriptor buffer full" + ); self.writer.buf[start] = (blen + 3) as u8; 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> { } impl<'a> Reader<'a> { - pub fn new(data: &'a [u8]) -> Self { + pub const fn new(data: &'a [u8]) -> Self { Self { data } } - pub fn eof(&self) -> bool { + pub const fn eof(&self) -> bool { self.data.is_empty() } @@ -102,7 +102,7 @@ pub fn foreach_endpoint(data: &[u8], mut f: impl FnMut(EndpointInfo)) -> Result< } descriptor_type::ENDPOINT => { ep.ep_address = EndpointAddress::from(r.read_u8()?); - f(ep) + f(ep); } _ => {} } 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}; use heapless::Vec; pub use crate::builder::{Builder, Config, FunctionBuilder, InterfaceAltBuilder, InterfaceBuilder}; -use crate::config::*; -use crate::control::*; -use crate::descriptor::*; +use crate::config::{MAX_HANDLER_COUNT, MAX_INTERFACE_COUNT}; +use crate::control::{InResponse, OutResponse, Recipient, Request, RequestType}; +use crate::descriptor::{descriptor_type, lang_id}; use crate::descriptor_reader::foreach_endpoint; use crate::driver::{Bus, ControlPipe, Direction, Driver, EndpointAddress, Event}; -use crate::types::*; +use crate::types::{InterfaceNumber, StringIndex}; /// The global state of the USB device. /// @@ -294,7 +294,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { /// After dropping the future, [`UsbDevice::disable()`] should be called /// before calling any other `UsbDevice` methods to fully reset the /// peripheral. - pub async fn run_until_suspend(&mut self) -> () { + pub async fn run_until_suspend(&mut self) { while !self.inner.suspended { let control_fut = self.control.setup(); let bus_fut = self.inner.bus.poll(); @@ -364,6 +364,8 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { } async fn handle_control_in(&mut self, req: Request) { + const DEVICE_DESCRIPTOR_LEN: usize = 18; + let mut resp_length = req.length as usize; let max_packet_size = self.control.max_packet_size(); @@ -371,19 +373,15 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { // The host doesn't know our EP0 max packet size yet, and might assume // a full-length packet is a short packet, thinking we're done sending data. // See https://github.com/hathach/tinyusb/issues/184 - const DEVICE_DESCRIPTOR_LEN: usize = 18; - if self.inner.address == 0 - && max_packet_size < DEVICE_DESCRIPTOR_LEN - && (max_packet_size as usize) < resp_length - { + if self.inner.address == 0 && max_packet_size < DEVICE_DESCRIPTOR_LEN && max_packet_size < resp_length { trace!("received control req while not addressed: capping response to 1 packet."); resp_length = max_packet_size; } - match self.inner.handle_control_in(req, &mut self.control_buf) { + match self.inner.handle_control_in(req, self.control_buf) { InResponse::Accepted(data) => { let len = data.len().min(resp_length); - let need_zlp = len != resp_length && (len % usize::from(max_packet_size)) == 0; + let need_zlp = len != resp_length && (len % max_packet_size) == 0; let chunks = data[0..len] .chunks(max_packet_size) @@ -435,7 +433,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { self.control.accept_set_address(self.inner.address).await; self.inner.set_address_pending = false; } else { - self.control.accept().await + self.control.accept().await; } } OutResponse::Rejected => self.control.reject().await, @@ -548,9 +546,8 @@ impl<'d, D: Driver<'d>> Inner<'d, D> { OutResponse::Accepted } - (Request::SET_CONFIGURATION, CONFIGURATION_NONE_U16) => match self.device_state { - UsbDeviceState::Default => OutResponse::Accepted, - _ => { + (Request::SET_CONFIGURATION, CONFIGURATION_NONE_U16) => { + if self.device_state != UsbDeviceState::Default { debug!("SET_CONFIGURATION: unconfigured"); self.device_state = UsbDeviceState::Addressed; @@ -564,17 +561,15 @@ impl<'d, D: Driver<'d>> Inner<'d, D> { for h in &mut self.handlers { h.configured(false); } - - OutResponse::Accepted } - }, + OutResponse::Accepted + } _ => OutResponse::Rejected, }, (RequestType::Standard, Recipient::Interface) => { let iface_num = InterfaceNumber::new(req.index as _); - let iface = match self.interfaces.get_mut(iface_num.0 as usize) { - Some(iface) => iface, - None => return OutResponse::Rejected, + let Some(iface) = self.interfaces.get_mut(iface_num.0 as usize) else { + return OutResponse::Rejected; }; match req.request { @@ -650,9 +645,8 @@ impl<'d, D: Driver<'d>> Inner<'d, D> { _ => InResponse::Rejected, }, (RequestType::Standard, Recipient::Interface) => { - let iface = match self.interfaces.get_mut(req.index as usize) { - Some(iface) => iface, - None => return InResponse::Rejected, + let Some(iface) = self.interfaces.get_mut(req.index as usize) else { + return InResponse::Rejected; }; match req.request { @@ -706,7 +700,7 @@ impl<'d, D: Driver<'d>> Inner<'d, D> { } fn handle_control_in_delegated<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> { - unsafe fn extend_lifetime<'x, 'y>(r: InResponse<'x>) -> InResponse<'y> { + unsafe fn extend_lifetime<'y>(r: InResponse<'_>) -> InResponse<'y> { core::mem::transmute(r) } @@ -756,16 +750,12 @@ impl<'d, D: Driver<'d>> Inner<'d, D> { }; if let Some(s) = s { - if buf.len() < 2 { - panic!("control buffer too small"); - } + assert!(buf.len() >= 2, "control buffer too small"); buf[1] = descriptor_type::STRING; let mut pos = 2; for c in s.encode_utf16() { - if pos + 2 >= buf.len() { - panic!("control buffer too small"); - } + assert!(pos + 2 < buf.len(), "control buffer too small"); buf[pos..pos + 2].copy_from_slice(&c.to_le_bytes()); 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 @@ use core::mem::size_of; -use super::{capability_type, BosWriter}; +use crate::descriptor::{capability_type, BosWriter}; use crate::types::InterfaceNumber; /// 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 @@ pub struct InterfaceNumber(pub u8); impl InterfaceNumber { - pub(crate) fn new(index: u8) -> InterfaceNumber { + pub(crate) const fn new(index: u8) -> InterfaceNumber { InterfaceNumber(index) } } @@ -25,7 +25,7 @@ impl From for u8 { pub struct StringIndex(pub u8); impl StringIndex { - pub(crate) fn new(index: u8) -> StringIndex { + pub(crate) const fn new(index: u8) -> StringIndex { StringIndex(index) } }