Replaced get_device with get_device_filter, doc improvements, other improvements

This commit is contained in:
G2-Games 2024-02-02 00:12:05 -06:00
parent 0af8b86c25
commit 6ac7479879
5 changed files with 44 additions and 88 deletions

View file

@ -29,7 +29,6 @@ version = "0.3"
features = [ features = [
"Window", "Window",
"Navigator", "Navigator",
"console",
"Usb", "Usb",
"UsbDevice", "UsbDevice",
"UsbInterface", "UsbInterface",
@ -39,7 +38,6 @@ features = [
"UsbDeviceRequestOptions", "UsbDeviceRequestOptions",
"UsbInTransferResult", "UsbInTransferResult",
"UsbOutTransferResult", "UsbOutTransferResult",
"Storage"
] ]
# Non-wasm deps # Non-wasm deps

View file

@ -36,34 +36,7 @@ impl DeviceFilter {
} }
} }
pub async fn get_device(vendor_id: u16, product_id: u16) -> Result<UsbDevice, UsbError> { pub async fn get_device(device_filter: Vec<DeviceFilter>) -> Result<UsbDevice, UsbError> {
let devices = nusb::list_devices().unwrap();
let mut device_info = None;
for device in devices {
if device.vendor_id() == vendor_id && device.product_id() == product_id {
device_info = Some(device);
break;
}
}
let device_info = match device_info {
Some(dev) => dev,
None => return Err(UsbError::DeviceNotFound),
};
let device = match device_info.open() {
Ok(dev) => dev,
Err(_) => return Err(UsbError::CommunicationError),
};
Ok(UsbDevice {
device_info,
device,
})
}
pub async fn get_device_filter(device_filter: Vec<DeviceFilter>) -> Result<UsbDevice, UsbError> {
let devices = nusb::list_devices().unwrap(); let devices = nusb::list_devices().unwrap();
let mut device_info = None; let mut device_info = None;

View file

@ -19,6 +19,7 @@ pub struct UsbDevice {
#[wasm_bindgen] #[wasm_bindgen]
pub struct UsbInterface { pub struct UsbInterface {
device: WasmUsbDevice, device: WasmUsbDevice,
_number: u8,
} }
#[wasm_bindgen] #[wasm_bindgen]
@ -50,56 +51,7 @@ impl DeviceFilter {
} }
#[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(
let window = web_sys::window().unwrap();
let navigator = window.navigator();
let usb = navigator.usb();
let device_list: Array = JsFuture::from(Promise::resolve(&usb.get_devices()))
.await?
.into();
// Check if the device is already paired, if so, we don't need to request it again
for js_device in device_list {
let device: WasmUsbDevice = js_device.into();
if device.vendor_id() == vendor_id && device.product_id() == product_id {
let _open_promise = JsFuture::from(Promise::resolve(&device.open())).await?;
return Ok(UsbDevice { device });
}
}
let arr = Array::new();
let filter1 = js_sys::Object::new();
js_sys::Reflect::set(
&filter1,
&JsValue::from_str("vendorId"),
&JsValue::from(vendor_id),
)
.unwrap();
js_sys::Reflect::set(
&filter1,
&JsValue::from_str("productId"),
&JsValue::from(product_id),
)
.unwrap();
arr.push(&filter1);
let filters = JsValue::from(&arr);
let filters2 = UsbDeviceRequestOptions::new(&filters);
let device: WasmUsbDevice = JsFuture::from(Promise::resolve(&usb.request_device(&filters2)))
.await?
.into();
let _open_promise = JsFuture::from(Promise::resolve(&device.open())).await?;
Ok(UsbDevice { device })
}
#[wasm_bindgen]
pub async fn get_device_filter(
device_filter: Vec<DeviceFilter>, device_filter: Vec<DeviceFilter>,
) -> Result<UsbDevice, js_sys::Error> { ) -> Result<UsbDevice, js_sys::Error> {
let window = web_sys::window().unwrap(); let window = web_sys::window().unwrap();
@ -107,9 +59,11 @@ pub async fn get_device_filter(
let navigator = window.navigator(); let navigator = window.navigator();
let usb = navigator.usb(); let usb = navigator.usb();
let device_list: Array = JsFuture::from(Promise::resolve(&usb.get_devices())) let device_list: Array = match JsFuture::from(Promise::resolve(&usb.get_devices())).await {
.await? Ok(list) => list.into(),
.into(); Err(_) => Array::new(),
};
// Check if the device is already paired, if so, we don't need to request it again // Check if the device is already paired, if so, we don't need to request it again
for js_device in device_list { for js_device in device_list {
let device: WasmUsbDevice = js_device.into(); let device: WasmUsbDevice = js_device.into();
@ -142,6 +96,7 @@ pub async fn get_device_filter(
result result
}) })
{ {
let _open_promise = JsFuture::from(Promise::resolve(&device.open())).await?;
return Ok(UsbDevice { device }); return Ok(UsbDevice { device });
} }
} }
@ -222,13 +177,12 @@ impl Device for UsbDevice {
Ok(UsbInterface { Ok(UsbInterface {
device: self.device.clone(), device: self.device.clone(),
_number: number,
}) })
} }
async fn reset(&self) -> Result<(), UsbError> { async fn reset(&self) -> Result<(), UsbError> {
let promise = Promise::resolve(&self.device.reset()); let result = JsFuture::from(Promise::resolve(&self.device.reset())).await;
let result = JsFuture::from(promise).await;
match result { match result {
Ok(_) => Ok(()), Ok(_) => Ok(()),
@ -236,6 +190,17 @@ impl Device for UsbDevice {
} }
} }
/*
async fn forget(&self) -> Result<(), UsbError> {
let result = JsFuture::from(Promise::resolve(&self.device.forget())).await;
match result {
Ok(_) => Ok(()),
Err(_) => Err(UsbError::CommunicationError),
}
}
*/
async fn vendor_id(&self) -> u16 { async fn vendor_id(&self) -> u16 {
self.device.vendor_id() self.device.vendor_id()
} }

View file

@ -3,13 +3,24 @@
//! The idea is the user only has to write one way to access USB devices, which can be compiled //! The idea is the user only has to write one way to access USB devices, which can be compiled
//! to both WASM and native targets without any conditional compilation or configuration. //! to both WASM and native targets without any conditional compilation or configuration.
//! //!
//! For native device support, this library uses [nusb](https://docs.rs/nusb/latest/nusb/), a cross platform USB library written in Rust
//! and comparable to the very popular `libusb` C library. Web Assembly support is provided by [web-sys](https://docs.rs/web-sys/latest/web_sys/)
//! with the [Web USB API](https://developer.mozilla.org/en-US/docs/Web/API/WebUSB_API)
//!
//! When a [UsbInterface] is dropped, it is automatically released.
//!
//! ## Example: //! ## Example:
//! ```no_run //! ```no_run
//! # tokio_test::block_on(async { //! # tokio_test::block_on(async {
//! use cross_usb::usb::{Device, Interface, Recipient, ControlType, ControlIn}; //! use cross_usb::usb::{Device, Interface, Recipient, ControlType, ControlIn};
//! use cross_usb::device_filter;
//! //!
//! // Obtain a device using its VendorID and ProductID //! // Obtain a device using its VendorID and ProductID
//! let device = cross_usb::get_device(0x054c, 0x0186).await.expect("Failed to get device"); //! let filter = vec![
//! device_filter!{vendor_id: 0x054c, product_id: 0x00c9}
//! ];
//!
//! let device = cross_usb::get_device_filter(filter).await.expect("Failed to get device");
//! //!
//! // Obtain an interface of the device //! // Obtain an interface of the device
//! let interface = device.open_interface(0).await.expect("Failed to open interface"); //! let interface = device.open_interface(0).await.expect("Failed to open interface");

View file

@ -16,9 +16,18 @@ pub trait Device {
/// Open a specific interface of the device /// Open a specific interface of the device
async fn open_interface(&self, number: u8) -> Result<UsbInterface, UsbError>; async fn open_interface(&self, number: u8) -> Result<UsbInterface, UsbError>;
/// Reset the device, which causes it to no longer be usable /// Reset the device, which causes it to no longer be usable. You must
/// request a new device with [crate::get_device] or [crate::get_device_filter]
async fn reset(&self) -> Result<(), UsbError>; async fn reset(&self) -> Result<(), UsbError>;
/*
/// Remove the device from the paired devices list, causing it to no longer be usable.
/// You must request to reconnect using [crate::get_device] or [crate::get_device_filter]
///
/// **Note: Only does anything on WASM, on Native it simply resets the device**
async fn forget(&self) -> Result<(), UsbError>;
*/
/// 16 bit device Product ID /// 16 bit device Product ID
async fn product_id(&self) -> u16; async fn product_id(&self) -> u16;