use std::{fmt, slice}; use libusb1_sys::{libusb_endpoint_descriptor, libusb_interface, libusb_interface_descriptor}; use crate::endpoint_descriptor::{self, EndpointDescriptor}; /// A device interface. /// /// An interface can have several descriptors, each describing an alternate setting of the /// interface. pub struct Interface<'a> { descriptors: &'a [libusb_interface_descriptor], } impl<'a> Interface<'a> { /// Returns the interface's number. pub fn number(&self) -> u8 { self.descriptors[0].bInterfaceNumber } /// Returns an iterator over the interface's descriptors. pub fn descriptors(&self) -> InterfaceDescriptors<'a> { InterfaceDescriptors { iter: self.descriptors.iter(), } } } /// Iterator over an interface's descriptors. pub struct InterfaceDescriptors<'a> { iter: slice::Iter<'a, libusb_interface_descriptor>, } impl<'a> Iterator for InterfaceDescriptors<'a> { type Item = InterfaceDescriptor<'a>; fn next(&mut self) -> Option> { self.iter .next() .map(|descriptor| InterfaceDescriptor { descriptor }) } fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } } /// Describes an alternate setting for an interface. pub struct InterfaceDescriptor<'a> { descriptor: &'a libusb_interface_descriptor, } impl<'a> InterfaceDescriptor<'a> { /// 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 interface's number. pub fn interface_number(&self) -> u8 { self.descriptor.bInterfaceNumber } /// Returns the alternate setting number. pub fn setting_number(&self) -> u8 { self.descriptor.bAlternateSetting } /// Returns the interface's class code. pub fn class_code(&self) -> u8 { self.descriptor.bInterfaceClass } /// Returns the interface's sub class code. pub fn sub_class_code(&self) -> u8 { self.descriptor.bInterfaceSubClass } /// Returns the interface's protocol code. pub fn protocol_code(&self) -> u8 { self.descriptor.bInterfaceProtocol } /// Returns the index of the string descriptor that describes the interface. pub fn description_string_index(&self) -> Option { match self.descriptor.iInterface { 0 => None, n => Some(n), } } /// Returns the number of endpoints belonging to this interface. pub fn num_endpoints(&self) -> u8 { self.descriptor.bNumEndpoints } /// Returns an iterator over the interface's endpoint descriptors. pub fn endpoint_descriptors(&self) -> EndpointDescriptors<'a> { let endpoints = match self.descriptor.bNumEndpoints { 0 => &[], n => unsafe { slice::from_raw_parts(self.descriptor.endpoint, n as usize) }, }; EndpointDescriptors { iter: endpoints.iter(), } } /// Returns the unknown 'extra' bytes that libusb does not understand. pub fn extra(&self) -> &[u8] { unsafe { match (*self.descriptor).extra_length { len if len > 0 => slice::from_raw_parts((*self.descriptor).extra, len as usize), _ => &[], } } } } impl<'a> fmt::Debug for InterfaceDescriptor<'a> { fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { let mut debug = fmt.debug_struct("InterfaceDescriptor"); debug.field("bLength", &self.descriptor.bLength); debug.field("bDescriptorType", &self.descriptor.bDescriptorType); debug.field("bInterfaceNumber", &self.descriptor.bInterfaceNumber); debug.field("bAlternateSetting", &self.descriptor.bAlternateSetting); debug.field("bNumEndpoints", &self.descriptor.bNumEndpoints); debug.field("bInterfaceClass", &self.descriptor.bInterfaceClass); debug.field("bInterfaceSubClass", &self.descriptor.bInterfaceSubClass); debug.field("bInterfaceProtocol", &self.descriptor.bInterfaceProtocol); debug.field("iInterface", &self.descriptor.iInterface); debug.finish() } } /// Iterator over an interface's endpoint descriptors. pub struct EndpointDescriptors<'a> { iter: slice::Iter<'a, libusb_endpoint_descriptor>, } impl<'a> Iterator for EndpointDescriptors<'a> { type Item = EndpointDescriptor<'a>; fn next(&mut self) -> Option> { self.iter.next().map(endpoint_descriptor::from_libusb) } fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } } #[doc(hidden)] pub(crate) unsafe fn from_libusb(interface: &libusb_interface) -> Interface { let descriptors = slice::from_raw_parts(interface.altsetting, interface.num_altsetting as usize); debug_assert!(!descriptors.is_empty()); Interface { descriptors } } #[cfg(test)] mod test { #[test] fn it_has_interface_number() { assert_eq!( 42, unsafe { super::from_libusb(&interface!(interface_descriptor!(bInterfaceNumber: 42))) } .number() ); } #[test] fn it_has_interface_number_in_descriptor() { assert_eq!( vec!(42), unsafe { super::from_libusb(&interface!(interface_descriptor!(bInterfaceNumber: 42))) } .descriptors() .map(|setting| setting.interface_number()) .collect::>() ); } #[test] fn it_has_alternate_setting_number() { assert_eq!( vec!(42), unsafe { super::from_libusb(&interface!(interface_descriptor!(bAlternateSetting: 42))) } .descriptors() .map(|setting| setting.setting_number()) .collect::>() ); } #[test] fn it_has_class_code() { assert_eq!( vec!(42), unsafe { super::from_libusb(&interface!(interface_descriptor!(bInterfaceClass: 42))) } .descriptors() .map(|setting| setting.class_code()) .collect::>() ); } #[test] fn it_has_sub_class_code() { assert_eq!( vec!(42), unsafe { super::from_libusb(&interface!(interface_descriptor!(bInterfaceSubClass: 42))) } .descriptors() .map(|setting| setting.sub_class_code()) .collect::>() ); } #[test] fn it_has_protocol_code() { assert_eq!( vec!(42), unsafe { super::from_libusb(&interface!(interface_descriptor!(bInterfaceProtocol: 42))) } .descriptors() .map(|setting| setting.protocol_code()) .collect::>() ); } #[test] fn it_has_description_string_index() { assert_eq!( vec!(Some(42)), unsafe { super::from_libusb(&interface!(interface_descriptor!(iInterface: 42))) } .descriptors() .map(|setting| setting.description_string_index()) .collect::>() ); } #[test] fn it_handles_missing_description_string_index() { assert_eq!( vec!(None), unsafe { super::from_libusb(&interface!(interface_descriptor!(iInterface: 0))) } .descriptors() .map(|setting| setting.description_string_index()) .collect::>() ); } #[test] fn it_has_num_endpoints() { let endpoint1 = endpoint_descriptor!(bEndpointAddress: 0x81); let endpoint2 = endpoint_descriptor!(bEndpointAddress: 0x01); assert_eq!( vec!(2), unsafe { super::from_libusb(&interface!(interface_descriptor!(endpoint1, endpoint2))) } .descriptors() .map(|setting| setting.num_endpoints()) .collect::>() ); } #[test] fn it_has_endpoints() { let libusb_interface = interface!(interface_descriptor!( endpoint_descriptor!(bEndpointAddress: 0x87) )); let interface = unsafe { super::from_libusb(&libusb_interface) }; let endpoint_addresses = interface .descriptors() .next() .unwrap() .endpoint_descriptors() .map(|endpoint| endpoint.address()) .collect::>(); assert_eq!(vec![0x87], endpoint_addresses); } }