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