1 use std::{
2     fmt::{self, Debug},
3     mem,
4     ptr::NonNull,
5     sync::Mutex,
6     time::Duration,
7 };
8 
9 use libc::{c_int, c_uchar, c_uint};
10 use libusb1_sys::{constants::*, *};
11 
12 use crate::{
13     config_descriptor::ConfigDescriptor,
14     device::{self, Device},
15     device_descriptor::DeviceDescriptor,
16     error::{self, Error},
17     fields::{request_type, Direction, Recipient, RequestType},
18     interface_descriptor::InterfaceDescriptor,
19     language::Language,
20     UsbContext,
21 };
22 
23 /// Bit set representing claimed USB interfaces.
24 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
25 struct ClaimedInterfaces {
26     inner: [u128; 2],
27 }
28 
29 impl ClaimedInterfaces {
30     /// Create a new bit set.
new() -> Self31     fn new() -> Self {
32         Self { inner: [0, 0] }
33     }
34 
get_index_and_mask(interface: u8) -> (usize, u128)35     fn get_index_and_mask(interface: u8) -> (usize, u128) {
36         ((interface / 128) as usize, 1 << (interface % 128))
37     }
38 
39     /// Mark `interface` as claimed.
insert(&mut self, interface: u8)40     fn insert(&mut self, interface: u8) {
41         let (index, mask) = ClaimedInterfaces::get_index_and_mask(interface);
42         self.inner[index] |= mask;
43     }
44 
45     /// Mark `interface` as not claimed.
remove(&mut self, interface: u8)46     fn remove(&mut self, interface: u8) {
47         let (index, mask) = ClaimedInterfaces::get_index_and_mask(interface);
48         self.inner[index] &= !mask;
49     }
50 
51     /// Returns true if this set contains `interface`.
contains(&self, interface: u8) -> bool52     fn contains(&self, interface: u8) -> bool {
53         let (index, mask) = ClaimedInterfaces::get_index_and_mask(interface);
54         self.inner[index] & mask != 0
55     }
56 
57     /// Returns a count of the interfaces contained in this set.
size(&self) -> usize58     fn size(&self) -> usize {
59         self.inner.iter().map(|v| v.count_ones()).sum::<u32>() as usize
60     }
61 
62     /// Returns an iterator over the interfaces in this set.
iter(&self) -> ClaimedInterfacesIter63     fn iter(&self) -> ClaimedInterfacesIter {
64         ClaimedInterfacesIter::new(self)
65     }
66 }
67 
68 /// Iterator over interfaces.
69 struct ClaimedInterfacesIter<'a> {
70     // Next interface to check as a possible value to return from the interator.
71     index: u16,
72 
73     // Number of elements remaining in this iterator.
74     remaining: usize,
75 
76     // The ClaimedInterfaces object that we're iterating over.
77     source: &'a ClaimedInterfaces,
78 }
79 
80 impl ClaimedInterfacesIter<'_> {
81     /// Create a new iterator over the interfaces in `source`.
new(source: &ClaimedInterfaces) -> ClaimedInterfacesIter82     fn new(source: &ClaimedInterfaces) -> ClaimedInterfacesIter {
83         ClaimedInterfacesIter {
84             index: 0,
85             remaining: source.size(),
86             source,
87         }
88     }
89 }
90 
91 impl<'a> Iterator for ClaimedInterfacesIter<'a> {
92     type Item = u8;
93 
next(&mut self) -> Option<u8>94     fn next(&mut self) -> Option<u8> {
95         while self.index <= u8::MAX as u16 {
96             let index = self.index as u8;
97             let contains = self.source.contains(index);
98             self.index += 1;
99             if contains {
100                 self.remaining -= 1;
101                 return Some(index);
102             }
103         }
104         None
105     }
106 
size_hint(&self) -> (usize, Option<usize>)107     fn size_hint(&self) -> (usize, Option<usize>) {
108         (self.remaining, Some(self.remaining))
109     }
110 }
111 
112 /// A handle to an open USB device.
113 pub struct DeviceHandle<T: UsbContext> {
114     context: T,
115     handle: Option<NonNull<libusb_device_handle>>,
116     interfaces: Mutex<ClaimedInterfaces>,
117 }
118 
119 impl<T: UsbContext> Drop for DeviceHandle<T> {
120     /// Closes the device.
drop(&mut self)121     fn drop(&mut self) {
122         unsafe {
123             let interfaces = self.interfaces.lock().unwrap();
124             for iface in interfaces.iter() {
125                 libusb_release_interface(self.as_raw(), iface as c_int);
126             }
127 
128             if let Some(handle) = self.handle {
129                 libusb_close(handle.as_ptr());
130             }
131         }
132     }
133 }
134 
135 unsafe impl<T: UsbContext> Send for DeviceHandle<T> {}
136 unsafe impl<T: UsbContext> Sync for DeviceHandle<T> {}
137 
138 impl<T: UsbContext> Debug for DeviceHandle<T> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result139     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
140         f.debug_struct("DeviceHandle")
141             .field("device", &self.device())
142             .field("handle", &self.handle)
143             .field("interfaces", &*self.interfaces.lock().unwrap())
144             .finish()
145     }
146 }
147 
148 impl<T: UsbContext + PartialEq> PartialEq for DeviceHandle<T> {
eq(&self, other: &Self) -> bool149     fn eq(&self, other: &Self) -> bool {
150         self.context == other.context
151             && self.handle == other.handle
152             && *self.interfaces.lock().unwrap() == *other.interfaces.lock().unwrap()
153     }
154 }
155 
156 impl<T: UsbContext + PartialEq> Eq for DeviceHandle<T> {}
157 
158 impl<T: UsbContext> DeviceHandle<T> {
159     /// Get the raw libusb_device_handle pointer, for advanced use in unsafe code.
160     ///
161     /// This structure tracks claimed interfaces, and will get out if sync if interfaces are
162     /// manipulated externally. Use only libusb endpoint IO functions.
as_raw(&self) -> *mut libusb_device_handle163     pub fn as_raw(&self) -> *mut libusb_device_handle {
164         // Safety: handle is Some() after initialization
165         match self.handle {
166             Some(it) => it.as_ptr(),
167             _ => unreachable!(),
168         }
169     }
170 
171     /// Consumes the `DeviceHandle`, returning the raw libusb_device_handle
172     /// pointer, for advanced use in unsafe code.
173     ///
174     /// # Safety
175     ///
176     /// Panics if you have any claimed interfaces on this handle.
into_raw(mut self) -> *mut libusb_device_handle177     pub fn into_raw(mut self) -> *mut libusb_device_handle {
178         assert_eq!(self.interfaces.lock().unwrap().size(), 0);
179         match self.handle.take() {
180             Some(it) => it.as_ptr(),
181             _ => unreachable!(),
182         }
183     }
184 
185     /// Get the context associated with this device
context(&self) -> &T186     pub fn context(&self) -> &T {
187         &self.context
188     }
189 
190     /// Get the device associated to this handle
device(&self) -> Device<T>191     pub fn device(&self) -> Device<T> {
192         unsafe {
193             device::Device::from_libusb(
194                 self.context.clone(),
195                 std::ptr::NonNull::new_unchecked(libusb_get_device(self.as_raw())),
196             )
197         }
198     }
199 
200     /// # Safety
201     ///
202     /// Converts an existing `libusb_device_handle` pointer into a `DeviceHandle<T>`.
203     /// `handle` must be a pointer to a valid `libusb_device_handle`. Rusb assumes ownership of the handle, and will close it on `drop`.
from_libusb( context: T, handle: NonNull<libusb_device_handle>, ) -> DeviceHandle<T>204     pub unsafe fn from_libusb(
205         context: T,
206         handle: NonNull<libusb_device_handle>,
207     ) -> DeviceHandle<T> {
208         DeviceHandle {
209             context,
210             handle: Some(handle),
211             interfaces: Mutex::new(ClaimedInterfaces::new()),
212         }
213     }
214 
215     /// Returns the active configuration number.
active_configuration(&self) -> crate::Result<u8>216     pub fn active_configuration(&self) -> crate::Result<u8> {
217         let mut config = mem::MaybeUninit::<c_int>::uninit();
218 
219         try_unsafe!(libusb_get_configuration(self.as_raw(), config.as_mut_ptr()));
220         Ok(unsafe { config.assume_init() } as u8)
221     }
222 
223     /// Sets the device's active configuration.
set_active_configuration(&self, config: u8) -> crate::Result<()>224     pub fn set_active_configuration(&self, config: u8) -> crate::Result<()> {
225         try_unsafe!(libusb_set_configuration(self.as_raw(), c_int::from(config)));
226         Ok(())
227     }
228 
229     /// Puts the device in an unconfigured state.
unconfigure(&self) -> crate::Result<()>230     pub fn unconfigure(&self) -> crate::Result<()> {
231         try_unsafe!(libusb_set_configuration(self.as_raw(), -1));
232         Ok(())
233     }
234 
235     /// Resets the device.
reset(&self) -> crate::Result<()>236     pub fn reset(&self) -> crate::Result<()> {
237         try_unsafe!(libusb_reset_device(self.as_raw()));
238         Ok(())
239     }
240 
241     /// Clear the halt/stall condition for an endpoint.
clear_halt(&self, endpoint: u8) -> crate::Result<()>242     pub fn clear_halt(&self, endpoint: u8) -> crate::Result<()> {
243         try_unsafe!(libusb_clear_halt(self.as_raw(), endpoint));
244         Ok(())
245     }
246 
247     /// Indicates whether the device has an attached kernel driver.
248     ///
249     /// This method is not supported on all platforms.
kernel_driver_active(&self, iface: u8) -> crate::Result<bool>250     pub fn kernel_driver_active(&self, iface: u8) -> crate::Result<bool> {
251         match unsafe { libusb_kernel_driver_active(self.as_raw(), c_int::from(iface)) } {
252             0 => Ok(false),
253             1 => Ok(true),
254             err => Err(error::from_libusb(err)),
255         }
256     }
257 
258     /// Detaches an attached kernel driver from the device.
259     ///
260     /// This method is not supported on all platforms.
detach_kernel_driver(&self, iface: u8) -> crate::Result<()>261     pub fn detach_kernel_driver(&self, iface: u8) -> crate::Result<()> {
262         try_unsafe!(libusb_detach_kernel_driver(
263             self.as_raw(),
264             c_int::from(iface)
265         ));
266         Ok(())
267     }
268 
269     /// Attaches a kernel driver to the device.
270     ///
271     /// This method is not supported on all platforms.
attach_kernel_driver(&self, iface: u8) -> crate::Result<()>272     pub fn attach_kernel_driver(&self, iface: u8) -> crate::Result<()> {
273         try_unsafe!(libusb_attach_kernel_driver(
274             self.as_raw(),
275             c_int::from(iface)
276         ));
277         Ok(())
278     }
279 
280     /// Enable/disable automatic kernel driver detachment.
281     ///
282     /// When this is enabled rusb will automatically detach the
283     /// kernel driver on an interface when claiming the interface, and
284     /// attach it when releasing the interface.
285     ///
286     /// On platforms which do not have support, this function will
287     /// return `Error::NotSupported`, and rusb will continue as if
288     /// this function was never called.
set_auto_detach_kernel_driver(&self, auto_detach: bool) -> crate::Result<()>289     pub fn set_auto_detach_kernel_driver(&self, auto_detach: bool) -> crate::Result<()> {
290         try_unsafe!(libusb_set_auto_detach_kernel_driver(
291             self.as_raw(),
292             auto_detach.into()
293         ));
294         Ok(())
295     }
296 
297     /// Claims one of the device's interfaces.
298     ///
299     /// An interface must be claimed before operating on it. All claimed interfaces are released
300     /// when the device handle goes out of scope.
claim_interface(&self, iface: u8) -> crate::Result<()>301     pub fn claim_interface(&self, iface: u8) -> crate::Result<()> {
302         try_unsafe!(libusb_claim_interface(self.as_raw(), c_int::from(iface)));
303         self.interfaces.lock().unwrap().insert(iface);
304         Ok(())
305     }
306 
307     /// Releases a claimed interface.
release_interface(&self, iface: u8) -> crate::Result<()>308     pub fn release_interface(&self, iface: u8) -> crate::Result<()> {
309         try_unsafe!(libusb_release_interface(self.as_raw(), c_int::from(iface)));
310         self.interfaces.lock().unwrap().remove(iface);
311         Ok(())
312     }
313 
314     /// Sets an interface's active setting.
set_alternate_setting(&self, iface: u8, setting: u8) -> crate::Result<()>315     pub fn set_alternate_setting(&self, iface: u8, setting: u8) -> crate::Result<()> {
316         try_unsafe!(libusb_set_interface_alt_setting(
317             self.as_raw(),
318             c_int::from(iface),
319             c_int::from(setting)
320         ));
321         Ok(())
322     }
323 
324     /// Reads from an interrupt endpoint.
325     ///
326     /// This function attempts to read from the interrupt endpoint with the address given by the
327     /// `endpoint` parameter and fills `buf` with any data received from the endpoint. The function
328     /// blocks up to the amount of time specified by `timeout`. Minimal `timeout` is 1 milliseconds,
329     /// anything smaller will result in an infinite block.
330     ///
331     /// If the return value is `Ok(n)`, then `buf` is populated with `n` bytes of data received
332     /// from the endpoint.
333     ///
334     /// ## Errors
335     ///
336     /// If this function encounters any form of error while fulfilling the transfer request, an
337     /// error variant will be returned. If an error variant is returned, no bytes were read.
338     ///
339     /// The errors returned by this function include:
340     ///
341     /// * `InvalidParam` if the endpoint is not an input endpoint.
342     /// * `Timeout` if the transfer timed out.
343     /// * `Pipe` if the endpoint halted.
344     /// * `Overflow` if the device offered more data.
345     /// * `NoDevice` if the device has been disconnected.
346     /// * `Io` if the transfer encountered an I/O error.
read_interrupt( &self, endpoint: u8, buf: &mut [u8], timeout: Duration, ) -> crate::Result<usize>347     pub fn read_interrupt(
348         &self,
349         endpoint: u8,
350         buf: &mut [u8],
351         timeout: Duration,
352     ) -> crate::Result<usize> {
353         if endpoint & LIBUSB_ENDPOINT_DIR_MASK != LIBUSB_ENDPOINT_IN {
354             return Err(Error::InvalidParam);
355         }
356         let mut transferred = mem::MaybeUninit::<c_int>::uninit();
357         unsafe {
358             match libusb_interrupt_transfer(
359                 self.as_raw(),
360                 endpoint,
361                 buf.as_mut_ptr() as *mut c_uchar,
362                 buf.len() as c_int,
363                 transferred.as_mut_ptr(),
364                 timeout.as_millis() as c_uint,
365             ) {
366                 0 => Ok(transferred.assume_init() as usize),
367                 err if err == LIBUSB_ERROR_INTERRUPTED => {
368                     let transferred = transferred.assume_init();
369                     if transferred > 0 {
370                         Ok(transferred as usize)
371                     } else {
372                         Err(error::from_libusb(err))
373                     }
374                 }
375                 err => Err(error::from_libusb(err)),
376             }
377         }
378     }
379 
380     /// Writes to an interrupt endpoint.
381     ///
382     /// This function attempts to write the contents of `buf` to the interrupt endpoint with the
383     /// address given by the `endpoint` parameter. The function blocks up to the amount of time
384     /// specified by `timeout`. Minimal `timeout` is 1 milliseconds, anything smaller will
385     /// result in an infinite block.
386     ///
387     /// If the return value is `Ok(n)`, then `n` bytes of `buf` were written to the endpoint.
388     ///
389     /// ## Errors
390     ///
391     /// If this function encounters any form of error while fulfilling the transfer request, an
392     /// error variant will be returned. If an error variant is returned, no bytes were written.
393     ///
394     /// The errors returned by this function include:
395     ///
396     /// * `InvalidParam` if the endpoint is not an output endpoint.
397     /// * `Timeout` if the transfer timed out.
398     /// * `Pipe` if the endpoint halted.
399     /// * `NoDevice` if the device has been disconnected.
400     /// * `Io` if the transfer encountered an I/O error.
write_interrupt( &self, endpoint: u8, buf: &[u8], timeout: Duration, ) -> crate::Result<usize>401     pub fn write_interrupt(
402         &self,
403         endpoint: u8,
404         buf: &[u8],
405         timeout: Duration,
406     ) -> crate::Result<usize> {
407         if endpoint & LIBUSB_ENDPOINT_DIR_MASK != LIBUSB_ENDPOINT_OUT {
408             return Err(Error::InvalidParam);
409         }
410         let mut transferred = mem::MaybeUninit::<c_int>::uninit();
411         unsafe {
412             match libusb_interrupt_transfer(
413                 self.as_raw(),
414                 endpoint,
415                 buf.as_ptr() as *mut c_uchar,
416                 buf.len() as c_int,
417                 transferred.as_mut_ptr(),
418                 timeout.as_millis() as c_uint,
419             ) {
420                 0 => Ok(transferred.assume_init() as usize),
421                 err if err == LIBUSB_ERROR_INTERRUPTED => {
422                     let transferred = transferred.assume_init();
423                     if transferred > 0 {
424                         Ok(transferred as usize)
425                     } else {
426                         Err(error::from_libusb(err))
427                     }
428                 }
429                 err => Err(error::from_libusb(err)),
430             }
431         }
432     }
433 
434     /// Reads from a bulk endpoint.
435     ///
436     /// This function attempts to read from the bulk endpoint with the address given by the
437     /// `endpoint` parameter and fills `buf` with any data received from the endpoint. The function
438     /// blocks up to the amount of time specified by `timeout`. Minimal `timeout` is 1 milliseconds,
439     /// anything smaller will result in an infinite block.
440     ///
441     /// If the return value is `Ok(n)`, then `buf` is populated with `n` bytes of data received
442     /// from the endpoint.
443     ///
444     /// ## Errors
445     ///
446     /// If this function encounters any form of error while fulfilling the transfer request, an
447     /// error variant will be returned. If an error variant is returned, no bytes were read.
448     ///
449     /// The errors returned by this function include:
450     ///
451     /// * `InvalidParam` if the endpoint is not an input endpoint.
452     /// * `Timeout` if the transfer timed out.
453     /// * `Pipe` if the endpoint halted.
454     /// * `Overflow` if the device offered more data.
455     /// * `NoDevice` if the device has been disconnected.
456     /// * `Io` if the transfer encountered an I/O error.
read_bulk( &self, endpoint: u8, buf: &mut [u8], timeout: Duration, ) -> crate::Result<usize>457     pub fn read_bulk(
458         &self,
459         endpoint: u8,
460         buf: &mut [u8],
461         timeout: Duration,
462     ) -> crate::Result<usize> {
463         if endpoint & LIBUSB_ENDPOINT_DIR_MASK != LIBUSB_ENDPOINT_IN {
464             return Err(Error::InvalidParam);
465         }
466         let mut transferred = mem::MaybeUninit::<c_int>::uninit();
467         unsafe {
468             match libusb_bulk_transfer(
469                 self.as_raw(),
470                 endpoint,
471                 buf.as_mut_ptr() as *mut c_uchar,
472                 buf.len() as c_int,
473                 transferred.as_mut_ptr(),
474                 timeout.as_millis() as c_uint,
475             ) {
476                 0 => Ok(transferred.assume_init() as usize),
477                 err if err == LIBUSB_ERROR_INTERRUPTED || err == LIBUSB_ERROR_TIMEOUT => {
478                     let transferred = transferred.assume_init();
479                     if transferred > 0 {
480                         Ok(transferred as usize)
481                     } else {
482                         Err(error::from_libusb(err))
483                     }
484                 }
485                 err => Err(error::from_libusb(err)),
486             }
487         }
488     }
489 
490     /// Writes to a bulk endpoint.
491     ///
492     /// This function attempts to write the contents of `buf` to the bulk endpoint with the address
493     /// given by the `endpoint` parameter. The function blocks up to the amount of time specified
494     /// by `timeout`. Minimal `timeout` is 1 milliseconds, anything smaller will result in an
495     /// infinite block.
496     ///
497     /// If the return value is `Ok(n)`, then `n` bytes of `buf` were written to the endpoint.
498     ///
499     /// ## Errors
500     ///
501     /// If this function encounters any form of error while fulfilling the transfer request, an
502     /// error variant will be returned. If an error variant is returned, no bytes were written.
503     ///
504     /// The errors returned by this function include:
505     ///
506     /// * `InvalidParam` if the endpoint is not an output endpoint.
507     /// * `Timeout` if the transfer timed out.
508     /// * `Pipe` if the endpoint halted.
509     /// * `NoDevice` if the device has been disconnected.
510     /// * `Io` if the transfer encountered an I/O error.
write_bulk(&self, endpoint: u8, buf: &[u8], timeout: Duration) -> crate::Result<usize>511     pub fn write_bulk(&self, endpoint: u8, buf: &[u8], timeout: Duration) -> crate::Result<usize> {
512         if endpoint & LIBUSB_ENDPOINT_DIR_MASK != LIBUSB_ENDPOINT_OUT {
513             return Err(Error::InvalidParam);
514         }
515         let mut transferred = mem::MaybeUninit::<c_int>::uninit();
516         unsafe {
517             match libusb_bulk_transfer(
518                 self.as_raw(),
519                 endpoint,
520                 buf.as_ptr() as *mut c_uchar,
521                 buf.len() as c_int,
522                 transferred.as_mut_ptr(),
523                 timeout.as_millis() as c_uint,
524             ) {
525                 0 => Ok(transferred.assume_init() as usize),
526                 err if err == LIBUSB_ERROR_INTERRUPTED || err == LIBUSB_ERROR_TIMEOUT => {
527                     let transferred = transferred.assume_init();
528                     if transferred > 0 {
529                         Ok(transferred as usize)
530                     } else {
531                         Err(error::from_libusb(err))
532                     }
533                 }
534                 err => Err(error::from_libusb(err)),
535             }
536         }
537     }
538 
539     /// Reads data using a control transfer.
540     ///
541     /// This function attempts to read data from the device using a control transfer and fills
542     /// `buf` with any data received during the transfer. The function blocks up to the amount of
543     /// time specified by `timeout`. Minimal `timeout` is 1 milliseconds, anything smaller will
544     /// result in an infinite block.
545     ///
546     /// The parameters `request_type`, `request`, `value`, and `index` specify the fields of the
547     /// control transfer setup packet (`bmRequestType`, `bRequest`, `wValue`, and `wIndex`
548     /// respectively). The values for each of these parameters shall be given in host-endian byte
549     /// order. The value for the `request_type` parameter can be built with the helper function,
550     /// [request_type()](fn.request_type.html). The meaning of the other parameters depends on the
551     /// type of control request.
552     ///
553     /// If the return value is `Ok(n)`, then `buf` is populated with `n` bytes of data.
554     ///
555     /// ## Errors
556     ///
557     /// If this function encounters any form of error while fulfilling the transfer request, an
558     /// error variant will be returned. If an error variant is returned, no bytes were read.
559     ///
560     /// The errors returned by this function include:
561     ///
562     /// * `InvalidParam` if `request_type` does not specify a read transfer.
563     /// * `Timeout` if the transfer timed out.
564     /// * `Pipe` if the control request was not supported by the device.
565     /// * `NoDevice` if the device has been disconnected.
566     /// * `Io` if the transfer encountered an I/O error.
read_control( &self, request_type: u8, request: u8, value: u16, index: u16, buf: &mut [u8], timeout: Duration, ) -> crate::Result<usize>567     pub fn read_control(
568         &self,
569         request_type: u8,
570         request: u8,
571         value: u16,
572         index: u16,
573         buf: &mut [u8],
574         timeout: Duration,
575     ) -> crate::Result<usize> {
576         if request_type & LIBUSB_ENDPOINT_DIR_MASK != LIBUSB_ENDPOINT_IN {
577             return Err(Error::InvalidParam);
578         }
579         let res = unsafe {
580             libusb_control_transfer(
581                 self.as_raw(),
582                 request_type,
583                 request,
584                 value,
585                 index,
586                 buf.as_mut_ptr() as *mut c_uchar,
587                 buf.len() as u16,
588                 timeout.as_millis() as c_uint,
589             )
590         };
591 
592         if res < 0 {
593             Err(error::from_libusb(res))
594         } else {
595             Ok(res as usize)
596         }
597     }
598 
599     /// Writes data using a control transfer.
600     ///
601     /// This function attempts to write the contents of `buf` to the device using a control
602     /// transfer. The function blocks up to the amount of time specified by `timeout`.
603     /// Minimal `timeout` is 1 milliseconds, anything smaller will result in an infinite block.
604     ///
605     /// The parameters `request_type`, `request`, `value`, and `index` specify the fields of the
606     /// control transfer setup packet (`bmRequestType`, `bRequest`, `wValue`, and `wIndex`
607     /// respectively). The values for each of these parameters shall be given in host-endian byte
608     /// order. The value for the `request_type` parameter can be built with the helper function,
609     /// [request_type()](fn.request_type.html). The meaning of the other parameters depends on the
610     /// type of control request.
611     ///
612     /// If the return value is `Ok(n)`, then `n` bytes of `buf` were transfered.
613     ///
614     /// ## Errors
615     ///
616     /// If this function encounters any form of error while fulfilling the transfer request, an
617     /// error variant will be returned. If an error variant is returned, no bytes were read.
618     ///
619     /// The errors returned by this function include:
620     ///
621     /// * `InvalidParam` if `request_type` does not specify a write transfer.
622     /// * `Timeout` if the transfer timed out.
623     /// * `Pipe` if the control request was not supported by the device.
624     /// * `NoDevice` if the device has been disconnected.
625     /// * `Io` if the transfer encountered an I/O error.
write_control( &self, request_type: u8, request: u8, value: u16, index: u16, buf: &[u8], timeout: Duration, ) -> crate::Result<usize>626     pub fn write_control(
627         &self,
628         request_type: u8,
629         request: u8,
630         value: u16,
631         index: u16,
632         buf: &[u8],
633         timeout: Duration,
634     ) -> crate::Result<usize> {
635         if request_type & LIBUSB_ENDPOINT_DIR_MASK != LIBUSB_ENDPOINT_OUT {
636             return Err(Error::InvalidParam);
637         }
638         let res = unsafe {
639             libusb_control_transfer(
640                 self.as_raw(),
641                 request_type,
642                 request,
643                 value,
644                 index,
645                 buf.as_ptr() as *mut c_uchar,
646                 buf.len() as u16,
647                 timeout.as_millis() as c_uint,
648             )
649         };
650 
651         if res < 0 {
652             Err(error::from_libusb(res))
653         } else {
654             Ok(res as usize)
655         }
656     }
657 
658     /// Reads the languages supported by the device's string descriptors.
659     ///
660     /// This function returns a list of languages that can be used to read the device's string
661     /// descriptors.
read_languages(&self, timeout: Duration) -> crate::Result<Vec<Language>>662     pub fn read_languages(&self, timeout: Duration) -> crate::Result<Vec<Language>> {
663         let mut buf = [0u8; 255];
664 
665         let len = self.read_control(
666             request_type(Direction::In, RequestType::Standard, Recipient::Device),
667             LIBUSB_REQUEST_GET_DESCRIPTOR,
668             u16::from(LIBUSB_DT_STRING) << 8,
669             0,
670             &mut buf,
671             timeout,
672         )?;
673 
674         if len < 2 || buf[0] != len as u8 || len & 0x01 != 0 {
675             return Err(Error::BadDescriptor);
676         }
677 
678         if len == 2 {
679             return Ok(Vec::new());
680         }
681 
682         Ok(buf[0..len]
683             .chunks(2)
684             .skip(1)
685             .map(|chunk| {
686                 let lang_id = u16::from(chunk[0]) | u16::from(chunk[1]) << 8;
687                 crate::language::from_lang_id(lang_id)
688             })
689             .collect())
690     }
691 
692     /// Reads a ascii string descriptor from the device.
693     ///
read_string_descriptor_ascii(&self, index: u8) -> crate::Result<String>694     pub fn read_string_descriptor_ascii(&self, index: u8) -> crate::Result<String> {
695         let mut buf = Vec::<u8>::with_capacity(255);
696 
697         let ptr = buf.as_mut_ptr() as *mut c_uchar;
698         let capacity = buf.capacity() as i32;
699 
700         let res =
701             unsafe { libusb_get_string_descriptor_ascii(self.as_raw(), index, ptr, capacity) };
702 
703         if res < 0 {
704             return Err(error::from_libusb(res));
705         }
706 
707         unsafe {
708             buf.set_len(res as usize);
709         }
710 
711         String::from_utf8(buf).map_err(|_| Error::Other)
712     }
713 
714     /// Reads a string descriptor from the device.
715     ///
716     /// `language` should be one of the languages returned from [`read_languages`](#method.read_languages).
read_string_descriptor( &self, language: Language, index: u8, timeout: Duration, ) -> crate::Result<String>717     pub fn read_string_descriptor(
718         &self,
719         language: Language,
720         index: u8,
721         timeout: Duration,
722     ) -> crate::Result<String> {
723         let mut buf = [0u16; 128];
724 
725         let len = {
726             // SAFETY: since we create slice from existing slice pointer valid
727             // alignment of [u8] less or equal to the [u16]
728             // size is less then allocated buffer (128 * 2 = 256 => 256 < 255)
729             let buf = unsafe {
730                 std::slice::from_raw_parts_mut(
731                     buf.as_mut_ptr().cast::<u8>(),
732                     255, // Some devices choke on size > 255
733                 )
734             };
735 
736             let len = self.read_control(
737                 request_type(Direction::In, RequestType::Standard, Recipient::Device),
738                 LIBUSB_REQUEST_GET_DESCRIPTOR,
739                 u16::from(LIBUSB_DT_STRING) << 8 | u16::from(index),
740                 language.lang_id(),
741                 buf,
742                 timeout,
743             )?;
744 
745             if len < 2 || buf[0] != len as u8 || len & 0x01 != 0 {
746                 return Err(Error::BadDescriptor);
747             }
748 
749             len
750         };
751 
752         if len == 2 {
753             return Ok(String::new());
754         }
755 
756         // len in bytes, skip first element(it's contain descriptor type and len)
757         String::from_utf16(&buf[1..(len / 2)]).map_err(|_| Error::Other)
758     }
759 
760     /// Reads the device's manufacturer string descriptor (ascii).
read_manufacturer_string_ascii( &self, device: &DeviceDescriptor, ) -> crate::Result<String>761     pub fn read_manufacturer_string_ascii(
762         &self,
763         device: &DeviceDescriptor,
764     ) -> crate::Result<String> {
765         match device.manufacturer_string_index() {
766             None => Err(Error::InvalidParam),
767             Some(n) => self.read_string_descriptor_ascii(n),
768         }
769     }
770 
771     /// Reads the device's manufacturer string descriptor.
read_manufacturer_string( &self, language: Language, device: &DeviceDescriptor, timeout: Duration, ) -> crate::Result<String>772     pub fn read_manufacturer_string(
773         &self,
774         language: Language,
775         device: &DeviceDescriptor,
776         timeout: Duration,
777     ) -> crate::Result<String> {
778         match device.manufacturer_string_index() {
779             None => Err(Error::InvalidParam),
780             Some(n) => self.read_string_descriptor(language, n, timeout),
781         }
782     }
783 
784     /// Reads the device's product string descriptor (ascii).
read_product_string_ascii(&self, device: &DeviceDescriptor) -> crate::Result<String>785     pub fn read_product_string_ascii(&self, device: &DeviceDescriptor) -> crate::Result<String> {
786         match device.product_string_index() {
787             None => Err(Error::InvalidParam),
788             Some(n) => self.read_string_descriptor_ascii(n),
789         }
790     }
791 
792     /// Reads the device's product string descriptor.
read_product_string( &self, language: Language, device: &DeviceDescriptor, timeout: Duration, ) -> crate::Result<String>793     pub fn read_product_string(
794         &self,
795         language: Language,
796         device: &DeviceDescriptor,
797         timeout: Duration,
798     ) -> crate::Result<String> {
799         match device.product_string_index() {
800             None => Err(Error::InvalidParam),
801             Some(n) => self.read_string_descriptor(language, n, timeout),
802         }
803     }
804 
805     /// Reads the device's serial number string descriptor (ascii).
read_serial_number_string_ascii( &self, device: &DeviceDescriptor, ) -> crate::Result<String>806     pub fn read_serial_number_string_ascii(
807         &self,
808         device: &DeviceDescriptor,
809     ) -> crate::Result<String> {
810         match device.serial_number_string_index() {
811             None => Err(Error::InvalidParam),
812             Some(n) => self.read_string_descriptor_ascii(n),
813         }
814     }
815 
816     /// Reads the device's serial number string descriptor.
read_serial_number_string( &self, language: Language, device: &DeviceDescriptor, timeout: Duration, ) -> crate::Result<String>817     pub fn read_serial_number_string(
818         &self,
819         language: Language,
820         device: &DeviceDescriptor,
821         timeout: Duration,
822     ) -> crate::Result<String> {
823         match device.serial_number_string_index() {
824             None => Err(Error::InvalidParam),
825             Some(n) => self.read_string_descriptor(language, n, timeout),
826         }
827     }
828 
829     /// Reads the string descriptor for a configuration's description.
read_configuration_string( &self, language: Language, configuration: &ConfigDescriptor, timeout: Duration, ) -> crate::Result<String>830     pub fn read_configuration_string(
831         &self,
832         language: Language,
833         configuration: &ConfigDescriptor,
834         timeout: Duration,
835     ) -> crate::Result<String> {
836         match configuration.description_string_index() {
837             None => Err(Error::InvalidParam),
838             Some(n) => self.read_string_descriptor(language, n, timeout),
839         }
840     }
841 
842     /// Reads the string descriptor for a interface's description.
read_interface_string( &self, language: Language, interface: &InterfaceDescriptor, timeout: Duration, ) -> crate::Result<String>843     pub fn read_interface_string(
844         &self,
845         language: Language,
846         interface: &InterfaceDescriptor,
847         timeout: Duration,
848     ) -> crate::Result<String> {
849         match interface.description_string_index() {
850             None => Err(Error::InvalidParam),
851             Some(n) => self.read_string_descriptor(language, n, timeout),
852         }
853     }
854 }
855 
856 #[cfg(test)]
857 mod tests {
858     use super::ClaimedInterfaces;
859     use std::u8;
860 
861     #[test]
claimed_interfaces_empty()862     fn claimed_interfaces_empty() {
863         let empty = ClaimedInterfaces::new();
864         assert_eq!(empty.size(), 0);
865         for i in 0..=u8::MAX {
866             assert!(!empty.contains(i), "empty set should not contain {}", i);
867         }
868 
869         let mut iter = empty.iter();
870         assert_eq!(iter.size_hint(), (0, Some(0)));
871         assert_eq!(iter.next(), None);
872     }
873 
874     #[test]
claimed_interfaces_one_element()875     fn claimed_interfaces_one_element() {
876         let mut interfaces = ClaimedInterfaces::new();
877         interfaces.insert(94);
878         assert_eq!(interfaces.size(), 1);
879         assert!(interfaces.contains(94));
880         for i in 0..=u8::MAX {
881             if i == 94 {
882                 continue;
883             }
884             assert!(
885                 !interfaces.contains(i),
886                 "interfaces should not contain {}",
887                 i
888             );
889         }
890 
891         let mut iter = interfaces.iter();
892         assert_eq!(iter.size_hint(), (1, Some(1)));
893         assert_eq!(iter.next(), Some(94));
894         assert_eq!(iter.size_hint(), (0, Some(0)));
895         assert_eq!(iter.next(), None);
896     }
897 
898     #[test]
claimed_interfaces_many_elements()899     fn claimed_interfaces_many_elements() {
900         let mut interfaces = ClaimedInterfaces::new();
901         let elements = vec![94, 0, 255, 17, 183, 6];
902 
903         for (index, &interface) in elements.iter().enumerate() {
904             interfaces.insert(interface);
905             assert_eq!(interfaces.size(), index + 1);
906         }
907 
908         // Validate contains().
909         for &interface in elements.iter() {
910             assert!(
911                 interfaces.contains(interface),
912                 "interfaces should contain {}",
913                 interface
914             );
915         }
916 
917         // Validate iter().
918         let contents = interfaces.iter().collect::<Vec<_>>().sort();
919         assert_eq!(contents, elements.clone().sort());
920 
921         // Validate size_hint().
922         let mut iter = interfaces.iter();
923         let mut read = 0;
924         loop {
925             assert!(
926                 read <= elements.len(),
927                 "read elements {} should not exceed elements size {}",
928                 read,
929                 elements.len()
930             );
931             let remaining = elements.len() - read;
932             assert_eq!(iter.size_hint(), (remaining, Some(remaining)));
933             match iter.next() {
934                 Some(_) => read += 1,
935                 None => break,
936             }
937         }
938     }
939 }
940