Skip to content

Commit 2dd5aad

Browse files
richodcuddeback
authored andcommitted
Hotplug support
1 parent fde8413 commit 2dd5aad

File tree

2 files changed

+127
-0
lines changed

2 files changed

+127
-0
lines changed

examples/hotplug.rs

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
extern crate libusb_sys as ffi;
2+
extern crate libc;
3+
4+
use libc::{c_int, c_void, timeval};
5+
6+
use std::mem;
7+
use std::ptr;
8+
use std::time::Instant;
9+
10+
fn main() {
11+
let mut context: *mut ::ffi::libusb_context = unsafe { mem::uninitialized() };
12+
13+
match unsafe { ::ffi::libusb_init(&mut context) } {
14+
0 => (),
15+
e => panic!("libusb_init: {}", get_error(e)),
16+
};
17+
18+
if unsafe { ::ffi::libusb_has_capability(::ffi::LIBUSB_CAP_HAS_HOTPLUG) == 0 } {
19+
panic!("libusb doesn't support hotplug on this platform");
20+
}
21+
22+
let mut callback_handle = unsafe { mem::uninitialized() };
23+
24+
let res = unsafe {
25+
::ffi::libusb_hotplug_register_callback(
26+
context,
27+
::ffi::LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | ::ffi::LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT,
28+
::ffi::LIBUSB_HOTPLUG_ENUMERATE,
29+
::ffi::LIBUSB_HOTPLUG_MATCH_ANY,
30+
::ffi::LIBUSB_HOTPLUG_MATCH_ANY,
31+
::ffi::LIBUSB_HOTPLUG_MATCH_ANY,
32+
callback_fn,
33+
ptr::null_mut() as *mut c_void,
34+
&mut callback_handle as *mut ::ffi::libusb_hotplug_callback_handle,
35+
)
36+
};
37+
38+
if res != ::ffi::LIBUSB_SUCCESS {
39+
panic!("libusb_hotplug_register_callback: {}", get_error(res));
40+
}
41+
42+
let start = Instant::now();
43+
let mut timeout = timeval {
44+
tv_sec: 0,
45+
tv_usec: 100_000,
46+
};
47+
48+
while start.elapsed().as_secs() < 30 {
49+
match unsafe { ::ffi::libusb_handle_events_timeout_completed(context, &mut timeout, ptr::null_mut()) } {
50+
0 => (),
51+
e => panic!("libusb_handle_events: {}", get_error(e)),
52+
};
53+
}
54+
55+
unsafe {
56+
::ffi::libusb_hotplug_deregister_callback(context, callback_handle);
57+
::ffi::libusb_exit(context);
58+
}
59+
}
60+
61+
extern "C" fn callback_fn(_ctx: *mut ::ffi::libusb_context, device: *mut ::ffi::libusb_device, event: ::ffi::libusb_hotplug_event, _data: *mut c_void) -> i32 {
62+
let event_name = match event {
63+
::ffi::LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED => "ATTACH",
64+
::ffi::LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT => "REMOVE",
65+
_ => "OTHER",
66+
};
67+
68+
let mut device_descriptor = unsafe { mem::uninitialized() };
69+
70+
unsafe {
71+
match ::ffi::libusb_get_device_descriptor(device, &mut device_descriptor) {
72+
0 => {
73+
println!(
74+
"{}: {:04X}:{:04X} {}.{}.{}",
75+
event_name,
76+
device_descriptor.idVendor,
77+
device_descriptor.idProduct,
78+
::ffi::libusb_get_bus_number(device),
79+
::ffi::libusb_get_port_number(device),
80+
::ffi::libusb_get_device_address(device),
81+
);
82+
},
83+
e => println!("libusb_get_device_descriptor: {}", get_error(e)),
84+
};
85+
}
86+
87+
0
88+
}
89+
90+
fn get_error(err: c_int) -> &'static str {
91+
match err {
92+
::ffi::LIBUSB_SUCCESS => "success",
93+
::ffi::LIBUSB_ERROR_IO => "I/O error",
94+
::ffi::LIBUSB_ERROR_INVALID_PARAM => "invalid parameter",
95+
::ffi::LIBUSB_ERROR_ACCESS => "access denied",
96+
::ffi::LIBUSB_ERROR_NO_DEVICE => "no such device",
97+
::ffi::LIBUSB_ERROR_NOT_FOUND => "entity not found",
98+
::ffi::LIBUSB_ERROR_BUSY => "resource busy",
99+
::ffi::LIBUSB_ERROR_TIMEOUT => "opteration timed out",
100+
::ffi::LIBUSB_ERROR_OVERFLOW => "overflow error",
101+
::ffi::LIBUSB_ERROR_PIPE => "pipe error",
102+
::ffi::LIBUSB_ERROR_INTERRUPTED => "system call interrupted",
103+
::ffi::LIBUSB_ERROR_NO_MEM => "insufficient memory",
104+
::ffi::LIBUSB_ERROR_NOT_SUPPORTED => "operation not supported",
105+
::ffi::LIBUSB_ERROR_OTHER | _ => "other error"
106+
}
107+
}

