1use num_traits::FromPrimitive;
6use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Ref};
7
8#[repr(u8)]
9#[derive(num_derive::FromPrimitive)]
10pub enum DescriptorType {
11 Device = 0x01,
12 Config = 0x02,
13 r#String = 0x03,
14 Interface = 0x04,
15 Endpoint = 0x05,
16 DeviceQualifier = 0x06,
17 OtherSpeedConfig = 0x07,
18 InterfacePower = 0x08,
19 InterfaceAssociation = 0x0b,
20 Hid = 0x21,
21 Hidreport = 0x22,
22 Hidphysical = 0x23,
23 CsInterface = 0x24,
24 CsEndpoint = 0x25,
25 SsEpCompanion = 0x30,
26 SsIsochEpCompanion = 0x31,
27}
28
29#[repr(C, packed)]
30#[derive(IntoBytes, KnownLayout, FromBytes, Immutable)]
31pub struct DeviceDescriptor {
32 pub b_length: u8,
33 pub b_descriptor_type: u8,
34 pub bcd_usb: u16,
35 pub b_device_class: u8,
36 pub b_device_sub_class: u8,
37 pub b_device_protocol: u8,
38 pub b_max_packet_size0: u8,
39 pub id_vendor: u16,
40 pub id_product: u16,
41 pub bcd_device: u16,
42 pub i_manufacturer: u8,
43 pub i_product: u8,
44 pub i_serial_number: u8,
45 pub b_num_configurations: u8,
46}
47
48#[repr(C, packed)]
49#[derive(IntoBytes, KnownLayout, FromBytes, Immutable)]
50pub struct ConfigurationDescriptor {
51 pub b_length: u8,
52 pub b_descriptor_type: u8,
53 pub w_total_length: u16,
54 pub b_num_interfaces: u8,
55 pub b_configuration_value: u8,
56 pub i_configuration: u8,
57 pub bm_attributes: u8,
58 pub b_max_power: u8,
59}
60
61#[repr(C, packed)]
62#[derive(IntoBytes, KnownLayout, FromBytes, Immutable)]
63pub struct InterfaceInfoDescriptor {
64 pub b_length: u8,
65 pub b_descriptor_type: u8,
66 pub b_interface_number: u8,
67 pub b_alternate_setting: u8,
68 pub b_num_endpoints: u8,
69 pub b_interface_class: u8,
70 pub b_interface_sub_class: u8,
71 pub b_interface_protocol: u8,
72 pub i_interface: u8,
73}
74
75#[repr(C, packed)]
76#[derive(IntoBytes, KnownLayout, FromBytes, Immutable)]
77pub struct EndpointInfoDescriptor {
78 pub b_length: u8,
79 pub b_descriptor_type: u8,
80 pub b_endpoint_address: u8,
81 pub bm_attributes: u8,
82 pub w_max_packet_size: u16,
83 pub b_interval: u8,
84}
85
86#[repr(C, packed)]
87#[derive(IntoBytes, KnownLayout, FromBytes, Immutable)]
88pub struct HidDescriptor {
89 pub b_length: u8,
90 pub b_descriptor_type: u8,
91 pub bcd_hid: u16,
92 pub b_country_code: u8,
93 pub b_num_descriptors: u8,
94}
95
96#[repr(C, packed)]
97#[derive(IntoBytes, KnownLayout, FromBytes, Immutable)]
98pub struct SsEpCompDescriptorInfo {
99 pub b_length: u8,
100 pub b_descriptor_type: u8,
101 pub b_max_burst: u8,
102 pub bm_attributes: u8,
103 pub w_bytes_per_interval: u8,
104}
105
106#[repr(C, packed)]
107#[derive(IntoBytes, KnownLayout, FromBytes, Immutable)]
108pub struct SsIsochEpCompDescriptor {
109 pub b_length: u8,
110 pub b_descriptor_type: u8,
111 pub w_reserved: u16,
112 pub dw_bytes_per_interval: u32,
113}
114
115#[repr(C, packed)]
116#[derive(IntoBytes, KnownLayout, FromBytes, Immutable)]
117pub struct InterfaceAssocDescriptor {
118 pub b_length: u8,
119 pub b_descriptor_type: u8,
120 pub b_first_interface: u8,
121 pub b_interface_count: u8,
122 pub b_function_class: u8,
123 pub b_function_sub_class: u8,
124 pub b_function_protocol: u8,
125 pub i_function: u8,
126}
127
128#[repr(C, packed)]
129#[derive(IntoBytes, KnownLayout, FromBytes, Immutable)]
130pub struct HidDescriptorEntry {
131 pub b_descriptor_type: u8,
132 pub w_descriptor_length: u16,
133}
134
135pub struct DescriptorIterator<'a> {
136 offset: usize,
137 buffer: &'a [u8],
138}
139
140impl<'a> DescriptorIterator<'a> {
141 pub fn new(buffer: &'a [u8]) -> DescriptorIterator<'a> {
142 DescriptorIterator { offset: 0, buffer }
143 }
144}
145
146pub struct HidDescriptorIter<'a> {
147 offset: usize,
148 buffer: &'a [u8],
149}
150
151impl<'a> HidDescriptorIter<'a> {
152 fn new(buffer: &'a [u8]) -> HidDescriptorIter<'a> {
153 HidDescriptorIter { offset: std::mem::size_of::<HidDescriptor>(), buffer }
154 }
155
156 pub fn get(&self) -> Ref<&[u8], HidDescriptor> {
157 Ref::from_bytes(&self.buffer[0..(std::mem::size_of::<HidDescriptor>())]).unwrap()
158 }
159}
160
161impl<'a> Iterator for HidDescriptorIter<'a> {
162 type Item = Ref<&'a [u8], HidDescriptorEntry>;
163
164 fn next(&mut self) -> Option<Self::Item> {
165 let len = std::mem::size_of::<HidDescriptorEntry>();
166 if self.offset + len > self.buffer.len() {
167 return None;
168 }
169 let slice = &self.buffer[self.offset..self.offset + len];
170 self.offset += len;
171
172 Ref::from_bytes(slice).ok()
173 }
174}
175
176pub enum Descriptor<'a> {
177 Config(Ref<&'a [u8], ConfigurationDescriptor>),
178 Interface(Ref<&'a [u8], InterfaceInfoDescriptor>),
179 InterfaceAssociation(Ref<&'a [u8], InterfaceAssocDescriptor>),
180 Endpoint(Ref<&'a [u8], EndpointInfoDescriptor>),
181 Hid(HidDescriptorIter<'a>),
182 SsEpCompanion(Ref<&'a [u8], SsEpCompDescriptorInfo>),
183 SsIsochEpCompanion(Ref<&'a [u8], SsIsochEpCompDescriptor>),
184 Unknown(&'a [u8]),
185}
186
187impl<'a> Iterator for DescriptorIterator<'a> {
188 type Item = Descriptor<'a>;
189
190 fn next(&mut self) -> Option<Self::Item> {
191 if self.offset + 2 > self.buffer.len() {
192 return None;
193 }
194
195 let length = self.buffer[self.offset] as usize;
196 let desc_type = self.buffer[self.offset + 1];
197
198 if length == 0 || length > self.buffer.len() {
199 return None;
200 }
201
202 let slice = &self.buffer[self.offset..self.offset + length];
203
204 let desc = match DescriptorType::from_u8(desc_type) {
205 Some(DescriptorType::Config) => {
206 Ref::from_bytes(slice).map(|d| Descriptor::Config(d)).ok()
207 }
208 Some(DescriptorType::Interface) => {
209 Ref::from_bytes(slice).map(|d| Descriptor::Interface(d)).ok()
210 }
211 Some(DescriptorType::Endpoint) => {
212 Ref::from_bytes(slice).map(|d| Descriptor::Endpoint(d)).ok()
213 }
214 Some(DescriptorType::Hid) => {
215 if length < std::mem::size_of::<HidDescriptor>() {
216 None
217 } else {
218 Some(Descriptor::Hid(HidDescriptorIter::new(
219 &self.buffer[self.offset..self.offset + length],
220 )))
221 }
222 }
223 Some(DescriptorType::SsEpCompanion) => {
224 Ref::from_bytes(slice).map(|d| Descriptor::SsEpCompanion(d)).ok()
225 }
226 Some(DescriptorType::SsIsochEpCompanion) => {
227 Ref::from_bytes(slice).map(|d| Descriptor::SsIsochEpCompanion(d)).ok()
228 }
229 Some(DescriptorType::InterfaceAssociation) => {
230 Ref::from_bytes(slice).map(|d| Descriptor::InterfaceAssociation(d)).ok()
231 }
232 _ => Some(Descriptor::Unknown(slice)),
233 };
234
235 self.offset += length;
236 desc
237 }
238}
239
240pub struct UsbSpeed(pub u32);
241
242impl std::fmt::Display for UsbSpeed {
243 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
244 match self.0 {
245 1 => write!(f, "FULL"),
246 2 => write!(f, "LOW"),
247 3 => write!(f, "HIGH"),
248 4 => write!(f, "SUPER"),
249 _ => write!(f, "<unknown>"),
250 }
251 }
252}
253
254pub const EN_US: u16 = 0x0409;