diff --git a/.travis.yml b/.travis.yml index 122dbd9..98e384a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,6 @@ sudo: false language: rust rust: - - 1.3.0 - stable - beta - nightly diff --git a/Cargo.toml b/Cargo.toml index 577deec..182a8d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ readme = "README.md" keywords = ["usb", "libusb", "hardware", "bindings"] [dependencies] -bit-set = "0.2.0" +bit-set = "0.5.0" libusb-sys = "0.2.3" libc = "0.2" diff --git a/examples/list_devices.rs b/examples/list_devices.rs index 4169c3e..65e5781 100644 --- a/examples/list_devices.rs +++ b/examples/list_devices.rs @@ -106,6 +106,12 @@ fn print_config(config_desc: &libusb::ConfigDescriptor, handle: &mut Option5}", config_desc.self_powered()); println!(" Remote Wakeup {:>5}", config_desc.remote_wakeup()); println!(" bMaxPower {:4}mW", config_desc.max_power()); + + if let Some(extra) = config_desc.extra() { + println!(" Extra: {:?}", extra); + } else { + println!(" Extra: None"); + } } fn print_interface(interface_desc: &libusb::InterfaceDescriptor, handle: &mut Option) { @@ -119,6 +125,12 @@ fn print_interface(interface_desc: &libusb::InterfaceDescriptor, handle: &mut Op println!(" iInterface {:3} {}", interface_desc.description_string_index().unwrap_or(0), handle.as_mut().map_or(String::new(), |h| h.handle.read_interface_string(h.language, interface_desc, h.timeout).unwrap_or(String::new()))); + + if let Some(extra) = interface_desc.extra() { + println!(" Extra: {:?}", extra); + } else { + println!(" Extra: None"); + } } fn print_endpoint(endpoint_desc: &libusb::EndpointDescriptor) { @@ -130,6 +142,12 @@ fn print_endpoint(endpoint_desc: &libusb::EndpointDescriptor) { println!(" Usage Type {:?}", endpoint_desc.usage_type()); println!(" wMaxPacketSize {:#06x}", endpoint_desc.max_packet_size()); println!(" bInterval {:3}", endpoint_desc.interval()); + + if let Some(extra) = endpoint_desc.extra() { + println!(" Extra: {:?}", extra); + } else { + println!(" Extra: None"); + } } fn get_speed(speed: libusb::Speed) -> &'static str { diff --git a/src/config_descriptor.rs b/src/config_descriptor.rs index c982f2e..667ac97 100644 --- a/src/config_descriptor.rs +++ b/src/config_descriptor.rs @@ -1,5 +1,4 @@ use std::fmt; -use std::mem; use std::slice; use libusb::*; @@ -33,7 +32,7 @@ impl ConfigDescriptor { /// Returns the device's maximum power consumption (in milliwatts) in this configuration. pub fn max_power(&self) -> u16 { unsafe { - (*self.descriptor).bMaxPower as u16 * 2 + u16::from((*self.descriptor).bMaxPower) * 2 } } @@ -79,6 +78,19 @@ impl ConfigDescriptor { Interfaces { iter: interfaces.iter() } } + + /// Returns the unknown 'extra' bytes that libusb does not understand. + pub fn extra(&self) -> Option<& [u8]> { + unsafe { + match (*self.descriptor).extra_length { + len if len > 0 => Some(slice::from_raw_parts( + (*self.descriptor).extra, + len as usize, + )), + _ => None, + } + } + } } impl fmt::Debug for ConfigDescriptor { @@ -86,7 +98,7 @@ impl fmt::Debug for ConfigDescriptor { let mut debug = fmt.debug_struct("ConfigDescriptor"); let descriptor: &libusb_config_descriptor = unsafe { - mem::transmute(self.descriptor) + &*self.descriptor }; debug.field("bLength", &descriptor.bLength); diff --git a/src/context.rs b/src/context.rs index 4033cb4..ca67d4e 100644 --- a/src/context.rs +++ b/src/context.rs @@ -32,7 +32,7 @@ impl Context { try_unsafe!(libusb_init(&mut context)); - Ok(Context { context: context }) + Ok(Context { context }) } /// Sets the log level of a `libusb` context. @@ -91,7 +91,7 @@ impl Context { /// /// Returns a device handle for the first device found matching `vendor_id` and `product_id`. /// On error, or if the device could not be found, it returns `None`. - pub fn open_device_with_vid_pid<'a>(&'a self, vendor_id: u16, product_id: u16) -> Option> { + pub fn open_device_with_vid_pid(&self, vendor_id: u16, product_id: u16) -> Option { let handle = unsafe { libusb_open_device_with_vid_pid(self.context, vendor_id, product_id) }; if handle.is_null() { @@ -105,6 +105,7 @@ impl Context { /// Library logging levels. +#[derive(Clone,Copy)] pub enum LogLevel { /// No messages are printed by `libusb` (default). None, @@ -125,8 +126,8 @@ pub enum LogLevel { } impl LogLevel { - fn as_c_int(&self) -> c_int { - match *self { + fn as_c_int(self) -> c_int { + match self { LogLevel::None => LIBUSB_LOG_LEVEL_NONE, LogLevel::Error => LIBUSB_LOG_LEVEL_ERROR, LogLevel::Warning => LIBUSB_LOG_LEVEL_WARNING, diff --git a/src/device.rs b/src/device.rs index cbfda2b..3534341 100644 --- a/src/device.rs +++ b/src/device.rs @@ -86,6 +86,11 @@ impl<'a> Device<'a> { Ok(unsafe { device_handle::from_libusb(self.context, handle) }) } + + /// Returns the device's port number + pub fn port_number(&self) -> u8 { + unsafe { libusb_get_port_number(self.device) } + } } #[doc(hidden)] @@ -93,7 +98,7 @@ pub unsafe fn from_libusb<'a>(context: PhantomData<&'a Context>, device: *mut li libusb_ref_device(device); Device { - context: context, - device: device, + context, + device, } } diff --git a/src/device_handle.rs b/src/device_handle.rs index eb9c360..15be9b4 100644 --- a/src/device_handle.rs +++ b/src/device_handle.rs @@ -49,7 +49,7 @@ impl<'a> DeviceHandle<'a> { /// Sets the device's active configuration. pub fn set_active_configuration(&mut self, config: u8) -> ::Result<()> { - try_unsafe!(libusb_set_configuration(self.handle, config as c_int)); + try_unsafe!(libusb_set_configuration(self.handle, c_int::from(config))); Ok(()) } @@ -69,7 +69,7 @@ impl<'a> DeviceHandle<'a> { /// /// This method is not supported on all platforms. pub fn kernel_driver_active(&self, iface: u8) -> ::Result { - match unsafe { libusb_kernel_driver_active(self.handle, iface as c_int) } { + match unsafe { libusb_kernel_driver_active(self.handle, c_int::from(iface)) } { 0 => Ok(false), 1 => Ok(true), err => Err(error::from_libusb(err)), @@ -80,7 +80,7 @@ impl<'a> DeviceHandle<'a> { /// /// This method is not supported on all platforms. pub fn detach_kernel_driver(&mut self, iface: u8) -> ::Result<()> { - try_unsafe!(libusb_detach_kernel_driver(self.handle, iface as c_int)); + try_unsafe!(libusb_detach_kernel_driver(self.handle, c_int::from(iface))); Ok(()) } @@ -88,7 +88,7 @@ impl<'a> DeviceHandle<'a> { /// /// This method is not supported on all platforms. pub fn attach_kernel_driver(&mut self, iface: u8) -> ::Result<()> { - try_unsafe!(libusb_attach_kernel_driver(self.handle, iface as c_int)); + try_unsafe!(libusb_attach_kernel_driver(self.handle, c_int::from(iface))); Ok(()) } @@ -97,21 +97,21 @@ impl<'a> DeviceHandle<'a> { /// An interface must be claimed before operating on it. All claimed interfaces are released /// when the device handle goes out of scope. pub fn claim_interface(&mut self, iface: u8) -> ::Result<()> { - try_unsafe!(libusb_claim_interface(self.handle, iface as c_int)); + try_unsafe!(libusb_claim_interface(self.handle, c_int::from(iface))); self.interfaces.insert(iface as usize); Ok(()) } /// Releases a claimed interface. pub fn release_interface(&mut self, iface: u8) -> ::Result<()> { - try_unsafe!(libusb_release_interface(self.handle, iface as c_int)); - self.interfaces.remove(&(iface as usize)); + try_unsafe!(libusb_release_interface(self.handle, c_int::from(iface))); + self.interfaces.remove(iface as usize); Ok(()) } /// Sets an interface's active setting. pub fn set_alternate_setting(&mut self, iface: u8, setting: u8) -> ::Result<()> { - try_unsafe!(libusb_set_interface_alt_setting(self.handle, iface as c_int, setting as c_int)); + try_unsafe!(libusb_set_interface_alt_setting(self.handle, c_int::from(iface), c_int::from(setting))); Ok(()) } @@ -146,7 +146,7 @@ impl<'a> DeviceHandle<'a> { let ptr = buf.as_mut_ptr() as *mut c_uchar; let len = buf.len() as c_int; - let timeout_ms = (timeout.as_secs() * 1000 + timeout.subsec_nanos() as u64 / 1_000_000) as c_uint; + let timeout_ms = (timeout.as_secs() * 1000 + u64::from(timeout.subsec_nanos()) / 1_000_000) as c_uint; match unsafe { libusb_interrupt_transfer(self.handle, endpoint, ptr, len, &mut transferred, timeout_ms) } { 0 => { @@ -192,7 +192,7 @@ impl<'a> DeviceHandle<'a> { let ptr = buf.as_ptr() as *mut c_uchar; let len = buf.len() as c_int; - let timeout_ms = (timeout.as_secs() * 1000 + timeout.subsec_nanos() as u64 / 1_000_000) as c_uint; + let timeout_ms = (timeout.as_secs() * 1000 + u64::from(timeout.subsec_nanos()) / 1_000_000) as c_uint; match unsafe { libusb_interrupt_transfer(self.handle, endpoint, ptr, len, &mut transferred, timeout_ms) } { 0 => { @@ -240,7 +240,7 @@ impl<'a> DeviceHandle<'a> { let ptr = buf.as_mut_ptr() as *mut c_uchar; let len = buf.len() as c_int; - let timeout_ms = (timeout.as_secs() * 1000 + timeout.subsec_nanos() as u64 / 1_000_000) as c_uint; + let timeout_ms = (timeout.as_secs() * 1000 + u64::from(timeout.subsec_nanos()) / 1_000_000) as c_uint; match unsafe { libusb_bulk_transfer(self.handle, endpoint, ptr, len, &mut transferred, timeout_ms) } { 0 => { @@ -286,7 +286,7 @@ impl<'a> DeviceHandle<'a> { let ptr = buf.as_ptr() as *mut c_uchar; let len = buf.len() as c_int; - let timeout_ms = (timeout.as_secs() * 1000 + timeout.subsec_nanos() as u64 / 1_000_000) as c_uint; + let timeout_ms = (timeout.as_secs() * 1000 + u64::from(timeout.subsec_nanos()) / 1_000_000) as c_uint; match unsafe { libusb_bulk_transfer(self.handle, endpoint, ptr, len, &mut transferred, timeout_ms) } { 0 => { @@ -337,7 +337,7 @@ impl<'a> DeviceHandle<'a> { let ptr = buf.as_mut_ptr() as *mut c_uchar; let len = buf.len() as u16; - let timeout_ms = (timeout.as_secs() * 1000 + timeout.subsec_nanos() as u64 / 1_000_000) as c_uint; + let timeout_ms = (timeout.as_secs() * 1000 + u64::from(timeout.subsec_nanos()) / 1_000_000) as c_uint; let res = unsafe { libusb_control_transfer(self.handle, request_type, request, value, index, ptr, len, timeout_ms) @@ -383,7 +383,7 @@ impl<'a> DeviceHandle<'a> { let ptr = buf.as_ptr() as *mut c_uchar; let len = buf.len() as u16; - let timeout_ms = (timeout.as_secs() * 1000 + timeout.subsec_nanos() as u64 / 1_000_000) as c_uint; + let timeout_ms = (timeout.as_secs() * 1000 + u64::from(timeout.subsec_nanos()) / 1_000_000) as c_uint; let res = unsafe { libusb_control_transfer(self.handle, request_type, request, value, index, ptr, len, timeout_ms) @@ -403,13 +403,13 @@ impl<'a> DeviceHandle<'a> { pub fn read_languages(&self, timeout: Duration) -> ::Result> { let mut buf = Vec::::with_capacity(256); - let mut buf_slice = unsafe { + let buf_slice = unsafe { slice::from_raw_parts_mut((&mut buf[..]).as_mut_ptr(), buf.capacity()) }; let len = try!(self.read_control(request_type(Direction::In, RequestType::Standard, Recipient::Device), LIBUSB_REQUEST_GET_DESCRIPTOR, - (LIBUSB_DT_STRING as u16) << 8, + u16::from(LIBUSB_DT_STRING) << 8, 0, buf_slice, timeout)); @@ -419,7 +419,7 @@ impl<'a> DeviceHandle<'a> { } Ok(buf.chunks(2).skip(1).map(|chunk| { - let lang_id = chunk[0] as u16 | (chunk[1] as u16) << 8; + let lang_id = u16::from(chunk[0]) | u16::from(chunk[1]) << 8; ::language::from_lang_id(lang_id) }).collect()) } @@ -430,13 +430,13 @@ impl<'a> DeviceHandle<'a> { pub fn read_string_descriptor(&self, language: Language, index: u8, timeout: Duration) -> ::Result { let mut buf = Vec::::with_capacity(256); - let mut buf_slice = unsafe { + let buf_slice = unsafe { slice::from_raw_parts_mut((&mut buf[..]).as_mut_ptr(), buf.capacity()) }; let len = try!(self.read_control(request_type(Direction::In, RequestType::Standard, Recipient::Device), LIBUSB_REQUEST_GET_DESCRIPTOR, - (LIBUSB_DT_STRING as u16) << 8 | index as u16, + u16::from(LIBUSB_DT_STRING) << 8 | u16::from(index), language.lang_id(), buf_slice, timeout)); @@ -446,7 +446,7 @@ impl<'a> DeviceHandle<'a> { } let utf16: Vec = buf.chunks(2).skip(1).map(|chunk| { - chunk[0] as u16 | (chunk[1] as u16) << 8 + u16::from(chunk[0]) | u16::from(chunk[1]) << 8 }).collect(); String::from_utf16(&utf16[..]).map_err(|_| Error::Other) @@ -497,7 +497,7 @@ impl<'a> DeviceHandle<'a> { pub unsafe fn from_libusb<'a>(context: PhantomData<&'a Context>, handle: *mut libusb_device_handle) -> DeviceHandle<'a> { DeviceHandle { _context: context, - handle: handle, + handle, interfaces: BitSet::with_capacity(u8::max_value() as usize + 1), } } diff --git a/src/device_list.rs b/src/device_list.rs index 8a22e54..afdcca0 100644 --- a/src/device_list.rs +++ b/src/device_list.rs @@ -28,6 +28,9 @@ impl<'a> DeviceList<'a> { self.len } + /// Returns true if the list is empty, else returns false. + pub fn is_empty(&self) -> bool { self.len == 0 } + /// Returns an iterator over the devices in the list. /// /// The iterator yields a sequence of `Device` objects. @@ -70,10 +73,10 @@ impl<'a, 'b> Iterator for Devices<'a, 'b> { #[doc(hidden)] -pub unsafe fn from_libusb<'a>(_context: &'a Context, list: *const *mut libusb_device, len: usize,) -> DeviceList<'a> { +pub unsafe fn from_libusb(_context: &Context, list: *const *mut libusb_device, len: usize,) -> DeviceList { DeviceList { context: PhantomData, - list: list, - len: len, + list, + len, } } diff --git a/src/endpoint_descriptor.rs b/src/endpoint_descriptor.rs index bdfc559..f17d8fb 100644 --- a/src/endpoint_descriptor.rs +++ b/src/endpoint_descriptor.rs @@ -1,4 +1,5 @@ use std::fmt; +use std::slice; use libusb::*; @@ -71,6 +72,18 @@ impl<'a> EndpointDescriptor<'a> { pub fn interval(&self) -> u8 { self.descriptor.bInterval } + + /// Returns the unknown 'extra' bytes that libusb does not understand. + pub fn extra(&'a self) -> Option<&'a [u8]> { + unsafe { + match (*self.descriptor).extra_length { + len if len > 0 => { + Some(slice::from_raw_parts((*self.descriptor).extra, len as usize)) + }, + _ => None + } + } + } } impl<'a> fmt::Debug for EndpointDescriptor<'a> { diff --git a/src/fields.rs b/src/fields.rs index 69798aa..f4223c5 100644 --- a/src/fields.rs +++ b/src/fields.rs @@ -163,20 +163,20 @@ impl Version { } /// Returns the major version. - pub fn major(&self) -> u8 { - let Version(major, _, _) = *self; + pub fn major(self) -> u8 { + let Version(major, _, _) = self; major } /// Returns the minor version. - pub fn minor(&self) -> u8 { - let Version(_, minor, _) = *self; + pub fn minor(self) -> u8 { + let Version(_, minor, _) = self; minor } /// Returns the sub minor version. - pub fn sub_minor(&self) -> u8 { - let Version(_, _, sub_minor) = *self; + pub fn sub_minor(self) -> u8 { + let Version(_, _, sub_minor) = self; sub_minor } } diff --git a/src/interface_descriptor.rs b/src/interface_descriptor.rs index 83563ee..5bcca46 100644 --- a/src/interface_descriptor.rs +++ b/src/interface_descriptor.rs @@ -37,7 +37,7 @@ impl<'a> Iterator for InterfaceDescriptors<'a> { fn next(&mut self) -> Option> { self.iter.next().map(|descriptor| { - InterfaceDescriptor { descriptor: descriptor } + InterfaceDescriptor { descriptor } }) } @@ -102,6 +102,18 @@ impl<'a> InterfaceDescriptor<'a> { EndpointDescriptors { iter: endpoints.iter() } } + + /// Returns the unknown 'extra' bytes that libusb does not understand. + pub fn extra(&'a self) -> Option<&'a [u8]> { + unsafe { + match (*self.descriptor).extra_length { + len if len > 0 => { + Some( slice::from_raw_parts((*self.descriptor).extra, len as usize) ) + }, + _ => None + } + } + } } impl<'a> fmt::Debug for InterfaceDescriptor<'a> { @@ -145,9 +157,9 @@ impl<'a> Iterator for EndpointDescriptors<'a> { #[doc(hidden)] pub unsafe fn from_libusb(interface: &libusb_interface) -> Interface { let descriptors = slice::from_raw_parts(interface.altsetting, interface.num_altsetting as usize); - debug_assert!(descriptors.len() > 0); + debug_assert!(!descriptors.is_empty()); - Interface { descriptors: descriptors } + Interface { descriptors } } diff --git a/src/language.rs b/src/language.rs index 458eb7e..078c4b5 100644 --- a/src/language.rs +++ b/src/language.rs @@ -19,24 +19,24 @@ impl Language { /// /// Each language's `LANGID` is defined by the USB forum /// (http://www.usb.org/developers/docs/USB_LANGIDs.pdf). - pub fn lang_id(&self) -> u16 { + pub fn lang_id(self) -> u16 { self.raw } /// Returns the primary language. - pub fn primary_language(&self) -> PrimaryLanguage { + pub fn primary_language(self) -> PrimaryLanguage { PrimaryLanguage::from_raw(self.raw) } /// Returns the sub language. - pub fn sub_language(&self) -> SubLanguage { + pub fn sub_language(self) -> SubLanguage { SubLanguage::from_raw(self.primary_language(), self.raw) } } #[doc(hidden)] pub fn from_lang_id(raw: u16) -> Language { - Language { raw: raw } + Language { raw } } diff --git a/src/version.rs b/src/version.rs index bc47a29..941c1a7 100644 --- a/src/version.rs +++ b/src/version.rs @@ -1,6 +1,5 @@ use std::ffi::CStr; use std::fmt; -use std::mem; use std::str; use libusb::*; @@ -37,7 +36,7 @@ impl LibraryVersion { match str::from_utf8(cstr.to_bytes()) { Ok(s) => { - if s.len() > 0 { + if !s.is_empty() { Some(s) } else { @@ -68,7 +67,7 @@ impl fmt::Debug for LibraryVersion { /// Returns a structure with the version of the running libusb library. pub fn version() -> LibraryVersion { let version: &'static libusb_version = unsafe { - mem::transmute(libusb_get_version()) + &*libusb_get_version() }; LibraryVersion { inner: version }