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