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