1 use std::{
2     fmt::{self, Debug},
3     mem,
4     ptr::NonNull,
5 };
6 
7 use libusb1_sys::*;
8 
9 use crate::{
10     config_descriptor::{self, ConfigDescriptor},
11     device_descriptor::{self, DeviceDescriptor},
12     device_handle::DeviceHandle,
13     error,
14     fields::{self, Speed},
15     Error, UsbContext,
16 };
17 
18 /// A reference to a USB device.
19 #[derive(Eq, PartialEq)]
20 pub struct Device<T: UsbContext> {
21     context: T,
22     device: NonNull<libusb_device>,
23 }
24 
25 impl<T: UsbContext> Drop for Device<T> {
26     /// Releases the device reference.
drop(&mut self)27     fn drop(&mut self) {
28         unsafe {
29             libusb_unref_device(self.device.as_ptr());
30         }
31     }
32 }
33 
34 impl<T: UsbContext> Clone for Device<T> {
clone(&self) -> Self35     fn clone(&self) -> Self {
36         unsafe { Self::from_libusb(self.context.clone(), self.device) }
37     }
38 }
39 
40 unsafe impl<T: UsbContext> Send for Device<T> {}
41 unsafe impl<T: UsbContext> Sync for Device<T> {}
42 
43 impl<T: UsbContext> Debug for Device<T> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result44     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
45         let descriptor = match self.device_descriptor() {
46             Ok(descriptor) => descriptor,
47             Err(e) => {
48                 return write!(f, "Can't read device descriptor {:?}", e);
49             }
50         };
51         write!(
52             f,
53             "Bus {:03} Device {:03}: ID {:04x}:{:04x}",
54             self.bus_number(),
55             self.address(),
56             descriptor.vendor_id(),
57             descriptor.product_id(),
58         )
59     }
60 }
61 
62 impl<T: UsbContext> Device<T> {
63     /// Get the raw libusb_device pointer, for advanced use in unsafe code
as_raw(&self) -> *mut libusb_device64     pub fn as_raw(&self) -> *mut libusb_device {
65         self.device.as_ptr()
66     }
67 
68     /// Get the context associated with this device
context(&self) -> &T69     pub fn context(&self) -> &T {
70         &self.context
71     }
72 
73     /// # Safety
74     ///
75     /// Converts an existing `libusb_device` pointer into a `Device<T>`.
76     /// `device` must be a pointer to a valid `libusb_device`. Rusb increments refcount.
from_libusb(context: T, device: NonNull<libusb_device>) -> Device<T>77     pub unsafe fn from_libusb(context: T, device: NonNull<libusb_device>) -> Device<T> {
78         libusb_ref_device(device.as_ptr());
79 
80         Device { context, device }
81     }
82 
83     /// Reads the device descriptor.
device_descriptor(&self) -> crate::Result<DeviceDescriptor>84     pub fn device_descriptor(&self) -> crate::Result<DeviceDescriptor> {
85         let mut descriptor = mem::MaybeUninit::<libusb_device_descriptor>::uninit();
86 
87         // since libusb 1.0.16, this function always succeeds
88         try_unsafe!(libusb_get_device_descriptor(
89             self.device.as_ptr(),
90             descriptor.as_mut_ptr()
91         ));
92 
93         Ok(device_descriptor::from_libusb(unsafe {
94             descriptor.assume_init()
95         }))
96     }
97 
98     /// Reads a configuration descriptor.
config_descriptor(&self, config_index: u8) -> crate::Result<ConfigDescriptor>99     pub fn config_descriptor(&self, config_index: u8) -> crate::Result<ConfigDescriptor> {
100         let mut config = mem::MaybeUninit::<*const libusb_config_descriptor>::uninit();
101 
102         try_unsafe!(libusb_get_config_descriptor(
103             self.device.as_ptr(),
104             config_index,
105             config.as_mut_ptr()
106         ));
107 
108         Ok(unsafe { config_descriptor::from_libusb(config.assume_init()) })
109     }
110 
111     /// Reads the configuration descriptor for the current configuration.
active_config_descriptor(&self) -> crate::Result<ConfigDescriptor>112     pub fn active_config_descriptor(&self) -> crate::Result<ConfigDescriptor> {
113         let mut config = mem::MaybeUninit::<*const libusb_config_descriptor>::uninit();
114 
115         try_unsafe!(libusb_get_active_config_descriptor(
116             self.device.as_ptr(),
117             config.as_mut_ptr()
118         ));
119 
120         Ok(unsafe { config_descriptor::from_libusb(config.assume_init()) })
121     }
122 
123     /// Returns the number of the bus that the device is connected to.
bus_number(&self) -> u8124     pub fn bus_number(&self) -> u8 {
125         unsafe { libusb_get_bus_number(self.device.as_ptr()) }
126     }
127 
128     /// Returns the device's address on the bus that it's connected to.
address(&self) -> u8129     pub fn address(&self) -> u8 {
130         unsafe { libusb_get_device_address(self.device.as_ptr()) }
131     }
132 
133     /// Returns the device's connection speed.
speed(&self) -> Speed134     pub fn speed(&self) -> Speed {
135         fields::speed_from_libusb(unsafe { libusb_get_device_speed(self.device.as_ptr()) })
136     }
137 
138     /// Opens the device.
open(&self) -> crate::Result<DeviceHandle<T>>139     pub fn open(&self) -> crate::Result<DeviceHandle<T>> {
140         let mut handle = mem::MaybeUninit::<*mut libusb_device_handle>::uninit();
141 
142         try_unsafe!(libusb_open(self.device.as_ptr(), handle.as_mut_ptr()));
143 
144         Ok(unsafe {
145             let ptr = NonNull::new(handle.assume_init()).ok_or(Error::NoDevice)?;
146             DeviceHandle::from_libusb(self.context.clone(), ptr)
147         })
148     }
149 
150     /// Returns the device's port number
port_number(&self) -> u8151     pub fn port_number(&self) -> u8 {
152         unsafe { libusb_get_port_number(self.device.as_ptr()) }
153     }
154 
155     /// Returns the device's parent
get_parent(&self) -> Option<Self>156     pub fn get_parent(&self) -> Option<Self> {
157         let device = unsafe { libusb_get_parent(self.device.as_ptr()) };
158         NonNull::new(device)
159             .map(|device| unsafe { Device::from_libusb(self.context.clone(), device) })
160     }
161 
162     ///  Get the list of all port numbers from root for the specified device
port_numbers(&self) -> Result<Vec<u8>, Error>163     pub fn port_numbers(&self) -> Result<Vec<u8>, Error> {
164         // As per the USB 3.0 specs, the current maximum limit for the depth is 7.
165         let mut ports = [0; 7];
166 
167         let result = unsafe {
168             libusb_get_port_numbers(self.device.as_ptr(), ports.as_mut_ptr(), ports.len() as i32)
169         };
170 
171         let ports_number = if result < 0 {
172             return Err(error::from_libusb(result));
173         } else {
174             result
175         };
176         Ok(ports[0..ports_number as usize].to_vec())
177     }
178 }
179