Implemented bulk transfers, cleaned up code, added some docs

This commit is contained in:
G2-Games 2024-01-31 12:05:39 -06:00
parent 8b624b0136
commit 1a350800cf
5 changed files with 58 additions and 13 deletions

View file

@ -2,6 +2,17 @@
name = "cross_usb" name = "cross_usb"
version = "0.1.0" version = "0.1.0"
authors = ["G2-Games <ke0bhogsg@gmail.com>"] authors = ["G2-Games <ke0bhogsg@gmail.com>"]
repository = "https://github.com/G2-Games/cross-usb"
documentation = "https://docs.rs/cross_usb"
description = """
A a Rust USB library which works seamlessly across both native and WASM targets
"""
keywords = ["usb", "wasm", "web-usb"]
categories = ["wasm", "web-programming", "hardware-support"]
readme = "README.md"
license = "AGPL-3.0"
edition = "2021" edition = "2021"
[lib] [lib]
@ -28,6 +39,7 @@ features = [
"UsbControlTransferParameters", "UsbControlTransferParameters",
"UsbDeviceRequestOptions", "UsbDeviceRequestOptions",
"UsbInTransferResult", "UsbInTransferResult",
"UsbOutTransferResult",
"Storage" "Storage"
] ]

View file

@ -12,7 +12,6 @@ pub struct UsbInterface {
interface: nusb::Interface, interface: nusb::Interface,
} }
/// Gets a single device from the VendorID and ProductID
pub async fn get_device(vendor_id: u16, product_id: u16) -> Result<UsbDevice, Box<dyn Error>> { pub async fn get_device(vendor_id: u16, product_id: u16) -> Result<UsbDevice, Box<dyn Error>> {
let devices = nusb::list_devices().unwrap(); let devices = nusb::list_devices().unwrap();
@ -100,8 +99,8 @@ impl<'a> Interface<'a> for UsbInterface {
Ok(self.interface.bulk_in(endpoint, request_buffer).await.into_result()?) Ok(self.interface.bulk_in(endpoint, request_buffer).await.into_result()?)
} }
async fn bulk_out(&self, endpoint: u8, data: Vec<u8>) -> Result<usize, Box<dyn Error>> { async fn bulk_out(&self, endpoint: u8, data: &[u8]) -> Result<usize, Box<dyn Error>> {
match self.interface.bulk_out(endpoint, data).await.into_result() { match self.interface.bulk_out(endpoint, data.to_vec()).await.into_result() {
Ok(len) => Ok(len.actual_length()), Ok(len) => Ok(len.actual_length()),
Err(e) => Err(e.into()) Err(e) => Err(e.into())
} }

View file

@ -10,6 +10,7 @@ use web_sys::{
UsbInterface as WasmUsbInterface, UsbInterface as WasmUsbInterface,
UsbControlTransferParameters, UsbControlTransferParameters,
UsbInTransferResult, UsbInTransferResult,
UsbOutTransferResult,
UsbRecipient, UsbRecipient,
UsbRequestType, UsbRequestType,
UsbDeviceRequestOptions, UsbDeviceRequestOptions,
@ -30,7 +31,6 @@ pub struct UsbInterface {
device: WasmUsbDevice, device: WasmUsbDevice,
} }
/// Gets a single device from the VendorID and ProductID
#[wasm_bindgen] #[wasm_bindgen]
pub async fn get_device(vendor_id: u16, product_id: u16) -> Result<UsbDevice, js_sys::Error> { pub async fn get_device(vendor_id: u16, product_id: u16) -> Result<UsbDevice, js_sys::Error> {
let window = web_sys::window().unwrap(); let window = web_sys::window().unwrap();
@ -136,9 +136,8 @@ impl<'a> Interface<'a> for UsbInterface {
let length = data.length; let length = data.length;
let params: UsbControlTransferParameters = data.into(); let params: UsbControlTransferParameters = data.into();
let result = JsFuture::from(Promise::resolve( let promise = Promise::resolve(&self.device.control_transfer_in(&params, length));
&self.device.control_transfer_in(&params, length) let result = JsFuture::from(promise).await;
)).await;
let transfer_result: UsbInTransferResult = match result { let transfer_result: UsbInTransferResult = match result {
Ok(res) => res.into(), Ok(res) => res.into(),
@ -169,12 +168,40 @@ impl<'a> Interface<'a> for UsbInterface {
} }
} }
async fn bulk_in(&self, _endpoint: u8, _length: usize) -> Result<Vec<u8>, Box<dyn Error>> { async fn bulk_in(&self, endpoint: u8, length: usize) -> Result<Vec<u8>, Box<dyn Error>> {
todo!() let promise = Promise::resolve(&self.device.transfer_in(endpoint, length as u32));
let result = JsFuture::from(promise).await;
let transfer_result: UsbInTransferResult = match result {
Ok(res) => res.into(),
Err(err) => return Err(format!("Error {:?}", err).into()),
};
let data = match transfer_result.data() {
Some(res) => res.buffer(),
None => return Err("No data returned".into()),
};
let array = Uint8Array::new(&data);
Ok(array.to_vec())
} }
async fn bulk_out(&self, _endpoint: u8, _data: Vec<u8>) -> Result<usize, Box<dyn Error>> { async fn bulk_out(&self, endpoint: u8, data: &[u8]) -> Result<usize, Box<dyn Error>> {
todo!() let array = Uint8Array::from(data);
let array_obj = Object::try_from(&array).unwrap();
let promise = Promise::resolve(&self.device.transfer_out_with_buffer_source(endpoint, array_obj));
let result = JsFuture::from(promise).await;
let transfer_result: UsbOutTransferResult = match result {
Ok(res) => res.into(),
Err(err) => return Err(format!("Error {:?}", err).into()),
};
Ok(transfer_result.bytes_written() as usize)
} }
} }

View file

@ -7,3 +7,7 @@ pub mod context;
#[cfg(target_family = "wasm")] #[cfg(target_family = "wasm")]
#[path = "./backend/wasm.rs"] #[path = "./backend/wasm.rs"]
pub mod context; pub mod context;
/// Gets a single device from the VendorID and ProductID
#[doc(inline)]
pub use crate::context::get_device;

View file

@ -37,16 +37,19 @@ pub trait Device {
/// A specific interface of a USB device /// A specific interface of a USB device
pub trait Interface<'a> { pub trait Interface<'a> {
/// A USB control in transfer (device to host) /// A USB control in transfer (device to host)
/// Returns a [Result] with the bytes in a `Vec<u8>`
async fn control_in(&self, data: ControlIn) -> Result<Vec<u8>, Box<dyn Error>>; async fn control_in(&self, data: ControlIn) -> Result<Vec<u8>, Box<dyn Error>>;
/// A USB control out transfer (host to device) /// A USB control out transfer (host to device)
async fn control_out(&self, data: ControlOut<'a>) -> Result<(), Box<dyn Error>>; async fn control_out(&self, data: ControlOut<'a>) -> Result<(), Box<dyn Error>>;
/// A USB bulk in transfer (device to host) /// A USB bulk in transfer (device to host)
/// Returns a [Result] with the bytes in a `Vec<u8>`
async fn bulk_in(&self, endpoint: u8, length: usize) -> Result<Vec<u8>, Box<dyn Error>>; async fn bulk_in(&self, endpoint: u8, length: usize) -> Result<Vec<u8>, Box<dyn Error>>;
/// A USB bulk out transfer (host to device) /// A USB bulk out transfer (host to device).
async fn bulk_out(&self, endpoint: u8, data: Vec<u8>) -> Result<usize, Box<dyn Error>>; /// Returns a [Result] with the number of bytes transferred
async fn bulk_out(&self, endpoint: u8, data: &[u8]) -> Result<usize, Box<dyn Error>>;
async fn interrupt_in(&self, _endpoint: u8, _buf: Vec<u8>) { async fn interrupt_in(&self, _endpoint: u8, _buf: Vec<u8>) {
unimplemented!() unimplemented!()