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