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