Skip to content
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

First try rusb-async #143

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ travis-ci = { repository = "a1ien/rusb" }
vendored = [ "libusb1-sys/vendored" ]

[workspace]
members = ["libusb1-sys"]
members = [ "libusb1-sys", "rusb-async" ]

[dependencies]
libusb1-sys = { path = "libusb1-sys", version = "0.6.0" }
Expand Down
22 changes: 22 additions & 0 deletions rusb-async/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[package]
name = "rusb-async"
version = "0.0.1-alpha"
edition = "2021"
authors = [
"Ilya Averyanov <a1ien.n3t@gmail.com>",
"Ryan Butler <thebutlah@gmail.com>",
"Kevin Mehall <km@kevinmehall.net>"
]

description = "Rust library for accessing USB devices."
license = "MIT"
homepage = "https://github.com/a1ien/rusb"
repository = "https://github.com/a1ien/rusb.git"
keywords = ["usb", "libusb", "async"]

[features]
vendored = [ "rusb/vendored" ]

[dependencies]
rusb = { path = "..", version = "0.9.1" }
libc = "0.2"
54 changes: 54 additions & 0 deletions rusb-async/examples/read_async.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use rusb_async::TransferPool;

use rusb::{Context, UsbContext};

use std::str::FromStr;
use std::sync::Arc;
use std::time::Duration;

fn convert_argument(input: &str) -> u16 {
if input.starts_with("0x") {
return u16::from_str_radix(input.trim_start_matches("0x"), 16).unwrap();
}
u16::from_str_radix(input, 10)
.expect("Invalid input, be sure to add `0x` for hexadecimal values.")
}

fn main() {
let args: Vec<String> = std::env::args().collect();

if args.len() < 4 {
eprintln!("Usage: read_async <base-10/0xbase-16> <base-10/0xbase-16> <endpoint>");
return;
}

let vid = convert_argument(args[1].as_ref());
let pid = convert_argument(args[2].as_ref());
let endpoint: u8 = FromStr::from_str(args[3].as_ref()).unwrap();

let ctx = Context::new().expect("Could not initialize libusb");
let device = Arc::new(
ctx.open_device_with_vid_pid(vid, pid)
.expect("Could not find device"),
);

const NUM_TRANSFERS: usize = 32;
const BUF_SIZE: usize = 64;

let mut async_pool = TransferPool::new(device).expect("Failed to create async pool!");

while async_pool.pending() < NUM_TRANSFERS {
async_pool
.submit_bulk(endpoint, Vec::with_capacity(BUF_SIZE))
.expect("Failed to submit transfer");
}

let timeout = Duration::from_secs(10);
loop {
let data = async_pool.poll(timeout).expect("Transfer failed");
println!("Got data: {} {:?}", data.len(), data);
async_pool
.submit_bulk(endpoint, data)
.expect("Failed to resubmit transfer");
}
}
73 changes: 73 additions & 0 deletions rusb-async/examples/read_write_async.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use rusb_async::TransferPool;

use rusb::{Context, UsbContext};

use std::time::Duration;
use std::{sync::Arc, thread};

fn main() {
let args: Vec<String> = std::env::args().collect();

if args.len() < 5 {
eprintln!("Usage: read_write_async <vendor-id> <product-id> <out-endpoint> <in-endpoint> (all numbers hex)");
return;
}

let vid = u16::from_str_radix(args[1].as_ref(), 16).unwrap();
let pid = u16::from_str_radix(args[2].as_ref(), 16).unwrap();
let out_endpoint = u8::from_str_radix(args[3].as_ref(), 16).unwrap();
let in_endpoint = u8::from_str_radix(args[4].as_ref(), 16).unwrap();

let ctx = Context::new().expect("Could not initialize libusb");
let device = Arc::new(
ctx.open_device_with_vid_pid(vid, pid)
.expect("Could not find device"),
);

thread::spawn({
let device = device.clone();
move || {
let mut write_pool = TransferPool::new(device).expect("Failed to create async pool!");

let mut i = 0u8;

loop {
let mut buf = if write_pool.pending() < 8 {
Vec::with_capacity(64)
} else {
write_pool
.poll(Duration::from_secs(5))
.expect("Failed to poll OUT transfer")
};

buf.clear();
buf.push(i);
buf.resize(64, 0x2);

write_pool
.submit_bulk(out_endpoint, buf)
.expect("Failed to submit OUT transfer");
println!("Wrote {}", i);
i = i.wrapping_add(1);
}
}
});

let mut read_pool = TransferPool::new(device).expect("Failed to create async pool!");

while read_pool.pending() < 8 {
read_pool
.submit_bulk(in_endpoint, Vec::with_capacity(1024))
.expect("Failed to submit IN transfer");
}

loop {
let data = read_pool
.poll(Duration::from_secs(10))
.expect("Failed to poll IN transfer");
println!("Got data: {} {:?}", data.len(), data[0]);
read_pool
.submit_bulk(in_endpoint, data)
.expect("Failed to resubmit IN transfer");
}
}
48 changes: 48 additions & 0 deletions rusb-async/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use std::{fmt, result};

/// A result of a function that may return a `Error`.
pub type Result<T> = result::Result<T, Error>;

#[derive(Debug)]
pub enum Error {
/// No transfers pending
NoTransfersPending,

/// Poll timed out
PollTimeout,

/// Transfer is stalled
Stall,

/// Device was disconnected
Disconnected,

/// Device sent more data than expected
Overflow,

/// Other Error
Other(&'static str),

/// Error code on other failure
Errno(&'static str, i32),

/// Transfer was cancelled
Cancelled,
}

impl fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter) -> std::result::Result<(), fmt::Error> {
match self {
Error::NoTransfersPending => fmt.write_str("No transfers pending"),
Error::PollTimeout => fmt.write_str("Poll timed out"),
Error::Stall => fmt.write_str("Transfer is stalled"),
Error::Disconnected => fmt.write_str("Device was disconnected"),
Error::Overflow => fmt.write_str("Device sent more data than expected"),
Error::Other(s) => write!(fmt, "Other Error: {s}"),
Error::Errno(s, n) => write!(fmt, "{s} ERRNO: {n}"),
Error::Cancelled => fmt.write_str("Transfer was cancelled"),
}
}
}

impl std::error::Error for Error {}
Loading