crab_usb/common/
device.rs

1use alloc::{boxed::Box, string::String, vec::Vec};
2use core::fmt::{Debug, Display};
3use log::debug;
4use usb_if::{
5    descriptor::{
6        Class, ConfigurationDescriptor, DescriptorType, InterfaceDescriptor, LanguageId,
7        decode_string_descriptor,
8    },
9    host::{ControlSetup, USBError},
10    transfer::{Recipient, Request, RequestType},
11};
12
13use crate::Interface;
14
15pub struct Device {
16    pub descriptor: usb_if::descriptor::DeviceDescriptor,
17    info: Info,
18    raw: Box<dyn usb_if::host::Device>,
19    lang_id: LanguageId,
20}
21
22#[derive(Default)]
23struct Info {
24    configurations: Vec<ConfigurationDescriptor>,
25    manufacturer_string: String,
26    product_string: String,
27    serial_number_string: String,
28}
29
30impl Device {
31    pub(crate) async fn new(
32        raw: Box<dyn usb_if::host::Device>,
33        descriptor: usb_if::descriptor::DeviceDescriptor,
34    ) -> Result<Self, USBError> {
35        let mut s = Self {
36            descriptor,
37            info: Info::default(),
38            raw,
39            lang_id: LanguageId::EnglishUnitedStates,
40        };
41        s.lang_id = s.defautl_lang_id().await?;
42        s.info.manufacturer_string = match s.descriptor.manufacturer_string_index {
43            Some(index) => s.string_descriptor(index.get()).await?,
44            None => String::new(),
45        };
46
47        s.info.product_string = match s.descriptor.product_string_index {
48            Some(index) => s.string_descriptor(index.get()).await?,
49            None => String::new(),
50        };
51
52        s.info.serial_number_string = match s.descriptor.serial_number_string_index {
53            Some(index) => s.string_descriptor(index.get()).await?,
54            None => String::new(),
55        };
56
57        s.init_configs().await?;
58        Ok(s)
59    }
60
61    pub fn lang_id(&self) -> LanguageId {
62        self.lang_id
63    }
64
65    pub fn set_lang_id(&mut self, lang_id: LanguageId) {
66        self.lang_id = lang_id;
67    }
68
69    pub fn manufacturer_string(&self) -> &str {
70        &self.info.manufacturer_string
71    }
72
73    pub fn product_string(&self) -> &str {
74        &self.info.product_string
75    }
76
77    pub fn serial_number_string(&self) -> &str {
78        &self.info.serial_number_string
79    }
80
81    pub async fn set_configuration(&mut self, configuration: u8) -> Result<(), USBError> {
82        self.raw.set_configuration(configuration).await
83    }
84
85    pub async fn get_configuration(&mut self) -> Result<u8, USBError> {
86        self.raw.get_configuration().await
87    }
88
89    pub async fn claim_interface(
90        &mut self,
91        interface: u8,
92        alternate: u8,
93    ) -> Result<Interface, USBError> {
94        let mut desc = self.find_interface_desc(interface, alternate)?;
95        desc.string = Some(match desc.string_index {
96            Some(index) => self.string_descriptor(index.get()).await?,
97            None => String::new(),
98        });
99        self.raw
100            .claim_interface(interface, alternate)
101            .await
102            .map(|raw| Interface {
103                descriptor: desc,
104                raw,
105            })
106    }
107
108    pub(crate) async fn init_configs(&mut self) -> Result<(), USBError> {
109        if self.info.configurations.is_empty() {
110            debug!("No configurations found, reading configuration descriptors");
111            for i in 0..self.descriptor.num_configurations {
112                let config_desc = self.read_configuration_descriptor(i).await?;
113                self.info.configurations.push(config_desc);
114            }
115        }
116        Ok(())
117    }
118
119    fn find_interface_desc(
120        &self,
121        interface: u8,
122        alternate: u8,
123    ) -> Result<InterfaceDescriptor, USBError> {
124        for config in &self.info.configurations {
125            for iface in &config.interfaces {
126                if iface.interface_number == interface {
127                    for alt in &iface.alt_settings {
128                        if alt.alternate_setting == alternate {
129                            return Ok(alt.clone());
130                        }
131                    }
132                }
133            }
134        }
135        Err(USBError::NotFound)
136    }
137
138    pub fn configurations(&self) -> &[ConfigurationDescriptor] {
139        &self.info.configurations
140    }
141
142    pub async fn current_configuration_descriptor(
143        &mut self,
144    ) -> Result<ConfigurationDescriptor, USBError> {
145        let value = self.raw.get_configuration().await?;
146        if value == 0 {
147            return Err(USBError::NotFound);
148        }
149        for config in &self.info.configurations {
150            if config.configuration_value == value {
151                return Ok(config.clone());
152            }
153        }
154        Err(USBError::NotFound)
155    }
156
157    pub fn class(&self) -> Class {
158        self.descriptor.class()
159    }
160
161    pub fn vendor_id(&self) -> u16 {
162        self.descriptor.vendor_id
163    }
164
165    pub fn product_id(&self) -> u16 {
166        self.descriptor.product_id
167    }
168
169    pub async fn string_descriptor(&mut self, index: u8) -> Result<String, USBError> {
170        let mut data = alloc::vec![0u8; 256];
171        self.get_descriptor(
172            DescriptorType::STRING,
173            index,
174            self.lang_id().into(),
175            &mut data,
176        )
177        .await?;
178        let res = decode_string_descriptor(&data).map_err(|e| USBError::Other(e.into()))?;
179        Ok(res)
180    }
181
182    async fn get_descriptor(
183        &mut self,
184        desc_type: DescriptorType,
185        desc_index: u8,
186        language_id: u16,
187        buff: &mut [u8],
188    ) -> Result<(), USBError> {
189        self.raw
190            .control_in(
191                ControlSetup {
192                    request_type: RequestType::Standard,
193                    recipient: Recipient::Device,
194                    request: Request::GetDescriptor,
195                    value: ((desc_type.0 as u16) << 8) | desc_index as u16,
196                    index: language_id,
197                },
198                buff,
199            )?
200            .await?;
201        Ok(())
202    }
203
204    async fn read_configuration_descriptor(
205        &mut self,
206        index: u8,
207    ) -> Result<ConfigurationDescriptor, USBError> {
208        let mut header = alloc::vec![0u8; ConfigurationDescriptor::LEN]; // 配置描述符头部固定为9字节
209        self.get_descriptor(DescriptorType::CONFIGURATION, index, 0, &mut header)
210            .await?;
211
212        let total_length = u16::from_le_bytes(header[2..4].try_into().unwrap()) as usize;
213        // 获取完整的配置描述符(包括接口和端点描述符)
214        let mut full_data = alloc::vec![0u8; total_length];
215        debug!("Reading configuration descriptor for index {index}, total length: {total_length}");
216        self.get_descriptor(DescriptorType::CONFIGURATION, index, 0, &mut full_data)
217            .await?;
218        let parsed_config = ConfigurationDescriptor::parse(&full_data)
219            .ok_or(USBError::Other("config descriptor parse err".into()))?;
220        Ok(parsed_config)
221    }
222
223    async fn defautl_lang_id(&mut self) -> Result<LanguageId, USBError> {
224        let mut lang_buf = alloc::vec![0u8; 256];
225        self.raw
226            .control_in(
227                ControlSetup {
228                    request_type: RequestType::Standard,
229                    recipient: Recipient::Device,
230                    request: Request::GetDescriptor,
231                    value: ((DescriptorType::STRING.0 as u16) << 8),
232                    index: 0,
233                },
234                &mut lang_buf,
235            )?
236            .await?;
237        if lang_buf.len() >= 4
238            && (lang_buf[0] as usize) <= lang_buf.len()
239            && lang_buf[1] == DescriptorType::STRING.0
240        {
241            let dlen = lang_buf[0] as usize;
242            if dlen >= 4 {
243                let langid = u16::from_le_bytes([lang_buf[2], lang_buf[3]]);
244                return Ok(langid.into());
245            }
246        }
247
248        Ok(LanguageId::EnglishUnitedStates) // 默认返回英语(美国)
249    }
250}
251
252impl Debug for Device {
253    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
254        f.debug_struct("Device")
255            .field(
256                "id",
257                &alloc::format!(
258                    "{:04x}:{:04x}",
259                    self.descriptor.vendor_id,
260                    self.descriptor.product_id
261                ),
262            )
263            .field("class", &self.class())
264            .field("manufacturer_string", &self.info.manufacturer_string)
265            .field("product_string", &self.info.product_string)
266            .field("serial_number_string", &self.info.serial_number_string)
267            .field("lang", &self.lang_id())
268            .finish()
269    }
270}
271
272impl Display for Device {
273    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
274        write!(
275            f,
276            "{} ({:04x}:{:04x})",
277            self.info.product_string, self.descriptor.vendor_id, self.descriptor.product_id
278        )
279    }
280}