Skip to content

Commit

Permalink
First try rusb-async
Browse files Browse the repository at this point in the history
Co-authored-by: Ryan Butler <[email protected]>
Co-authored-by: Kevin Mehall <[email protected]>
  • Loading branch information
3 people committed Sep 4, 2022
1 parent bbd4d67 commit 4d955e4
Show file tree
Hide file tree
Showing 7 changed files with 667 additions and 1 deletion.
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 <[email protected]>",
"Ryan Butler <[email protected]>",
"Kevin Mehall <[email protected]>"
]

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

0 comments on commit 4d955e4

Please sign in to comment.