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