-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use rusb (libusb) or nusb instead of JNI calls #1
Comments
See
[package]
name = "android-rusb-test"
version = "0.1.0"
edition = "2021"
publish = false
[dependencies]
log = "0.4"
android_logger = "0.14"
android-activity = { version = "0.6", features = ["native-activity"] }
android-usbser = { version = "0.1.1", features = ["unsafe-rusb"] }
[lib]
name = "android_rusb_test"
crate-type = ["cdylib"]
path = "android_rusb_test.rs"
[package.metadata.android]
package = "com.example.android_rusb_test"
build_targets = [ "aarch64-linux-android" ]
[package.metadata.android.sdk]
min_sdk_version = 16
target_sdk_version = 30
[[package.metadata.android.uses_feature]]
name = "android.hardware.usb.host"
required = true
use android_activity::{AndroidApp, MainEvent, PollEvent};
use android_usbser::usb;
#[no_mangle]
fn android_main(app: AndroidApp) {
// TODO: `println` or `eprintln` macro must be used prior to any direct `libusb` call,
// even if `android_logger` is preferred. Otherwise it `create_rusb_context()` will crash
// while calling `libusb`. It might be fixed by putting `println` inside this function.
//
// `adb logcat <app_name>:D '*:S'` is for macros from `log` backed by `android_logger`;
// `adb logcat RustStdoutStderr:D '*:S'` is for `println` or `eprintln`.
let mut permitted_device = None;
let mut on_destroy = false;
loop {
app.poll_events(
Some(std::time::Duration::from_secs(1)), // timeout
|event| match event {
PollEvent::Main(MainEvent::Resume { loader: _, .. }) => {
println!("Main Resume.");
let usb_devs = usb::list_devices().unwrap();
if let Some(dev) = usb_devs.into_iter().next() {
if !dev.has_permission().unwrap_or(false) {
let _ = dev.request_permission();
} else {
permitted_device.replace(dev);
}
}
}
PollEvent::Main(MainEvent::Destroy) => {
println!("Main Destroy.");
on_destroy = true;
}
_ => (),
},
);
if on_destroy {
return;
}
if let Some(dev) = permitted_device.take() {
println!("opening device {}", dev.path_name());
let conn = dev.open_device().unwrap();
println!("open_device() success.");
unsafe {
println!("before create_rusb_context().");
if let Ok(mut ctx) = usb::create_rusb_context() {
println!("create_rusb_context() success.");
match conn.create_rusb_connection(&mut ctx) {
Ok(_) => {
println!("Success!"); // desired
return; // exit on success
}
Err(e) => eprintln!("Error: {e}"),
}
}
}
}
}
} Log:
(Another problem: it calls |
Hmm you shouldn’t need root for wrap sys device. You should disable device scanning the libusb context. Otherwise I think even wrap sys device could trigger a scan (resulting in perms error and maybe also segfault)
Get Outlook for iOS<https://aka.ms/o0ukef>
…________________________________
From: wu bobo ***@***.***>
Sent: Thursday, November 7, 2024 4:43:52 AM
To: wuwbobo2021/android-usbser-rs ***@***.***>
Cc: Dhruv Gramopadhye ***@***.***>; Assign ***@***.***>
Subject: Re: [wuwbobo2021/android-usbser-rs] Use rusb (libusb) or nusb instead of JNI calls (Issue #1)
libusb_wrap_sys_device() currently fails on my devices (currently I'm not giving root permission to the test application).
See README.md for preparing the building environment. Test code:
Cargo.toml:
[package]
name = "android-rusb-test"
version = "0.1.0"
edition = "2021"
publish = false
[dependencies]
log = "0.4"
android_logger = "0.14"
android-activity = { version = "0.6", features = ["native-activity"] }
android-usbser = { version = "0.1.1", features = ["unsafe-rusb"] }
[lib]
name = "android_rusb_test"
crate-type = ["cdylib"]
path = "android_rusb_test.rs"
[package.metadata.android]
package = "com.example.android_rusb_test"
build_targets = [ "aarch64-linux-android" ]
[package.metadata.android.sdk]
min_sdk_version = 16
target_sdk_version = 30
[[package.metadata.android.uses_feature]]
name = "android.hardware.usb.host"
required = true
android_rusb_test.rs:
use android_activity::{AndroidApp, MainEvent, PollEvent};
use android_usbser::usb;
#[no_mangle]
fn android_main(app: AndroidApp) {
// TODO: `println` or `eprintln` macro must be used prior to any direct `libusb` call,
// even if `android_logger` is preferred. Otherwise it `create_rusb_context()` will crash
// while calling `libusb`. It might be fixed by putting `println` inside this function.
//
// `adb logcat <app_name>:D '*:S'` is for macros from `log` backed by `android_logger`;
// `adb logcat RustStdoutStderr:D '*:S'` is for `println` or `eprintln`.
let mut permitted_device = None;
let mut on_destroy = false;
loop {
app.poll_events(
Some(std::time::Duration::from_secs(1)), // timeout
|event| match event {
PollEvent::Main(MainEvent::Resume { loader: _, .. }) => {
println!("Main Resume.");
let usb_devs = usb::list_devices().unwrap();
if let Some(dev) = usb_devs.into_iter().next() {
if !dev.has_permission().unwrap_or(false) {
let _ = dev.request_permission();
} else {
permitted_device.replace(dev);
}
}
}
PollEvent::Main(MainEvent::Destroy) => {
println!("Main Destroy.");
on_destroy = true;
}
_ => (),
},
);
if on_destroy {
return;
}
if let Some(dev) = permitted_device.take() {
println!("opening device {}", dev.path_name());
let conn = dev.open_device().unwrap();
println!("open_device() success.");
unsafe {
println!("before create_rusb_context().");
if let Ok(mut ctx) = usb::create_rusb_context() {
println!("create_rusb_context() success.");
match conn.create_rusb_connection(&mut ctx) {
Ok(_) => {
println!("Success!"); // desired
return; // exit on success
}
Err(e) => eprintln!("Error: {e}"),
}
}
}
}
}
}
Log:
adb logcat RustStdoutStderr:D '*:S'
--------- beginning of crash
--------- beginning of system
--------- beginning of main
11-07 19:37:53.637 21286 21299 I RustStdoutStderr: Main Resume.
11-07 19:37:55.283 21286 21299 I RustStdoutStderr: Main Resume.
11-07 19:37:56.196 21286 21299 I RustStdoutStderr: Main Resume.
11-07 19:37:56.202 21286 21299 I RustStdoutStderr: opening device /dev/bus/usb/001/009
11-07 19:37:56.206 21286 21299 I RustStdoutStderr: open_device() success.
11-07 19:37:56.206 21286 21299 I RustStdoutStderr: before create_rusb_context().
11-07 19:37:56.206 21286 21299 I RustStdoutStderr: create_rusb_context() success.
11-07 19:37:56.206 21286 21299 I RustStdoutStderr: before libusb_wrap_sys_device(). fd: 0x0000001c
11-07 19:37:56.206 21286 21299 I RustStdoutStderr: [timestamp] [threadID] facility level [function call] <message>
11-07 19:37:56.206 21286 21299 I RustStdoutStderr: --------------------------------------------------------------------------------
11-07 19:37:56.206 21286 21299 I RustStdoutStderr: [ 0.000517] [00005334] libusb: debug [libusb_wrap_sys_device] wrap_sys_device 0x7f940c6eec
11-07 19:37:56.206 21286 21299 I RustStdoutStderr: [ 0.000552] [00005334] libusb: debug [linux_get_device_address] getting address for device: (null) detached: 1
11-07 19:37:56.206 21286 21299 I RustStdoutStderr: [ 0.000563] [00005334] libusb: error [op_wrap_sys_device] connectinfo failed, errno=9
11-07 19:37:56.206 21286 21299 I RustStdoutStderr: [ 0.000571] [00005334] libusb: debug [libusb_wrap_sys_device] wrap_sys_device 0x7f940c6eec returns -1
11-07 19:37:56.206 21286 21299 I RustStdoutStderr: Error: Input/Output Error
11-07 19:37:56.206 21286 21299 I RustStdoutStderr: [ 0.000586] [00005334] libusb: debug [libusb_exit]
11-07 19:37:56.206 21286 21299 I RustStdoutStderr: [ 0.000594] [00005334] libusb: debug [usbi_remove_event_source] remove fd 31
11-07 19:37:56.206 21286 21299 I RustStdoutStderr: [ 0.000608] [00005334] libusb: debug [usbi_remove_event_source] remove fd 30
(Another problem: it calls dev.request_permission() for double times before dev.has_permission() returns true.)
—
Reply to this email directly, view it on GitHub<#1 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/ACTRHOD6LYIAXFHOMBIBH4TZ7NOARAVCNFSM6AAAAABRHXRGY2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDINRSGE2DKNBZGU>.
You are receiving this because you were assigned.Message ID: ***@***.***>
|
I think I just flashed my STM32F103 Blue Pill with a USB CDC maximum speed test (data transfer from device to host), On my PC the speed reaches 960KB/s with the Linux CDC-ACM driver, 950KB/s with libusb (kernel driver detached), but it's 445KB/s with my Android library. My current use case requires at least 530KB/s. All of them passed my integrity check with 4MB of data (loops of 256 bytes, 0x00~0xfe incremental byte values, frame number in the last byte). Well, while if let Some(dev) = permitted_device.take() {
println!("opening device {}", dev.path_name());
let conn = dev.open_device().unwrap();
println!("open_device() success.");
let nusb_dev = unsafe {
use std::os::fd::*;
let raw_fd = conn.get_raw_fd().unwrap();
let owned_fd = OwnedFd::from_raw_fd(raw_fd as RawFd);
drop(conn);
nusb::Device::from_fd(owned_fd)
};
if let Err(e) = nusb_dev {
println!("{:?}", e);
return;
}
println!("Success!");
let nusb_dev = nusb_dev.unwrap();
for conf in nusb_dev.configurations() {
println!("{:#?}", conf);
}
} |
Have you opened the |
I have, but not in the context of your serial port codebase. Honestly nusb is nice since it eliminates the native dependency. One my projects has switched over the nusb already (from rusb), so i say go for it and ditch rusb |
I have published the new version that uses Would you like to check out the unsafe operations for avoiding Besides, if you'd like to point out my mistake in PS: you will become an owner of this crate if you want to. |
In the TODO list README, you have the following item. I just wanted to make an issue so that we could track it
This will help us with performance while actively communicating with the device.
I've written several USB drivers for Android, including native drivers. libusb does work on an unrooted android, but it does not have enough permissions to scan for devices. Instead, we must open a device through android's APIs (get permissions too), then pass the file descriptor down into native code. This strategy is sound for rusb (and I'm sure also nusb will work too).
Anyhow I'm happy to help out with this implementation. Can you assign this issue to me? Thanks for you work on this repo :)
The text was updated successfully, but these errors were encountered: