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}
36
37impl From<u8> for DescriptorType {
38    fn from(value: u8) -> Self {
39        Self(value)
40    }
41}
42
43impl From<DescriptorType> for u8 {
44    fn from(desc_type: DescriptorType) -> Self {
45        desc_type.0
46    }
47}
48
49#[derive(Debug, Clone)]
50pub struct DeviceDescriptor {
51    pub usb_version: u16,
52    pub class: u8,
53    pub subclass: u8,
54    pub protocol: u8,
55    pub max_packet_size_0: u8,
56    pub vendor_id: u16,
57    pub product_id: u16,
58    pub device_version: u16,
59    pub manufacturer_string_index: Option<NonZero<u8>>,
60    pub product_string_index: Option<NonZero<u8>>,
61    pub serial_number_string_index: Option<NonZero<u8>>,
62    pub num_configurations: u8,
63}
64
65impl DeviceDescriptor {
66    pub fn parse(data: &[u8]) -> Option<Self> {
67        parser::DeviceDescriptor::new(data).map(Into::into)
68    }
69
70    pub const LEN: usize = 18;
71
72    pub fn class(&self) -> Class {
73        Class::from_class_and_subclass(self.class, self.subclass, self.protocol)
74    }
75}
76
77#[derive(Debug, Clone)]
78pub struct InterfaceDescriptor {
79    pub interface_number: u8,
80    pub alternate_setting: u8,
81    pub class: u8,
82    pub subclass: u8,
83    pub protocol: u8,
84    pub string_index: Option<NonZero<u8>>,
85    pub string: Option<String>,
86    pub num_endpoints: u8,
87    pub endpoints: Vec<EndpointDescriptor>,
88}
89
90impl InterfaceDescriptor {
91    pub fn class(&self) -> Class {
92        Class::from_class_and_subclass(self.class, self.subclass, self.protocol)
93    }
94}
95
96/// Endpoint type.
97#[derive(Debug, Copy, Clone, PartialEq, Eq)]
98pub enum EndpointType {
99    /// Control endpoint.
100    Control = 0,
101
102    /// Isochronous endpoint.
103    Isochronous = 1,
104
105    /// Bulk endpoint.
106    Bulk = 2,
107
108    /// Interrupt endpoint.
109    Interrupt = 3,
110}
111
112#[derive(Debug, Clone)]
113pub struct EndpointDescriptor {
114    pub address: u8,
115    pub max_packet_size: u16,
116    pub transfer_type: EndpointType,
117    pub direction: Direction,
118    pub packets_per_microframe: usize,
119    pub interval: u8,
120}
121
122impl EndpointDescriptor {
123    pub fn dci(&self) -> u8 {
124        // DCI = (endpoint_number * 2) + direction
125        // Control endpoint always has DCI 1
126        let endpoint_number = self.address & 0x0F; // Extract endpoint number (low 4 bits)
127        (endpoint_number * 2)
128            + match self.transfer_type {
129                EndpointType::Control => 1, // Control endpoint always has DCI 1
130                _ => {
131                    if self.direction == Direction::In {
132                        1
133                    } else {
134                        0
135                    }
136                }
137            }
138    }
139}
140
141#[derive(Debug, Clone)]
142pub struct InterfaceDescriptors {
143    pub interface_number: u8,
144    pub alt_settings: Vec<InterfaceDescriptor>,
145}
146
147impl InterfaceDescriptors {
148    pub fn first_alt_setting(&self) -> InterfaceDescriptor {
149        self.alt_settings.first().cloned().unwrap()
150    }
151}
152
153#[derive(Debug, Clone)]
154pub struct ConfigurationDescriptor {
155    pub num_interfaces: u8,
156    pub configuration_value: u8,
157    pub attributes: u8,
158    pub max_power: u8,
159    pub string_index: Option<NonZero<u8>>,
160    pub string: Option<String>,
161    pub interfaces: Vec<InterfaceDescriptors>,
162}
163
164impl ConfigurationDescriptor {
165    pub fn parse(data: &[u8]) -> Option<Self> {
166        parser::ConfigurationDescriptor::new(data).map(Into::into)
167    }
168
169    pub const LEN: usize = 9;
170}
171
172impl From<parser::DeviceDescriptor> for DeviceDescriptor {
173    fn from(desc: parser::DeviceDescriptor) -> Self {
174        DeviceDescriptor {
175            usb_version: desc.usb_version(),
176            class: desc.class(),
177            subclass: desc.subclass(),
178            protocol: desc.protocol(),
179            max_packet_size_0: desc.max_packet_size_0(),
180            vendor_id: desc.vendor_id(),
181            product_id: desc.product_id(),
182            device_version: desc.device_version(),
183            manufacturer_string_index: desc.manufacturer_string_index(),
184            product_string_index: desc.product_string_index(),
185            serial_number_string_index: desc.serial_number_string_index(),
186            num_configurations: desc.num_configurations(),
187        }
188    }
189}
190
191impl From<parser::EndpointDescriptor<'_>> for EndpointDescriptor {
192    fn from(desc: parser::EndpointDescriptor) -> Self {
193        EndpointDescriptor {
194            address: desc.address(),
195            max_packet_size: desc.max_packet_size() as _,
196            direction: desc.direction(),
197            transfer_type: desc.transfer_type(),
198            packets_per_microframe: desc.packets_per_microframe() as usize,
199            interval: desc.interval(),
200        }
201    }
202}
203
204impl From<parser::ConfigurationDescriptor<'_>> for ConfigurationDescriptor {
205    fn from(desc: parser::ConfigurationDescriptor) -> Self {
206        ConfigurationDescriptor {
207            num_interfaces: desc.num_interfaces(),
208            configuration_value: desc.configuration_value(),
209            attributes: desc.attributes(),
210            max_power: desc.max_power(),
211            string_index: desc.string_index(),
212            interfaces: desc.interfaces().map(InterfaceDescriptors::from).collect(),
213            string: None,
214        }
215    }
216}
217
218impl From<parser::InterfaceDescriptor<'_>> for InterfaceDescriptor {
219    fn from(desc: parser::InterfaceDescriptor) -> Self {
220        InterfaceDescriptor {
221            interface_number: desc.interface_number(),
222            alternate_setting: desc.alternate_setting(),
223            class: desc.class(),
224            subclass: desc.subclass(),
225            protocol: desc.protocol(),
226            string_index: desc.string_index(),
227            num_endpoints: desc.num_endpoints(),
228            endpoints: desc.endpoints().map(EndpointDescriptor::from).collect(),
229            string: None,
230        }
231    }
232}
233
234impl From<parser::InterfaceDescriptors<'_>> for InterfaceDescriptors {
235    fn from(desc: parser::InterfaceDescriptors) -> Self {
236        InterfaceDescriptors {
237            interface_number: desc.interface_number(),
238            alt_settings: desc.alt_settings().map(InterfaceDescriptor::from).collect(),
239        }
240    }
241}