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