diff options
| author | Dario Nieuwenhuis <[email protected]> | 2023-10-16 23:23:10 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-10-16 23:23:10 +0000 |
| commit | 7fd868ade91ebd92cf68016cd40cbbad30a5918e (patch) | |
| tree | d2a94357c0e192a4ec633aaa57b9579f2f2b2922 | |
| parent | 6e6df229795e3ff44fc213e03e022bf38f2de47e (diff) | |
| parent | 31d4516516940720101300a40d0d6d2bb8d1728e (diff) | |
Merge pull request #2068 from barafael/const_usb_config_builder_new
Constify UsbDevice Config::new (and clippy fixes) in embassy-usb
| -rw-r--r-- | embassy-usb/build.rs | 8 | ||||
| -rw-r--r-- | embassy-usb/src/builder.rs | 44 | ||||
| -rw-r--r-- | embassy-usb/src/class/cdc_acm.rs | 53 | ||||
| -rw-r--r-- | embassy-usb/src/class/cdc_ncm/mod.rs | 63 | ||||
| -rw-r--r-- | embassy-usb/src/class/hid.rs | 36 | ||||
| -rw-r--r-- | embassy-usb/src/class/midi.rs | 16 | ||||
| -rw-r--r-- | embassy-usb/src/control.rs | 2 | ||||
| -rw-r--r-- | embassy-usb/src/descriptor.rs | 34 | ||||
| -rw-r--r-- | embassy-usb/src/descriptor_reader.rs | 6 | ||||
| -rw-r--r-- | embassy-usb/src/lib.rs | 54 | ||||
| -rw-r--r-- | embassy-usb/src/msos.rs | 2 | ||||
| -rw-r--r-- | embassy-usb/src/types.rs | 4 |
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 @@ | |||
| 1 | use heapless::Vec; | 1 | use heapless::Vec; |
| 2 | 2 | ||
| 3 | use crate::config::*; | 3 | use crate::config::MAX_HANDLER_COUNT; |
| 4 | use crate::descriptor::{BosWriter, DescriptorWriter}; | 4 | use crate::descriptor::{BosWriter, DescriptorWriter}; |
| 5 | use crate::driver::{Driver, Endpoint, EndpointType}; | 5 | use crate::driver::{Driver, Endpoint, EndpointType}; |
| 6 | #[cfg(feature = "msos-descriptor")] | 6 | #[cfg(feature = "msos-descriptor")] |
| 7 | use crate::msos::{DeviceLevelDescriptor, FunctionLevelDescriptor, MsOsDescriptorWriter}; | 7 | use crate::msos::{DeviceLevelDescriptor, FunctionLevelDescriptor, MsOsDescriptorWriter}; |
| 8 | use crate::types::*; | 8 | use crate::types::{InterfaceNumber, StringIndex}; |
| 9 | use crate::{Handler, Interface, UsbDevice, MAX_INTERFACE_COUNT, STRING_INDEX_CUSTOM_START}; | 9 | use 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`]. |
| 15 | pub struct Config<'a> { | 15 | pub 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 | ||
| 100 | impl<'a> Config<'a> { | 100 | impl<'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 | ||
| 372 | impl<'a, 'd, D: Driver<'d>> InterfaceBuilder<'a, 'd, D> { | 370 | impl<'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 | ||
| 423 | impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> { | 421 | impl<'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 | ||
| 12 | use crate::control::{self, InResponse, OutResponse, Recipient, Request, RequestType}; | 12 | use crate::control::{self, InResponse, OutResponse, Recipient, Request, RequestType}; |
| 13 | use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut}; | 13 | use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut}; |
| 14 | use crate::types::*; | 14 | use crate::types::InterfaceNumber; |
| 15 | use crate::{Builder, Handler}; | 15 | use 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 | ||
| 42 | impl<'a> Default for State<'a> { | ||
| 43 | fn default() -> Self { | ||
| 44 | Self::new() | ||
| 45 | } | ||
| 46 | } | ||
| 47 | |||
| 42 | impl<'a> State<'a> { | 48 | impl<'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 | ||
| 104 | impl ControlShared { | 110 | impl 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 | ||
| 208 | impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> { | 213 | impl<'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> { | |||
| 356 | impl<'d> ControlChanged<'d> { | 361 | impl<'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 | ||
| 17 | use core::intrinsics::copy_nonoverlapping; | 17 | use core::intrinsics::copy_nonoverlapping; |
| 18 | use core::mem::{size_of, MaybeUninit}; | 18 | use core::mem::{size_of, MaybeUninit}; |
| 19 | use core::ptr::addr_of; | ||
| 19 | 20 | ||
| 20 | use crate::control::{self, InResponse, OutResponse, Recipient, Request, RequestType}; | 21 | use crate::control::{self, InResponse, OutResponse, Recipient, Request, RequestType}; |
| 21 | use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut}; | 22 | use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut}; |
| 22 | use crate::types::*; | 23 | use crate::types::{InterfaceNumber, StringIndex}; |
| 23 | use crate::{Builder, Handler}; | 24 | use crate::{Builder, Handler}; |
| 24 | 25 | ||
| 25 | pub mod embassy_net; | 26 | pub 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 | ||
| 64 | const NTB_MAX_SIZE: usize = 2048; | 65 | const NTB_MAX_SIZE: usize = 2048; |
| 65 | const SIG_NTH: u32 = 0x484d434e; | 66 | const SIG_NTH: u32 = 0x484d_434e; |
| 66 | const SIG_NDP_NO_FCS: u32 = 0x304d434e; | 67 | const SIG_NDP_NO_FCS: u32 = 0x304d_434e; |
| 67 | const SIG_NDP_WITH_FCS: u32 = 0x314d434e; | 68 | const SIG_NDP_WITH_FCS: u32 = 0x314d_434e; |
| 68 | 69 | ||
| 69 | const ALTERNATE_SETTING_DISABLED: u8 = 0x00; | 70 | const ALTERNATE_SETTING_DISABLED: u8 = 0x00; |
| 70 | const ALTERNATE_SETTING_ENABLED: u8 = 0x01; | 71 | const ALTERNATE_SETTING_ENABLED: u8 = 0x01; |
| @@ -111,7 +112,7 @@ struct NtbParametersDir { | |||
| 111 | 112 | ||
| 112 | fn byteify<T>(buf: &mut [u8], data: T) -> &[u8] { | 113 | fn 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 | ||
| 125 | impl<'a> Default for State<'a> { | ||
| 126 | fn default() -> Self { | ||
| 127 | Self::new() | ||
| 128 | } | ||
| 129 | } | ||
| 130 | |||
| 124 | impl<'a> State<'a> { | 131 | impl<'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)] | ||
| 135 | struct ControlShared { | 143 | struct ControlShared { |
| 136 | mac_addr: [u8; 6], | 144 | mac_addr: [u8; 6], |
| 137 | } | 145 | } |
| 138 | 146 | ||
| 139 | impl Default for ControlShared { | ||
| 140 | fn default() -> Self { | ||
| 141 | ControlShared { mac_addr: [0; 6] } | ||
| 142 | } | ||
| 143 | } | ||
| 144 | |||
| 145 | struct Control<'a> { | 147 | struct 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 | ||
| 65 | impl ReportId { | 65 | impl 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 | ||
| 82 | impl<'d> Default for State<'d> { | ||
| 83 | fn default() -> Self { | ||
| 84 | Self::new() | ||
| 85 | } | ||
| 86 | } | ||
| 87 | |||
| 82 | impl<'d> State<'d> { | 88 | impl<'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 | ||
| 150 | impl<'d, D: Driver<'d>, const READ_N: usize, const WRITE_N: usize> HidReaderWriter<'d, D, READ_N, WRITE_N> { | 156 | impl<'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 | ||
| 225 | impl From<EndpointError> for ReadError { | 231 | impl 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 | ||
| 287 | impl<'d, D: Driver<'d>, const N: usize> HidReader<'d, D, N> { | 292 | impl<'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 | ||
| 41 | impl<'d, D: Driver<'d>> MidiClass<'d, D> { | 41 | impl<'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 | ||
| 3 | use crate::builder::Config; | 3 | use crate::builder::Config; |
| 4 | use crate::driver::EndpointInfo; | 4 | use crate::driver::EndpointInfo; |
| 5 | use crate::types::*; | 5 | use crate::types::{InterfaceNumber, StringIndex}; |
| 6 | use crate::CONFIGURATION_VALUE; | 6 | use 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 | ||
| 281 | impl<'a> BosWriter<'a> { | 278 | impl<'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 | ||
| 13 | impl<'a> Reader<'a> { | 13 | impl<'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}; | |||
| 24 | use heapless::Vec; | 24 | use heapless::Vec; |
| 25 | 25 | ||
| 26 | pub use crate::builder::{Builder, Config, FunctionBuilder, InterfaceAltBuilder, InterfaceBuilder}; | 26 | pub use crate::builder::{Builder, Config, FunctionBuilder, InterfaceAltBuilder, InterfaceBuilder}; |
| 27 | use crate::config::*; | 27 | use crate::config::{MAX_HANDLER_COUNT, MAX_INTERFACE_COUNT}; |
| 28 | use crate::control::*; | 28 | use crate::control::{InResponse, OutResponse, Recipient, Request, RequestType}; |
| 29 | use crate::descriptor::*; | 29 | use crate::descriptor::{descriptor_type, lang_id}; |
| 30 | use crate::descriptor_reader::foreach_endpoint; | 30 | use crate::descriptor_reader::foreach_endpoint; |
| 31 | use crate::driver::{Bus, ControlPipe, Direction, Driver, EndpointAddress, Event}; | 31 | use crate::driver::{Bus, ControlPipe, Direction, Driver, EndpointAddress, Event}; |
| 32 | use crate::types::*; | 32 | use 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 | ||
| 7 | use core::mem::size_of; | 7 | use core::mem::size_of; |
| 8 | 8 | ||
| 9 | use super::{capability_type, BosWriter}; | 9 | use crate::descriptor::{capability_type, BosWriter}; |
| 10 | use crate::types::InterfaceNumber; | 10 | use 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 @@ | |||
| 7 | pub struct InterfaceNumber(pub u8); | 7 | pub struct InterfaceNumber(pub u8); |
| 8 | 8 | ||
| 9 | impl InterfaceNumber { | 9 | impl 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 { | |||
| 25 | pub struct StringIndex(pub u8); | 25 | pub struct StringIndex(pub u8); |
| 26 | 26 | ||
| 27 | impl StringIndex { | 27 | impl 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 | } |
