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}