1use std::mem::size_of;
6
7use static_assertions::const_assert;
8use zerocopy::FromBytes;
9use zerocopy::Immutable;
10use zerocopy::IntoBytes;
11use zerocopy::KnownLayout;
12
13pub enum DescriptorType {
15 Device = 0x01,
16 Configuration = 0x02,
17 Interface = 0x04,
18 Endpoint = 0x05,
19}
20
21pub trait Descriptor {
23 fn descriptor_type() -> DescriptorType;
25}
26
27#[allow(non_snake_case)]
29#[derive(Copy, Clone, Debug, Default, FromBytes, Immutable, IntoBytes, KnownLayout)]
30#[repr(C, packed)]
31pub struct DescriptorHeader {
32 pub bLength: u8,
33 pub bDescriptorType: u8,
34}
35
36fn _assert_descriptor_header() {
37 const_assert!(size_of::<DescriptorHeader>() == 2);
38}
39
40#[allow(non_snake_case)]
43#[derive(Copy, Clone, Debug, Default, FromBytes, Immutable, IntoBytes, KnownLayout)]
44#[repr(C, packed)]
45pub struct DeviceDescriptor {
46 pub bcdUSB: u16,
47 pub bDeviceClass: u8,
48 pub bDeviceSubClass: u8,
49 pub bDeviceProtocol: u8,
50 pub bMaxPacketSize0: u8,
51 pub idVendor: u16,
52 pub idProduct: u16,
53 pub bcdDevice: u16,
54 pub iManufacturer: u8,
55 pub iProduct: u8,
56 pub iSerialNumber: u8,
57 pub bNumConfigurations: u8,
58}
59
60impl Descriptor for DeviceDescriptor {
61 fn descriptor_type() -> DescriptorType {
62 DescriptorType::Device
63 }
64}
65
66fn _assert_device_descriptor() {
67 const_assert!(size_of::<DeviceDescriptor>() == 18 - 2);
68}
69
70#[allow(non_snake_case)]
73#[derive(Copy, Clone, Debug, Default, FromBytes, Immutable, IntoBytes, KnownLayout)]
74#[repr(C, packed)]
75pub struct ConfigDescriptor {
76 pub wTotalLength: u16,
77 pub bNumInterfaces: u8,
78 pub bConfigurationValue: u8,
79 pub iConfiguration: u8,
80 pub bmAttributes: u8,
81 pub bMaxPower: u8,
82}
83
84impl Descriptor for ConfigDescriptor {
85 fn descriptor_type() -> DescriptorType {
86 DescriptorType::Configuration
87 }
88}
89
90fn _assert_config_descriptor() {
91 const_assert!(size_of::<ConfigDescriptor>() == 9 - 2);
92}
93
94impl ConfigDescriptor {
95 pub fn num_interfaces(&self) -> u8 {
96 self.bNumInterfaces
97 }
98}
99
100#[allow(non_snake_case)]
103#[derive(Copy, Clone, Debug, Default, FromBytes, Immutable, IntoBytes, KnownLayout)]
104#[repr(C, packed)]
105pub struct InterfaceDescriptor {
106 pub bInterfaceNumber: u8,
107 pub bAlternateSetting: u8,
108 pub bNumEndpoints: u8,
109 pub bInterfaceClass: u8,
110 pub bInterfaceSubClass: u8,
111 pub bInterfaceProtocol: u8,
112 pub iInterface: u8,
113}
114
115impl Descriptor for InterfaceDescriptor {
116 fn descriptor_type() -> DescriptorType {
117 DescriptorType::Interface
118 }
119}
120
121fn _assert_interface_descriptor() {
122 const_assert!(size_of::<InterfaceDescriptor>() == 9 - 2);
123}
124
125#[allow(non_snake_case)]
128#[derive(Copy, Clone, Debug, Default, FromBytes, Immutable, IntoBytes, KnownLayout)]
129#[repr(C, packed)]
130pub struct EndpointDescriptor {
131 pub bEndpointAddress: u8,
132 pub bmAttributes: u8,
133 pub wMaxPacketSize: u16,
134 pub bInterval: u8,
135}
136
137impl Descriptor for EndpointDescriptor {
138 fn descriptor_type() -> DescriptorType {
139 DescriptorType::Endpoint
140 }
141}
142
143fn _assert_endpoint_descriptor() {
144 const_assert!(size_of::<EndpointDescriptor>() == 7 - 2);
145}
146
147const ENDPOINT_DESCRIPTOR_DIRECTION_MASK: u8 = 1 << 7;
148const ENDPOINT_DESCRIPTOR_NUMBER_MASK: u8 = 0xf;
149const ENDPOINT_DESCRIPTOR_ATTRIBUTES_TYPE_MASK: u8 = 0x3;
150
151#[derive(PartialEq, Eq)]
153pub enum EndpointType {
154 Control,
155 Isochronous,
156 Bulk,
157 Interrupt,
158}
159
160#[derive(PartialEq, Eq, Clone, Copy)]
162pub enum EndpointDirection {
163 HostToDevice = 0,
164 DeviceToHost = 1,
165}
166pub const ENDPOINT_DIRECTION_OFFSET: u8 = 7;
168
169impl EndpointDescriptor {
170 pub fn get_direction(&self) -> EndpointDirection {
172 let direction = self.bEndpointAddress & ENDPOINT_DESCRIPTOR_DIRECTION_MASK;
173 if direction != 0 {
174 EndpointDirection::DeviceToHost
175 } else {
176 EndpointDirection::HostToDevice
177 }
178 }
179
180 pub fn get_endpoint_number(&self) -> u8 {
182 self.bEndpointAddress & ENDPOINT_DESCRIPTOR_NUMBER_MASK
183 }
184
185 pub fn get_endpoint_type(&self) -> Option<EndpointType> {
187 let ep_type = self.bmAttributes & ENDPOINT_DESCRIPTOR_ATTRIBUTES_TYPE_MASK;
188 match ep_type {
189 0 => Some(EndpointType::Control),
190 1 => Some(EndpointType::Isochronous),
191 2 => Some(EndpointType::Bulk),
192 3 => Some(EndpointType::Interrupt),
193 _ => None,
194 }
195 }
196}
197
198pub const DATA_PHASE_DIRECTION_OFFSET: u8 = 7;
200pub const DATA_PHASE_DIRECTION: u8 = 1u8 << DATA_PHASE_DIRECTION_OFFSET;
202#[derive(Copy, Clone, PartialEq, Eq)]
204pub enum ControlRequestDataPhaseTransferDirection {
205 HostToDevice = 0,
206 DeviceToHost = 1,
207}
208
209pub const CONTROL_REQUEST_TYPE_OFFSET: u8 = 5;
211pub const CONTROL_REQUEST_TYPE: u8 = 0b11 << CONTROL_REQUEST_TYPE_OFFSET;
213#[derive(PartialEq, Eq)]
215pub enum ControlRequestType {
216 Standard = 0,
217 Class = 1,
218 Vendor = 2,
219 Reserved = 3,
220}
221
222pub const REQUEST_RECIPIENT_TYPE: u8 = 0b1111;
224#[derive(PartialEq, Eq)]
226pub enum ControlRequestRecipient {
227 Device = 0,
228 Interface = 1,
229 Endpoint = 2,
230 Other = 3,
231 Reserved,
232}
233
234#[derive(PartialEq, Eq)]
236pub enum StandardControlRequest {
237 GetStatus = 0,
238 ClearFeature = 1,
239 SetFeature = 3,
240 SetAddress = 5,
241 GetDescriptor = 6,
242 SetDescriptor = 7,
243 GetConfiguration = 8,
244 SetConfiguration = 9,
245 GetInterface = 10,
246 SetInterface = 11,
247 SynchFrame = 12,
248}
249
250#[repr(C, packed)]
252#[derive(Copy, Clone, Debug, FromBytes, Immutable, IntoBytes, KnownLayout)]
253pub struct UsbRequestSetup {
254 pub request_type: u8, pub request: u8, pub value: u16, pub index: u16, pub length: u16, }
261
262fn _assert_usb_request_setup() {
263 const_assert!(size_of::<UsbRequestSetup>() == 8);
264}
265
266impl UsbRequestSetup {
267 pub fn new(
268 request_type: u8,
269 request: u8,
270 value: u16,
271 index: u16,
272 length: u16,
273 ) -> UsbRequestSetup {
274 UsbRequestSetup {
275 request_type,
276 request,
277 value,
278 index,
279 length,
280 }
281 }
282
283 pub fn get_type(&self) -> ControlRequestType {
285 let ty = (self.request_type & CONTROL_REQUEST_TYPE) >> CONTROL_REQUEST_TYPE_OFFSET;
286 match ty {
287 0 => ControlRequestType::Standard,
288 1 => ControlRequestType::Class,
289 2 => ControlRequestType::Vendor,
290 _ => ControlRequestType::Reserved,
291 }
292 }
293
294 pub fn get_direction(&self) -> ControlRequestDataPhaseTransferDirection {
296 let dir = (self.request_type & DATA_PHASE_DIRECTION) >> DATA_PHASE_DIRECTION_OFFSET;
297 match dir {
298 0 => ControlRequestDataPhaseTransferDirection::HostToDevice,
299 _ => ControlRequestDataPhaseTransferDirection::DeviceToHost,
300 }
301 }
302
303 pub fn get_recipient(&self) -> ControlRequestRecipient {
305 let recipient = self.request_type & REQUEST_RECIPIENT_TYPE;
306 match recipient {
307 0 => ControlRequestRecipient::Device,
308 1 => ControlRequestRecipient::Interface,
309 2 => ControlRequestRecipient::Endpoint,
310 3 => ControlRequestRecipient::Other,
311 _ => ControlRequestRecipient::Reserved,
312 }
313 }
314
315 pub fn get_standard_request(&self) -> Option<StandardControlRequest> {
317 if self.get_type() != ControlRequestType::Standard {
318 return None;
319 }
320 match self.request {
321 0 => Some(StandardControlRequest::GetStatus),
323 1 => Some(StandardControlRequest::ClearFeature),
324 3 => Some(StandardControlRequest::SetFeature),
325 5 => Some(StandardControlRequest::SetAddress),
326 6 => Some(StandardControlRequest::GetDescriptor),
327 7 => Some(StandardControlRequest::SetDescriptor),
328 8 => Some(StandardControlRequest::GetConfiguration),
329 9 => Some(StandardControlRequest::SetConfiguration),
330 10 => Some(StandardControlRequest::GetInterface),
331 11 => Some(StandardControlRequest::SetInterface),
332 12 => Some(StandardControlRequest::SynchFrame),
333 _ => None,
334 }
335 }
336}
337
338pub fn control_request_type(
340 type_: ControlRequestType,
341 dir: ControlRequestDataPhaseTransferDirection,
342 recipient: ControlRequestRecipient,
343) -> u8 {
344 ((type_ as u8) << CONTROL_REQUEST_TYPE_OFFSET)
345 | ((dir as u8) << DATA_PHASE_DIRECTION_OFFSET)
346 | (recipient as u8)
347}
348
349pub enum DeviceSpeed {
351 Full,
352 Low,
353 High,
354 Super,
355 SuperPlus,
356}
357
358#[cfg(test)]
359#[allow(clippy::unusual_byte_groupings)]
360mod tests {
361 use super::*;
362
363 #[test]
364 fn control_request_types() {
365 assert_eq!(
366 control_request_type(
367 ControlRequestType::Standard,
368 ControlRequestDataPhaseTransferDirection::HostToDevice,
369 ControlRequestRecipient::Device
370 ),
371 0b0_00_00000
372 );
373 assert_eq!(
374 control_request_type(
375 ControlRequestType::Standard,
376 ControlRequestDataPhaseTransferDirection::DeviceToHost,
377 ControlRequestRecipient::Device
378 ),
379 0b1_00_00000
380 );
381 assert_eq!(
382 control_request_type(
383 ControlRequestType::Standard,
384 ControlRequestDataPhaseTransferDirection::HostToDevice,
385 ControlRequestRecipient::Interface
386 ),
387 0b0_00_00001
388 );
389 assert_eq!(
390 control_request_type(
391 ControlRequestType::Class,
392 ControlRequestDataPhaseTransferDirection::HostToDevice,
393 ControlRequestRecipient::Device
394 ),
395 0b0_01_00000
396 );
397 }
398}