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]; 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 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) }
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}