1 use std::{fmt, slice};
2 
3 use libusb1_sys::{libusb_endpoint_descriptor, libusb_interface, libusb_interface_descriptor};
4 
5 use crate::endpoint_descriptor::{self, EndpointDescriptor};
6 
7 /// A device interface.
8 ///
9 /// An interface can have several descriptors, each describing an alternate setting of the
10 /// interface.
11 pub struct Interface<'a> {
12     descriptors: &'a [libusb_interface_descriptor],
13 }
14 
15 impl<'a> Interface<'a> {
16     /// Returns the interface's number.
number(&self) -> u817     pub fn number(&self) -> u8 {
18         self.descriptors[0].bInterfaceNumber
19     }
20 
21     /// Returns an iterator over the interface's descriptors.
descriptors(&self) -> InterfaceDescriptors<'a>22     pub fn descriptors(&self) -> InterfaceDescriptors<'a> {
23         InterfaceDescriptors {
24             iter: self.descriptors.iter(),
25         }
26     }
27 }
28 
29 /// Iterator over an interface's descriptors.
30 pub struct InterfaceDescriptors<'a> {
31     iter: slice::Iter<'a, libusb_interface_descriptor>,
32 }
33 
34 impl<'a> Iterator for InterfaceDescriptors<'a> {
35     type Item = InterfaceDescriptor<'a>;
36 
next(&mut self) -> Option<InterfaceDescriptor<'a>>37     fn next(&mut self) -> Option<InterfaceDescriptor<'a>> {
38         self.iter
39             .next()
40             .map(|descriptor| InterfaceDescriptor { descriptor })
41     }
42 
size_hint(&self) -> (usize, Option<usize>)43     fn size_hint(&self) -> (usize, Option<usize>) {
44         self.iter.size_hint()
45     }
46 }
47 
48 /// Describes an alternate setting for an interface.
49 pub struct InterfaceDescriptor<'a> {
50     descriptor: &'a libusb_interface_descriptor,
51 }
52 
53 impl<'a> InterfaceDescriptor<'a> {
54     /// Returns the size of the descriptor in bytes
length(&self) -> u855     pub fn length(&self) -> u8 {
56         self.descriptor.bLength
57     }
58 
59     /// Returns the descriptor type
descriptor_type(&self) -> u860     pub fn descriptor_type(&self) -> u8 {
61         self.descriptor.bDescriptorType
62     }
63 
64     /// Returns the interface's number.
interface_number(&self) -> u865     pub fn interface_number(&self) -> u8 {
66         self.descriptor.bInterfaceNumber
67     }
68 
69     /// Returns the alternate setting number.
setting_number(&self) -> u870     pub fn setting_number(&self) -> u8 {
71         self.descriptor.bAlternateSetting
72     }
73 
74     /// Returns the interface's class code.
class_code(&self) -> u875     pub fn class_code(&self) -> u8 {
76         self.descriptor.bInterfaceClass
77     }
78 
79     /// Returns the interface's sub class code.
sub_class_code(&self) -> u880     pub fn sub_class_code(&self) -> u8 {
81         self.descriptor.bInterfaceSubClass
82     }
83 
84     /// Returns the interface's protocol code.
protocol_code(&self) -> u885     pub fn protocol_code(&self) -> u8 {
86         self.descriptor.bInterfaceProtocol
87     }
88 
89     /// Returns the index of the string descriptor that describes the interface.
description_string_index(&self) -> Option<u8>90     pub fn description_string_index(&self) -> Option<u8> {
91         match self.descriptor.iInterface {
92             0 => None,
93             n => Some(n),
94         }
95     }
96 
97     /// Returns the number of endpoints belonging to this interface.
num_endpoints(&self) -> u898     pub fn num_endpoints(&self) -> u8 {
99         self.descriptor.bNumEndpoints
100     }
101 
102     /// Returns an iterator over the interface's endpoint descriptors.
endpoint_descriptors(&self) -> EndpointDescriptors<'a>103     pub fn endpoint_descriptors(&self) -> EndpointDescriptors<'a> {
104         let endpoints = match self.descriptor.bNumEndpoints {
105             0 => &[],
106             n => unsafe { slice::from_raw_parts(self.descriptor.endpoint, n as usize) },
107         };
108 
109         EndpointDescriptors {
110             iter: endpoints.iter(),
111         }
112     }
113 
114     /// Returns the unknown 'extra' bytes that libusb does not understand.
extra(&self) -> &[u8]115     pub fn extra(&self) -> &[u8] {
116         unsafe {
117             match (*self.descriptor).extra_length {
118                 len if len > 0 => slice::from_raw_parts((*self.descriptor).extra, len as usize),
119                 _ => &[],
120             }
121         }
122     }
123 }
124 
125 impl<'a> fmt::Debug for InterfaceDescriptor<'a> {
fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>126     fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
127         let mut debug = fmt.debug_struct("InterfaceDescriptor");
128 
129         debug.field("bLength", &self.descriptor.bLength);
130         debug.field("bDescriptorType", &self.descriptor.bDescriptorType);
131         debug.field("bInterfaceNumber", &self.descriptor.bInterfaceNumber);
132         debug.field("bAlternateSetting", &self.descriptor.bAlternateSetting);
133         debug.field("bNumEndpoints", &self.descriptor.bNumEndpoints);
134         debug.field("bInterfaceClass", &self.descriptor.bInterfaceClass);
135         debug.field("bInterfaceSubClass", &self.descriptor.bInterfaceSubClass);
136         debug.field("bInterfaceProtocol", &self.descriptor.bInterfaceProtocol);
137         debug.field("iInterface", &self.descriptor.iInterface);
138 
139         debug.finish()
140     }
141 }
142 
143 /// Iterator over an interface's endpoint descriptors.
144 pub struct EndpointDescriptors<'a> {
145     iter: slice::Iter<'a, libusb_endpoint_descriptor>,
146 }
147 
148 impl<'a> Iterator for EndpointDescriptors<'a> {
149     type Item = EndpointDescriptor<'a>;
150 
next(&mut self) -> Option<EndpointDescriptor<'a>>151     fn next(&mut self) -> Option<EndpointDescriptor<'a>> {
152         self.iter.next().map(endpoint_descriptor::from_libusb)
153     }
154 
size_hint(&self) -> (usize, Option<usize>)155     fn size_hint(&self) -> (usize, Option<usize>) {
156         self.iter.size_hint()
157     }
158 }
159 
160 #[doc(hidden)]
from_libusb(interface: &libusb_interface) -> Interface161 pub(crate) unsafe fn from_libusb(interface: &libusb_interface) -> Interface {
162     let descriptors =
163         slice::from_raw_parts(interface.altsetting, interface.num_altsetting as usize);
164     debug_assert!(!descriptors.is_empty());
165 
166     Interface { descriptors }
167 }
168 
169 #[cfg(test)]
170 mod test {
171     #[test]
it_has_interface_number()172     fn it_has_interface_number() {
173         assert_eq!(
174             42,
175             unsafe { super::from_libusb(&interface!(interface_descriptor!(bInterfaceNumber: 42))) }
176                 .number()
177         );
178     }
179 
180     #[test]
it_has_interface_number_in_descriptor()181     fn it_has_interface_number_in_descriptor() {
182         assert_eq!(
183             vec!(42),
184             unsafe { super::from_libusb(&interface!(interface_descriptor!(bInterfaceNumber: 42))) }
185                 .descriptors()
186                 .map(|setting| setting.interface_number())
187                 .collect::<Vec<_>>()
188         );
189     }
190 
191     #[test]
it_has_alternate_setting_number()192     fn it_has_alternate_setting_number() {
193         assert_eq!(
194             vec!(42),
195             unsafe {
196                 super::from_libusb(&interface!(interface_descriptor!(bAlternateSetting: 42)))
197             }
198             .descriptors()
199             .map(|setting| setting.setting_number())
200             .collect::<Vec<_>>()
201         );
202     }
203 
204     #[test]
it_has_class_code()205     fn it_has_class_code() {
206         assert_eq!(
207             vec!(42),
208             unsafe { super::from_libusb(&interface!(interface_descriptor!(bInterfaceClass: 42))) }
209                 .descriptors()
210                 .map(|setting| setting.class_code())
211                 .collect::<Vec<_>>()
212         );
213     }
214 
215     #[test]
it_has_sub_class_code()216     fn it_has_sub_class_code() {
217         assert_eq!(
218             vec!(42),
219             unsafe {
220                 super::from_libusb(&interface!(interface_descriptor!(bInterfaceSubClass: 42)))
221             }
222             .descriptors()
223             .map(|setting| setting.sub_class_code())
224             .collect::<Vec<_>>()
225         );
226     }
227 
228     #[test]
it_has_protocol_code()229     fn it_has_protocol_code() {
230         assert_eq!(
231             vec!(42),
232             unsafe {
233                 super::from_libusb(&interface!(interface_descriptor!(bInterfaceProtocol: 42)))
234             }
235             .descriptors()
236             .map(|setting| setting.protocol_code())
237             .collect::<Vec<_>>()
238         );
239     }
240 
241     #[test]
it_has_description_string_index()242     fn it_has_description_string_index() {
243         assert_eq!(
244             vec!(Some(42)),
245             unsafe { super::from_libusb(&interface!(interface_descriptor!(iInterface: 42))) }
246                 .descriptors()
247                 .map(|setting| setting.description_string_index())
248                 .collect::<Vec<_>>()
249         );
250     }
251 
252     #[test]
it_handles_missing_description_string_index()253     fn it_handles_missing_description_string_index() {
254         assert_eq!(
255             vec!(None),
256             unsafe { super::from_libusb(&interface!(interface_descriptor!(iInterface: 0))) }
257                 .descriptors()
258                 .map(|setting| setting.description_string_index())
259                 .collect::<Vec<_>>()
260         );
261     }
262 
263     #[test]
it_has_num_endpoints()264     fn it_has_num_endpoints() {
265         let endpoint1 = endpoint_descriptor!(bEndpointAddress: 0x81);
266         let endpoint2 = endpoint_descriptor!(bEndpointAddress: 0x01);
267 
268         assert_eq!(
269             vec!(2),
270             unsafe { super::from_libusb(&interface!(interface_descriptor!(endpoint1, endpoint2))) }
271                 .descriptors()
272                 .map(|setting| setting.num_endpoints())
273                 .collect::<Vec<_>>()
274         );
275     }
276 
277     #[test]
it_has_endpoints()278     fn it_has_endpoints() {
279         let libusb_interface = interface!(interface_descriptor!(
280             endpoint_descriptor!(bEndpointAddress: 0x87)
281         ));
282         let interface = unsafe { super::from_libusb(&libusb_interface) };
283 
284         let endpoint_addresses = interface
285             .descriptors()
286             .next()
287             .unwrap()
288             .endpoint_descriptors()
289             .map(|endpoint| endpoint.address())
290             .collect::<Vec<_>>();
291 
292         assert_eq!(vec![0x87], endpoint_addresses);
293     }
294 }
295