From 5b7cf79dff6a9984990b0448aaf5f31f741a207c Mon Sep 17 00:00:00 2001 From: Yuriy Larin Date: Thu, 27 Aug 2020 22:24:18 +0300 Subject: [PATCH 01/12] added new structs, callbacks, methods --- src/lib.rs | 267 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 263 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 25ae199..a94b7af 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,8 +2,9 @@ extern crate libc; -use libc::{c_void, c_int, c_uint, c_char, c_uchar, c_short, ssize_t, timeval}; +use std::convert::TryInto; +use libc::{c_char, c_int, c_short, c_uchar, c_uint, c_void, ssize_t, timeval}; #[repr(C)] pub struct libusb_context { @@ -126,6 +127,7 @@ pub struct libusb_bos_dev_capability_descriptor { pub bLength: u8, pub bDescriptorType: u8, pub bDevCapabilityType: u8, + pub dev_capability_data: [u8;0], } #[allow(non_snake_case)] @@ -135,6 +137,7 @@ pub struct libusb_bos_descriptor { pub bDescriptorType: u8, pub wTotalLength: u16, pub bNumDeviceCaps: u8, + pub dev_capability: *mut [libusb_bos_dev_capability_descriptor;0], } #[allow(non_snake_case)] @@ -169,6 +172,30 @@ pub struct libusb_container_id_descriptor { pub ContainerId: [u8; 16], } +#[allow(non_snake_case)] +#[repr(C)] +struct libusb_control_setup { + /// Request type. Bits 0:4 determine recipient, see + /// libusb_request_recipient. Bits 5:6 determine type, see + /// libusb_request_type. Bit 7 determines data transfer direction, see + /// libusb_endpoint_direction. + pub bmRequestType: u8, + /// Request. If the type bits of bmRequestType are equal to + /// libusb_request_type::LIBUSB_REQUEST_TYPE_STANDARD + /// "LIBUSB_REQUEST_TYPE_STANDARD" then this field refers to + /// libusb_standard_request. For other cases, use of this field is + /// application-specific. + pub bRequest: u8, + /// Value. Varies according to request + pub wValue: u16, + /// Index. Varies according to request, typically used to pass an index or offset + pub wIndex: u16, + /// Number of bytes to transfer + pub wLength: u16, +} + +pub const LIBUSB_CONTROL_SETUP_SIZE: usize = std::mem::size_of::(); + #[repr(C)] pub struct libusb_transfer { pub dev_handle: *mut libusb_device_handle, @@ -195,6 +222,7 @@ pub struct libusb_pollfd { pub type libusb_transfer_cb_fn = extern "C" fn(*mut libusb_transfer); pub type libusb_pollfd_added_cb = extern "C" fn(c_int, c_short, *mut c_void); pub type libusb_pollfd_removed_cb = extern "C" fn(c_int, *mut c_void); +pub type libusb_log_cb = extern "C" fn(*mut libusb_context, c_int/*libusb_log_level*/, *const c_char /*str to log?*/); // libusb_error pub const LIBUSB_SUCCESS: c_int = 0; @@ -240,6 +268,9 @@ pub const LIBUSB_LOG_LEVEL_WARNING: c_int = 2; pub const LIBUSB_LOG_LEVEL_INFO: c_int = 3; pub const LIBUSB_LOG_LEVEL_DEBUG: c_int = 4; +/// libusb_log_cb_mode +pub const LIBUSB_LOG_CB_GLOBAL: u8 = 1 << 0; +pub const LIBUSB_LOG_CB_CONTEXT: u8 = 1 << 1; // libusb_class_code pub const LIBUSB_CLASS_PER_INTERFACE: u8 = 0; @@ -268,6 +299,18 @@ pub const LIBUSB_SPEED_LOW: c_int = 1; pub const LIBUSB_SPEED_FULL: c_int = 2; pub const LIBUSB_SPEED_HIGH: c_int = 3; pub const LIBUSB_SPEED_SUPER: c_int = 4; +/// The device is operating at super speed plus (10000MBit/s). +pub const LIBUSB_SPEED_SUPER_PLUS: c_int = 5; + +// libusb_supported_speed +/// Low speed operation supported (1.5MBit/s). +pub const LIBUSB_LOW_SPEED_OPERATION: c_int = 1; +/// Full speed operation supported (12MBit/s). +pub const LIBUSB_FULL_SPEED_OPERATION: c_int = 2; +/// High speed operation supported (480MBit/s). +pub const LIBUSB_HIGH_SPEED_OPERATION: c_int = 4; +/// Superspeed operation supported (5000MBit/s). +pub const LIBUSB_SUPER_SPEED_OPERATION: c_int = 8; // libusb_descriptor_type @@ -357,6 +400,7 @@ extern "C" { pub fn libusb_init(context: *mut *mut libusb_context) -> c_int; pub fn libusb_exit(context: *mut libusb_context); pub fn libusb_set_debug(context: *mut libusb_context, level: c_int); + pub fn libusb_set_log_cb(context: *mut libusb_context, cd: libusb_log_cb, mode: c_int /*libusb_log_level*/); pub fn libusb_get_device_list(context: *mut libusb_context, list: *mut *const *mut libusb_device) -> ssize_t; pub fn libusb_free_device_list(list: *const *mut libusb_device, unref_devices: c_int); @@ -375,6 +419,7 @@ extern "C" { pub fn libusb_get_bus_number(dev: *const libusb_device) -> u8; pub fn libusb_get_port_number(dev: *mut libusb_device) -> u8; pub fn libusb_get_port_numbers(dev: *mut libusb_device, port_numbers: *mut u8, port_numbers_len: c_int) -> c_int; + pub fn libusb_get_port_path(context: *mut libusb_context, dev: *mut libusb_device, path: *mut u8, path_length: u8) -> c_int; pub fn libusb_get_device_address(dev: *const libusb_device) -> u8; pub fn libusb_get_device_speed(dev: *const libusb_device) -> c_int; pub fn libusb_get_max_packet_size(dev: *const libusb_device, endpoint: c_uchar) -> c_int; @@ -446,7 +491,221 @@ extern "C" { // defined as static inline in libusb.h -pub unsafe fn libusb_get_string_descriptor(dev_handle: *mut libusb_device_handle, desc_index: u8, langid: u16, data: *mut c_uchar, length: c_int) -> c_int -{ - libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_IN, LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_STRING as u16) << 8 | desc_index as u16, langid, data, length as u16, 1000) +pub unsafe fn libusb_get_string_descriptor(dev_handle: *mut libusb_device_handle, + desc_index: u8, + langid: u16, + data: *mut c_uchar, + length: c_int) -> c_int { + libusb_control_transfer(dev_handle, + LIBUSB_ENDPOINT_IN, + LIBUSB_REQUEST_GET_DESCRIPTOR, + (LIBUSB_DT_STRING as u16) << 8 | desc_index as u16, + langid, data, + length as u16, + 1000) +} + +#[repr(C)] +union ToLe16 { + b8: [u8;2], + b16: u16 +} + +/// Convert a 16-bit value from host-endian to little-endian format. On +/// little endian systems, this function does nothing. On big endian systems, +/// the bytes are swapped. +/// x the host-endian value to convert +/// returns the value in little-endian byte order +pub fn libusb_cpu_to_le16(x: u16) -> u16 { + let _temp = ToLe16 { + b8: [(x >> 8) as u8,(x & 0xff) as u8] + }; + unsafe { _temp.b16 } +} + +/// Get the data section of a control transfer. This convenience function is here +/// to remind you that the data does not start until 8 bytes into the actual +/// buffer, as the setup packet comes first. +/// +/// Calling this function only makes sense from a transfer callback function, +/// or situations where you have already allocated a suitably sized buffer at +/// transfer->buffer. +/// +/// param transfer a transfer +/// returns pointer to the first byte of the data section +pub unsafe fn libusb_control_transfer_get_data(transfer: *mut libusb_transfer) -> *mut c_uchar { + (*transfer).buffer.offset(LIBUSB_CONTROL_SETUP_SIZE as isize) } + +/// Helper function to populate the setup packet (first 8 bytes of the data +/// buffer) for a control transfer. The wIndex, wValue and wLength values should +/// be given in host-endian byte order. +pub unsafe fn libusb_fill_control_setup(buffer: *mut c_uchar, + bmRequestType: u8, + bRequest: u8, + wValue: u16, + wIndex: u16, + wLength: u16) { + let setup: &mut libusb_control_setup = std::mem::transmute(buffer); + setup.bmRequestType = bmRequestType; + setup.bRequest = bRequest; + setup.wValue = libusb_cpu_to_le16(wValue); + setup.wIndex = libusb_cpu_to_le16(wIndex); + setup.wLength = libusb_cpu_to_le16(wLength); +} + +/// Helper function to populate the required \ref libusb_transfer fields +/// for a control transfer. +/// +/// If you pass a transfer buffer to this function, the first 8 bytes will +/// be interpreted as a control setup packet, and the wLength field will be +/// used to automatically populate the \ref libusb_transfer::length "length" +/// field of the transfer. Therefore the recommended approach is: +/// -# Allocate a suitably sized data buffer (including space for control setup) +/// -# Call libusb_fill_control_setup() +/// -# If this is a host-to-device transfer with a data stage, put the data +/// in place after the setup packet +/// -# Call this function +/// -# Call libusb_submit_transfer() +/// +/// It is also legal to pass a NULL buffer to this function, in which case this +/// function will not attempt to populate the length field. Remember that you +/// must then populate the buffer and length fields later. +pub unsafe fn libusb_fill_control_transfer(transfer: *mut libusb_transfer, + dev_handle: *mut libusb_device_handle, + buffer: *mut c_uchar, + callback: libusb_transfer_cb_fn, + user_data: *mut c_void, + timeout: c_uint) { + // struct libusb_control_setup *setup = (struct libusb_control_setup *)(void *) buffer; + let setup: *mut libusb_control_setup = std::mem::transmute(buffer); + (*transfer).dev_handle = dev_handle; + (*transfer).endpoint = 0; + (*transfer).transfer_type = LIBUSB_TRANSFER_TYPE_CONTROL; + (*transfer).timeout = timeout; + (*transfer).buffer = buffer; + let ptr = setup as *const usize; + if !ptr.is_null() { + let size_of_result = libusb_cpu_to_le16((*setup).wLength); + (*transfer).length = (LIBUSB_CONTROL_SETUP_SIZE + std::mem::size_of::()).try_into().unwrap(); + } + (*transfer).user_data = user_data; + (*transfer).callback = callback; +} + +/// Helper function to populate the required \ref libusb_transfer fields +/// for a bulk transfer. +/// +/// param transfer the transfer to populate +/// param dev_handle handle of the device that will handle the transfer +/// param endpoint address of the endpoint where this transfer will be sent +/// param buffer data buffer +/// param length length of data buffer +/// param callback callback function to be invoked on transfer completion +/// param user_data user data to pass to callback function +/// param timeout timeout for the transfer in milliseconds +pub unsafe fn libusb_fill_bulk_transfer(transfer: *mut libusb_transfer, + dev_handle: *mut libusb_device_handle, + endpoint: c_uchar, + buffer: *mut c_uchar, + length: c_int, + callback: libusb_transfer_cb_fn, + user_data: *mut c_void, + timeout: c_uint) { + (*transfer).dev_handle = dev_handle; + (*transfer).endpoint = endpoint; + (*transfer).transfer_type = LIBUSB_TRANSFER_TYPE_BULK; + (*transfer).timeout = timeout; + (*transfer).buffer = buffer; + (*transfer).length = length; + (*transfer).user_data = user_data; + (*transfer).callback = callback; +} + +/// Helper function to populate the required \ref libusb_transfer fields +/// for a bulk transfer using bulk streams. +/// +/// Since version 1.0.19, \ref LIBUSB_API_VERSION >= 0x01000103 +/// +/// param transfer the transfer to populate +/// param dev_handle handle of the device that will handle the transfer +/// param endpoint address of the endpoint where this transfer will be sent +/// param stream_id bulk stream id for this transfer +/// param buffer data buffer +/// param length length of data buffer +/// param callback callback function to be invoked on transfer completion +/// param user_data user data to pass to callback function +/// param timeout timeout for the transfer in milliseconds +pub unsafe fn libusb_fill_bulk_stream_transfer(transfer: *mut libusb_transfer, + dev_handle: *mut libusb_device_handle, + endpoint: c_uchar, + stream_id: u32, + buffer: *mut c_uchar, + length: c_int, + callback: libusb_transfer_cb_fn, + user_data: *mut c_void, + timeout: c_uint) { + libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer, + length, callback, user_data, timeout); + (*transfer).transfer_type = LIBUSB_TRANSFER_TYPE_BULK_STREAM; + libusb_transfer_set_stream_id(transfer, stream_id); +} + +/// Helper function to populate the required \ref libusb_transfer fields +/// for an interrupt transfer. +/// +/// param transfer the transfer to populate +/// param dev_handle handle of the device that will handle the transfer +/// param endpoint address of the endpoint where this transfer will be sent +/// param buffer data buffer +/// param length length of data buffer +/// param callback callback function to be invoked on transfer completion +/// param user_data user data to pass to callback function +/// param timeout timeout for the transfer in milliseconds +pub unsafe fn libusb_fill_interrupt_transfer(transfer: *mut libusb_transfer, + dev_handle: *mut libusb_device_handle, + endpoint: c_uchar, + buffer: *mut c_uchar, + length: c_int, + callback: libusb_transfer_cb_fn, + user_data: *mut c_void, + timeout: c_uint) { + (*transfer).dev_handle = dev_handle; + (*transfer).endpoint = endpoint; + (*transfer).transfer_type = LIBUSB_TRANSFER_TYPE_INTERRUPT; + (*transfer).timeout = timeout; + (*transfer).buffer = buffer; + (*transfer).length = length; + (*transfer).user_data = user_data; + (*transfer).callback = callback; +} + +pub unsafe fn libusb_fill_iso_transfer(transfer: *mut libusb_transfer, + dev_handle: *mut libusb_device_handle, + endpoint: c_uchar, + buffer: *mut c_uchar, + length: c_int, + num_iso_packets: c_int, + callback: libusb_transfer_cb_fn, + user_data: *mut c_void, + timeout: c_uint) { + (*transfer).dev_handle = dev_handle; + (*transfer).endpoint = endpoint; + (*transfer).transfer_type = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS; + (*transfer).timeout = timeout; + (*transfer).buffer = buffer; + (*transfer).length = length; + (*transfer).num_iso_packets = num_iso_packets; + (*transfer).user_data = user_data; + (*transfer).callback = callback; +} + +pub unsafe fn libusb_set_iso_packet_lengths(transfer: *mut libusb_transfer, + length: c_uint) { + // int i; + // for (i = 0; i < (*transfer).num_iso_packets; i++) { + // (*transfer).so_packet_desc[i].length = length; + // } + // for (*transfer).so_packet_desc[] = + unimplemented!() +} \ No newline at end of file From b6aeda40b14ece0a335338f07b1499d2d25d2862 Mon Sep 17 00:00:00 2001 From: Yuriy Larin Date: Thu, 27 Aug 2020 22:42:29 +0300 Subject: [PATCH 02/12] lib_usb updated to MaybeUninit --- examples/libusb_info.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/libusb_info.rs b/examples/libusb_info.rs index 6d46f5b..2be84b2 100644 --- a/examples/libusb_info.rs +++ b/examples/libusb_info.rs @@ -3,6 +3,7 @@ extern crate libusb_sys as ffi; use std::mem; use std::str; use std::ffi::CStr; +use std::mem::MaybeUninit; fn main() { print_version(); @@ -21,14 +22,15 @@ fn print_version() { } fn print_capabilities() { - let mut context: *mut ::ffi::libusb_context = unsafe { mem::uninitialized() }; + let mut context_uninit: MaybeUninit::<*mut ::ffi::libusb_context> = MaybeUninit::uninit(); // library must be initialized before calling libusb_has_capabililty() - match unsafe { ::ffi::libusb_init(&mut context) } { + match unsafe { ::ffi::libusb_init(context_uninit.as_mut_ptr()) } { 0 => (), e => panic!("libusb_init: {}", e) }; + let context = unsafe { context_uninit.assume_init() }; unsafe { ::ffi::libusb_set_debug(context, ::ffi::LIBUSB_LOG_LEVEL_DEBUG); ::ffi::libusb_set_debug(context, ::ffi::LIBUSB_LOG_LEVEL_INFO); From c78f0edad09c1951bf82b3789825c34dbfeaf5c7 Mon Sep 17 00:00:00 2001 From: Yuriy Larin Date: Thu, 27 Aug 2020 22:43:03 +0300 Subject: [PATCH 03/12] list_device is updated to MaybeUninit --- examples/list_devices.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/examples/list_devices.rs b/examples/list_devices.rs index 01a524e..4dd5c58 100644 --- a/examples/list_devices.rs +++ b/examples/list_devices.rs @@ -4,33 +4,32 @@ extern crate libc; use libc::{c_int,c_uchar}; use std::mem; -use std::ptr; -use std::slice; +use std::{mem::{MaybeUninit}, slice, ptr}; fn main() { - let mut context: *mut ::ffi::libusb_context = unsafe { mem::uninitialized() }; + let mut context_uninit: MaybeUninit::<*mut ::ffi::libusb_context> = MaybeUninit::uninit(); - match unsafe { ::ffi::libusb_init(&mut context) } { + match unsafe { ::ffi::libusb_init(context_uninit.as_mut_ptr()) } { 0 => (), e => panic!("libusb_init: {}", get_error(e)) }; - + let context = unsafe { context_uninit.assume_init() }; list_devices(context); unsafe { ::ffi::libusb_exit(context) }; } fn list_devices(context: *mut ::ffi::libusb_context) { - let mut device_list: *const *mut ::ffi::libusb_device = unsafe { mem::uninitialized() }; + let mut device_list_uninit: MaybeUninit::<*const *mut ffi::libusb_device> = MaybeUninit::uninit(); - let len = unsafe { ::ffi::libusb_get_device_list(context, &mut device_list) }; + let get_device_list_result = unsafe { ::ffi::libusb_get_device_list(context, device_list_uninit.as_mut_ptr()) }; - if len < 0 { - println!("libusb_get_device_list: {}", get_error(len as c_int)); + if get_device_list_result < 0 { + println!("libusb_get_device_list: {}", get_error(get_device_list_result as c_int)); return; } - - let devs = unsafe { slice::from_raw_parts(device_list, len as usize) }; + let device_list: *const *mut ffi::libusb_device = unsafe { device_list_uninit.assume_init() }; + let devs = unsafe { slice::from_raw_parts(device_list, get_device_list_result as usize) }; for dev in devs { display_device(dev); @@ -40,18 +39,18 @@ fn list_devices(context: *mut ::ffi::libusb_context) { } fn display_device(dev: &*mut ::ffi::libusb_device) { - let mut descriptor: ::ffi::libusb_device_descriptor = unsafe { mem::uninitialized() }; + let mut descriptor_uninit: MaybeUninit::<::ffi::libusb_device_descriptor> = MaybeUninit::uninit(); let mut handle: *mut ::ffi::libusb_device_handle = ptr::null_mut(); let bus = unsafe { ::ffi::libusb_get_bus_number(*dev) }; let address = unsafe { ::ffi::libusb_get_device_address(*dev) }; let speed = unsafe { ::ffi::libusb_get_device_speed(*dev) }; - let has_descriptor = match unsafe { ::ffi::libusb_get_device_descriptor(*dev, &mut descriptor) } { + let has_descriptor = match unsafe { ::ffi::libusb_get_device_descriptor(*dev, descriptor_uninit.as_mut_ptr()) } { 0 => true, _ => false }; - + let descriptor = unsafe { descriptor_uninit.assume_init() }; if unsafe { ::ffi::libusb_open(*dev, &mut handle) } < 0 { println!("Couldn't open device, some information will be missing"); handle = ptr::null_mut(); @@ -94,10 +93,11 @@ fn display_device(dev: &*mut ::ffi::libusb_device) { print_device_descriptor(handle, &descriptor); for i in 0..descriptor.bNumConfigurations { - let mut descriptor: *const ::ffi::libusb_config_descriptor = unsafe { mem::uninitialized() }; + let mut descriptor_uninit: MaybeUninit::<*const ::ffi::libusb_config_descriptor> = MaybeUninit::uninit(); - match unsafe { ::ffi::libusb_get_config_descriptor(*dev, i, &mut descriptor) } { + match unsafe { ::ffi::libusb_get_config_descriptor(*dev, i, descriptor_uninit.as_mut_ptr()) } { 0 => { + let descriptor = unsafe { descriptor_uninit.assume_init() }; let config = unsafe { &*descriptor }; let interfaces = unsafe { slice::from_raw_parts(config.interface, config.bNumInterfaces as usize) }; From 5406a0fc9c4c55ee4fe1d0df8b5224ee9aa45e33 Mon Sep 17 00:00:00 2001 From: Yuriy Larin Date: Mon, 31 Aug 2020 21:25:45 +0300 Subject: [PATCH 04/12] added 'LIBUSB_SPEED_SUPER_PLUS' value --- examples/list_devices.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/list_devices.rs b/examples/list_devices.rs index 4dd5c58..361d05d 100644 --- a/examples/list_devices.rs +++ b/examples/list_devices.rs @@ -3,7 +3,6 @@ extern crate libc; use libc::{c_int,c_uchar}; -use std::mem; use std::{mem::{MaybeUninit}, slice, ptr}; fn main() { @@ -62,7 +61,7 @@ fn display_device(dev: &*mut ::ffi::libusb_device) { print!(" ID {:04x}:{:04x}", descriptor.idVendor, descriptor.idProduct); } - print!(" {}", get_device_speed(speed)); + print!(", Speed : {}", get_device_speed(speed)); if has_descriptor { if descriptor.iManufacturer > 0 { @@ -223,6 +222,7 @@ fn get_error(err: c_int) -> &'static str { fn get_device_speed(speed: c_int) -> &'static str { match speed { + ::ffi::LIBUSB_SPEED_SUPER_PLUS => "10000 Mbps", ::ffi::LIBUSB_SPEED_SUPER => "5000 Mbps", ::ffi::LIBUSB_SPEED_HIGH => " 480 Mbps", ::ffi::LIBUSB_SPEED_FULL => " 12 Mbps", From e52481b4aa1b4134b6070c578ea330039c3dfd45 Mon Sep 17 00:00:00 2001 From: Yuriy Larin Date: Mon, 31 Aug 2020 21:27:42 +0300 Subject: [PATCH 05/12] updated to using 'MaybeUninit' --- examples/read_device.rs | 74 ++++++++++++++++++++++++++++------------- 1 file changed, 51 insertions(+), 23 deletions(-) diff --git a/examples/read_device.rs b/examples/read_device.rs index 2a469a8..02babcf 100644 --- a/examples/read_device.rs +++ b/examples/read_device.rs @@ -3,11 +3,11 @@ extern crate libc; use libc::{c_int,c_uint,c_uchar}; -use std::mem; use std::slice; use std::io::{Read,Cursor}; use std::str::FromStr; +use std::mem::MaybeUninit; #[derive(Debug)] struct Endpoint { @@ -28,11 +28,17 @@ fn main() { let vid: u16 = FromStr::from_str(args[1].as_ref()).unwrap(); let pid: u16 = FromStr::from_str(args[2].as_ref()).unwrap(); - let mut context: *mut ::ffi::libusb_context = unsafe { mem::uninitialized() }; - let mut device_list: *const *mut ::ffi::libusb_device = unsafe { mem::uninitialized() }; + let mut context_uninit: MaybeUninit<*mut ffi::libusb_context> = MaybeUninit::uninit(); + let context: *mut ffi::libusb_context; - match unsafe { ::ffi::libusb_init(&mut context) } { - 0 => (), + // let mut device_list: *const *mut ::ffi::libusb_device = unsafe { mem::uninitialized() }; + let mut device_list_uninit: MaybeUninit<*const *mut ffi::libusb_device> = MaybeUninit::uninit(); + let device_list: *const *mut ffi::libusb_device; + + match unsafe { ::ffi::libusb_init(context_uninit.as_mut_ptr()) } { + 0 => { + context = unsafe { context_uninit.assume_init() } + }, e => panic!("libusb_init: {}", e) }; @@ -46,19 +52,22 @@ fn main() { let device = unsafe { ::ffi::libusb_get_device(handle) }; unsafe { ::ffi::libusb_ref_device(device) }; - if unsafe { ::ffi::libusb_get_device_list(context, &mut device_list) } >= 0 { + if unsafe { ::ffi::libusb_get_device_list(context, device_list_uninit.as_mut_ptr()) } >= 0 { + device_list = unsafe { device_list_uninit.assume_init() }; print_device_tree(device); println!(""); - unsafe { ::ffi::libusb_free_device_list(device_list, 1) }; } let languages = get_language_ids(handle); println!("Supported languages: {:?}", languages); - let mut active_config: c_int = unsafe { mem::uninitialized() }; - match unsafe { ::ffi::libusb_get_configuration(handle, &mut active_config) } { - 0 => println!("Active configuration: {}", active_config), + let mut active_config_uninit = MaybeUninit::::zeroed(); + match unsafe { ::ffi::libusb_get_configuration(handle, active_config_uninit.as_mut_ptr()) } { + 0 => { + let active_config = unsafe { active_config_uninit.assume_init() }; + println!("Active configuration: {}", active_config) + }, e => println!("libusb_get_configuration: {}", e) } println!(""); @@ -149,17 +158,21 @@ fn get_language_ids(handle: *mut ::ffi::libusb_device_handle) -> Vec { } fn find_readable_endpoint(device: *mut ::ffi::libusb_device, transfer_type: u8) -> Option { - let mut device_descriptor: ::ffi::libusb_device_descriptor = unsafe { mem::uninitialized() }; + let mut descriptor_uninit: MaybeUninit = MaybeUninit::uninit(); - match unsafe { ::ffi::libusb_get_device_descriptor(device, &mut device_descriptor) } { + match unsafe { ::ffi::libusb_get_device_descriptor(device, descriptor_uninit.as_mut_ptr()) } { 0 => { + let device_descriptor: ffi::libusb_device_descriptor = unsafe { descriptor_uninit.assume_init() }; + for i in 0..device_descriptor.bNumConfigurations { - let mut config_ptr: *const ::ffi::libusb_config_descriptor = unsafe { mem::uninitialized() }; + let configuration_config_ptr_uninit: MaybeUninit<*mut *const ffi::libusb_config_descriptor> = MaybeUninit::uninit(); - match unsafe { ::ffi::libusb_get_config_descriptor(device, i, &mut config_ptr) } { + match unsafe { ::ffi::libusb_get_config_descriptor(device, i, *configuration_config_ptr_uninit.as_ptr()) } { 0 => { - let config_descriptor = unsafe { &*config_ptr }; - let interfaces = unsafe { slice::from_raw_parts(config_descriptor.interface, config_descriptor.bNumInterfaces as usize) }; + let config_descriptor: *mut *const ffi::libusb_config_descriptor = unsafe { configuration_config_ptr_uninit.assume_init() }; + + let interfaces = unsafe { slice::from_raw_parts((*(*config_descriptor)).interface, + (*(*config_descriptor)).bNumInterfaces as usize) }; for iface in interfaces { let settings = unsafe { slice::from_raw_parts(iface.altsetting, iface.num_altsetting as usize) }; @@ -173,7 +186,7 @@ fn find_readable_endpoint(device: *mut ::ffi::libusb_device, transfer_type: u8) if is_input && matches_type { return Some(Endpoint { - config: config_descriptor.bConfigurationValue, + config: unsafe { (*(*config_descriptor)).bConfigurationValue }, iface: iface_descriptor.bInterfaceNumber, setting: iface_descriptor.bAlternateSetting, address: endpoint_descriptor.bEndpointAddress @@ -197,7 +210,7 @@ fn find_readable_endpoint(device: *mut ::ffi::libusb_device, transfer_type: u8) } fn read_endpoint(handle: *mut ::ffi::libusb_device_handle, device: *mut ::ffi::libusb_device, endpoint: Endpoint, transfer_type: u8) { - println!("Reading from endpoint: {:?}", endpoint); + println!("Reading from the endpoint: {:?}", endpoint); let has_kernel_driver = unsafe { if ::ffi::libusb_kernel_driver_active(handle, endpoint.iface as c_int) == 1 { @@ -222,17 +235,26 @@ fn read_endpoint(handle: *mut ::ffi::libusb_device_handle, device: *mut ::ffi::l match unsafe { ::ffi::libusb_claim_interface(handle, endpoint.iface as c_int) } { 0 => { - match unsafe { ::ffi::libusb_set_interface_alt_setting(handle, endpoint.iface as c_int, endpoint.setting as c_int) } { + match unsafe { ::ffi::libusb_set_interface_alt_setting(handle, + endpoint.iface as c_int, + endpoint.setting as c_int) } { 0 => { let mut vec = Vec::::with_capacity(256); let timeout: c_uint = 1000; - let mut transferred: c_int = unsafe { mem::uninitialized() }; + let mut transferred_uninit = MaybeUninit::::zeroed(); + let transferred: c_int; match transfer_type { ::ffi::LIBUSB_TRANSFER_TYPE_INTERRUPT => { - match unsafe { ::ffi::libusb_interrupt_transfer(handle, endpoint.address as c_uchar, (&vec[..]).as_ptr() as *mut c_uchar, vec.capacity() as c_int, &mut transferred, timeout) } { + match unsafe { ::ffi::libusb_interrupt_transfer(handle, + endpoint.address as c_uchar, + (&vec[..]).as_ptr() as *mut c_uchar, + vec.capacity() as c_int, + transferred_uninit.as_mut_ptr(), + timeout) } { 0 => { + transferred = unsafe { transferred_uninit.assume_init() }; unsafe { vec.set_len(transferred as usize) }; println!(" - read: {:?}", vec); }, @@ -240,8 +262,14 @@ fn read_endpoint(handle: *mut ::ffi::libusb_device_handle, device: *mut ::ffi::l } }, ::ffi::LIBUSB_TRANSFER_TYPE_BULK => { - match unsafe { ::ffi::libusb_bulk_transfer(handle, endpoint.address as c_uchar, (&vec[..]).as_ptr() as *mut c_uchar, vec.capacity() as c_int, &mut transferred, timeout) } { + match unsafe { ::ffi::libusb_bulk_transfer(handle, + endpoint.address as c_uchar, + (&vec[..]).as_ptr() as *mut c_uchar, + vec.capacity() as c_int, + transferred_uninit.as_mut_ptr(), + timeout) } { 0 => { + transferred = unsafe { transferred_uninit.assume_init() }; unsafe { vec.set_len(transferred as usize) }; println!(" - read: {:?}", vec); }, @@ -251,7 +279,7 @@ fn read_endpoint(handle: *mut ::ffi::libusb_device_handle, device: *mut ::ffi::l tt => println!(" - can't read endpoint with transfer type {}", tt) } }, - e => println!("libusb_set_interface_alt_setting: {}", e) + e => println!("libusb_set_interface_alt_setting: {}", e), } match unsafe { ::ffi::libusb_release_interface(handle, endpoint.iface as c_int) } { From 47f9bd2a533d7068f5ab9f6b4923b013cc91cfd9 Mon Sep 17 00:00:00 2001 From: Yuriy Larin Date: Mon, 31 Aug 2020 21:38:03 +0300 Subject: [PATCH 06/12] fixed latest method --- src/lib.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a94b7af..c20dd2c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -537,6 +537,7 @@ pub unsafe fn libusb_control_transfer_get_data(transfer: *mut libusb_transfer) - (*transfer).buffer.offset(LIBUSB_CONTROL_SETUP_SIZE as isize) } +#[allow(non_snake_case)] /// Helper function to populate the setup packet (first 8 bytes of the data /// buffer) for a control transfer. The wIndex, wValue and wLength values should /// be given in host-endian byte order. @@ -586,7 +587,7 @@ pub unsafe fn libusb_fill_control_transfer(transfer: *mut libusb_transfer, (*transfer).buffer = buffer; let ptr = setup as *const usize; if !ptr.is_null() { - let size_of_result = libusb_cpu_to_le16((*setup).wLength); + // let size_of_result = libusb_cpu_to_le16((*setup).wLength); (*transfer).length = (LIBUSB_CONTROL_SETUP_SIZE + std::mem::size_of::()).try_into().unwrap(); } (*transfer).user_data = user_data; @@ -702,10 +703,7 @@ pub unsafe fn libusb_fill_iso_transfer(transfer: *mut libusb_transfer, pub unsafe fn libusb_set_iso_packet_lengths(transfer: *mut libusb_transfer, length: c_uint) { - // int i; - // for (i = 0; i < (*transfer).num_iso_packets; i++) { - // (*transfer).so_packet_desc[i].length = length; - // } - // for (*transfer).so_packet_desc[] = - unimplemented!() + for one_descriptor in (*transfer).iso_packet_desc.iter_mut() { + one_descriptor.length = length; + } } \ No newline at end of file From 0e241fad28d64ef2838a290af00af83fb30403c6 Mon Sep 17 00:00:00 2001 From: Yuriy Larin Date: Mon, 31 Aug 2020 21:41:52 +0300 Subject: [PATCH 07/12] minor code clean up --- examples/libusb_info.rs | 2 +- examples/list_devices.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/libusb_info.rs b/examples/libusb_info.rs index 2be84b2..65db6bb 100644 --- a/examples/libusb_info.rs +++ b/examples/libusb_info.rs @@ -22,7 +22,7 @@ fn print_version() { } fn print_capabilities() { - let mut context_uninit: MaybeUninit::<*mut ::ffi::libusb_context> = MaybeUninit::uninit(); + let mut context_uninit: MaybeUninit<*mut ::ffi::libusb_context> = MaybeUninit::uninit(); // library must be initialized before calling libusb_has_capabililty() match unsafe { ::ffi::libusb_init(context_uninit.as_mut_ptr()) } { diff --git a/examples/list_devices.rs b/examples/list_devices.rs index 361d05d..1e4c9cf 100644 --- a/examples/list_devices.rs +++ b/examples/list_devices.rs @@ -6,7 +6,7 @@ use libc::{c_int,c_uchar}; use std::{mem::{MaybeUninit}, slice, ptr}; fn main() { - let mut context_uninit: MaybeUninit::<*mut ::ffi::libusb_context> = MaybeUninit::uninit(); + let mut context_uninit: MaybeUninit<*mut ::ffi::libusb_context> = MaybeUninit::uninit(); match unsafe { ::ffi::libusb_init(context_uninit.as_mut_ptr()) } { 0 => (), @@ -19,7 +19,7 @@ fn main() { } fn list_devices(context: *mut ::ffi::libusb_context) { - let mut device_list_uninit: MaybeUninit::<*const *mut ffi::libusb_device> = MaybeUninit::uninit(); + let mut device_list_uninit: MaybeUninit<*const *mut ffi::libusb_device> = MaybeUninit::uninit(); let get_device_list_result = unsafe { ::ffi::libusb_get_device_list(context, device_list_uninit.as_mut_ptr()) }; @@ -38,7 +38,7 @@ fn list_devices(context: *mut ::ffi::libusb_context) { } fn display_device(dev: &*mut ::ffi::libusb_device) { - let mut descriptor_uninit: MaybeUninit::<::ffi::libusb_device_descriptor> = MaybeUninit::uninit(); + let mut descriptor_uninit: MaybeUninit<::ffi::libusb_device_descriptor> = MaybeUninit::uninit(); let mut handle: *mut ::ffi::libusb_device_handle = ptr::null_mut(); let bus = unsafe { ::ffi::libusb_get_bus_number(*dev) }; @@ -92,7 +92,7 @@ fn display_device(dev: &*mut ::ffi::libusb_device) { print_device_descriptor(handle, &descriptor); for i in 0..descriptor.bNumConfigurations { - let mut descriptor_uninit: MaybeUninit::<*const ::ffi::libusb_config_descriptor> = MaybeUninit::uninit(); + let mut descriptor_uninit: MaybeUninit<*const ::ffi::libusb_config_descriptor> = MaybeUninit::uninit(); match unsafe { ::ffi::libusb_get_config_descriptor(*dev, i, descriptor_uninit.as_mut_ptr()) } { 0 => { From 642aa2c1f8e1f4e48645685bf08e333b75dcc02b Mon Sep 17 00:00:00 2001 From: Yuriy Larin Date: Thu, 10 Sep 2020 21:15:55 +0300 Subject: [PATCH 08/12] minor update --- examples/read_device.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/read_device.rs b/examples/read_device.rs index 02babcf..468bb27 100644 --- a/examples/read_device.rs +++ b/examples/read_device.rs @@ -20,8 +20,8 @@ struct Endpoint { fn main() { let args: Vec = std::env::args().collect(); - if args.len() < 3 { - println!("usage: show_device "); + if args.len() < 2 { + println!("usage: "); return; } From 4c90c130e886080f2f912d8c026062812797564d Mon Sep 17 00:00:00 2001 From: Yuriy Larin Date: Thu, 10 Sep 2020 22:20:57 +0300 Subject: [PATCH 09/12] commented out, looks like not neede call ? --- examples/list_devices.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/list_devices.rs b/examples/list_devices.rs index 1e4c9cf..2424c89 100644 --- a/examples/list_devices.rs +++ b/examples/list_devices.rs @@ -50,10 +50,10 @@ fn display_device(dev: &*mut ::ffi::libusb_device) { _ => false }; let descriptor = unsafe { descriptor_uninit.assume_init() }; - if unsafe { ::ffi::libusb_open(*dev, &mut handle) } < 0 { +/* if unsafe { ::ffi::libusb_open(*dev, &mut handle) } < 0 { println!("Couldn't open device, some information will be missing"); handle = ptr::null_mut(); - } + }*/ print!("Bus {:03} Device {:03}", bus, address); From c9acf7749c408a2e7113acee8da159733e090d43 Mon Sep 17 00:00:00 2001 From: Yuriy Larin Date: Thu, 10 Sep 2020 22:21:50 +0300 Subject: [PATCH 10/12] examples without using ffi::libusb_open_device_with_vid_pid() --- examples/read_device_in_loop.rs | 334 ++++++++++++++++++++++++++++++++ 1 file changed, 334 insertions(+) create mode 100644 examples/read_device_in_loop.rs diff --git a/examples/read_device_in_loop.rs b/examples/read_device_in_loop.rs new file mode 100644 index 0000000..3e84d1b --- /dev/null +++ b/examples/read_device_in_loop.rs @@ -0,0 +1,334 @@ +extern crate libusb_sys as ffi; +extern crate libc; + +use libc::{c_int,c_uint,c_uchar}; + +use std::slice; + +use std::io::{Read,Cursor}; +use std::str::FromStr; +use std::mem::MaybeUninit; +use std::ptr::{copy, null}; +use std::ptr; + +#[derive(Debug)] +struct Endpoint { + config: u8, + iface: u8, + setting: u8, + address: u8 +} + +fn main() { + let args: Vec = std::env::args().collect(); + + if args.len() < 2 { + println!("usage: "); + return; + } + + println!("try parse : {}", args[1]); + let vid: u16 = FromStr::from_str(args[1].as_ref()).unwrap(); + println!("try parse : {}", args[2]); + let pid: u16 = FromStr::from_str(args[2].as_ref()).unwrap(); + + let mut context_uninit: MaybeUninit<*mut ffi::libusb_context> = MaybeUninit::uninit(); + let context: *mut ffi::libusb_context; + match unsafe { ::ffi::libusb_init(context_uninit.as_mut_ptr()) } { + 0 => { + context = unsafe { context_uninit.assume_init() } + }, + e => panic!("libusb_init: {}", e) + }; + + let mut device_list_uninit: MaybeUninit<*const *mut ffi::libusb_device> = MaybeUninit::uninit(); + let get_device_list_result = unsafe { ::ffi::libusb_get_device_list(context, device_list_uninit.as_mut_ptr()) }; + if get_device_list_result < 0 { + println!("libusb_get_device_list: {}", get_device_list_result); + return; + } + let device_list: *const *mut ffi::libusb_device = unsafe { device_list_uninit.assume_init() }; + let devs = unsafe { slice::from_raw_parts(device_list, get_device_list_result as usize) }; + + for device in devs { + print_device_tree(*device); + println!(""); + let mut handle: *mut ffi::libusb_device_handle = ptr::null_mut(); + if unsafe { ffi::libusb_open(device.cast(), &mut handle) } < 0 { + println!("Couldn't open device [{:?}], some information will be missing", device); + continue; + } + + if !handle.is_null() { + match unsafe { ::ffi::libusb_reset_device(handle) } { + 0 => { + unsafe { ::ffi::libusb_set_auto_detach_kernel_driver(handle, 0) }; + + let device = unsafe { ::ffi::libusb_get_device(handle) }; + unsafe { ::ffi::libusb_ref_device(device) }; + + let languages = get_language_ids(handle); + println!("Supported languages: {:?}", languages); + + let mut active_config_uninit = MaybeUninit::::zeroed(); + match unsafe { ::ffi::libusb_get_configuration(handle, active_config_uninit.as_mut_ptr()) } { + 0 => { + let active_config = unsafe { active_config_uninit.assume_init() }; + println!("Active configuration: {}", active_config) + }, + e => println!("libusb_get_configuration: {}", e) + } + println!(""); + + match find_readable_endpoint(device, ::ffi::LIBUSB_TRANSFER_TYPE_INTERRUPT, vid, pid) { + Some(ep) => read_endpoint(handle, device, ep, ::ffi::LIBUSB_TRANSFER_TYPE_INTERRUPT), + None => println!("No readable interrupt endpoint") + } + println!(""); + + match find_readable_endpoint(device, ::ffi::LIBUSB_TRANSFER_TYPE_BULK, vid, pid) { + Some(ep) => read_endpoint(handle, device, ep, ::ffi::LIBUSB_TRANSFER_TYPE_BULK), + None => println!("No readable bulk endpoint") + } + + unsafe { ::ffi::libusb_unref_device(device) }; + }, + e => println!("libusb_reset_device: {}", e) + } + unsafe { ::ffi::libusb_close(handle) }; + } else { + println!("ERROR on opening by ffi::libusb_open(...)"); + } + + + } + unsafe { ::ffi::libusb_free_device_list(device_list, 1) }; + + + unsafe { ::ffi::libusb_exit(context) }; +} + +fn print_device_tree(device: *mut ::ffi::libusb_device) -> usize { + if device.is_null() { + return 0; + } + + let parent = unsafe { ::ffi::libusb_get_parent(device) }; + let depth = print_device_tree(parent); + + for _ in 0..depth { + print!(" "); + } + + let bus = unsafe { ::ffi::libusb_get_bus_number(device) }; + let address = unsafe { ::ffi::libusb_get_device_address(device) }; + + println!("Bus {:03} Device {:03}", bus, address); + + return depth + 1; +} + +fn get_language_ids(handle: *mut ::ffi::libusb_device_handle) -> Vec { + let mut buf = Vec::::with_capacity(255); + let len = unsafe { ::ffi::libusb_get_string_descriptor(handle, 0, 0, (&mut buf[..]).as_mut_ptr() as *mut c_uchar, buf.capacity() as c_int) }; + + let mut languages = Vec::::new(); + + if len >= 0 { + unsafe { buf.set_len(len as usize) }; + + if buf.len() >= 2 { + let num_languages = (buf.len() - 2) / 2; + languages.reserve(num_languages); + + let mut cursor = Cursor::new(buf); + cursor.set_position(2); + + for _ in 0..num_languages { + let mut bytes = Vec::::with_capacity(2); + + match cursor.read(unsafe { slice::from_raw_parts_mut((&mut bytes[..]).as_mut_ptr(), bytes.capacity()) }) { + Ok(len) => { + if len == 2 { + unsafe { bytes.set_len(len) }; + + let langid = (bytes[1] as u16) << 8 | (bytes[0] as u16); + languages.push(langid) + } + else { + return languages; + } + }, + Err(_) => return languages + } + } + } + } + else { + println!("libusb_get_string_descriptor: {}", len); + } + + languages +} + +fn find_readable_endpoint(device: *mut ::ffi::libusb_device, + transfer_type: u8, + vid: u16, + pid: u16) -> Option { + + let mut descriptor_uninit: MaybeUninit = MaybeUninit::uninit(); + + match unsafe { ::ffi::libusb_get_device_descriptor(device, descriptor_uninit.as_mut_ptr()) } { + 0 => { + let device_descriptor: ffi::libusb_device_descriptor = unsafe { descriptor_uninit.assume_init() }; + + println!("Check Device '{} : {}'", device_descriptor.idVendor, device_descriptor.idProduct); + if vid <= 0 && pid <= 0 && device_descriptor.idVendor != vid && device_descriptor.idProduct != pid { + // skip device + println!("Device '{:03} : {:03}' skipped, because doesn't equal to '{} : {}'", + device_descriptor.idVendor, device_descriptor.idProduct, vid , pid); + return None; + } + + + for i in 0..device_descriptor.bNumConfigurations { + + let configuration_config_ptr_uninit: MaybeUninit<*mut *const ffi::libusb_config_descriptor> = MaybeUninit::uninit(); + match unsafe { ::ffi::libusb_get_config_descriptor(device, i, *configuration_config_ptr_uninit.as_ptr()) } { + 0 => { + let config_descriptor: *mut *const ffi::libusb_config_descriptor = unsafe { configuration_config_ptr_uninit.assume_init() }; + + let interfaces = unsafe { + slice::from_raw_parts((*(*config_descriptor)).interface, + (*(*config_descriptor)).bNumInterfaces as usize) + }; + + for iface in interfaces { + let settings = unsafe { slice::from_raw_parts(iface.altsetting, iface.num_altsetting as usize) }; + + for iface_descriptor in settings { + let endpoints = unsafe { slice::from_raw_parts(iface_descriptor.endpoint, iface_descriptor.bNumEndpoints as usize) }; + + for endpoint_descriptor in endpoints { + let is_input = endpoint_descriptor.bEndpointAddress & ::ffi::LIBUSB_ENDPOINT_DIR_MASK == ::ffi::LIBUSB_ENDPOINT_IN; + let matches_type = endpoint_descriptor.bmAttributes & ::ffi::LIBUSB_TRANSFER_TYPE_MASK == transfer_type; + + if is_input && matches_type { + return Some(Endpoint { + config: unsafe { (*(*config_descriptor)).bConfigurationValue }, + iface: iface_descriptor.bInterfaceNumber, + setting: iface_descriptor.bAlternateSetting, + address: endpoint_descriptor.bEndpointAddress + }); + } + } + } + } + unsafe { ffi::libusb_free_config_descriptor(*config_descriptor) }; + }, + e => println!("libusb_get_config_descriptor: {}", e) + } + } + + None + }, + e => { + println!("libusb_get_device_descriptor: {}", e); + None + } + } +} + +fn read_endpoint(handle: *mut ::ffi::libusb_device_handle, device: *mut ::ffi::libusb_device, endpoint: Endpoint, transfer_type: u8) { + println!("Reading from the endpoint: {:?}", endpoint); + + let has_kernel_driver = unsafe { + if ::ffi::libusb_kernel_driver_active(handle, endpoint.iface as c_int) == 1 { + match ::ffi::libusb_detach_kernel_driver(handle, endpoint.iface as c_int) { + 0 => (), + e => println!("libusb_detach_kernel_driver: {}", e) + } + + true + } + else { + false + } + }; + + println!(" - kernel driver? {}", has_kernel_driver); + + match unsafe { ::ffi::libusb_set_configuration(handle, endpoint.config as c_int) } { + 0 => { + println!(" - max packet size: {}", unsafe { ::ffi::libusb_get_max_packet_size(device, endpoint.address as c_uchar) }); + println!(" - max iso packet size: {}", unsafe { ::ffi::libusb_get_max_iso_packet_size(device, endpoint.address as c_uchar) }); + + match unsafe { ::ffi::libusb_claim_interface(handle, endpoint.iface as c_int) } { + 0 => { + match unsafe { ::ffi::libusb_set_interface_alt_setting(handle, + endpoint.iface as c_int, + endpoint.setting as c_int) } { + 0 => { + let mut vec = Vec::::with_capacity(256); + let timeout: c_uint = 1000; + + let mut transferred_uninit = MaybeUninit::::zeroed(); + let transferred: c_int; + + match transfer_type { + ::ffi::LIBUSB_TRANSFER_TYPE_INTERRUPT => { + match unsafe { ::ffi::libusb_interrupt_transfer(handle, + endpoint.address as c_uchar, + (&vec[..]).as_ptr() as *mut c_uchar, + vec.capacity() as c_int, + transferred_uninit.as_mut_ptr(), + timeout) } { + 0 => { + transferred = unsafe { transferred_uninit.assume_init() }; + unsafe { vec.set_len(transferred as usize) }; + println!(" - read: {:?}", vec); + }, + e => println!("libusb_interrupt_transfer: {}", e) + } + }, + ::ffi::LIBUSB_TRANSFER_TYPE_BULK => { + match unsafe { ::ffi::libusb_bulk_transfer(handle, + endpoint.address as c_uchar, + (&vec[..]).as_ptr() as *mut c_uchar, + vec.capacity() as c_int, + transferred_uninit.as_mut_ptr(), + timeout) } { + 0 => { + transferred = unsafe { transferred_uninit.assume_init() }; + unsafe { vec.set_len(transferred as usize) }; + println!(" - read: {:?}", vec); + }, + e => println!("libusb_interrupt_transfer: {}", e) + } + }, + tt => println!(" - can't read endpoint with transfer type {}", tt) + } + }, + e => println!("libusb_set_interface_alt_setting: {}", e), + } + + match unsafe { ::ffi::libusb_release_interface(handle, endpoint.iface as c_int) } { + 0 => (), + e => println!("libusb_release_interface: {}", e) + } + }, + e => println!("libusb_claim_interface: {}", e) + } + }, + e => println!("libusb_set_configuration: {}", e) + } + + + + if has_kernel_driver { + match unsafe { ::ffi::libusb_attach_kernel_driver(handle, endpoint.iface as c_int) } { + 0 => (), + e => println!("libusb_attach_kernel_driver: {}", e) + } + } +} From c7a5bd27559425bbd66504ade57a12bd55cd05c1 Mon Sep 17 00:00:00 2001 From: Yuriy Larin Date: Sun, 11 Oct 2020 19:58:07 +0300 Subject: [PATCH 11/12] added setting callback function --- examples/libusb_info.rs | 13 +++++++++++++ examples/list_devices.rs | 22 +++++++++++++++++----- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/examples/libusb_info.rs b/examples/libusb_info.rs index 65db6bb..3759254 100644 --- a/examples/libusb_info.rs +++ b/examples/libusb_info.rs @@ -1,9 +1,20 @@ extern crate libusb_sys as ffi; +extern crate libc; use std::mem; use std::str; use std::ffi::CStr; use std::mem::MaybeUninit; +use libc::{c_char, c_int}; + +#[link(name = "libusb-1.0")] +extern "C" fn call_libusb_log_cb(context: *mut ::ffi::libusb_context, log_level: c_int, log_message: *const c_char) { + if !context.is_null() { + println!("{} : {:?}", log_level, &log_message); + } else { + println!("No USB context"); + } +} fn main() { print_version(); @@ -39,6 +50,8 @@ fn print_capabilities() { ::ffi::libusb_set_debug(context, ::ffi::LIBUSB_LOG_LEVEL_NONE); } + unsafe { ::ffi::libusb_set_log_cb(context, call_libusb_log_cb,::ffi::LIBUSB_LOG_LEVEL_DEBUG) }; + println!("has capability? {}", unsafe { ::ffi::libusb_has_capability(::ffi::LIBUSB_CAP_HAS_CAPABILITY) }); println!("has hotplug? {}", unsafe { ::ffi::libusb_has_capability(::ffi::LIBUSB_CAP_HAS_HOTPLUG) }); println!("has HID access? {}", unsafe { ::ffi::libusb_has_capability(::ffi::LIBUSB_CAP_HAS_HID_ACCESS) }); diff --git a/examples/list_devices.rs b/examples/list_devices.rs index 2424c89..f15d754 100644 --- a/examples/list_devices.rs +++ b/examples/list_devices.rs @@ -1,10 +1,15 @@ extern crate libusb_sys as ffi; extern crate libc; -use libc::{c_int,c_uchar}; +use libc::{c_int, c_uchar, c_char}; use std::{mem::{MaybeUninit}, slice, ptr}; +#[link(name = "libusb-1.0")] +extern "C" fn call_libusb_log_cb(_context: *mut ::ffi::libusb_context, log_level: c_int, log_message: *const c_char) { + println!("USB_CallBack - {:?} : {:?}", log_level, log_message); +} + fn main() { let mut context_uninit: MaybeUninit<*mut ::ffi::libusb_context> = MaybeUninit::uninit(); @@ -13,6 +18,13 @@ fn main() { e => panic!("libusb_init: {}", get_error(e)) }; let context = unsafe { context_uninit.assume_init() }; + unsafe { + // ::ffi::libusb_set_debug(context, ::ffi::LIBUSB_LOG_LEVEL_DEBUG); + // ::ffi::libusb_set_debug(context, ::ffi::LIBUSB_LOG_LEVEL_INFO); + // ::ffi::libusb_set_debug(context, ::ffi::LIBUSB_LOG_LEVEL_WARNING); + ::ffi::libusb_set_debug(context, ::ffi::LIBUSB_LOG_LEVEL_ERROR); + } + unsafe { ::ffi::libusb_set_log_cb(context, call_libusb_log_cb,::ffi::LIBUSB_LOG_LEVEL_DEBUG) }; list_devices(context); unsafe { ::ffi::libusb_exit(context) }; @@ -50,10 +62,10 @@ fn display_device(dev: &*mut ::ffi::libusb_device) { _ => false }; let descriptor = unsafe { descriptor_uninit.assume_init() }; -/* if unsafe { ::ffi::libusb_open(*dev, &mut handle) } < 0 { - println!("Couldn't open device, some information will be missing"); + if unsafe { ::ffi::libusb_open(*dev, &mut handle) } < 0 { + println!("Couldn't open device, some information will be missing"); // luck of OS permissions usually handle = ptr::null_mut(); - }*/ + } print!("Bus {:03} Device {:03}", bus, address); @@ -86,7 +98,7 @@ fn display_device(dev: &*mut ::ffi::libusb_device) { } } - println!(""); + println!("\n--------------------------------------------------"); if has_descriptor { print_device_descriptor(handle, &descriptor); From e39684f303069ac110b4a022fa4be5f00f8d1418 Mon Sep 17 00:00:00 2001 From: Yuriy Larin Date: Sun, 11 Oct 2020 19:58:36 +0300 Subject: [PATCH 12/12] added setting usb debug level --- examples/read_device_in_loop.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/examples/read_device_in_loop.rs b/examples/read_device_in_loop.rs index 3e84d1b..675d1cb 100644 --- a/examples/read_device_in_loop.rs +++ b/examples/read_device_in_loop.rs @@ -8,7 +8,6 @@ use std::slice; use std::io::{Read,Cursor}; use std::str::FromStr; use std::mem::MaybeUninit; -use std::ptr::{copy, null}; use std::ptr; #[derive(Debug)] @@ -40,6 +39,12 @@ fn main() { }, e => panic!("libusb_init: {}", e) }; + // unsafe { + // ::ffi::libusb_set_debug(context, ::ffi::LIBUSB_LOG_LEVEL_DEBUG); + // ::ffi::libusb_set_debug(context, ::ffi::LIBUSB_LOG_LEVEL_INFO); + // ::ffi::libusb_set_debug(context, ::ffi::LIBUSB_LOG_LEVEL_WARNING); + // ::ffi::libusb_set_debug(context, ::ffi::LIBUSB_LOG_LEVEL_ERROR); + // } let mut device_list_uninit: MaybeUninit<*const *mut ffi::libusb_device> = MaybeUninit::uninit(); let get_device_list_result = unsafe { ::ffi::libusb_get_device_list(context, device_list_uninit.as_mut_ptr()) };