dcuddeback / libusb-rs Goto Github PK
View Code? Open in Web Editor NEWA safe Rust wrapper for libusb.
License: MIT License
A safe Rust wrapper for libusb.
License: MIT License
control_transfer
is not yet implemented in InterfaceHandle althought the binding is present in libusb-sys.
Any plan on that? Do you accept PR on this?
[Slightly OT but related]: xxx_transfer should have been implemented on DeviceHandle, no? I agree it makes sense on InterfaceHandle but
Is it possible to use this crate for embedded devices, ex, for targeting ARM chipsets?
I have modify the read_control() in device_handle.rs to print out some useful informations:
pub fn read_control(&self, request_type: u8, request: u8, value: u16, index: u16, buf: &mut [u8], timeout: Duration) -> ::Result<usize> {
if request_type & LIBUSB_ENDPOINT_DIR_MASK != LIBUSB_ENDPOINT_IN {
return Err(Error::InvalidParam);
}
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 res = unsafe {
println!("libusb_control_transfer: len {:?}",len);
libusb_control_transfer(self.handle, request_type, request, value, index, ptr, len, timeout_ms)
};
println!("libusb_control_transfer: res {:?}",res);
if res < 0 {
Err(error::from_libusb(res))
} else {
Ok(res as usize)
}
}
When I try to read my bluetooth HID mouse, I got the error.
Here is the out put:
libusb_control_transfer: len 256
libusb_control_transfer: res -8
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Overflow', src\libcore\result.rs:999:5
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
After modify
pub fn read_languages(&self, timeout: Duration) -> ::Result<Vec<Language>> {
let mut buf = Vec::<u8>::with_capacity(256)
....
to
pub fn read_languages(&self, timeout: Duration) -> ::Result<Vec<Language>> {
let mut buf = Vec::<u8>::with_capacity(65)
....
it just works. Here is the output:
libusb_control_transfer: len 65
libusb_control_transfer: res 4
My enviroment:
Default host: x86_64-pc-windows-gnu
installed toolchains
nightly-2019-04-21-i686-pc-windows-msvc (default)
installed targets for active toolchain
i686-pc-windows-msvc
nightly-2019-04-21-i686-pc-windows-msvc (default)
rustc 1.36.0-nightly (33fe1131c 2019-04-20)
libusb-1.0.dll version: 1.0.20.11004
Documentation on docs.rs does not regenerate itself automatically with new versions of docs.rs, and it seems that the one for libusb is just as dated as the last release. Even if there were no changes during this whole period, please somehow force docs.rs to refresh its html. There were some cool and useful features introduced in rust docs lately.
@dcuddeback looking to file an unmaintained advisory against this but wanted to check in with you first.
The reason this is important is that libusb is building against an old version of bit-sec
that has an invalid Cargo.toml
that will no longer be recognized as of Cargo 1.79, breaking builds of libusb and everyone who depends on it (see rust-lang/cargo#13824)
Looking over this repo,
bit-set
issues have not gotten attention (#15, #45)Since the start of 2022, the only public activity for @dcuddeback 's profile is two commits to their dotfiles.
There was some activity on libusb-sys in 2021 that was never released.
I'm aware of the repeated queries to this repo (@AJAnderson) and the various forks (@a1lien, etc), but no one else has come out and asked...
Is @dcuddeback available and willing to transfer ownership of this repository and the associated project on crates.io?
Ditto for libusb.sys, and libudev-rs, for that matter.
The goal would be to consolidate all the outstanding PR's and forks, and then proceed with a new async/await API for the asynchronous calls in libusb.
I see isochronous transfers aren't provided. Are there any plans for them?
hi. thanks for making this library wrapper. one thing i would love to use but don't see implemented is the hotplug functionality. from the docs:
int libusb_hotplug_register_callback | ( | libusb_context * | ctx,
-- | -- | -- | --
| | libusb_hotplug_event | events,
| | libusb_hotplug_flag | flags,
| | int | vendor_id,
| | int | product_id,
| | int | dev_class,
| | libusb_hotplug_callback_fn | cb_fn,
| | void * | user_data,
| | libusb_hotplug_callback_handle * | handle
| )
is this already available and i'm missing something?
Seeing @bitbegin's issue (#17), I tried to use the GNU toolchain, but ended up with an error.
I'm on Windows 10 Home 64 bit.
rustup override set stable-x86_64-pc-windows-gnu
pkg-config-lite
%PATH%
to pkg-config-lite-0.28-1\bin
%PKG_CONFIG_PATH%
to pkg-config-lite-0.28-1\libs
I createdpkg-config
was working using pkg-config -v
libusb
for Windows by clicking Downloads > Latest Windows binarieslibusb.pc
file in the PKG_CONFIG_PATH
directory:# libusb.pc
prefix=C:/Users/Tom/Desktop/pkg-config-lite-0.28-1/libs/libusb
exec_prefix=${prefix}
includedir=${prefix}/include/libusb-1.0
libdir=${exec_prefix}/MinGW64/dll # `/dll`?
Name: libusb
Description: libusb
Version: 1.0
Cflags: -I${includedir}
Libs: -L${libdir} -llibusb-1.0
Here's what pkg-config --libs --cflags libusb-1.0
spits out for me:
-IC:/Users/Tom/Desktop/pkg-config-lite-0.28-1/libs/libusb/include/libusb-1.0 -LC:/Users/Tom/Desktop/pkg-config-lite-0.28-1/libs/libusb/MinGW64/dll -llibusb-1.0
I am using this example code based on what's in the README.md
file of this repository:
extern crate libusb;
fn main() {
let context = libusb::Context::new().unwrap();
for device in context.devices().unwrap().iter() {
let device_desc = device.device_descriptor().unwrap();
println!("Bus {:03} Device {:03} ID {:04x}:{:04x}",
device.bus_number(),
device.address(),
device_desc.vendor_id(),
device_desc.product_id());
}
println!("Hello, world!");
}
Running cargo run
then links just fine and runs the binary which subsequently fails with the 3221225781
exit code, which is 0xC0000135
, which means STATUS_DLL_NOT_FOUND
.
I suspect this is because I am using the dll
directory, not the static
directory, but with that one, I just get linked errors.
@dcuddeback would you be able to advise here?
https://github.com/a1ien/rusb.git also publish to crates.io https://crates.io/crates/rusb
on linux ubuntu 22.04 x64
rust 1.62.1
I think is because libusbsys is in 0.6x, and the project need to update dependencies.
Libusb is crashing on libusbsys during build.
error: failed to run custom build command for `libusb-sys v0.2.3`
Caused by:
process didn't exit successfully: `/home/jcbritobr/Workspace/rust/systempr/target/debug/build/libusb-sys-540c2f6b8faff6ab/build-script-build` (exit status: 101)
--- stdout
cargo:rerun-if-env-changed=LIBUSB_1.0_NO_PKG_CONFIG
cargo:rerun-if-env-changed=PKG_CONFIG_x86_64-unknown-linux-gnu
cargo:rerun-if-env-changed=PKG_CONFIG_x86_64_unknown_linux_gnu
cargo:rerun-if-env-changed=HOST_PKG_CONFIG
cargo:rerun-if-env-changed=PKG_CONFIG
cargo:rerun-if-env-changed=LIBUSB_1.0_STATIC
cargo:rerun-if-env-changed=LIBUSB_1.0_DYNAMIC
cargo:rerun-if-env-changed=PKG_CONFIG_ALL_STATIC
cargo:rerun-if-env-changed=PKG_CONFIG_ALL_DYNAMIC
cargo:rerun-if-env-changed=PKG_CONFIG_PATH_x86_64-unknown-linux-gnu
cargo:rerun-if-env-changed=PKG_CONFIG_PATH_x86_64_unknown_linux_gnu
cargo:rerun-if-env-changed=HOST_PKG_CONFIG_PATH
cargo:rerun-if-env-changed=PKG_CONFIG_PATH
cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_x86_64-unknown-linux-gnu
cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_x86_64_unknown_linux_gnu
cargo:rerun-if-env-changed=HOST_PKG_CONFIG_LIBDIR
cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR
cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64-unknown-linux-gnu
cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64_unknown_linux_gnu
cargo:rerun-if-env-changed=HOST_PKG_CONFIG_SYSROOT_DIR
cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR
I'm trying to use the read_device()
function from the example, but read_languages() returns Err(Overflow).
Why?
Btw, the device I'm trying to read is a Corsair K95 RGB keyboard:
Bus 002 Device 009 ID 1b1c:1b11 12 Mbps
Device Descriptor:
bcdUSB 2.00
bDeviceClass 0x00
bDeviceSubClass 0x00
bDeviceProtocol 0x00
bMaxPacketSize0 64
idVendor 0x1b1c
idProduct 0x1b11
bcdDevice 2.05
iManufacturer 1
iProduct 2
iSerialNumber 3
bNumConfigurations 1
Config Descriptor:
bNumInterfaces 3
bConfigurationValue 1
iConfiguration 0
bmAttributes:
Self Powered false
Remote Wakeup true
bMaxPower 500mW
Interface Descriptor:
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 0x03
bInterfaceSubClass 0x01
bInterfaceProtocol 0x01
iInterface 0
Endpoint Descriptor:
bEndpointAddress 0x81 EP 1 In
bmAttributes:
Transfer Type Interrupt
Synch Type NoSync
Usage Type Data
wMaxPacketSize 0x0008
bInterval 8
Interface Descriptor:
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 0x03
bInterfaceSubClass 0x00
bInterfaceProtocol 0x00
iInterface 0
Endpoint Descriptor:
bEndpointAddress 0x82 EP 2 In
bmAttributes:
Transfer Type Interrupt
Synch Type NoSync
Usage Type Data
wMaxPacketSize 0x0040
bInterval 1
Interface Descriptor:
bInterfaceNumber 2
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 0x03
bInterfaceSubClass 0x00
bInterfaceProtocol 0x00
iInterface 0
Endpoint Descriptor:
bEndpointAddress 0x03 EP 3 Out
bmAttributes:
Transfer Type Interrupt
Synch Type NoSync
Usage Type Data
wMaxPacketSize 0x0040
bInterval 1
I note that all the methods for Device
require &mut
instead of &
. Is this needed? Can we consider those methods to be interior mutable and use a constant reference instead?
Motivation: I am trying to use Iterator::find()
to locate a device of interest, and the predicate function must take a constant reference as a parameter. I need to call device_descriptor()
inside the predicate but cannot without a mutable reference.
extern crate libusb;
fn check_device(device: &mut libusb::Device) -> bool {
let device_desc = device.device_descriptor().unwrap();
(device_desc.vendor_id() == 0xffff) && (device_desc.product_id() == 3)
}
fn main() {
let mut context = libusb::Context::new().unwrap();
let mut device = context.devices().unwrap().iter().find(check_device).unwrap(); // error: check_device must take immutable ref.
let device_desc = device.device_descriptor().unwrap();
println!("Bus {:03} Device {:03} ID {:04x}:{:04x}",
device.bus_number(),
device.address(),
device_desc.vendor_id(),
device_desc.product_id());
}
I can't find a way to hold a DeviceHandle
in a struct and pass it around. It has a lifetime that must be longer than the Context
object that created it. However, even when Boxing the Context and the DeviceHandle together, it's impossible to store a handle.
Did anyone get this to work? I need to store the handle because of how I have a transport-agnostic library built. It also uses the hid
crate where the Handle
type does not have a lifetime defined, but just documents that it cannot outlive the HidManager
type. So I can just manually drop the Handle before dropping the manager.
@dcuddeback I saw a comment where you assume all users will create the Context
in main and then just keep it around. Well, I'm not an end user, but a library implementer. The library connects to devices that support with WebUSB, HID and an HTTP bridge daemon. So the Context
is created inside the library code and it's impossible to create the context and have it outlive the interface client object that the library returns.
I keep getting "InvalidParam"
I have no idea what I am doing wrong here. I know a param is incorrect but witch one is it?
Part of my code:
let mut data: Vec<u8> = Vec::new();
handle.read_control(
request_type(Direction::Out, RequestType::Class, Recipient::Interface),
0x09,
0x0200,
0x0000,
data.as_mut_slice(),
Duration::from_secs(1)
).expect("Cant get data");
Info about the usb device I'm trying to talk with:
Frame 1: 36 bytes on wire (288 bits), 36 bytes captured (288 bits) on interface 0
USB URB
[Source: host]
[Destination: 6.1.0]
USBPcap pseudoheader length: 28
IRP ID: 0xffffe00029ceb500
IRP USBD_STATUS: USBD_STATUS_SUCCESS (0x00000000)
URB Function: URB_FUNCTION_CLASS_INTERFACE (0x001b)
IRP information: 0x00, Direction: FDO -> PDO
URB bus id: 6
Device address: 1
Endpoint: 0x00, Direction: OUT
0... .... = Direction: OUT (0)
.000 0000 = Endpoint value: 0
URB transfer type: URB_CONTROL (0x02)
Packet Data Length: 8
[Response in: 2]
Control transfer stage: Setup (0)
[bInterfaceClass: Unknown (0xffff)]
URB setup
bmRequestType: 0x21
0... .... = Direction: Host-to-device
.01. .... = Type: Class (0x01)
...0 0001 = Recipient: Interface (0x01)
bRequest: 9
wValue: 0x0200
wIndex: 0 (0x0000)
wLength: 64
I'd like to have a struct that contains an InterfaceHandle
objects so that I can use the bulk_transfer
method. I'm having trouble doing this because an InterfaceHandle
object contains a reference to a DeviceHandle
object, which contains a reference to a Context
object. I'd be fine having the Context
object be global, but I'd like to have the DeviceHandle
and InterfaceHandle
objects held in the same struct. But Rust has trouble with structs that contain references to objects within itself.
So what's the best approach for having a struct contain an InterfaceHandle
? I can see a few options:
Rc
and RefCell
as is suggested by reem in this postDeviceHandle
, and then use claim_interface
to get the InterfaceHandle
every time I need it.libusb-sys
crate directly, and just carry around the pointers.Here's an example of what I'm trying to do:
struct MyDevice<'a> {
dev_handle: libusb::DeviceHandle<'a>,
usb_interface: libusb::InterfaceHandle<'a>,
}
impl<'a> MyDevice<'a> {
fn open(usb_ctx: &'a mut libusb::Context) -> Result<Self, libusb::UsbError> {
let mut devices = try!(usb_ctx.devices());
let mut dev_ref = devices.iter().next().unwrap();
let mut dev_handle = try!(dev_ref.open());
let interface = try!(dev_handle.claim_interface(0));
Ok(MyDevice { dev_handle: dev_handle, usb_interface: interface })
}
}
This fails to compile, saying that dev_handle
does not live long enough.
rust msvc environment can't use pkg-config-sys crate. Is there any solutions?
I was trying out the read_device.rs
example but ran into a problem: when running the configure_endpoint
function, claim_interface
gave an Error::Access
when ran. I suspect this might be a problem of OS X, but I am currently stuck. Any help would be greatly appreciated!
Hi there,
This is the first and foremost library for interacting with libusb in Rust but it seems to be gathering dust. Are you still actively maintaining this at all?
afaict, rust-embedded/wg#40 has the latest developments for Rust USB support. if anyone else is looking for this or has more info, please mention it.
thanks
libusb version: libusb-1.0.21-2-x86_64
Linux Kernel: x86_64 Linux 4.13.11-1-ARCH
2006 Motherboard USB2.0 Compatible
Intel chipset
Fails finding device.
lsusb info:
Bus 001 Device 010: ID 045e:02e6 Microsoft Corp. Wireless XBox Controller Dongle
read_device error:
./target/debug/read_device 1118 742
could not find device 045e:02e6
It appears libusb-rs does not support the libusb async API. Any plans or thoughts on this?
I've used the async API from C++ before and am considering doing it from Rust.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.