src/lib.rs

+20
Original file line numberDiff line numberDiff line change
@@ -192,10 +192,14 @@ pub struct libusb_pollfd {
192192
pub events: c_short,
193193
}
194194

195+
196+
pub type libusb_hotplug_callback_handle = c_int;
197+
pub type libusb_hotplug_callback_fn = extern "C" fn(*mut libusb_context, *mut libusb_device, libusb_hotplug_event, *mut c_void) -> c_int;
195198
pub type libusb_transfer_cb_fn = extern "C" fn(*mut libusb_transfer);
196199
pub type libusb_pollfd_added_cb = extern "C" fn(c_int, c_short, *mut c_void);
197200
pub type libusb_pollfd_removed_cb = extern "C" fn(c_int, *mut c_void);
198201

202+
199203
// libusb_error
200204
pub const LIBUSB_SUCCESS: c_int = 0;
201205
pub const LIBUSB_ERROR_IO: c_int = -1;
@@ -347,6 +351,18 @@ pub const LIBUSB_REQUEST_SET_SEL: u8 = 0x30;
347351
pub const LIBUSB_SET_ISOCH_DELAY: u8 = 0x31;
348352

349353

354+
// libusb_hotplug_event
355+
pub type libusb_hotplug_event = c_int;
356+
pub const LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED: libusb_hotplug_event = 1 << 0;
357+
pub const LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT: libusb_hotplug_event = 1 << 1;
358+
359+
360+
// libusb_hotplug_flag
361+
pub const LIBUSB_HOTPLUG_NO_FLAGS: c_int = 0;
362+
pub const LIBUSB_HOTPLUG_MATCH_ANY: c_int = -1;
363+
pub const LIBUSB_HOTPLUG_ENUMERATE: c_int = 1 << 0;
364+
365+
350366
extern "C" {
351367
pub fn libusb_get_version() -> *const libusb_version;
352368
pub fn libusb_has_capability(capability: u32) -> c_int;
@@ -442,6 +458,10 @@ extern "C" {
442458
pub fn libusb_get_next_timeout(context: *mut libusb_context, tv: *mut timeval) -> c_int;
443459
pub fn libusb_get_pollfds(context: *mut libusb_context) -> *const *mut libusb_pollfd;
444460
pub fn libusb_set_pollfd_notifiers(context: *mut libusb_context, added_cb: libusb_pollfd_added_cb, removed_cb: libusb_pollfd_removed_cb, user_data: *mut c_void);
461+
462+
pub fn libusb_hotplug_register_callback(context: *mut libusb_context, events: c_int, flags: c_int, vendor_id: c_int, product_id: c_int, dev_class: c_int, cb_fn: libusb_hotplug_callback_fn, user_data: *mut c_void, callback_handle: *mut libusb_hotplug_callback_handle) -> c_int;
463+
pub fn libusb_hotplug_deregister_callback(context: *mut libusb_context, callback_handle: libusb_hotplug_callback_handle);
464+
pub fn libusb_hotplug_get_user_data(context: *mut libusb_context, callback_handle: libusb_hotplug_callback_handle) -> *mut c_void;
445465
}
446466

447467

0 commit comments

Comments
 (0)