Skip to main content

usb_if/descriptor/
mod.rs

1use core::num::NonZero;
2
3use alloc::{string::String, vec::Vec};
4
5use crate::transfer::Direction;
6
7mod class_code;
8mod lang_id;
9mod parser;
10
11pub use class_code::*;
12pub use lang_id::*;
13pub use parser::decode_string_descriptor;
14
15#[repr(C)]
16#[derive(Debug, Clone)]
17pub struct DescriptorType(pub u8);
18
19impl DescriptorType {
20    pub const DEVICE: Self = Self(0x01);
21    pub const CONFIGURATION: Self = Self(0x02);
22    pub const STRING: Self = Self(0x03);
23    pub const INTERFACE: Self = Self(0x04);
24    pub const ENDPOINT: Self = Self(0x05);
25    // Reserved 6
26    // Reserved 7
27    pub const INTERFACE_POWER: Self = Self(0x08);
28    pub const OTG: Self = Self(0x09);
29    pub const DEBUG: Self = Self(0x0A);
30    pub const INTERFACE_ASSOCIATION: Self = Self(0x0B);
31    pub const BOS: Self = Self(0x0F);
32    pub const DEVICE_CAPABILITY: Self = Self(0x10);
33    pub const SUPERSPEED_USB_ENDPOINT_COMPANION: Self = Self(0x30);
34    pub const SUPERSPEEDPLUS_ISOCHRONOUS_ENDPOINT_COMPANION: Self = Self(0x31);
35    pub const HUB: Self = Self(0x29);
36}
37
38impl From<u8> for DescriptorType {
39    fn from(value: u8) -> Self {
40        Self(value)
41    }
42}
43
44impl From<DescriptorType> for u8 {
45    fn from(desc_type: DescriptorType) -> Self {
46        desc_type.0
47    }
48}
49
50#[derive(Debug, Clone, Copy)]
51#[repr(C)]
52pub struct DeviceDescriptorBase {
53    pub length: u8,
54    pub descriptor_type: u8,
55    pub usb_version: u16,
56    pub class: u8,
57    pub subclass: u8,
58    pub protocol: u8,
59    pub max_packet_size_0: u8,
60}
61
62impl DeviceDescriptorBase {
63    pub fn class(&self) -> Class {
64        Class::from_class_and_subclass(self.class, self.subclass, self.protocol)
65    }
66}
67
68#[derive(Debug, Clone)]
69pub struct DeviceDescriptor {
70    pub usb_version: u16,
71    pub class: u8,
72    pub subclass: u8,
73    pub protocol: u8,
74    pub max_packet_size_0: u8,
75    pub vendor_id: u16,
76    pub product_id: u16,
77    pub device_version: u16,
78    pub manufacturer_string_index: Option<NonZero<u8>>,
79    pub product_string_index: Option<NonZero<u8>>,
80    pub serial_number_string_index: Option<NonZero<u8>>,
81    pub num_configurations: u8,
82}
83
84impl DeviceDescriptor {
85    pub fn parse(data: &[u8]) -> Option<Self> {
86        parser::DeviceDescriptor::new(data).map(Into::into)
87    }
88
89    pub const LEN: usize = 18;
90
91    pub fn class(&self) -> Class {
92        Class::from_class_and_subclass(self.class, self.subclass, self.protocol)
93    }
94}
95
96#[derive(Debug, Clone)]
97pub struct InterfaceDescriptor {
98    pub interface_number: u8,
99    pub alternate_setting: u8,
100    pub class: u8,
101    pub subclass: u8,
102    pub protocol: u8,
103    pub string_index: Option<NonZero<u8>>,
104    pub string: Option<String>,
105    pub num_endpoints: u8,
106    pub endpoints: Vec<EndpointDescriptor>,
107}
108
109impl InterfaceDescriptor {
110    pub fn class(&self) -> Class {
111        Class::from_class_and_subclass(self.class, self.subclass, self.protocol)
112    }
113}
114
115/// Endpoint type.
116#[derive(Debug, Copy, Clone, PartialEq, Eq)]
117pub enum EndpointType {
118    /// Control endpoint.
119    Control = 0,
120
121    /// Isochronous endpoint.
122    Isochronous = 1,
123
124    /// Bulk endpoint.
125    Bulk = 2,
126
127    /// Interrupt endpoint.
128    Interrupt = 3,
129}
130
131#[derive(Debug, Clone)]
132pub struct EndpointDescriptor {
133    pub address: u8,
134    pub max_packet_size: u16,
135    pub transfer_type: EndpointType,
136    pub direction: Direction,
137    pub packets_per_microframe: usize,
138    pub interval: u8,
139}
140
141impl EndpointDescriptor {
142    pub fn dci(&self) -> u8 {
143        // DCI = (endpoint_number * 2) + direction
144        // Control endpoint always has DCI 1
145        let endpoint_number = self.address & 0x0F; // Extract endpoint number (low 4 bits)
146        (endpoint_number * 2)
147            + match self.transfer_type {
148                EndpointType::Control => 1, // Control endpoint always has DCI 1
149                _ => {
150                    if self.direction == Direction::In {
151                        1
152                    } else {
153                        0
154                    }
155                }
156            }
157    }
158}
159
160#[derive(Debug, Clone)]
161pub struct InterfaceDescriptors {
162    pub interface_number: u8,
163    pub alt_settings: Vec<InterfaceDescriptor>,
164}
165
166impl InterfaceDescriptors {
167    pub fn first_alt_setting(&self) -> InterfaceDescriptor {
168        self.alt_settings.first().cloned().unwrap()
169    }
170}
171
172#[derive(Debug, Clone)]
173pub struct ConfigurationDescriptor {
174    pub num_interfaces: u8,
175    pub configuration_value: u8,
176    pub attributes: u8,
177    pub max_power: u8,
178    pub string_index: Option<NonZero<u8>>,
179    pub string: Option<String>,
180    pub interfaces: Vec<InterfaceDescriptors>,
181}
182
183impl ConfigurationDescriptor {
184    pub fn parse(data: &[u8]) -> Option<Self> {
185        parser::ConfigurationDescriptor::new(data).map(Into::into)
186    }
187
188    pub const LEN: usize = 9;
189}
190
191impl From<parser::DeviceDescriptor> for DeviceDescriptor {
192    fn from(desc: parser::DeviceDescriptor) -> Self {
193        DeviceDescriptor {
194            usb_version: desc.usb_version(),
195            class: desc.class(),
196            subclass: desc.subclass(),
197            protocol: desc.protocol(),
198            max_packet_size_0: desc.max_packet_size_0(),
199            vendor_id: desc.vendor_id(),
200            product_id: desc.product_id(),
201            device_version: desc.device_version(),
202            manufacturer_string_index: desc.manufacturer_string_index(),
203            product_string_index: desc.product_string_index(),
204            serial_number_string_index: desc.serial_number_string_index(),
205            num_configurations: desc.num_configurations(),
206        }
207    }
208}
209
210impl From<parser::EndpointDescriptor<'_>> for EndpointDescriptor {
211    fn from(desc: parser::EndpointDescriptor) -> Self {
212        EndpointDescriptor {
213            address: desc.address(),
214            max_packet_size: desc.max_packet_size() as _,
215            direction: desc.direction(),
216            transfer_type: desc.transfer_type(),
217            packets_per_microframe: desc.packets_per_microframe() as usize,
218            interval: desc.interval(),
219        }
220    }
221}
222
223impl From<parser::ConfigurationDescriptor<'_>> for ConfigurationDescriptor {
224    fn from(desc: parser::ConfigurationDescriptor) -> Self {
225        ConfigurationDescriptor {
226            num_interfaces: desc.num_interfaces(),
227            configuration_value: desc.configuration_value(),
228            attributes: desc.attributes(),
229            max_power: desc.max_power(),
230            string_index: desc.string_index(),
231            interfaces: desc.interfaces().map(InterfaceDescriptors::from).collect(),
232            string: None,
233        }
234    }
235}
236
237impl From<parser::InterfaceDescriptor<'_>> for InterfaceDescriptor {
238    fn from(desc: parser::InterfaceDescriptor) -> Self {
239        InterfaceDescriptor {
240            interface_number: desc.interface_number(),
241            alternate_setting: desc.alternate_setting(),
242            class: desc.class(),
243            subclass: desc.subclass(),
244            protocol: desc.protocol(),
245            string_index: desc.string_index(),
246            num_endpoints: desc.num_endpoints(),
247            endpoints: desc.endpoints().map(EndpointDescriptor::from).collect(),
248            string: None,
249        }
250    }
251}
252
253impl From<parser::InterfaceDescriptors<'_>> for InterfaceDescriptors {
254    fn from(desc: parser::InterfaceDescriptors) -> Self {
255        InterfaceDescriptors {
256            interface_number: desc.interface_number(),
257            alt_settings: desc.alt_settings().map(InterfaceDescriptor::from).collect(),
258        }
259    }
260}