1#![no_std]
2#![allow(async_fn_in_trait)]
3#![doc = include_str!("../README.md")]
4#![warn(missing_docs)]
5
6pub(crate) mod fmt;
8
9pub mod class;
10pub mod control;
11pub mod descriptor;
12pub mod handler;
13
14use core::cell::RefCell;
15use core::marker::PhantomData;
16
17use embassy_sync::blocking_mutex::Mutex as BlockingMutex;
18use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
19use embassy_sync::mutex::Mutex as AsyncMutex;
20use embassy_usb_driver::host::{DeviceEvent, HostError, PipeError, UsbHostAllocator, UsbHostController, UsbPipe, pipe};
21pub use embassy_usb_driver::host::{SplitInfo, SplitSpeed};
22use embassy_usb_driver::{Direction as UsbDirection, EndpointAddress, EndpointInfo, EndpointType, Speed};
23
24use crate::control::{ControlPipeExt, SetupPacket};
25use crate::descriptor::{ConfigurationDescriptor, DeviceDescriptor, USBDescriptor};
26pub use crate::handler::BusRoute;
27use crate::handler::EnumerationInfo;
28
29#[derive(Debug)]
31#[cfg_attr(feature = "defmt", derive(defmt::Format))]
32pub enum EnumerationError {
33 Transfer(PipeError),
35 InvalidDescriptor,
37 ConfigBufferTooSmall(usize),
39 NoPipe,
41 RequestFailed,
43}
44
45impl From<PipeError> for EnumerationError {
46 fn from(e: PipeError) -> Self {
47 Self::Transfer(e)
48 }
49}
50
51impl From<HostError> for EnumerationError {
52 fn from(e: HostError) -> Self {
53 match e {
54 HostError::PipeError(e) => Self::Transfer(e),
55 HostError::InvalidDescriptor => Self::InvalidDescriptor,
56 HostError::RequestFailed => Self::RequestFailed,
57 _ => Self::NoPipe,
58 }
59 }
60}
61
62impl core::fmt::Display for EnumerationError {
63 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
64 match self {
65 Self::Transfer(_e) => write!(f, "Transfer error during enumeration"),
66 Self::InvalidDescriptor => write!(f, "Invalid descriptor"),
67 Self::ConfigBufferTooSmall(size) => {
68 write!(f, "Configuration buffer too small: device requires {} bytes", size)
69 }
70 Self::NoPipe => write!(f, "No free pipe or no free device address"),
71 Self::RequestFailed => write!(f, "Device did not respond"),
72 }
73 }
74}
75
76impl core::error::Error for EnumerationError {}
77
78pub struct BusState {
85 addr_bitmap: BlockingMutex<CriticalSectionRawMutex, RefCell<[usize; 127usize.div_ceil(usize::BITS as usize)]>>,
86 enum_lock: AsyncMutex<CriticalSectionRawMutex, ()>,
87}
88
89impl BusState {
90 pub const fn new() -> Self {
92 Self {
93 addr_bitmap: BlockingMutex::new(RefCell::new([0usize; _])),
94 enum_lock: AsyncMutex::new(()),
95 }
96 }
97
98 fn alloc_address(&self) -> Option<u8> {
104 self.addr_bitmap.lock(|b| {
105 let mut b = b.borrow_mut();
106 for addr in 1u8..=127 {
107 let word = (addr / usize::BITS as u8) as usize;
108 let bit = addr % usize::BITS as u8;
109 if b[word] & (1usize << bit) == 0 {
110 b[word] |= 1usize << bit;
111 return Some(addr);
112 }
113 }
114 None
115 })
116 }
117
118 pub fn free_address(&self, addr: u8) {
122 if addr >= 1 && addr <= 127 {
123 self.addr_bitmap.lock(|b| {
124 let mut b = b.borrow_mut();
125 let word = (addr / usize::BITS as u8) as usize;
126 let bit = addr % usize::BITS as u8;
127 b[word] &= !(1usize << bit);
128 });
129 }
130 }
131}
132
133impl Default for BusState {
134 fn default() -> Self {
135 Self::new()
136 }
137}
138
139pub struct BusController<'d, C: UsbHostController<'d>> {
149 driver: C,
150 _phantom: PhantomData<&'d ()>,
151}
152
153impl<'d, C: UsbHostController<'d>> BusController<'d, C> {
154 pub fn controller(&self) -> &C {
156 &self.driver
157 }
158
159 pub fn controller_mut(&mut self) -> &mut C {
161 &mut self.driver
162 }
163
164 pub async fn wait_for_device_event(&mut self) -> DeviceEvent {
169 self.driver.wait_for_device_event().await
170 }
171
172 pub async fn wait_for_connection(&mut self) -> Speed {
178 loop {
179 match self.driver.wait_for_device_event().await {
180 DeviceEvent::Connected(speed) => {
181 info!("USB device connected, speed: {:?}", speed);
182 return speed;
183 }
184 DeviceEvent::Disconnected => continue,
185 _ => continue,
186 }
187 }
188 }
189}
190
191#[derive(Clone)]
201pub struct BusHandle<'d, A: UsbHostAllocator<'d>> {
202 alloc: A,
203 state: &'d BusState,
204}
205
206impl<'d, A: UsbHostAllocator<'d>> BusHandle<'d, A> {
207 pub fn state(&self) -> &'d BusState {
209 self.state
210 }
211
212 pub fn free_address(&self, addr: u8) {
217 self.state.free_address(addr);
218 }
219
220 pub async fn enumerate(
250 &self,
251 route: BusRoute,
252 config_buf: &mut [u8],
253 ) -> Result<(EnumerationInfo, usize), EnumerationError> {
254 use embassy_time::Timer;
255
256 use crate::descriptor::DeviceDescriptorPartial;
257
258 let _enum_guard = self.state.enum_lock.lock().await;
261
262 let addr = self.state.alloc_address().ok_or(EnumerationError::NoPipe)?;
263
264 let ep0_info = EndpointInfo {
265 addr: EndpointAddress::from_parts(0, UsbDirection::In),
266 ep_type: EndpointType::Control,
267 max_packet_size: route.device_speed().max_packet_size(),
268 interval_ms: 0,
269 };
270
271 let mut ch = self
272 .alloc
273 .alloc_pipe::<pipe::Control, pipe::InOut>(0, &ep0_info, route.split())
274 .map_err(|_| {
275 self.state.free_address(addr);
276 EnumerationError::NoPipe
277 })?;
278
279 trace!("[enum] Getting max_packet_size for new device");
280 let max_packet_size0 = {
281 let mut max_retries = 10;
282 loop {
283 match ch
284 .request_descriptor::<DeviceDescriptorPartial, { DeviceDescriptorPartial::SIZE }>(0, false)
285 .await
286 {
287 Ok(desc) => break desc.max_packet_size0,
288 Err(e) => {
289 warn!("Request descriptor error: {:?}, retries: {}", e, max_retries);
290 if max_retries > 0 {
291 max_retries -= 1;
292 Timer::after_millis(1).await;
293 continue;
294 } else {
295 self.state.free_address(addr);
296 return Err(e.into());
297 }
298 }
299 }
300 }
301 };
302 if !matches!(max_packet_size0, 8 | 16 | 32 | 64) {
304 self.state.free_address(addr);
305 return Err(EnumerationError::InvalidDescriptor);
306 }
307
308 ch.device_set_address(addr).await?;
309 Timer::after_millis(2).await;
311
312 drop(ch);
314
315 let ep0_info = EndpointInfo {
316 addr: EndpointAddress::from_parts(0, UsbDirection::In),
317 ep_type: EndpointType::Control,
318 max_packet_size: max_packet_size0 as u16,
319 interval_ms: 0,
320 };
321
322 let mut ch = self
323 .alloc
324 .alloc_pipe::<pipe::Control, pipe::InOut>(addr, &ep0_info, route.split())
325 .map_err(|_| {
326 self.state.free_address(addr);
327 EnumerationError::NoPipe
328 })?;
329
330 let retries = 5;
331 let dev_desc = async {
332 for _ in 0..retries {
333 match ch
334 .request_descriptor::<DeviceDescriptor, { DeviceDescriptor::SIZE }>(0, false)
335 .await
336 {
337 Err(HostError::PipeError(PipeError::Timeout)) => {
338 Timer::after_millis(1).await;
339 continue;
340 }
341 v => return v,
342 }
343 }
344 Err(HostError::PipeError(PipeError::Timeout))
345 }
346 .await?;
347
348 info!(
349 "Device: VID={:04x} PID={:04x} class={:02x}",
350 dev_desc.vendor_id, dev_desc.product_id, dev_desc.device_class
351 );
352
353 let setup = SetupPacket::get_config_descriptor(0, 9);
355 let n = ch
356 .control_in(&setup.to_bytes(), &mut config_buf[..9])
357 .await
358 .inspect_err(|_| self.state.free_address(addr))?;
359
360 if n < 9 {
361 self.state.free_address(addr);
362 return Err(EnumerationError::InvalidDescriptor);
363 }
364
365 let config_header = ConfigurationDescriptor::try_from_bytes(&config_buf[..9])
366 .map_err(|_| EnumerationError::InvalidDescriptor)?;
367 let total_len = config_header.total_len as usize;
368
369 if total_len > config_buf.len() {
370 self.state.free_address(addr);
371 return Err(EnumerationError::ConfigBufferTooSmall(total_len));
372 }
373
374 let setup = SetupPacket::get_config_descriptor(0, total_len as u16);
376 let n = ch.control_in(&setup.to_bytes(), &mut config_buf[..total_len]).await?;
377
378 if n != total_len {
380 self.state.free_address(addr);
381 return Err(EnumerationError::InvalidDescriptor);
382 }
383
384 trace!("Config descriptor: {} bytes", n);
385
386 let setup = SetupPacket::set_configuration(config_header.configuration_value);
388 ch.control_out(&setup.to_bytes(), &[])
389 .await
390 .inspect_err(|_| self.state.free_address(addr))?;
391
392 info!("Device configured (config={})", config_header.configuration_value);
393
394 drop(ch);
396
397 Ok((
398 EnumerationInfo {
399 device_address: addr,
400 route,
401 device_desc: dev_desc,
402 },
403 n,
404 ))
405 }
406}
407
408impl<'d, A: UsbHostAllocator<'d>> UsbHostAllocator<'d> for BusHandle<'d, A> {
409 type Pipe<T: pipe::Type, D: pipe::Direction> = A::Pipe<T, D>;
410
411 fn alloc_pipe<T: pipe::Type, D: pipe::Direction>(
412 &self,
413 addr: u8,
414 endpoint: &EndpointInfo,
415 split: Option<SplitInfo>,
416 ) -> Result<Self::Pipe<T, D>, HostError> {
417 self.alloc.alloc_pipe::<T, D>(addr, endpoint, split)
418 }
419}
420
421pub fn bus<'d, C: UsbHostController<'d>>(
429 driver: C,
430 state: &'d BusState,
431) -> (BusController<'d, C>, BusHandle<'d, C::Allocator>) {
432 let alloc = driver.allocator();
433 (
434 BusController {
435 driver,
436 _phantom: PhantomData,
437 },
438 BusHandle { alloc, state },
439 )
440}