use std::fmt; use libusb1_sys::*; use crate::fields::Version; /// Describes a device. pub struct DeviceDescriptor { descriptor: libusb_device_descriptor, } impl DeviceDescriptor { /// Returns the size of the descriptor in bytes pub fn length(&self) -> u8 { self.descriptor.bLength } /// Returns the descriptor type pub fn descriptor_type(&self) -> u8 { self.descriptor.bDescriptorType } /// Returns the device's maximum supported USB version. pub fn usb_version(&self) -> Version { Version::from_bcd(self.descriptor.bcdUSB) } /// Returns the manufacturer's version of the device. pub fn device_version(&self) -> Version { Version::from_bcd(self.descriptor.bcdDevice) } /// Returns the index of the string descriptor that contains the manufacturer name. pub fn manufacturer_string_index(&self) -> Option { match self.descriptor.iManufacturer { 0 => None, n => Some(n), } } /// Returns the index of the string descriptor that contains the product name. pub fn product_string_index(&self) -> Option { match self.descriptor.iProduct { 0 => None, n => Some(n), } } /// Returns the index of the string descriptor that contains the device's serial number. pub fn serial_number_string_index(&self) -> Option { match self.descriptor.iSerialNumber { 0 => None, n => Some(n), } } /// Returns the device's class code. pub fn class_code(&self) -> u8 { self.descriptor.bDeviceClass } /// Returns the device's sub class code. pub fn sub_class_code(&self) -> u8 { self.descriptor.bDeviceSubClass } /// Returns the device's protocol code. pub fn protocol_code(&self) -> u8 { self.descriptor.bDeviceProtocol } /// Returns the device's vendor ID. pub fn vendor_id(&self) -> u16 { self.descriptor.idVendor } /// Returns the device's product ID. pub fn product_id(&self) -> u16 { self.descriptor.idProduct } /// Returns the maximum packet size of the device's first endpoint. pub fn max_packet_size(&self) -> u8 { self.descriptor.bMaxPacketSize0 } /// Returns the number of config descriptors available for the device. pub fn num_configurations(&self) -> u8 { self.descriptor.bNumConfigurations } } impl fmt::Debug for DeviceDescriptor { fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { let mut debug = fmt.debug_struct("DeviceDescriptor"); debug.field("bLength", &self.descriptor.bLength); debug.field("bDescriptorType", &self.descriptor.bDescriptorType); debug.field("bcdUSB", &self.descriptor.bcdUSB); debug.field("bDeviceClass", &self.descriptor.bDeviceClass); debug.field("bDeviceSubClass", &self.descriptor.bDeviceSubClass); debug.field("bDeviceProtocol", &self.descriptor.bDeviceProtocol); debug.field("bMaxPacketSize", &self.descriptor.bMaxPacketSize0); debug.field("idVendor", &self.descriptor.idVendor); debug.field("idProduct", &self.descriptor.idProduct); debug.field("bcdDevice", &self.descriptor.bcdDevice); debug.field("iManufacturer", &self.descriptor.iManufacturer); debug.field("iProduct", &self.descriptor.iProduct); debug.field("iSerialNumber", &self.descriptor.iSerialNumber); debug.field("bNumConfigurations", &self.descriptor.bNumConfigurations); debug.finish() } } #[doc(hidden)] pub fn from_libusb(device: libusb_device_descriptor) -> DeviceDescriptor { DeviceDescriptor { descriptor: device } } #[cfg(test)] mod test { use crate::fields::Version; #[test] fn it_has_usb_version() { assert_eq!( Version::from_bcd(0x1234), super::from_libusb(device_descriptor!(bcdUSB: 0x1234)).usb_version() ); } #[test] fn it_has_device_version() { assert_eq!( Version::from_bcd(0x1234), super::from_libusb(device_descriptor!(bcdDevice: 0x1234)).device_version() ); } #[test] fn it_has_manufacturer_string_index() { assert_eq!( Some(42), super::from_libusb(device_descriptor!(iManufacturer: 42)).manufacturer_string_index() ); } #[test] fn it_handles_missing_manufacturer_string_index() { assert_eq!( None, super::from_libusb(device_descriptor!(iManufacturer: 0)).manufacturer_string_index() ); } #[test] fn it_has_product_string_index() { assert_eq!( Some(42), super::from_libusb(device_descriptor!(iProduct: 42)).product_string_index() ); } #[test] fn it_handles_missing_product_string_index() { assert_eq!( None, super::from_libusb(device_descriptor!(iProduct: 0)).product_string_index() ); } #[test] fn it_has_serial_number_string_index() { assert_eq!( Some(42), super::from_libusb(device_descriptor!(iSerialNumber: 42)).serial_number_string_index() ); } #[test] fn it_handles_missing_serial_number_string_index() { assert_eq!( None, super::from_libusb(device_descriptor!(iSerialNumber: 0)).serial_number_string_index() ); } #[test] fn it_has_class_code() { assert_eq!( 42, super::from_libusb(device_descriptor!(bDeviceClass: 42)).class_code() ); } #[test] fn it_has_sub_class_code() { assert_eq!( 42, super::from_libusb(device_descriptor!(bDeviceSubClass: 42)).sub_class_code() ); } #[test] fn it_has_protocol_code() { assert_eq!( 42, super::from_libusb(device_descriptor!(bDeviceProtocol: 42)).protocol_code() ); } #[test] fn it_has_vendor_id() { assert_eq!( 42, super::from_libusb(device_descriptor!(idVendor: 42)).vendor_id() ); } #[test] fn it_has_product_id() { assert_eq!( 42, super::from_libusb(device_descriptor!(idProduct: 42)).product_id() ); } #[test] fn it_has_max_packet_size() { assert_eq!( 42, super::from_libusb(device_descriptor!(bMaxPacketSize0: 42)).max_packet_size() ); } #[test] fn it_has_num_configurations() { assert_eq!( 3, super::from_libusb(device_descriptor!(bNumConfigurations: 3)).num_configurations() ); } }