Skip to main content

crab_usb/
device.rs

1use alloc::{boxed::Box, string::String};
2use anyhow::anyhow;
3use core::{
4    any::Any,
5    fmt::{Debug, Display},
6};
7
8use usb_if::{
9    descriptor::{
10        ConfigurationDescriptor, DescriptorType, DeviceDescriptor, InterfaceDescriptor, LanguageId,
11        decode_string_descriptor,
12    },
13    err::{TransferError, USBError},
14    host::ControlSetup,
15};
16
17use crate::backend::ty::ep::EndpointKind;
18use crate::backend::ty::{DeviceInfoOp, DeviceOp, ep::EndpointControl};
19
20pub struct DeviceInfo {
21    pub(crate) inner: Box<dyn DeviceInfoOp>,
22}
23
24impl DeviceInfo {
25    pub fn descriptor(&self) -> &DeviceDescriptor {
26        self.inner.descriptor()
27    }
28
29    pub fn configurations(&self) -> &[ConfigurationDescriptor] {
30        self.inner.configuration_descriptors()
31    }
32
33    pub fn interface_descriptors<'a>(
34        &'a self,
35    ) -> impl Iterator<Item = &'a InterfaceDescriptor> + 'a {
36        self.configurations().iter().flat_map(|config| {
37            config
38                .interfaces
39                .iter()
40                .flat_map(|interface| interface.alt_settings.first())
41        })
42    }
43
44    pub fn product_id(&self) -> u16 {
45        self.descriptor().product_id
46    }
47
48    pub fn vendor_id(&self) -> u16 {
49        self.descriptor().vendor_id
50    }
51}
52
53impl Debug for DeviceInfo {
54    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
55        f.debug_struct("DeviceInfo")
56            .field("backend", &self.inner.backend_name())
57            .field("vender_id", &self.inner.descriptor().vendor_id)
58            .field("product_id", &self.inner.descriptor().product_id)
59            .finish()
60    }
61}
62
63impl Display for DeviceInfo {
64    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
65        write!(
66            f,
67            "{:04x}:{:04x}",
68            self.inner.descriptor().vendor_id,
69            self.inner.descriptor().product_id
70        )
71    }
72}
73
74pub struct Device {
75    pub(crate) inner: Box<dyn DeviceOp>,
76    lang_id: LanguageId,
77    manufacturer: Option<String>,
78    current_interface: Option<(u8, u8)>,
79}
80
81impl Debug for Device {
82    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
83        f.debug_struct("Device")
84            .field("backend", &self.inner.backend_name())
85            .field("vender_id", &self.inner.descriptor().vendor_id)
86            .field("product_id", &self.inner.descriptor().product_id)
87            .finish()
88    }
89}
90
91impl<T: DeviceOp> From<T> for Device {
92    fn from(inner: T) -> Self {
93        Self {
94            inner: Box::new(inner),
95            current_interface: None,
96            lang_id: LanguageId::default(),
97            manufacturer: None,
98        }
99    }
100}
101
102impl From<Box<dyn DeviceOp>> for Device {
103    fn from(inner: Box<dyn DeviceOp>) -> Self {
104        Self {
105            inner,
106            current_interface: None,
107            lang_id: LanguageId::default(),
108            manufacturer: None,
109        }
110    }
111}
112
113impl Device {
114    pub(crate) async fn init(&mut self) -> Result<(), USBError> {
115        self.manufacturer = self.read_manufacturer().await;
116        Ok(())
117    }
118
119    pub fn product_id(&self) -> u16 {
120        self.descriptor().product_id
121    }
122
123    pub fn vendor_id(&self) -> u16 {
124        self.descriptor().vendor_id
125    }
126
127    pub fn slot_id(&self) -> u8 {
128        self.inner.id() as _
129    }
130
131    pub async fn claim_interface(&mut self, interface: u8, alternate: u8) -> Result<(), USBError> {
132        trace!("Claiming interface {interface}, alternate {alternate}");
133        self.inner.claim_interface(interface, alternate).await?;
134        self.current_interface = Some((interface, alternate));
135        Ok(())
136    }
137
138    pub fn descriptor(&self) -> &DeviceDescriptor {
139        self.inner.descriptor()
140    }
141
142    pub fn configurations(&self) -> &[ConfigurationDescriptor] {
143        self.inner.configuration_descriptors()
144    }
145
146    pub fn manufacturer(&self) -> Option<&str> {
147        self.manufacturer.as_deref()
148    }
149
150    pub async fn set_configuration(&mut self, configuration_value: u8) -> crate::err::Result {
151        self.inner.set_configuration(configuration_value).await
152    }
153
154    pub fn ep_ctrl(&mut self) -> &mut EndpointControl {
155        self.inner.ep_ctrl()
156    }
157
158    async fn read_manufacturer(&mut self) -> Option<String> {
159        let idx = self.descriptor().manufacturer_string_index?;
160        self.string_descriptor(idx.get()).await.ok()
161    }
162
163    pub fn lang_id(&self) -> LanguageId {
164        self.lang_id
165    }
166
167    pub fn set_lang_id(&mut self, lang_id: LanguageId) {
168        self.lang_id = lang_id;
169    }
170
171    pub async fn string_descriptor(&mut self, index: u8) -> Result<String, USBError> {
172        let mut data = alloc::vec![0u8; 256];
173        let lang_id = self.lang_id();
174        self.ep_ctrl()
175            .get_descriptor(DescriptorType::STRING, index, lang_id.into(), &mut data)
176            .await?;
177        let res = decode_string_descriptor(&data)?;
178        Ok(res)
179    }
180
181    pub async fn control_in(
182        &mut self,
183        param: ControlSetup,
184        buff: &mut [u8],
185    ) -> Result<usize, TransferError> {
186        self.ep_ctrl().control_in(param, buff).await
187    }
188
189    pub async fn control_out(
190        &mut self,
191        param: ControlSetup,
192        buff: &[u8],
193    ) -> Result<usize, TransferError> {
194        self.ep_ctrl().control_out(param, buff).await
195    }
196
197    pub async fn update_hub(
198        &mut self,
199        params: crate::backend::ty::HubParams,
200    ) -> Result<(), USBError> {
201        self.inner.update_hub(params).await
202    }
203
204    pub async fn current_configuration_descriptor(
205        &mut self,
206    ) -> Result<ConfigurationDescriptor, USBError> {
207        let value = self.ep_ctrl().get_configuration().await?;
208        if value == 0 {
209            return Err(USBError::NotFound);
210        }
211        for config in self.configurations() {
212            if config.configuration_value == value {
213                return Ok(config.clone());
214            }
215        }
216        Err(USBError::NotFound)
217    }
218
219    pub async fn get_endpoint(&mut self, address: u8) -> Result<EndpointKind, USBError> {
220        let ep_desc = self.find_ep_desc(address)?.clone();
221        let base = self.inner.get_endpoint(&ep_desc)?;
222        match (ep_desc.transfer_type, ep_desc.direction) {
223            (usb_if::descriptor::EndpointType::Control, _) => {
224                Ok(EndpointKind::Control(base.into()))
225            }
226            (usb_if::descriptor::EndpointType::Isochronous, usb_if::transfer::Direction::In) => {
227                Ok(EndpointKind::IsochronousIn(base.into()))
228            }
229            (usb_if::descriptor::EndpointType::Isochronous, usb_if::transfer::Direction::Out) => {
230                Ok(EndpointKind::IsochronousOut(base.into()))
231            }
232            (usb_if::descriptor::EndpointType::Bulk, usb_if::transfer::Direction::In) => {
233                Ok(EndpointKind::BulkIn(base.into()))
234            }
235            (usb_if::descriptor::EndpointType::Bulk, usb_if::transfer::Direction::Out) => {
236                Ok(EndpointKind::BulkOut(base.into()))
237            }
238            (usb_if::descriptor::EndpointType::Interrupt, usb_if::transfer::Direction::In) => {
239                Ok(EndpointKind::InterruptIn(base.into()))
240            }
241            (usb_if::descriptor::EndpointType::Interrupt, usb_if::transfer::Direction::Out) => {
242                Ok(EndpointKind::InterruptOut(base.into()))
243            }
244        }
245    }
246
247    #[allow(unused)]
248    pub(crate) fn as_raw<T: DeviceOp>(&self) -> &T {
249        (self.inner.as_ref() as &dyn Any)
250            .downcast_ref::<T>()
251            .unwrap()
252    }
253
254    #[allow(unused)]
255    pub(crate) fn as_raw_mut<T: DeviceOp>(&mut self) -> &mut T {
256        (self.inner.as_mut() as &mut dyn Any)
257            .downcast_mut::<T>()
258            .unwrap()
259    }
260
261    fn find_ep_desc(
262        &self,
263        address: u8,
264    ) -> core::result::Result<&usb_if::descriptor::EndpointDescriptor, USBError> {
265        let (interface_number, alternate_setting) = match self.current_interface {
266            Some((i, a)) => (i, a),
267            None => Err(anyhow!("Interface not claim"))?,
268        };
269        for config in self.configurations() {
270            for interface in &config.interfaces {
271                if interface.interface_number == interface_number {
272                    for alt in &interface.alt_settings {
273                        if alt.alternate_setting == alternate_setting {
274                            for ep in &alt.endpoints {
275                                if ep.address == address {
276                                    return Ok(ep);
277                                }
278                            }
279                        }
280                    }
281                }
282            }
283        }
284        Err(USBError::NotFound)
285    }
286}
287
288impl Display for Device {
289    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
290        write!(
291            f,
292            "{:04x}:{:04x}",
293            self.inner.descriptor().vendor_id,
294            self.inner.descriptor().product_id
295        )
296    }
297}