Skip to content
19 changes: 17 additions & 2 deletions examples/libusb_info.rs
Original file line number Diff line number Diff line change
@@ -1,8 +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();
Expand All @@ -21,14 +33,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);
Expand All @@ -37,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) });
Expand Down
54 changes: 33 additions & 21 deletions examples/list_devices.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,46 @@
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;
use std::ptr;
use std::slice;
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: *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() };
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) };
}

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);
Expand All @@ -40,20 +50,20 @@ 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");
println!("Couldn't open device, some information will be missing"); // luck of OS permissions usually
handle = ptr::null_mut();
}

Expand All @@ -63,7 +73,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 {
Expand All @@ -88,16 +98,17 @@ fn display_device(dev: &*mut ::ffi::libusb_device) {
}
}

println!("");
println!("\n--------------------------------------------------");

if has_descriptor {
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) };

Expand Down Expand Up @@ -223,6 +234,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",
Expand Down
78 changes: 53 additions & 25 deletions examples/read_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -20,19 +20,25 @@ struct Endpoint {
fn main() {
let args: Vec<String> = std::env::args().collect();

if args.len() < 3 {
println!("usage: show_device <vendor-id> <product-id>");
if args.len() < 2 {
println!("usage: <vendor-id> <product-id>");
return;
}

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)
};

Expand All @@ -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::<c_int>::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!("");
Expand Down Expand Up @@ -149,17 +158,21 @@ fn get_language_ids(handle: *mut ::ffi::libusb_device_handle) -> Vec<u16> {
}

fn find_readable_endpoint(device: *mut ::ffi::libusb_device, transfer_type: u8) -> Option<Endpoint> {
let mut device_descriptor: ::ffi::libusb_device_descriptor = unsafe { mem::uninitialized() };
let mut descriptor_uninit: MaybeUninit<ffi::libusb_device_descriptor> = 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) };
Expand All @@ -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
Expand All @@ -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 {
Expand All @@ -222,26 +235,41 @@ 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::<u8>::with_capacity(256);
let timeout: c_uint = 1000;

let mut transferred: c_int = unsafe { mem::uninitialized() };
let mut transferred_uninit = MaybeUninit::<c_int>::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);
},
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, &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);
},
Expand All @@ -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) } {
Expand Down
Loading