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