xref: /aosp_15_r20/external/crosvm/usb_util/src/descriptor.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2019 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeMap;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::mem::size_of;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::ops::Deref;
8*bb4ee6a4SAndroid Build Coastguard Worker 
9*bb4ee6a4SAndroid Build Coastguard Worker use base::warn;
10*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::FromBytes;
11*bb4ee6a4SAndroid Build Coastguard Worker 
12*bb4ee6a4SAndroid Build Coastguard Worker use crate::types;
13*bb4ee6a4SAndroid Build Coastguard Worker use crate::types::Descriptor;
14*bb4ee6a4SAndroid Build Coastguard Worker use crate::types::DescriptorHeader;
15*bb4ee6a4SAndroid Build Coastguard Worker use crate::types::EndpointDescriptor;
16*bb4ee6a4SAndroid Build Coastguard Worker use crate::Error;
17*bb4ee6a4SAndroid Build Coastguard Worker use crate::Result;
18*bb4ee6a4SAndroid Build Coastguard Worker 
19*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone)]
20*bb4ee6a4SAndroid Build Coastguard Worker pub struct DeviceDescriptorTree {
21*bb4ee6a4SAndroid Build Coastguard Worker     // Full descriptor tree in the original format returned by the device.
22*bb4ee6a4SAndroid Build Coastguard Worker     raw: Vec<u8>,
23*bb4ee6a4SAndroid Build Coastguard Worker     inner: types::DeviceDescriptor,
24*bb4ee6a4SAndroid Build Coastguard Worker     // Map of bConfigurationValue to ConfigDescriptor
25*bb4ee6a4SAndroid Build Coastguard Worker     config_descriptors: BTreeMap<u8, ConfigDescriptorTree>,
26*bb4ee6a4SAndroid Build Coastguard Worker     // Map of config index to bConfigurationValue.
27*bb4ee6a4SAndroid Build Coastguard Worker     config_values: BTreeMap<u8, u8>,
28*bb4ee6a4SAndroid Build Coastguard Worker }
29*bb4ee6a4SAndroid Build Coastguard Worker 
30*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone)]
31*bb4ee6a4SAndroid Build Coastguard Worker pub struct ConfigDescriptorTree {
32*bb4ee6a4SAndroid Build Coastguard Worker     offset: usize,
33*bb4ee6a4SAndroid Build Coastguard Worker     inner: types::ConfigDescriptor,
34*bb4ee6a4SAndroid Build Coastguard Worker     // Map of (bInterfaceNumber, bAlternateSetting) to InterfaceDescriptor
35*bb4ee6a4SAndroid Build Coastguard Worker     interface_descriptors: BTreeMap<(u8, u8), InterfaceDescriptorTree>,
36*bb4ee6a4SAndroid Build Coastguard Worker }
37*bb4ee6a4SAndroid Build Coastguard Worker 
38*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone)]
39*bb4ee6a4SAndroid Build Coastguard Worker pub struct InterfaceDescriptorTree {
40*bb4ee6a4SAndroid Build Coastguard Worker     offset: usize,
41*bb4ee6a4SAndroid Build Coastguard Worker     inner: types::InterfaceDescriptor,
42*bb4ee6a4SAndroid Build Coastguard Worker     // Map of bEndpointAddress to EndpointDescriptor
43*bb4ee6a4SAndroid Build Coastguard Worker     endpoint_descriptors: BTreeMap<u8, EndpointDescriptor>,
44*bb4ee6a4SAndroid Build Coastguard Worker }
45*bb4ee6a4SAndroid Build Coastguard Worker 
46*bb4ee6a4SAndroid Build Coastguard Worker impl DeviceDescriptorTree {
get_config_descriptor(&self, config_value: u8) -> Option<&ConfigDescriptorTree>47*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_config_descriptor(&self, config_value: u8) -> Option<&ConfigDescriptorTree> {
48*bb4ee6a4SAndroid Build Coastguard Worker         self.config_descriptors.get(&config_value)
49*bb4ee6a4SAndroid Build Coastguard Worker     }
50*bb4ee6a4SAndroid Build Coastguard Worker 
51*bb4ee6a4SAndroid Build Coastguard Worker     /// Retrieve the Nth configuration descriptor in the device descriptor.
52*bb4ee6a4SAndroid Build Coastguard Worker     /// `config_index`: 0-based index into the list of configuration descriptors.
get_config_descriptor_by_index( &self, config_index: u8, ) -> Option<&ConfigDescriptorTree>53*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_config_descriptor_by_index(
54*bb4ee6a4SAndroid Build Coastguard Worker         &self,
55*bb4ee6a4SAndroid Build Coastguard Worker         config_index: u8,
56*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Option<&ConfigDescriptorTree> {
57*bb4ee6a4SAndroid Build Coastguard Worker         self.config_descriptors
58*bb4ee6a4SAndroid Build Coastguard Worker             .get(self.config_values.get(&config_index)?)
59*bb4ee6a4SAndroid Build Coastguard Worker     }
60*bb4ee6a4SAndroid Build Coastguard Worker 
61*bb4ee6a4SAndroid Build Coastguard Worker     /// Access the raw descriptor tree as a slice of bytes.
raw(&self) -> &[u8]62*bb4ee6a4SAndroid Build Coastguard Worker     pub fn raw(&self) -> &[u8] {
63*bb4ee6a4SAndroid Build Coastguard Worker         &self.raw
64*bb4ee6a4SAndroid Build Coastguard Worker     }
65*bb4ee6a4SAndroid Build Coastguard Worker }
66*bb4ee6a4SAndroid Build Coastguard Worker 
67*bb4ee6a4SAndroid Build Coastguard Worker impl Deref for DeviceDescriptorTree {
68*bb4ee6a4SAndroid Build Coastguard Worker     type Target = types::DeviceDescriptor;
69*bb4ee6a4SAndroid Build Coastguard Worker 
deref(&self) -> &types::DeviceDescriptor70*bb4ee6a4SAndroid Build Coastguard Worker     fn deref(&self) -> &types::DeviceDescriptor {
71*bb4ee6a4SAndroid Build Coastguard Worker         &self.inner
72*bb4ee6a4SAndroid Build Coastguard Worker     }
73*bb4ee6a4SAndroid Build Coastguard Worker }
74*bb4ee6a4SAndroid Build Coastguard Worker 
75*bb4ee6a4SAndroid Build Coastguard Worker impl ConfigDescriptorTree {
76*bb4ee6a4SAndroid Build Coastguard Worker     /// Get interface by number and alt setting.
get_interface_descriptor( &self, interface_num: u8, alt_setting: u8, ) -> Option<&InterfaceDescriptorTree>77*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_interface_descriptor(
78*bb4ee6a4SAndroid Build Coastguard Worker         &self,
79*bb4ee6a4SAndroid Build Coastguard Worker         interface_num: u8,
80*bb4ee6a4SAndroid Build Coastguard Worker         alt_setting: u8,
81*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Option<&InterfaceDescriptorTree> {
82*bb4ee6a4SAndroid Build Coastguard Worker         self.interface_descriptors
83*bb4ee6a4SAndroid Build Coastguard Worker             .get(&(interface_num, alt_setting))
84*bb4ee6a4SAndroid Build Coastguard Worker     }
85*bb4ee6a4SAndroid Build Coastguard Worker 
86*bb4ee6a4SAndroid Build Coastguard Worker     /// Get the offset of this configuration descriptor within the raw descriptor tree.
offset(&self) -> usize87*bb4ee6a4SAndroid Build Coastguard Worker     pub fn offset(&self) -> usize {
88*bb4ee6a4SAndroid Build Coastguard Worker         self.offset
89*bb4ee6a4SAndroid Build Coastguard Worker     }
90*bb4ee6a4SAndroid Build Coastguard Worker }
91*bb4ee6a4SAndroid Build Coastguard Worker 
92*bb4ee6a4SAndroid Build Coastguard Worker impl Deref for ConfigDescriptorTree {
93*bb4ee6a4SAndroid Build Coastguard Worker     type Target = types::ConfigDescriptor;
94*bb4ee6a4SAndroid Build Coastguard Worker 
deref(&self) -> &types::ConfigDescriptor95*bb4ee6a4SAndroid Build Coastguard Worker     fn deref(&self) -> &types::ConfigDescriptor {
96*bb4ee6a4SAndroid Build Coastguard Worker         &self.inner
97*bb4ee6a4SAndroid Build Coastguard Worker     }
98*bb4ee6a4SAndroid Build Coastguard Worker }
99*bb4ee6a4SAndroid Build Coastguard Worker 
100*bb4ee6a4SAndroid Build Coastguard Worker impl InterfaceDescriptorTree {
get_endpoint_descriptor(&self, ep_idx: u8) -> Option<&EndpointDescriptor>101*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_endpoint_descriptor(&self, ep_idx: u8) -> Option<&EndpointDescriptor> {
102*bb4ee6a4SAndroid Build Coastguard Worker         self.endpoint_descriptors.get(&ep_idx)
103*bb4ee6a4SAndroid Build Coastguard Worker     }
104*bb4ee6a4SAndroid Build Coastguard Worker 
105*bb4ee6a4SAndroid Build Coastguard Worker     /// Get the offset of this interface descriptor within the raw descriptor tree.
offset(&self) -> usize106*bb4ee6a4SAndroid Build Coastguard Worker     pub fn offset(&self) -> usize {
107*bb4ee6a4SAndroid Build Coastguard Worker         self.offset
108*bb4ee6a4SAndroid Build Coastguard Worker     }
109*bb4ee6a4SAndroid Build Coastguard Worker }
110*bb4ee6a4SAndroid Build Coastguard Worker 
111*bb4ee6a4SAndroid Build Coastguard Worker impl Deref for InterfaceDescriptorTree {
112*bb4ee6a4SAndroid Build Coastguard Worker     type Target = types::InterfaceDescriptor;
113*bb4ee6a4SAndroid Build Coastguard Worker 
deref(&self) -> &types::InterfaceDescriptor114*bb4ee6a4SAndroid Build Coastguard Worker     fn deref(&self) -> &types::InterfaceDescriptor {
115*bb4ee6a4SAndroid Build Coastguard Worker         &self.inner
116*bb4ee6a4SAndroid Build Coastguard Worker     }
117*bb4ee6a4SAndroid Build Coastguard Worker }
118*bb4ee6a4SAndroid Build Coastguard Worker 
119*bb4ee6a4SAndroid Build Coastguard Worker /// Given `data` containing a full set of descriptors as provided by the Linux kernel
120*bb4ee6a4SAndroid Build Coastguard Worker /// usbdevfs `descriptors` file, parse the descriptors into a tree data structure.
parse_usbfs_descriptors(data: &[u8]) -> Result<DeviceDescriptorTree>121*bb4ee6a4SAndroid Build Coastguard Worker pub fn parse_usbfs_descriptors(data: &[u8]) -> Result<DeviceDescriptorTree> {
122*bb4ee6a4SAndroid Build Coastguard Worker     let mut offset = 0;
123*bb4ee6a4SAndroid Build Coastguard Worker 
124*bb4ee6a4SAndroid Build Coastguard Worker     // Find the next descriptor of type T and return it and its offset.
125*bb4ee6a4SAndroid Build Coastguard Worker     // Any other descriptors encountered while searching for the expected type are skipped.
126*bb4ee6a4SAndroid Build Coastguard Worker     // The `offset` parameter will be advanced to point to the next byte after the returned
127*bb4ee6a4SAndroid Build Coastguard Worker     // descriptor.
128*bb4ee6a4SAndroid Build Coastguard Worker     fn next_descriptor<T: Descriptor + FromBytes>(
129*bb4ee6a4SAndroid Build Coastguard Worker         data: &[u8],
130*bb4ee6a4SAndroid Build Coastguard Worker         offset: &mut usize,
131*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<(T, usize)> {
132*bb4ee6a4SAndroid Build Coastguard Worker         let desc_type = T::descriptor_type() as u8;
133*bb4ee6a4SAndroid Build Coastguard Worker         loop {
134*bb4ee6a4SAndroid Build Coastguard Worker             let hdr = DescriptorHeader::read_from(
135*bb4ee6a4SAndroid Build Coastguard Worker                 data.get(*offset..*offset + size_of::<DescriptorHeader>())
136*bb4ee6a4SAndroid Build Coastguard Worker                     .ok_or(Error::DescriptorParse)?,
137*bb4ee6a4SAndroid Build Coastguard Worker             )
138*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(Error::DescriptorParse)?;
139*bb4ee6a4SAndroid Build Coastguard Worker             if hdr.bDescriptorType == desc_type {
140*bb4ee6a4SAndroid Build Coastguard Worker                 if usize::from(hdr.bLength) < size_of::<DescriptorHeader>() + size_of::<T>() {
141*bb4ee6a4SAndroid Build Coastguard Worker                     return Err(Error::DescriptorParse);
142*bb4ee6a4SAndroid Build Coastguard Worker                 }
143*bb4ee6a4SAndroid Build Coastguard Worker 
144*bb4ee6a4SAndroid Build Coastguard Worker                 let desc_offset = *offset;
145*bb4ee6a4SAndroid Build Coastguard Worker 
146*bb4ee6a4SAndroid Build Coastguard Worker                 *offset += size_of::<DescriptorHeader>();
147*bb4ee6a4SAndroid Build Coastguard Worker                 let desc = T::read_from(
148*bb4ee6a4SAndroid Build Coastguard Worker                     data.get(*offset..*offset + size_of::<T>())
149*bb4ee6a4SAndroid Build Coastguard Worker                         .ok_or(Error::DescriptorParse)?,
150*bb4ee6a4SAndroid Build Coastguard Worker                 )
151*bb4ee6a4SAndroid Build Coastguard Worker                 .ok_or(Error::DescriptorParse)?;
152*bb4ee6a4SAndroid Build Coastguard Worker                 *offset += hdr.bLength as usize - size_of::<DescriptorHeader>();
153*bb4ee6a4SAndroid Build Coastguard Worker                 return Ok((desc, desc_offset));
154*bb4ee6a4SAndroid Build Coastguard Worker             } else {
155*bb4ee6a4SAndroid Build Coastguard Worker                 // Finding a ConfigDescriptor while looking for InterfaceDescriptor means
156*bb4ee6a4SAndroid Build Coastguard Worker                 // that we should advance to the next device configuration.
157*bb4ee6a4SAndroid Build Coastguard Worker                 if desc_type == types::InterfaceDescriptor::descriptor_type() as u8
158*bb4ee6a4SAndroid Build Coastguard Worker                     && hdr.bDescriptorType == types::ConfigDescriptor::descriptor_type() as u8
159*bb4ee6a4SAndroid Build Coastguard Worker                 {
160*bb4ee6a4SAndroid Build Coastguard Worker                     return Err(Error::DescriptorParse);
161*bb4ee6a4SAndroid Build Coastguard Worker                 }
162*bb4ee6a4SAndroid Build Coastguard Worker 
163*bb4ee6a4SAndroid Build Coastguard Worker                 // Make sure we make forward progress.
164*bb4ee6a4SAndroid Build Coastguard Worker                 if hdr.bLength == 0 {
165*bb4ee6a4SAndroid Build Coastguard Worker                     return Err(Error::DescriptorParse);
166*bb4ee6a4SAndroid Build Coastguard Worker                 }
167*bb4ee6a4SAndroid Build Coastguard Worker 
168*bb4ee6a4SAndroid Build Coastguard Worker                 // Skip this entire descriptor, since it's not the right type.
169*bb4ee6a4SAndroid Build Coastguard Worker                 *offset += hdr.bLength as usize;
170*bb4ee6a4SAndroid Build Coastguard Worker             }
171*bb4ee6a4SAndroid Build Coastguard Worker         }
172*bb4ee6a4SAndroid Build Coastguard Worker     }
173*bb4ee6a4SAndroid Build Coastguard Worker 
174*bb4ee6a4SAndroid Build Coastguard Worker     let (raw_device_descriptor, _) = next_descriptor::<types::DeviceDescriptor>(data, &mut offset)?;
175*bb4ee6a4SAndroid Build Coastguard Worker     let mut device_descriptor = DeviceDescriptorTree {
176*bb4ee6a4SAndroid Build Coastguard Worker         raw: data.into(),
177*bb4ee6a4SAndroid Build Coastguard Worker         inner: raw_device_descriptor,
178*bb4ee6a4SAndroid Build Coastguard Worker         config_descriptors: BTreeMap::new(),
179*bb4ee6a4SAndroid Build Coastguard Worker         config_values: BTreeMap::new(),
180*bb4ee6a4SAndroid Build Coastguard Worker     };
181*bb4ee6a4SAndroid Build Coastguard Worker 
182*bb4ee6a4SAndroid Build Coastguard Worker     for cfg_idx in 0..device_descriptor.bNumConfigurations {
183*bb4ee6a4SAndroid Build Coastguard Worker         if let Ok((raw_config_descriptor, config_offset)) =
184*bb4ee6a4SAndroid Build Coastguard Worker             next_descriptor::<types::ConfigDescriptor>(&device_descriptor.raw, &mut offset)
185*bb4ee6a4SAndroid Build Coastguard Worker         {
186*bb4ee6a4SAndroid Build Coastguard Worker             let mut config_descriptor = ConfigDescriptorTree {
187*bb4ee6a4SAndroid Build Coastguard Worker                 offset: config_offset,
188*bb4ee6a4SAndroid Build Coastguard Worker                 inner: raw_config_descriptor,
189*bb4ee6a4SAndroid Build Coastguard Worker                 interface_descriptors: BTreeMap::new(),
190*bb4ee6a4SAndroid Build Coastguard Worker             };
191*bb4ee6a4SAndroid Build Coastguard Worker 
192*bb4ee6a4SAndroid Build Coastguard Worker             while let Ok((raw_interface_descriptor, interface_offset)) =
193*bb4ee6a4SAndroid Build Coastguard Worker                 next_descriptor::<types::InterfaceDescriptor>(&device_descriptor.raw, &mut offset)
194*bb4ee6a4SAndroid Build Coastguard Worker             {
195*bb4ee6a4SAndroid Build Coastguard Worker                 let mut interface_descriptor = InterfaceDescriptorTree {
196*bb4ee6a4SAndroid Build Coastguard Worker                     offset: interface_offset,
197*bb4ee6a4SAndroid Build Coastguard Worker                     inner: raw_interface_descriptor,
198*bb4ee6a4SAndroid Build Coastguard Worker                     endpoint_descriptors: BTreeMap::new(),
199*bb4ee6a4SAndroid Build Coastguard Worker                 };
200*bb4ee6a4SAndroid Build Coastguard Worker 
201*bb4ee6a4SAndroid Build Coastguard Worker                 for ep_idx in 0..interface_descriptor.bNumEndpoints {
202*bb4ee6a4SAndroid Build Coastguard Worker                     if let Ok((endpoint_descriptor, _)) =
203*bb4ee6a4SAndroid Build Coastguard Worker                         next_descriptor::<EndpointDescriptor>(&device_descriptor.raw, &mut offset)
204*bb4ee6a4SAndroid Build Coastguard Worker                     {
205*bb4ee6a4SAndroid Build Coastguard Worker                         interface_descriptor
206*bb4ee6a4SAndroid Build Coastguard Worker                             .endpoint_descriptors
207*bb4ee6a4SAndroid Build Coastguard Worker                             .insert(ep_idx, endpoint_descriptor);
208*bb4ee6a4SAndroid Build Coastguard Worker                     } else {
209*bb4ee6a4SAndroid Build Coastguard Worker                         warn!("Could not read endpoint descriptor {}", ep_idx);
210*bb4ee6a4SAndroid Build Coastguard Worker                         break;
211*bb4ee6a4SAndroid Build Coastguard Worker                     }
212*bb4ee6a4SAndroid Build Coastguard Worker                 }
213*bb4ee6a4SAndroid Build Coastguard Worker 
214*bb4ee6a4SAndroid Build Coastguard Worker                 config_descriptor.interface_descriptors.insert(
215*bb4ee6a4SAndroid Build Coastguard Worker                     (
216*bb4ee6a4SAndroid Build Coastguard Worker                         interface_descriptor.bInterfaceNumber,
217*bb4ee6a4SAndroid Build Coastguard Worker                         interface_descriptor.bAlternateSetting,
218*bb4ee6a4SAndroid Build Coastguard Worker                     ),
219*bb4ee6a4SAndroid Build Coastguard Worker                     interface_descriptor,
220*bb4ee6a4SAndroid Build Coastguard Worker                 );
221*bb4ee6a4SAndroid Build Coastguard Worker             }
222*bb4ee6a4SAndroid Build Coastguard Worker 
223*bb4ee6a4SAndroid Build Coastguard Worker             for intf_idx in 0..config_descriptor.bNumInterfaces {
224*bb4ee6a4SAndroid Build Coastguard Worker                 if !config_descriptor
225*bb4ee6a4SAndroid Build Coastguard Worker                     .interface_descriptors
226*bb4ee6a4SAndroid Build Coastguard Worker                     .contains_key(&(intf_idx, 0))
227*bb4ee6a4SAndroid Build Coastguard Worker                 {
228*bb4ee6a4SAndroid Build Coastguard Worker                     warn!("device interface {} has no interface descriptors", intf_idx);
229*bb4ee6a4SAndroid Build Coastguard Worker                 }
230*bb4ee6a4SAndroid Build Coastguard Worker             }
231*bb4ee6a4SAndroid Build Coastguard Worker 
232*bb4ee6a4SAndroid Build Coastguard Worker             device_descriptor
233*bb4ee6a4SAndroid Build Coastguard Worker                 .config_values
234*bb4ee6a4SAndroid Build Coastguard Worker                 .insert(cfg_idx, config_descriptor.bConfigurationValue);
235*bb4ee6a4SAndroid Build Coastguard Worker             device_descriptor
236*bb4ee6a4SAndroid Build Coastguard Worker                 .config_descriptors
237*bb4ee6a4SAndroid Build Coastguard Worker                 .insert(config_descriptor.bConfigurationValue, config_descriptor);
238*bb4ee6a4SAndroid Build Coastguard Worker         } else {
239*bb4ee6a4SAndroid Build Coastguard Worker             warn!("Could not read config descriptor {}", cfg_idx);
240*bb4ee6a4SAndroid Build Coastguard Worker             break;
241*bb4ee6a4SAndroid Build Coastguard Worker         }
242*bb4ee6a4SAndroid Build Coastguard Worker     }
243*bb4ee6a4SAndroid Build Coastguard Worker 
244*bb4ee6a4SAndroid Build Coastguard Worker     Ok(device_descriptor)
245*bb4ee6a4SAndroid Build Coastguard Worker }
246*bb4ee6a4SAndroid Build Coastguard Worker 
247*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
248*bb4ee6a4SAndroid Build Coastguard Worker #[allow(clippy::useless_conversion)]
249*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
250*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
251*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
parse_descriptors_mass_storage()252*bb4ee6a4SAndroid Build Coastguard Worker     fn parse_descriptors_mass_storage() {
253*bb4ee6a4SAndroid Build Coastguard Worker         let data: &[u8] = &[
254*bb4ee6a4SAndroid Build Coastguard Worker             0x12, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x09, 0x81, 0x07, 0x80, 0x55, 0x10, 0x00,
255*bb4ee6a4SAndroid Build Coastguard Worker             0x01, 0x02, 0x03, 0x01, 0x09, 0x02, 0x2C, 0x00, 0x01, 0x01, 0x00, 0x80, 0x32, 0x09,
256*bb4ee6a4SAndroid Build Coastguard Worker             0x04, 0x00, 0x00, 0x02, 0x08, 0x06, 0x50, 0x00, 0x07, 0x05, 0x81, 0x02, 0x00, 0x04,
257*bb4ee6a4SAndroid Build Coastguard Worker             0x00, 0x06, 0x30, 0x0F, 0x00, 0x00, 0x00, 0x07, 0x05, 0x02, 0x02, 0x00, 0x04, 0x00,
258*bb4ee6a4SAndroid Build Coastguard Worker             0x06, 0x30, 0x0F, 0x00, 0x00, 0x00,
259*bb4ee6a4SAndroid Build Coastguard Worker         ];
260*bb4ee6a4SAndroid Build Coastguard Worker 
261*bb4ee6a4SAndroid Build Coastguard Worker         let d = parse_usbfs_descriptors(data).expect("parse_usbfs_descriptors failed");
262*bb4ee6a4SAndroid Build Coastguard Worker 
263*bb4ee6a4SAndroid Build Coastguard Worker         // The seemingly-redundant u16::from() calls avoid borrows of packed fields.
264*bb4ee6a4SAndroid Build Coastguard Worker 
265*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(d.bcdUSB), 0x03_00);
266*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.bDeviceClass, 0x00);
267*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.bDeviceSubClass, 0x00);
268*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.bDeviceProtocol, 0x00);
269*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.bMaxPacketSize0, 9);
270*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(d.idVendor), 0x0781);
271*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(d.idProduct), 0x5580);
272*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(d.bcdDevice), 0x00_10);
273*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.iManufacturer, 1);
274*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.iProduct, 2);
275*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.iSerialNumber, 3);
276*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.bNumConfigurations, 1);
277*bb4ee6a4SAndroid Build Coastguard Worker 
278*bb4ee6a4SAndroid Build Coastguard Worker         let c = d
279*bb4ee6a4SAndroid Build Coastguard Worker             .get_config_descriptor(1)
280*bb4ee6a4SAndroid Build Coastguard Worker             .expect("could not get config descriptor 1");
281*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(c.wTotalLength), 44);
282*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(c.bNumInterfaces, 1);
283*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(c.bConfigurationValue, 1);
284*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(c.iConfiguration, 0);
285*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(c.bmAttributes, 0x80);
286*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(c.bMaxPower, 50);
287*bb4ee6a4SAndroid Build Coastguard Worker 
288*bb4ee6a4SAndroid Build Coastguard Worker         let i = c
289*bb4ee6a4SAndroid Build Coastguard Worker             .get_interface_descriptor(0, 0)
290*bb4ee6a4SAndroid Build Coastguard Worker             .expect("could not get interface descriptor 0 alt setting 0");
291*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceNumber, 0);
292*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bAlternateSetting, 0);
293*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bNumEndpoints, 2);
294*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceClass, 0x08);
295*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceSubClass, 0x06);
296*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceProtocol, 0x50);
297*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.iInterface, 0);
298*bb4ee6a4SAndroid Build Coastguard Worker 
299*bb4ee6a4SAndroid Build Coastguard Worker         let e = i
300*bb4ee6a4SAndroid Build Coastguard Worker             .get_endpoint_descriptor(0)
301*bb4ee6a4SAndroid Build Coastguard Worker             .expect("could not get endpoint 0 descriptor");
302*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bEndpointAddress, 0x81);
303*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bmAttributes, 0x02);
304*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(e.wMaxPacketSize), 0x0400);
305*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bInterval, 0);
306*bb4ee6a4SAndroid Build Coastguard Worker 
307*bb4ee6a4SAndroid Build Coastguard Worker         let e = i
308*bb4ee6a4SAndroid Build Coastguard Worker             .get_endpoint_descriptor(1)
309*bb4ee6a4SAndroid Build Coastguard Worker             .expect("could not get endpoint 1 descriptor");
310*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bEndpointAddress, 0x02);
311*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bmAttributes, 0x02);
312*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(e.wMaxPacketSize), 0x0400);
313*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bInterval, 0);
314*bb4ee6a4SAndroid Build Coastguard Worker     }
315*bb4ee6a4SAndroid Build Coastguard Worker 
316*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
parse_descriptors_servo()317*bb4ee6a4SAndroid Build Coastguard Worker     fn parse_descriptors_servo() {
318*bb4ee6a4SAndroid Build Coastguard Worker         let data: &[u8] = &[
319*bb4ee6a4SAndroid Build Coastguard Worker             0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0xd1, 0x18, 0x1b, 0x50, 0x00, 0x01,
320*bb4ee6a4SAndroid Build Coastguard Worker             0x01, 0x02, 0x03, 0x01, 0x09, 0x02, 0x7c, 0x00, 0x06, 0x01, 0x04, 0xc0, 0xfa, 0x09,
321*bb4ee6a4SAndroid Build Coastguard Worker             0x04, 0x00, 0x00, 0x02, 0xff, 0x50, 0x01, 0x06, 0x07, 0x05, 0x81, 0x02, 0x40, 0x00,
322*bb4ee6a4SAndroid Build Coastguard Worker             0x0a, 0x07, 0x05, 0x01, 0x02, 0x40, 0x00, 0x00, 0x09, 0x04, 0x02, 0x00, 0x02, 0xff,
323*bb4ee6a4SAndroid Build Coastguard Worker             0x52, 0x01, 0x05, 0x07, 0x05, 0x83, 0x02, 0x40, 0x00, 0x0a, 0x07, 0x05, 0x03, 0x02,
324*bb4ee6a4SAndroid Build Coastguard Worker             0x40, 0x00, 0x00, 0x09, 0x04, 0x03, 0x00, 0x02, 0xff, 0x50, 0x01, 0x07, 0x07, 0x05,
325*bb4ee6a4SAndroid Build Coastguard Worker             0x84, 0x02, 0x10, 0x00, 0x0a, 0x07, 0x05, 0x04, 0x02, 0x10, 0x00, 0x00, 0x09, 0x04,
326*bb4ee6a4SAndroid Build Coastguard Worker             0x04, 0x00, 0x02, 0xff, 0x50, 0x01, 0x08, 0x07, 0x05, 0x85, 0x02, 0x10, 0x00, 0x0a,
327*bb4ee6a4SAndroid Build Coastguard Worker             0x07, 0x05, 0x05, 0x02, 0x10, 0x00, 0x00, 0x09, 0x04, 0x05, 0x00, 0x02, 0xff, 0x53,
328*bb4ee6a4SAndroid Build Coastguard Worker             0xff, 0x09, 0x07, 0x05, 0x86, 0x02, 0x40, 0x00, 0x0a, 0x07, 0x05, 0x06, 0x02, 0x40,
329*bb4ee6a4SAndroid Build Coastguard Worker             0x00, 0x00,
330*bb4ee6a4SAndroid Build Coastguard Worker         ];
331*bb4ee6a4SAndroid Build Coastguard Worker 
332*bb4ee6a4SAndroid Build Coastguard Worker         // Note: configuration 1 has bNumInterfaces == 6, but it actually only contains 5
333*bb4ee6a4SAndroid Build Coastguard Worker         // interface descriptors. This causes us to try to read beyond EOF, which should be
334*bb4ee6a4SAndroid Build Coastguard Worker         // silently ignored by parse_usbfs_descriptors so that we can use the rest of the
335*bb4ee6a4SAndroid Build Coastguard Worker         // descriptors.
336*bb4ee6a4SAndroid Build Coastguard Worker         let d = parse_usbfs_descriptors(data).expect("parse_usbfs_descriptors failed");
337*bb4ee6a4SAndroid Build Coastguard Worker 
338*bb4ee6a4SAndroid Build Coastguard Worker         // The seemingly-redundant u16::from() calls avoid borrows of packed fields.
339*bb4ee6a4SAndroid Build Coastguard Worker 
340*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(d.bcdUSB), 0x02_00);
341*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.bDeviceClass, 0x00);
342*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.bDeviceSubClass, 0x00);
343*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.bDeviceProtocol, 0x00);
344*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.bMaxPacketSize0, 64);
345*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(d.idVendor), 0x18d1);
346*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(d.idProduct), 0x501b);
347*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(d.bcdDevice), 0x01_00);
348*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.iManufacturer, 1);
349*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.iProduct, 2);
350*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.iSerialNumber, 3);
351*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.bNumConfigurations, 1);
352*bb4ee6a4SAndroid Build Coastguard Worker 
353*bb4ee6a4SAndroid Build Coastguard Worker         let c = d
354*bb4ee6a4SAndroid Build Coastguard Worker             .get_config_descriptor(1)
355*bb4ee6a4SAndroid Build Coastguard Worker             .expect("could not get config descriptor 1");
356*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(c.wTotalLength), 124);
357*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(c.bNumInterfaces, 6);
358*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(c.bConfigurationValue, 1);
359*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(c.iConfiguration, 4);
360*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(c.bmAttributes, 0xc0);
361*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(c.bMaxPower, 250);
362*bb4ee6a4SAndroid Build Coastguard Worker 
363*bb4ee6a4SAndroid Build Coastguard Worker         let i = c
364*bb4ee6a4SAndroid Build Coastguard Worker             .get_interface_descriptor(0, 0)
365*bb4ee6a4SAndroid Build Coastguard Worker             .expect("could not get interface descriptor 0 alt setting 0");
366*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceNumber, 0);
367*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bAlternateSetting, 0);
368*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bNumEndpoints, 2);
369*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceClass, 0xff);
370*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceSubClass, 0x50);
371*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceProtocol, 0x01);
372*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.iInterface, 6);
373*bb4ee6a4SAndroid Build Coastguard Worker 
374*bb4ee6a4SAndroid Build Coastguard Worker         let e = i
375*bb4ee6a4SAndroid Build Coastguard Worker             .get_endpoint_descriptor(0)
376*bb4ee6a4SAndroid Build Coastguard Worker             .expect("could not get endpoint 0 descriptor");
377*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bEndpointAddress, 0x81);
378*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bmAttributes, 0x02);
379*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(e.wMaxPacketSize), 0x0040);
380*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bInterval, 10);
381*bb4ee6a4SAndroid Build Coastguard Worker 
382*bb4ee6a4SAndroid Build Coastguard Worker         let e = i
383*bb4ee6a4SAndroid Build Coastguard Worker             .get_endpoint_descriptor(1)
384*bb4ee6a4SAndroid Build Coastguard Worker             .expect("could not get endpoint 1 descriptor");
385*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bEndpointAddress, 0x01);
386*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bmAttributes, 0x02);
387*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(e.wMaxPacketSize), 0x0040);
388*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bInterval, 0);
389*bb4ee6a4SAndroid Build Coastguard Worker 
390*bb4ee6a4SAndroid Build Coastguard Worker         let i = c
391*bb4ee6a4SAndroid Build Coastguard Worker             .get_interface_descriptor(2, 0)
392*bb4ee6a4SAndroid Build Coastguard Worker             .expect("could not get interface descriptor 2 alt setting 0");
393*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceNumber, 2);
394*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bAlternateSetting, 0);
395*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bNumEndpoints, 2);
396*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceClass, 0xff);
397*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceSubClass, 0x52);
398*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceProtocol, 0x01);
399*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.iInterface, 5);
400*bb4ee6a4SAndroid Build Coastguard Worker 
401*bb4ee6a4SAndroid Build Coastguard Worker         let e = i
402*bb4ee6a4SAndroid Build Coastguard Worker             .get_endpoint_descriptor(0)
403*bb4ee6a4SAndroid Build Coastguard Worker             .expect("could not get endpoint 0 descriptor");
404*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bEndpointAddress, 0x83);
405*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bmAttributes, 0x02);
406*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(e.wMaxPacketSize), 0x0040);
407*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bInterval, 10);
408*bb4ee6a4SAndroid Build Coastguard Worker 
409*bb4ee6a4SAndroid Build Coastguard Worker         let e = i
410*bb4ee6a4SAndroid Build Coastguard Worker             .get_endpoint_descriptor(1)
411*bb4ee6a4SAndroid Build Coastguard Worker             .expect("could not get endpoint 1 descriptor");
412*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bEndpointAddress, 0x03);
413*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bmAttributes, 0x02);
414*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(e.wMaxPacketSize), 0x0040);
415*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bInterval, 0);
416*bb4ee6a4SAndroid Build Coastguard Worker 
417*bb4ee6a4SAndroid Build Coastguard Worker         let i = c
418*bb4ee6a4SAndroid Build Coastguard Worker             .get_interface_descriptor(3, 0)
419*bb4ee6a4SAndroid Build Coastguard Worker             .expect("could not get interface descriptor 3 alt setting 0");
420*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceNumber, 3);
421*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bAlternateSetting, 0);
422*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bNumEndpoints, 2);
423*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceClass, 0xff);
424*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceSubClass, 0x50);
425*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceProtocol, 0x01);
426*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.iInterface, 7);
427*bb4ee6a4SAndroid Build Coastguard Worker 
428*bb4ee6a4SAndroid Build Coastguard Worker         let e = i
429*bb4ee6a4SAndroid Build Coastguard Worker             .get_endpoint_descriptor(0)
430*bb4ee6a4SAndroid Build Coastguard Worker             .expect("could not get endpoint 0 descriptor");
431*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bEndpointAddress, 0x84);
432*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bmAttributes, 0x02);
433*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(e.wMaxPacketSize), 0x0010);
434*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bInterval, 10);
435*bb4ee6a4SAndroid Build Coastguard Worker 
436*bb4ee6a4SAndroid Build Coastguard Worker         let e = i
437*bb4ee6a4SAndroid Build Coastguard Worker             .get_endpoint_descriptor(1)
438*bb4ee6a4SAndroid Build Coastguard Worker             .expect("could not get endpoint 1 descriptor");
439*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bEndpointAddress, 0x04);
440*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bmAttributes, 0x02);
441*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(e.wMaxPacketSize), 0x0010);
442*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bInterval, 0);
443*bb4ee6a4SAndroid Build Coastguard Worker 
444*bb4ee6a4SAndroid Build Coastguard Worker         let i = c
445*bb4ee6a4SAndroid Build Coastguard Worker             .get_interface_descriptor(4, 0)
446*bb4ee6a4SAndroid Build Coastguard Worker             .expect("could not get interface descriptor 4 alt setting 0");
447*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceNumber, 4);
448*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bAlternateSetting, 0);
449*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bNumEndpoints, 2);
450*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceClass, 0xff);
451*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceSubClass, 0x50);
452*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceProtocol, 0x01);
453*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.iInterface, 8);
454*bb4ee6a4SAndroid Build Coastguard Worker 
455*bb4ee6a4SAndroid Build Coastguard Worker         let e = i
456*bb4ee6a4SAndroid Build Coastguard Worker             .get_endpoint_descriptor(0)
457*bb4ee6a4SAndroid Build Coastguard Worker             .expect("could not get endpoint 0 descriptor");
458*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bEndpointAddress, 0x85);
459*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bmAttributes, 0x02);
460*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(e.wMaxPacketSize), 0x0010);
461*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bInterval, 10);
462*bb4ee6a4SAndroid Build Coastguard Worker 
463*bb4ee6a4SAndroid Build Coastguard Worker         let e = i
464*bb4ee6a4SAndroid Build Coastguard Worker             .get_endpoint_descriptor(1)
465*bb4ee6a4SAndroid Build Coastguard Worker             .expect("could not get endpoint 1 descriptor");
466*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bEndpointAddress, 0x05);
467*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bmAttributes, 0x02);
468*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(e.wMaxPacketSize), 0x0010);
469*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bInterval, 0);
470*bb4ee6a4SAndroid Build Coastguard Worker 
471*bb4ee6a4SAndroid Build Coastguard Worker         let i = c
472*bb4ee6a4SAndroid Build Coastguard Worker             .get_interface_descriptor(5, 0)
473*bb4ee6a4SAndroid Build Coastguard Worker             .expect("could not get interface descriptor 5 alt setting 0");
474*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceNumber, 5);
475*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bAlternateSetting, 0);
476*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bNumEndpoints, 2);
477*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceClass, 0xff);
478*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceSubClass, 0x53);
479*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceProtocol, 0xff);
480*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.iInterface, 9);
481*bb4ee6a4SAndroid Build Coastguard Worker 
482*bb4ee6a4SAndroid Build Coastguard Worker         let e = i
483*bb4ee6a4SAndroid Build Coastguard Worker             .get_endpoint_descriptor(0)
484*bb4ee6a4SAndroid Build Coastguard Worker             .expect("could not get endpoint 0 descriptor");
485*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bEndpointAddress, 0x86);
486*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bmAttributes, 0x02);
487*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(e.wMaxPacketSize), 0x0040);
488*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bInterval, 10);
489*bb4ee6a4SAndroid Build Coastguard Worker 
490*bb4ee6a4SAndroid Build Coastguard Worker         let e = i
491*bb4ee6a4SAndroid Build Coastguard Worker             .get_endpoint_descriptor(1)
492*bb4ee6a4SAndroid Build Coastguard Worker             .expect("could not get endpoint 1 descriptor");
493*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bEndpointAddress, 0x06);
494*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bmAttributes, 0x02);
495*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(e.wMaxPacketSize), 0x0040);
496*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bInterval, 0);
497*bb4ee6a4SAndroid Build Coastguard Worker     }
498*bb4ee6a4SAndroid Build Coastguard Worker 
499*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
parse_descriptors_adb()500*bb4ee6a4SAndroid Build Coastguard Worker     fn parse_descriptors_adb() {
501*bb4ee6a4SAndroid Build Coastguard Worker         let data: &[u8] = &[
502*bb4ee6a4SAndroid Build Coastguard Worker             0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0xd1, 0x18, 0xe7, 0x4e, 0x10, 0x03,
503*bb4ee6a4SAndroid Build Coastguard Worker             0x01, 0x02, 0x03, 0x01, 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0x80, 0xfa, 0x09,
504*bb4ee6a4SAndroid Build Coastguard Worker             0x04, 0x00, 0x00, 0x02, 0xff, 0x42, 0x01, 0x05, 0x07, 0x05, 0x01, 0x02, 0x00, 0x02,
505*bb4ee6a4SAndroid Build Coastguard Worker             0x00, 0x07, 0x05, 0x81, 0x02, 0x00, 0x02, 0x00,
506*bb4ee6a4SAndroid Build Coastguard Worker         ];
507*bb4ee6a4SAndroid Build Coastguard Worker 
508*bb4ee6a4SAndroid Build Coastguard Worker         let d = parse_usbfs_descriptors(data).expect("parse_usbfs_descriptors failed");
509*bb4ee6a4SAndroid Build Coastguard Worker 
510*bb4ee6a4SAndroid Build Coastguard Worker         // The seemingly-redundant u16::from() calls avoid borrows of packed fields.
511*bb4ee6a4SAndroid Build Coastguard Worker 
512*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(d.bcdUSB), 0x02_00);
513*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.bDeviceClass, 0x00);
514*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.bDeviceSubClass, 0x00);
515*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.bDeviceProtocol, 0x00);
516*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.bMaxPacketSize0, 64);
517*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(d.idVendor), 0x18d1);
518*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(d.idProduct), 0x4ee7);
519*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(d.bcdDevice), 0x03_10);
520*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.iManufacturer, 1);
521*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.iProduct, 2);
522*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.iSerialNumber, 3);
523*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.bNumConfigurations, 1);
524*bb4ee6a4SAndroid Build Coastguard Worker 
525*bb4ee6a4SAndroid Build Coastguard Worker         let c = d
526*bb4ee6a4SAndroid Build Coastguard Worker             .get_config_descriptor(1)
527*bb4ee6a4SAndroid Build Coastguard Worker             .expect("could not get config descriptor 1");
528*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(c.wTotalLength), 32);
529*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(c.bNumInterfaces, 1);
530*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(c.bConfigurationValue, 1);
531*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(c.iConfiguration, 0);
532*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(c.bmAttributes, 0x80);
533*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(c.bMaxPower, 250);
534*bb4ee6a4SAndroid Build Coastguard Worker 
535*bb4ee6a4SAndroid Build Coastguard Worker         let i = c
536*bb4ee6a4SAndroid Build Coastguard Worker             .get_interface_descriptor(0, 0)
537*bb4ee6a4SAndroid Build Coastguard Worker             .expect("could not get interface descriptor 0 alt setting 0");
538*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceNumber, 0);
539*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bAlternateSetting, 0);
540*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bNumEndpoints, 2);
541*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceClass, 0xff);
542*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceSubClass, 0x42);
543*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceProtocol, 0x01);
544*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.iInterface, 5);
545*bb4ee6a4SAndroid Build Coastguard Worker 
546*bb4ee6a4SAndroid Build Coastguard Worker         let e = i
547*bb4ee6a4SAndroid Build Coastguard Worker             .get_endpoint_descriptor(0)
548*bb4ee6a4SAndroid Build Coastguard Worker             .expect("could not get endpoint 0 descriptor");
549*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bEndpointAddress, 0x01);
550*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bmAttributes, 0x02);
551*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(e.wMaxPacketSize), 0x200);
552*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bInterval, 0);
553*bb4ee6a4SAndroid Build Coastguard Worker 
554*bb4ee6a4SAndroid Build Coastguard Worker         let e = i
555*bb4ee6a4SAndroid Build Coastguard Worker             .get_endpoint_descriptor(1)
556*bb4ee6a4SAndroid Build Coastguard Worker             .expect("could not get endpoint 1 descriptor");
557*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bEndpointAddress, 0x81);
558*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bmAttributes, 0x02);
559*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(e.wMaxPacketSize), 0x0200);
560*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bInterval, 0);
561*bb4ee6a4SAndroid Build Coastguard Worker     }
562*bb4ee6a4SAndroid Build Coastguard Worker 
563*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
parse_descriptors_multiple_altsettings()564*bb4ee6a4SAndroid Build Coastguard Worker     fn parse_descriptors_multiple_altsettings() {
565*bb4ee6a4SAndroid Build Coastguard Worker         let data: &[u8] = &[
566*bb4ee6a4SAndroid Build Coastguard Worker             // DeviceDescriptor
567*bb4ee6a4SAndroid Build Coastguard Worker             0x12, 0x01, 0x00, 0x02, 0xef, 0x02, 0x01, 0x40, 0x6d, 0x04, 0x43, 0x08, 0x13, 0x00,
568*bb4ee6a4SAndroid Build Coastguard Worker             0x00, 0x02, 0x01, 0x01, // ConfigDescriptor
569*bb4ee6a4SAndroid Build Coastguard Worker             0x09, 0x02, 0x0d, 0x0a, 0x03, 0x01, 0x00, 0x80, 0xfa,
570*bb4ee6a4SAndroid Build Coastguard Worker             // InterfaceDescriptor 0, 0
571*bb4ee6a4SAndroid Build Coastguard Worker             0x09, 0x04, 0x00, 0x00, 0x01, 0x0e, 0x01, 0x00, 0x00, // EndpointDescriptor
572*bb4ee6a4SAndroid Build Coastguard Worker             0x07, 0x05, 0x86, 0x03, 0x40, 0x00, 0x08, // InterfaceDescriptor 1, 0
573*bb4ee6a4SAndroid Build Coastguard Worker             0x09, 0x04, 0x01, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00,
574*bb4ee6a4SAndroid Build Coastguard Worker             // InterfaceDescriptor 1, 1
575*bb4ee6a4SAndroid Build Coastguard Worker             0x09, 0x04, 0x01, 0x01, 0x01, 0x0e, 0x02, 0x00, 0x00, // EndpointDescriptor
576*bb4ee6a4SAndroid Build Coastguard Worker             0x07, 0x05, 0x81, 0x05, 0xc0, 0x00, 0x01, // InterfaceDescriptor 2, 0
577*bb4ee6a4SAndroid Build Coastguard Worker             0x09, 0x04, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,
578*bb4ee6a4SAndroid Build Coastguard Worker         ];
579*bb4ee6a4SAndroid Build Coastguard Worker 
580*bb4ee6a4SAndroid Build Coastguard Worker         let d = parse_usbfs_descriptors(data).expect("parse_usbfs_descriptors failed");
581*bb4ee6a4SAndroid Build Coastguard Worker 
582*bb4ee6a4SAndroid Build Coastguard Worker         // The seemingly-redundant u16::from() calls avoid borrows of packed fields.
583*bb4ee6a4SAndroid Build Coastguard Worker 
584*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(d.bcdUSB), 0x02_00);
585*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.bDeviceClass, 0xef);
586*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.bDeviceSubClass, 0x02);
587*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.bDeviceProtocol, 0x01);
588*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.bMaxPacketSize0, 64);
589*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(d.idVendor), 0x046d);
590*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(d.idProduct), 0x0843);
591*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(d.bcdDevice), 0x00_13);
592*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.iManufacturer, 0);
593*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.iProduct, 2);
594*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.iSerialNumber, 1);
595*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(d.bNumConfigurations, 1);
596*bb4ee6a4SAndroid Build Coastguard Worker 
597*bb4ee6a4SAndroid Build Coastguard Worker         let c = d
598*bb4ee6a4SAndroid Build Coastguard Worker             .get_config_descriptor(1)
599*bb4ee6a4SAndroid Build Coastguard Worker             .expect("could not get config descriptor 1");
600*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(c.wTotalLength), 2573);
601*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(c.bNumInterfaces, 3);
602*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(c.bConfigurationValue, 1);
603*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(c.iConfiguration, 0);
604*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(c.bmAttributes, 0x80);
605*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(c.bMaxPower, 250);
606*bb4ee6a4SAndroid Build Coastguard Worker 
607*bb4ee6a4SAndroid Build Coastguard Worker         let i = c
608*bb4ee6a4SAndroid Build Coastguard Worker             .get_interface_descriptor(0, 0)
609*bb4ee6a4SAndroid Build Coastguard Worker             .expect("could not get interface descriptor 0 alt setting 0");
610*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceNumber, 0);
611*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bAlternateSetting, 0);
612*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bNumEndpoints, 1);
613*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceClass, 0x0e);
614*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceSubClass, 0x01);
615*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceProtocol, 0x00);
616*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.iInterface, 0x00);
617*bb4ee6a4SAndroid Build Coastguard Worker 
618*bb4ee6a4SAndroid Build Coastguard Worker         let e = i
619*bb4ee6a4SAndroid Build Coastguard Worker             .get_endpoint_descriptor(0)
620*bb4ee6a4SAndroid Build Coastguard Worker             .expect("could not get endpoint 0 descriptor");
621*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bEndpointAddress, 0x86);
622*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bmAttributes, 0x03);
623*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(e.wMaxPacketSize), 0x40);
624*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bInterval, 0x08);
625*bb4ee6a4SAndroid Build Coastguard Worker 
626*bb4ee6a4SAndroid Build Coastguard Worker         let i = c
627*bb4ee6a4SAndroid Build Coastguard Worker             .get_interface_descriptor(1, 0)
628*bb4ee6a4SAndroid Build Coastguard Worker             .expect("could not get interface descriptor 1 alt setting 0");
629*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceNumber, 1);
630*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bAlternateSetting, 0);
631*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bNumEndpoints, 0);
632*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceClass, 0x0e);
633*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceSubClass, 0x02);
634*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceProtocol, 0x00);
635*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.iInterface, 0x00);
636*bb4ee6a4SAndroid Build Coastguard Worker 
637*bb4ee6a4SAndroid Build Coastguard Worker         let i = c
638*bb4ee6a4SAndroid Build Coastguard Worker             .get_interface_descriptor(1, 1)
639*bb4ee6a4SAndroid Build Coastguard Worker             .expect("could not get interface descriptor 1 alt setting 1");
640*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceNumber, 1);
641*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bAlternateSetting, 1);
642*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bNumEndpoints, 1);
643*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceClass, 0x0e);
644*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceSubClass, 0x02);
645*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceProtocol, 0x00);
646*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.iInterface, 0x00);
647*bb4ee6a4SAndroid Build Coastguard Worker 
648*bb4ee6a4SAndroid Build Coastguard Worker         let e = i
649*bb4ee6a4SAndroid Build Coastguard Worker             .get_endpoint_descriptor(0)
650*bb4ee6a4SAndroid Build Coastguard Worker             .expect("could not get endpoint 0 descriptor");
651*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bEndpointAddress, 0x81);
652*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bmAttributes, 0x05);
653*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u16::from(e.wMaxPacketSize), 0xc0);
654*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(e.bInterval, 0x01);
655*bb4ee6a4SAndroid Build Coastguard Worker 
656*bb4ee6a4SAndroid Build Coastguard Worker         let i = c
657*bb4ee6a4SAndroid Build Coastguard Worker             .get_interface_descriptor(2, 0)
658*bb4ee6a4SAndroid Build Coastguard Worker             .expect("could not get interface descriptor 2 alt setting 0");
659*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceNumber, 2);
660*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bAlternateSetting, 0);
661*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bNumEndpoints, 0);
662*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceClass, 0x01);
663*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceSubClass, 0x01);
664*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.bInterfaceProtocol, 0x00);
665*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(i.iInterface, 0x00);
666*bb4ee6a4SAndroid Build Coastguard Worker     }
667*bb4ee6a4SAndroid Build Coastguard Worker 
668*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
parse_descriptors_length_0()669*bb4ee6a4SAndroid Build Coastguard Worker     fn parse_descriptors_length_0() {
670*bb4ee6a4SAndroid Build Coastguard Worker         // Device descriptor followed by a bogus descriptor with bLength == 0.
671*bb4ee6a4SAndroid Build Coastguard Worker         // Note that this was generated by a fuzzer, so field values may not make sense.
672*bb4ee6a4SAndroid Build Coastguard Worker         let data: &[u8] = &[
673*bb4ee6a4SAndroid Build Coastguard Worker             0x10, 0x00, 0x18, 0x25, 0x80, 0x80, 0xAC, 0x03, 0x22, 0x05, 0x00, 0x00, 0x00, 0x00,
674*bb4ee6a4SAndroid Build Coastguard Worker             0xC3, 0x2A, 0x00, 0x32, 0x00,
675*bb4ee6a4SAndroid Build Coastguard Worker         ];
676*bb4ee6a4SAndroid Build Coastguard Worker 
677*bb4ee6a4SAndroid Build Coastguard Worker         let d = parse_usbfs_descriptors(data);
678*bb4ee6a4SAndroid Build Coastguard Worker         if d.is_ok() {
679*bb4ee6a4SAndroid Build Coastguard Worker             panic!("parse_usbfs_descriptors should have failed");
680*bb4ee6a4SAndroid Build Coastguard Worker         }
681*bb4ee6a4SAndroid Build Coastguard Worker     }
682*bb4ee6a4SAndroid Build Coastguard Worker }
683