-
Notifications
You must be signed in to change notification settings - Fork 85
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: Ryan Butler <[email protected]> Co-authored-by: Kevin Mehall <[email protected]>
- Loading branch information
1 parent
bbd4d67
commit 4d955e4
Showing
7 changed files
with
667 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 {} |
Oops, something went wrong.