1use std::{
2 fmt::{self, Debug},
3 mem,
4 ptr::NonNull,
5 sync::Mutex,
6 time::Duration,
7};
8
9use libc::{c_int, c_uchar, c_uint};
10use libusb1_sys::{constants::*, *};
11
12use 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#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
25struct ClaimedInterfaces {
26 inner: [u128; 2],
27}
28
29impl ClaimedInterfaces {
30 fn new() -> Self {
32 Self { inner: [0, 0] }
33 }
34
35 fn get_index_and_mask(interface: u8) -> (usize, u128) {
36 ((interface / 128) as usize, 1 << (interface % 128))
37 }
38
39 fn insert(&mut self, interface: u8) {
41 let (index, mask) = ClaimedInterfaces::get_index_and_mask(interface);
42 self.inner[index] |= mask;
43 }
44
45 fn remove(&mut self, interface: u8) {
47 let (index, mask) = ClaimedInterfaces::get_index_and_mask(interface);
48 self.inner[index] &= !mask;
49 }
50
51 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 fn size(&self) -> usize {
59 self.inner.iter().map(|v| v.count_ones()).sum::<u32>() as usize
60 }
61
62 fn iter(&self) -> ClaimedInterfacesIter {
64 ClaimedInterfacesIter::new(self)
65 }
66}
67
68struct ClaimedInterfacesIter<'a> {
70 index: u16,
72
73 remaining: usize,
75
76 source: &'a ClaimedInterfaces,
78}
79
80impl ClaimedInterfacesIter<'_> {
81 fn new(source: &ClaimedInterfaces) -> ClaimedInterfacesIter {
83 ClaimedInterfacesIter {
84 index: 0,
85 remaining: source.size(),
86 source,
87 }
88 }
89}
90
91impl<'a> Iterator for ClaimedInterfacesIter<'a> {
92 type Item = u8;
93
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
107 fn size_hint(&self) -> (usize, Option<usize>) {
108 (self.remaining, Some(self.remaining))
109 }
110}
111
112pub struct DeviceHandle<T: UsbContext> {
114 context: T,
115 handle: Option<NonNull<libusb_device_handle>>,
116 interfaces: Mutex<ClaimedInterfaces>,
117}
118
119impl<T: UsbContext> Drop for DeviceHandle<T> {
120 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
135unsafe impl<T: UsbContext> Send for DeviceHandle<T> {}
136unsafe impl<T: UsbContext> Sync for DeviceHandle<T> {}
137
138impl<T: UsbContext> Debug for DeviceHandle<T> {
139 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
148impl<T: UsbContext + PartialEq> PartialEq for DeviceHandle<T> {
149 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
156impl<T: UsbContext + PartialEq> Eq for DeviceHandle<T> {}
157
158impl<T: UsbContext> DeviceHandle<T> {
159 pub fn as_raw(&self) -> *mut libusb_device_handle {
164 match self.handle {
166 Some(it) => it.as_ptr(),
167 _ => unreachable!(),
168 }
169 }
170
171 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 pub fn context(&self) -> &T {
187 &self.context
188 }
189
190 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 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 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 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 pub fn unconfigure(&self) -> crate::Result<()> {
231 try_unsafe!(libusb_set_configuration(self.as_raw(), -1));
232 Ok(())
233 }
234
235 pub fn reset(&self) -> crate::Result<()> {
237 try_unsafe!(libusb_reset_device(self.as_raw()));
238 Ok(())
239 }
240
241 pub fn clear_halt(&self, endpoint: u8) -> crate::Result<()> {
243 try_unsafe!(libusb_clear_halt(self.as_raw(), endpoint));
244 Ok(())
245 }
246
247 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 let buf = unsafe {
730 std::slice::from_raw_parts_mut(
731 buf.as_mut_ptr().cast::<u8>(),
732 255, )
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 String::from_utf16(&buf[1..(len / 2)]).map_err(|_| Error::Other)
758 }
759
760 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 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 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 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 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 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 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 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)]
857mod tests {
858 use super::ClaimedInterfaces;
859 use std::u8;
860
861 #[test]
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]
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]
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 for &interface in elements.iter() {
910 assert!(
911 interfaces.contains(interface),
912 "interfaces should contain {}",
913 interface
914 );
915 }
916
917 let contents = interfaces.iter().collect::<Vec<_>>().sort();
919 assert_eq!(contents, elements.clone().sort());
920
921 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}