crab_usb/common/
mod.rs

1use alloc::{boxed::Box, collections::BTreeMap, sync::Arc, vec::Vec};
2use core::{cell::UnsafeCell, fmt::Display, ptr::NonNull, sync::atomic::AtomicBool};
3use log::{info, trace};
4use usb_if::{
5    descriptor::{Class, ConfigurationDescriptor, DeviceDescriptor, EndpointDescriptor},
6    host::{Controller, ResultTransfer, USBError},
7};
8
9use crate::backend::xhci::Xhci;
10
11mod device;
12pub use device::*;
13
14pub struct EventHandler {
15    raw: Arc<HostRaw>,
16    running: Arc<AtomicBool>,
17}
18
19impl EventHandler {
20    pub fn handle_event(&self) -> bool {
21        if !self.running.load(core::sync::atomic::Ordering::Acquire) {
22            return false;
23        }
24        unsafe {
25            (&mut *self.raw.0.get()).handle_event();
26        }
27        true
28    }
29}
30
31struct HostRaw(UnsafeCell<Box<dyn Controller>>);
32
33unsafe impl Sync for HostRaw {}
34unsafe impl Send for HostRaw {}
35
36impl HostRaw {
37    fn new(raw: Box<dyn Controller>) -> Arc<Self> {
38        Arc::new(Self(UnsafeCell::new(raw)))
39    }
40}
41
42pub struct USBHost {
43    raw: Arc<HostRaw>,
44    running: Arc<AtomicBool>,
45}
46
47impl USBHost {
48    pub fn from_trait(raw: impl Controller) -> Self {
49        USBHost {
50            raw: HostRaw::new(Box::new(raw)),
51            running: Arc::new(AtomicBool::new(true)),
52        }
53    }
54
55    pub fn new_xhci(mmio_base: NonNull<u8>) -> Self {
56        let xhci = Xhci::new(mmio_base);
57        Self {
58            raw: HostRaw::new(xhci),
59            running: Arc::new(AtomicBool::new(true)),
60        }
61    }
62
63    #[cfg(feature = "libusb")]
64    pub fn new_libusb() -> Self {
65        let libusb = crate::backend::libusb::Libusb::new();
66        Self {
67            raw: Box::new(libusb),
68            running: Arc::new(AtomicBool::new(true)),
69        }
70    }
71
72    pub async fn init(&mut self) -> Result<(), USBError> {
73        self.host_mut().init().await
74    }
75
76    pub async fn device_list(&mut self) -> Result<impl Iterator<Item = DeviceInfo>, USBError> {
77        let devices = self.host_mut().device_list().await?;
78        let mut device_infos = Vec::with_capacity(devices.len());
79        for device in devices {
80            let device_info = DeviceInfo::from_box(device).await?;
81            device_infos.push(device_info);
82        }
83        Ok(device_infos.into_iter())
84    }
85
86    fn host_mut(&mut self) -> &mut Box<dyn Controller> {
87        unsafe { &mut *self.raw.0.get() }
88    }
89
90    fn handle_event(&mut self) {
91        self.host_mut().handle_event();
92    }
93
94    pub fn event_handler(&mut self) -> EventHandler {
95        EventHandler {
96            raw: self.raw.clone(),
97            running: self.running.clone(),
98        }
99    }
100}
101
102impl Drop for USBHost {
103    fn drop(&mut self) {
104        self.running
105            .store(false, core::sync::atomic::Ordering::Release);
106        trace!("USBHost is being dropped, stopping event handler");
107    }
108}
109
110pub struct DeviceInfo {
111    raw: Box<dyn usb_if::host::DeviceInfo>,
112    pub descriptor: DeviceDescriptor,
113    pub configurations: Vec<ConfigurationDescriptor>,
114}
115
116impl Display for DeviceInfo {
117    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
118        f.debug_struct("DeviceInfo")
119            .field(
120                "id",
121                &alloc::format!(
122                    "{:04x}:{:04x}",
123                    self.descriptor.vendor_id,
124                    self.descriptor.product_id
125                ),
126            )
127            .field("class", &self.class())
128            .finish()
129    }
130}
131
132impl DeviceInfo {
133    async fn from_box(mut raw: Box<dyn usb_if::host::DeviceInfo>) -> Result<Self, USBError> {
134        let desc = raw.descriptor().await?;
135        let mut configurations = Vec::with_capacity(desc.num_configurations as usize);
136        for i in 0..desc.num_configurations {
137            let config_desc = raw.configuration_descriptor(i).await?;
138
139            configurations.push(config_desc);
140        }
141        Ok(DeviceInfo {
142            raw,
143            descriptor: desc,
144            configurations,
145        })
146    }
147
148    pub async fn open(&mut self) -> Result<Device, USBError> {
149        let device = self.raw.open().await?;
150        Device::new(device, self.descriptor.clone()).await
151    }
152
153    pub fn class(&self) -> Class {
154        self.descriptor.class()
155    }
156
157    pub fn vendor_id(&self) -> u16 {
158        self.descriptor.vendor_id
159    }
160
161    pub fn product_id(&self) -> u16 {
162        self.descriptor.product_id
163    }
164
165    pub fn interface_descriptors(&self) -> Vec<usb_if::descriptor::InterfaceDescriptor> {
166        let mut interfaces = BTreeMap::new();
167        for config in &self.configurations {
168            for iface in &config.interfaces {
169                interfaces.insert(iface.interface_number, iface.first_alt_setting());
170            }
171        }
172        interfaces.values().cloned().collect()
173    }
174}
175
176pub struct Interface {
177    pub descriptor: usb_if::descriptor::InterfaceDescriptor,
178    raw: Box<dyn usb_if::host::Interface>,
179}
180
181impl Display for Interface {
182    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
183        f.debug_struct("Interface")
184            .field("string", self.descriptor.string.as_ref().unwrap())
185            .field("class", &self.class())
186            .finish()
187    }
188}
189
190impl Interface {
191    pub fn set_alt_setting(&mut self, alt_setting: u8) -> Result<(), USBError> {
192        self.raw.set_alt_setting(alt_setting)
193    }
194
195    pub fn class(&self) -> Class {
196        self.descriptor.class()
197    }
198
199    pub fn control_in<'a>(
200        &mut self,
201        setup: usb_if::host::ControlSetup,
202        data: &'a mut [u8],
203    ) -> ResultTransfer<'a> {
204        self.raw.control_in(setup, data)
205    }
206
207    pub async fn control_out<'a>(
208        &mut self,
209        setup: usb_if::host::ControlSetup,
210        data: &'a [u8],
211    ) -> usb_if::host::ResultTransfer<'a> {
212        self.raw.control_out(setup, data)
213    }
214
215    pub fn endpoint_bulk_in(&mut self, endpoint: u8) -> Result<EndpointBulkIn, USBError> {
216        let descriptor = self.find_ep_desc(endpoint)?.clone();
217        self.raw
218            .endpoint_bulk_in(endpoint)
219            .map(|raw| EndpointBulkIn { descriptor, raw })
220    }
221
222    pub fn endpoint_bulk_out(&mut self, endpoint: u8) -> Result<EndpointBulkOut, USBError> {
223        let descriptor = self.find_ep_desc(endpoint)?.clone();
224        self.raw
225            .endpoint_bulk_out(endpoint)
226            .map(|raw| EndpointBulkOut { descriptor, raw })
227    }
228
229    pub fn endpoint_interrupt_in(&mut self, endpoint: u8) -> Result<EndpointInterruptIn, USBError> {
230        let descriptor = self.find_ep_desc(endpoint)?.clone();
231        self.raw
232            .endpoint_interrupt_in(endpoint)
233            .map(|raw| EndpointInterruptIn { descriptor, raw })
234    }
235
236    pub fn endpoint_interrupt_out(
237        &mut self,
238        endpoint: u8,
239    ) -> Result<EndpointInterruptOut, USBError> {
240        let descriptor = self.find_ep_desc(endpoint)?.clone();
241        self.raw
242            .endpoint_interrupt_out(endpoint)
243            .map(|raw| EndpointInterruptOut { descriptor, raw })
244    }
245
246    pub fn endpoint_iso_in(&mut self, endpoint: u8) -> Result<EndpointIsoIn, USBError> {
247        let descriptor = self.find_ep_desc(endpoint)?.clone();
248        self.raw
249            .endpoint_iso_in(endpoint)
250            .map(|raw| EndpointIsoIn { descriptor, raw })
251    }
252
253    pub fn endpoint_iso_out(&mut self, endpoint: u8) -> Result<EndpointIsoOut, USBError> {
254        let descriptor = self.find_ep_desc(endpoint)?.clone();
255        self.raw
256            .endpoint_iso_out(endpoint)
257            .map(|raw| EndpointIsoOut { descriptor, raw })
258    }
259
260    fn find_ep_desc(&self, address: u8) -> Result<&EndpointDescriptor, USBError> {
261        self.descriptor
262            .endpoints
263            .iter()
264            .find(|ep| ep.address == address)
265            .ok_or(USBError::NotFound)
266    }
267}
268
269pub struct EndpointBulkIn {
270    pub descriptor: EndpointDescriptor,
271    raw: Box<dyn usb_if::host::EndpointBulkIn>,
272}
273
274impl EndpointBulkIn {
275    pub fn submit<'a>(&mut self, data: &'a mut [u8]) -> ResultTransfer<'a> {
276        self.raw.submit(data)
277    }
278}
279
280pub struct EndpointBulkOut {
281    pub descriptor: EndpointDescriptor,
282    raw: Box<dyn usb_if::host::EndpointBulkOut>,
283}
284
285impl EndpointBulkOut {
286    pub fn submit<'a>(&mut self, data: &'a [u8]) -> ResultTransfer<'a> {
287        self.raw.submit(data)
288    }
289}
290
291pub struct EndpointInterruptIn {
292    pub descriptor: EndpointDescriptor,
293    raw: Box<dyn usb_if::host::EndpointInterruptIn>,
294}
295
296impl EndpointInterruptIn {
297    pub fn submit<'a>(&mut self, data: &'a mut [u8]) -> ResultTransfer<'a> {
298        self.raw.submit(data)
299    }
300}
301
302pub struct EndpointInterruptOut {
303    pub descriptor: EndpointDescriptor,
304    raw: Box<dyn usb_if::host::EndpointInterruptOut>,
305}
306impl EndpointInterruptOut {
307    pub fn submit<'a>(&mut self, data: &'a [u8]) -> ResultTransfer<'a> {
308        self.raw.submit(data)
309    }
310}
311
312pub struct EndpointIsoIn {
313    pub descriptor: EndpointDescriptor,
314    raw: Box<dyn usb_if::host::EndpintIsoIn>,
315}
316
317impl EndpointIsoIn {
318    pub fn submit<'a>(&mut self, data: &'a mut [u8], num_iso_packets: usize) -> ResultTransfer<'a> {
319        self.raw.submit(data, num_iso_packets)
320    }
321}
322
323pub struct EndpointIsoOut {
324    pub descriptor: EndpointDescriptor,
325    raw: Box<dyn usb_if::host::EndpintIsoOut>,
326}
327
328impl EndpointIsoOut {
329    pub fn submit<'a>(&mut self, data: &'a [u8], num_iso_packets: usize) -> ResultTransfer<'a> {
330        self.raw.submit(data, num_iso_packets)
331    }
332}