• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 use std::mem::size_of;
6 
7 use static_assertions::const_assert;
8 use zerocopy::AsBytes;
9 use zerocopy::FromBytes;
10 
11 /// Standard USB descriptor types.
12 pub enum DescriptorType {
13     Device = 0x01,
14     Configuration = 0x02,
15     Interface = 0x04,
16     Endpoint = 0x05,
17 }
18 
19 /// Trait describing USB descriptors.
20 pub trait Descriptor {
21     /// Get the expected bDescriptorType value for this type of descriptor.
descriptor_type() -> DescriptorType22     fn descriptor_type() -> DescriptorType;
23 }
24 
25 /// Standard USB descriptor header common to all descriptor types.
26 #[allow(non_snake_case)]
27 #[derive(Copy, Clone, Debug, Default, FromBytes, AsBytes)]
28 #[repr(C, packed)]
29 pub struct DescriptorHeader {
30     pub bLength: u8,
31     pub bDescriptorType: u8,
32 }
33 
_assert_descriptor_header()34 fn _assert_descriptor_header() {
35     const_assert!(size_of::<DescriptorHeader>() == 2);
36 }
37 
38 /// Standard USB device descriptor as defined in USB 2.0 chapter 9,
39 /// not including the standard header.
40 #[allow(non_snake_case)]
41 #[derive(Copy, Clone, Debug, Default, FromBytes, AsBytes)]
42 #[repr(C, packed)]
43 pub struct DeviceDescriptor {
44     pub bcdUSB: u16,
45     pub bDeviceClass: u8,
46     pub bDeviceSubClass: u8,
47     pub bDeviceProtocol: u8,
48     pub bMaxPacketSize0: u8,
49     pub idVendor: u16,
50     pub idProduct: u16,
51     pub bcdDevice: u16,
52     pub iManufacturer: u8,
53     pub iProduct: u8,
54     pub iSerialNumber: u8,
55     pub bNumConfigurations: u8,
56 }
57 
58 impl Descriptor for DeviceDescriptor {
descriptor_type() -> DescriptorType59     fn descriptor_type() -> DescriptorType {
60         DescriptorType::Device
61     }
62 }
63 
_assert_device_descriptor()64 fn _assert_device_descriptor() {
65     const_assert!(size_of::<DeviceDescriptor>() == 18 - 2);
66 }
67 
68 /// Standard USB configuration descriptor as defined in USB 2.0 chapter 9,
69 /// not including the standard header.
70 #[allow(non_snake_case)]
71 #[derive(Copy, Clone, Debug, Default, FromBytes, AsBytes)]
72 #[repr(C, packed)]
73 pub struct ConfigDescriptor {
74     pub wTotalLength: u16,
75     pub bNumInterfaces: u8,
76     pub bConfigurationValue: u8,
77     pub iConfiguration: u8,
78     pub bmAttributes: u8,
79     pub bMaxPower: u8,
80 }
81 
82 impl Descriptor for ConfigDescriptor {
descriptor_type() -> DescriptorType83     fn descriptor_type() -> DescriptorType {
84         DescriptorType::Configuration
85     }
86 }
87 
_assert_config_descriptor()88 fn _assert_config_descriptor() {
89     const_assert!(size_of::<ConfigDescriptor>() == 9 - 2);
90 }
91 
92 impl ConfigDescriptor {
num_interfaces(&self) -> u893     pub fn num_interfaces(&self) -> u8 {
94         self.bNumInterfaces
95     }
96 }
97 
98 /// Standard USB interface descriptor as defined in USB 2.0 chapter 9,
99 /// not including the standard header.
100 #[allow(non_snake_case)]
101 #[derive(Copy, Clone, Debug, Default, FromBytes, AsBytes)]
102 #[repr(C, packed)]
103 pub struct InterfaceDescriptor {
104     pub bInterfaceNumber: u8,
105     pub bAlternateSetting: u8,
106     pub bNumEndpoints: u8,
107     pub bInterfaceClass: u8,
108     pub bInterfaceSubClass: u8,
109     pub bInterfaceProtocol: u8,
110     pub iInterface: u8,
111 }
112 
113 impl Descriptor for InterfaceDescriptor {
descriptor_type() -> DescriptorType114     fn descriptor_type() -> DescriptorType {
115         DescriptorType::Interface
116     }
117 }
118 
_assert_interface_descriptor()119 fn _assert_interface_descriptor() {
120     const_assert!(size_of::<InterfaceDescriptor>() == 9 - 2);
121 }
122 
123 /// Standard USB endpoint descriptor as defined in USB 2.0 chapter 9,
124 /// not including the standard header.
125 #[allow(non_snake_case)]
126 #[derive(Copy, Clone, Debug, Default, FromBytes, AsBytes)]
127 #[repr(C, packed)]
128 pub struct EndpointDescriptor {
129     pub bEndpointAddress: u8,
130     pub bmAttributes: u8,
131     pub wMaxPacketSize: u16,
132     pub bInterval: u8,
133 }
134 
135 impl Descriptor for EndpointDescriptor {
descriptor_type() -> DescriptorType136     fn descriptor_type() -> DescriptorType {
137         DescriptorType::Endpoint
138     }
139 }
140 
_assert_endpoint_descriptor()141 fn _assert_endpoint_descriptor() {
142     const_assert!(size_of::<EndpointDescriptor>() == 7 - 2);
143 }
144 
145 const ENDPOINT_DESCRIPTOR_DIRECTION_MASK: u8 = 1 << 7;
146 const ENDPOINT_DESCRIPTOR_NUMBER_MASK: u8 = 0xf;
147 const ENDPOINT_DESCRIPTOR_ATTRIBUTES_TYPE_MASK: u8 = 0x3;
148 
149 /// Endpoint types.
150 #[derive(PartialEq, Eq)]
151 pub enum EndpointType {
152     Control,
153     Isochronous,
154     Bulk,
155     Interrupt,
156 }
157 
158 /// Endpoint Directions.
159 #[derive(PartialEq, Eq, Clone, Copy)]
160 pub enum EndpointDirection {
161     HostToDevice = 0,
162     DeviceToHost = 1,
163 }
164 /// Endpoint direction offset.
165 pub const ENDPOINT_DIRECTION_OFFSET: u8 = 7;
166 
167 impl EndpointDescriptor {
168     // Get direction of this endpoint.
get_direction(&self) -> EndpointDirection169     pub fn get_direction(&self) -> EndpointDirection {
170         let direction = self.bEndpointAddress & ENDPOINT_DESCRIPTOR_DIRECTION_MASK;
171         if direction != 0 {
172             EndpointDirection::DeviceToHost
173         } else {
174             EndpointDirection::HostToDevice
175         }
176     }
177 
178     // Get endpoint number.
get_endpoint_number(&self) -> u8179     pub fn get_endpoint_number(&self) -> u8 {
180         self.bEndpointAddress & ENDPOINT_DESCRIPTOR_NUMBER_MASK
181     }
182 
183     // Get endpoint type.
get_endpoint_type(&self) -> Option<EndpointType>184     pub fn get_endpoint_type(&self) -> Option<EndpointType> {
185         let ep_type = self.bmAttributes & ENDPOINT_DESCRIPTOR_ATTRIBUTES_TYPE_MASK;
186         match ep_type {
187             0 => Some(EndpointType::Control),
188             1 => Some(EndpointType::Isochronous),
189             2 => Some(EndpointType::Bulk),
190             3 => Some(EndpointType::Interrupt),
191             _ => None,
192         }
193     }
194 }
195 
196 /// Offset of data phase transfer direction.
197 pub const DATA_PHASE_DIRECTION_OFFSET: u8 = 7;
198 /// Bit mask of data phase transfer direction.
199 pub const DATA_PHASE_DIRECTION: u8 = 1u8 << DATA_PHASE_DIRECTION_OFFSET;
200 // Types of data phase transfer directions.
201 #[derive(Copy, Clone, PartialEq, Eq)]
202 pub enum ControlRequestDataPhaseTransferDirection {
203     HostToDevice = 0,
204     DeviceToHost = 1,
205 }
206 
207 /// Offset of control request type.
208 pub const CONTROL_REQUEST_TYPE_OFFSET: u8 = 5;
209 /// Bit mask of control request type.
210 pub const CONTROL_REQUEST_TYPE: u8 = 0b11 << CONTROL_REQUEST_TYPE_OFFSET;
211 /// Request types.
212 #[derive(PartialEq, Eq)]
213 pub enum ControlRequestType {
214     Standard = 0,
215     Class = 1,
216     Vendor = 2,
217     Reserved = 3,
218 }
219 
220 /// Recipient type bits.
221 pub const REQUEST_RECIPIENT_TYPE: u8 = 0b1111;
222 /// Recipient type of control request.
223 #[derive(PartialEq, Eq)]
224 pub enum ControlRequestRecipient {
225     Device = 0,
226     Interface = 1,
227     Endpoint = 2,
228     Other = 3,
229     Reserved,
230 }
231 
232 /// Standard request defined in usb spec.
233 #[derive(PartialEq, Eq)]
234 pub enum StandardControlRequest {
235     GetStatus = 0x00,
236     ClearFeature = 0x01,
237     SetFeature = 0x03,
238     SetAddress = 0x05,
239     GetDescriptor = 0x06,
240     SetDescriptor = 0x07,
241     GetConfiguration = 0x08,
242     SetConfiguration = 0x09,
243     GetInterface = 0x0a,
244     SetInterface = 0x11,
245     SynchFrame = 0x12,
246 }
247 
248 /// RequestSetup is first part of control transfer buffer.
249 #[repr(C, packed)]
250 #[derive(Copy, Clone, Debug, FromBytes, AsBytes)]
251 pub struct UsbRequestSetup {
252     // USB Device Request. USB spec. rev. 2.0 9.3
253     pub request_type: u8, // bmRequestType
254     pub request: u8,      // bRequest
255     pub value: u16,       // wValue
256     pub index: u16,       // wIndex
257     pub length: u16,      // wLength
258 }
259 
_assert_usb_request_setup()260 fn _assert_usb_request_setup() {
261     const_assert!(size_of::<UsbRequestSetup>() == 8);
262 }
263 
264 impl UsbRequestSetup {
new( request_type: u8, request: u8, value: u16, index: u16, length: u16, ) -> UsbRequestSetup265     pub fn new(
266         request_type: u8,
267         request: u8,
268         value: u16,
269         index: u16,
270         length: u16,
271     ) -> UsbRequestSetup {
272         UsbRequestSetup {
273             request_type,
274             request,
275             value,
276             index,
277             length,
278         }
279     }
280 
281     /// Get type of request.
get_type(&self) -> ControlRequestType282     pub fn get_type(&self) -> ControlRequestType {
283         let ty = (self.request_type & CONTROL_REQUEST_TYPE) >> CONTROL_REQUEST_TYPE_OFFSET;
284         match ty {
285             0 => ControlRequestType::Standard,
286             1 => ControlRequestType::Class,
287             2 => ControlRequestType::Vendor,
288             _ => ControlRequestType::Reserved,
289         }
290     }
291 
292     /// Get request direction.
get_direction(&self) -> ControlRequestDataPhaseTransferDirection293     pub fn get_direction(&self) -> ControlRequestDataPhaseTransferDirection {
294         let dir = (self.request_type & DATA_PHASE_DIRECTION) >> DATA_PHASE_DIRECTION_OFFSET;
295         match dir {
296             0 => ControlRequestDataPhaseTransferDirection::HostToDevice,
297             _ => ControlRequestDataPhaseTransferDirection::DeviceToHost,
298         }
299     }
300 
301     /// Get recipient of this control transfer.
get_recipient(&self) -> ControlRequestRecipient302     pub fn get_recipient(&self) -> ControlRequestRecipient {
303         let recipient = self.request_type & REQUEST_RECIPIENT_TYPE;
304         match recipient {
305             0 => ControlRequestRecipient::Device,
306             1 => ControlRequestRecipient::Interface,
307             2 => ControlRequestRecipient::Endpoint,
308             3 => ControlRequestRecipient::Other,
309             _ => ControlRequestRecipient::Reserved,
310         }
311     }
312 
313     /// Return the type of standard control request.
get_standard_request(&self) -> Option<StandardControlRequest>314     pub fn get_standard_request(&self) -> Option<StandardControlRequest> {
315         if self.get_type() != ControlRequestType::Standard {
316             return None;
317         }
318         match self.request {
319             0x00 => Some(StandardControlRequest::GetStatus),
320             0x01 => Some(StandardControlRequest::ClearFeature),
321             0x03 => Some(StandardControlRequest::SetFeature),
322             0x05 => Some(StandardControlRequest::SetAddress),
323             0x06 => Some(StandardControlRequest::GetDescriptor),
324             0x07 => Some(StandardControlRequest::SetDescriptor),
325             0x08 => Some(StandardControlRequest::GetConfiguration),
326             0x09 => Some(StandardControlRequest::SetConfiguration),
327             0x0a => Some(StandardControlRequest::GetInterface),
328             0x11 => Some(StandardControlRequest::SetInterface),
329             0x12 => Some(StandardControlRequest::SynchFrame),
330             _ => None,
331         }
332     }
333 }
334 
335 /// Construct a bmRequestType value for a control request.
control_request_type( type_: ControlRequestType, dir: ControlRequestDataPhaseTransferDirection, recipient: ControlRequestRecipient, ) -> u8336 pub fn control_request_type(
337     type_: ControlRequestType,
338     dir: ControlRequestDataPhaseTransferDirection,
339     recipient: ControlRequestRecipient,
340 ) -> u8 {
341     ((type_ as u8) << CONTROL_REQUEST_TYPE_OFFSET)
342         | ((dir as u8) << DATA_PHASE_DIRECTION_OFFSET)
343         | (recipient as u8)
344 }
345 
346 /// USB device speed
347 pub enum DeviceSpeed {
348     Full,
349     Low,
350     High,
351     Super,
352     SuperPlus,
353 }
354 
355 #[cfg(test)]
356 #[allow(clippy::unusual_byte_groupings)]
357 mod tests {
358     use super::*;
359 
360     #[test]
control_request_types()361     fn control_request_types() {
362         assert_eq!(
363             control_request_type(
364                 ControlRequestType::Standard,
365                 ControlRequestDataPhaseTransferDirection::HostToDevice,
366                 ControlRequestRecipient::Device
367             ),
368             0b0_00_00000
369         );
370         assert_eq!(
371             control_request_type(
372                 ControlRequestType::Standard,
373                 ControlRequestDataPhaseTransferDirection::DeviceToHost,
374                 ControlRequestRecipient::Device
375             ),
376             0b1_00_00000
377         );
378         assert_eq!(
379             control_request_type(
380                 ControlRequestType::Standard,
381                 ControlRequestDataPhaseTransferDirection::HostToDevice,
382                 ControlRequestRecipient::Interface
383             ),
384             0b0_00_00001
385         );
386         assert_eq!(
387             control_request_type(
388                 ControlRequestType::Class,
389                 ControlRequestDataPhaseTransferDirection::HostToDevice,
390                 ControlRequestRecipient::Device
391             ),
392             0b0_01_00000
393         );
394     }
395 }
396