refactor: remove rusb backend, keep only nusb
- Delete lib/examples/ (unused upstream leftovers) - Remove rusb crate dependency - Define local Direction enum in consts.rs (Out=0x00, In=0x80) - Remove RusbUsbHostInterfaceHandler and RusbUsbHostDeviceHandler - Replace rusb device enumeration with nusb in new_from_host* - Update flake.nix cargoHash and Cargo.lock Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
80083fdf93
commit
e0aa6bfbf6
11 changed files with 16 additions and 546 deletions
58
Cargo.lock
generated
58
Cargo.lock
generated
|
|
@ -103,16 +103,6 @@ version = "1.11.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a0dd1ca384932ff3641c8718a02769f1698e7563dc6974ffd03346116310423"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
|
|
@ -220,12 +210,6 @@ dependencies = [
|
|||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.32"
|
||||
|
|
@ -366,18 +350,6 @@ version = "0.2.183"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d"
|
||||
|
||||
[[package]]
|
||||
name = "libusb1-sys"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da050ade7ac4ff1ba5379af847a10a10a8e284181e060105bf8d86960ce9ce0f"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.12.1"
|
||||
|
|
@ -525,12 +497,6 @@ version = "0.2.17"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic"
|
||||
version = "1.13.1"
|
||||
|
|
@ -602,17 +568,6 @@ version = "0.8.10"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
|
||||
|
||||
[[package]]
|
||||
name = "rusb"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab9f9ff05b63a786553a4c02943b74b34a988448671001e9a27e2f0565cc05a4"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"libusb1-sys",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "1.1.4"
|
||||
|
|
@ -662,12 +617,6 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.4.8"
|
||||
|
|
@ -787,7 +736,6 @@ dependencies = [
|
|||
"num-derive",
|
||||
"num-traits",
|
||||
"nusb",
|
||||
"rusb",
|
||||
"serde",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
|
|
@ -812,12 +760,6 @@ version = "0.2.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||
|
||||
[[package]]
|
||||
name = "vsock"
|
||||
version = "0.5.3"
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
src = self;
|
||||
|
||||
cargoHash = "sha256-ol61Q+2IYDZ4ZvJiLYJdfqaN23thuZ1QHDOSvNXHhvY=";
|
||||
cargoHash = "sha256-i2dRJ7n7J9K2PfjEUnIPS9pRXs61WUYYXAfJUmFxt/M=";
|
||||
|
||||
inherit nativeBuildInputs buildInputs;
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ tokio = { version = "1.22.0", features = ["rt", "net", "io-util", "sync", "time"
|
|||
log = "0.4.17"
|
||||
num-traits = "0.2.15"
|
||||
num-derive = "0.4.2"
|
||||
rusb = "0.9.3"
|
||||
serde = { version = "1.0", features = ["derive"], optional = true }
|
||||
nusb = { git = "https://git.dsg.is/dsg/nusb.git", rev = "c1380673" }
|
||||
tokio-util = { version = "0.7", features = ["rt"] }
|
||||
|
|
@ -23,4 +22,4 @@ env_logger = "0.11.7"
|
|||
|
||||
[features]
|
||||
default = []
|
||||
serde = ["dep:serde", "rusb/serde"]
|
||||
serde = ["dep:serde"]
|
||||
|
|
|
|||
|
|
@ -1,32 +0,0 @@
|
|||
use log::*;
|
||||
use std::net::*;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
env_logger::init();
|
||||
let handler = Arc::new(usbip_rs::cdc::UsbCdcAcmHandler::new());
|
||||
let server = Arc::new(usbip_rs::UsbIpServer::new_simulated(vec![
|
||||
usbip_rs::UsbDevice::new(0)
|
||||
.expect("create device")
|
||||
.with_interface(
|
||||
usbip_rs::ClassCode::CDC as u8,
|
||||
usbip_rs::cdc::CDC_ACM_SUBCLASS,
|
||||
0x00,
|
||||
Some("Test CDC ACM"),
|
||||
usbip_rs::cdc::UsbCdcAcmHandler::endpoints(),
|
||||
handler.clone() as Arc<dyn usbip_rs::UsbInterfaceHandler>,
|
||||
)
|
||||
.expect("add interface"),
|
||||
]));
|
||||
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 3240);
|
||||
tokio::spawn(usbip_rs::server(addr, server));
|
||||
|
||||
loop {
|
||||
// sleep 1s
|
||||
tokio::time::sleep(Duration::new(1, 0)).await;
|
||||
handler.tx_buffer.lock().unwrap().push(b'a');
|
||||
info!("Simulate a char input");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
use log::*;
|
||||
use std::net::*;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
env_logger::init();
|
||||
let handler = Arc::new(usbip_rs::hid::UsbHidKeyboardHandler::new_keyboard());
|
||||
let server = Arc::new(usbip_rs::UsbIpServer::new_simulated(vec![
|
||||
usbip_rs::UsbDevice::new(0)
|
||||
.expect("create device")
|
||||
.with_interface(
|
||||
usbip_rs::ClassCode::HID as u8,
|
||||
0x00,
|
||||
0x00,
|
||||
Some("Test HID"),
|
||||
vec![usbip_rs::UsbEndpoint {
|
||||
address: 0x81, // IN
|
||||
attributes: 0x03, // Interrupt
|
||||
max_packet_size: 0x08, // 8 bytes
|
||||
interval: 10,
|
||||
..Default::default()
|
||||
}],
|
||||
handler.clone() as Arc<dyn usbip_rs::UsbInterfaceHandler>,
|
||||
)
|
||||
.expect("add interface"),
|
||||
]));
|
||||
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 3240);
|
||||
tokio::spawn(usbip_rs::server(addr, server));
|
||||
|
||||
loop {
|
||||
// sleep 1s
|
||||
tokio::time::sleep(Duration::new(1, 0)).await;
|
||||
match usbip_rs::hid::UsbHidKeyboardReport::from_ascii(b'1') {
|
||||
Ok(report) => {
|
||||
handler.pending_key_events.lock().unwrap().push_back(report);
|
||||
info!("Simulate a key event");
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Failed to create key report: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
use std::net::*;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
env_logger::init();
|
||||
let server = Arc::new(usbip_rs::UsbIpServer::new_from_host());
|
||||
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 3240);
|
||||
tokio::spawn(usbip_rs::server(addr, server));
|
||||
|
||||
loop {
|
||||
// sleep 1s
|
||||
tokio::time::sleep(Duration::new(1, 0)).await;
|
||||
}
|
||||
}
|
||||
|
|
@ -52,9 +52,13 @@ pub enum EndpointAttributes {
|
|||
Interrupt,
|
||||
}
|
||||
|
||||
/// USB endpoint direction: IN or OUT
|
||||
/// Already exists in rusb crate
|
||||
pub use rusb::Direction;
|
||||
/// USB endpoint direction (bit 7 of endpoint address)
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub enum Direction {
|
||||
Out = 0x00,
|
||||
In = 0x80,
|
||||
}
|
||||
|
||||
/// Emulated max packet size of EP0
|
||||
pub const EP0_MAX_PACKET_SIZE: u16 = 64;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
use super::*;
|
||||
use rusb::Version as rusbVersion;
|
||||
|
||||
#[derive(Clone, Default, Debug)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct Version {
|
||||
|
|
@ -9,22 +7,6 @@ pub struct Version {
|
|||
pub patch: u8,
|
||||
}
|
||||
|
||||
impl From<rusbVersion> for Version {
|
||||
fn from(value: rusbVersion) -> Self {
|
||||
Self {
|
||||
major: value.major(),
|
||||
minor: value.minor(),
|
||||
patch: value.sub_minor(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Version> for rusbVersion {
|
||||
fn from(val: Version) -> Self {
|
||||
rusbVersion(val.major, val.minor, val.patch)
|
||||
}
|
||||
}
|
||||
|
||||
/// bcdDevice
|
||||
impl From<u16> for Version {
|
||||
fn from(value: u16) -> Self {
|
||||
|
|
|
|||
174
lib/src/host.rs
174
lib/src/host.rs
|
|
@ -17,180 +17,6 @@ pub fn nusb_speed_to_linux(speed: nusb::Speed) -> u32 {
|
|||
}
|
||||
}
|
||||
|
||||
/// A handler to pass requests to interface of a rusb USB device of the host
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct RusbUsbHostInterfaceHandler {
|
||||
handle: Arc<Mutex<DeviceHandle<GlobalContext>>>,
|
||||
}
|
||||
|
||||
impl RusbUsbHostInterfaceHandler {
|
||||
pub fn new(handle: Arc<Mutex<DeviceHandle<GlobalContext>>>) -> Self {
|
||||
Self { handle }
|
||||
}
|
||||
}
|
||||
|
||||
impl UsbInterfaceHandler for RusbUsbHostInterfaceHandler {
|
||||
fn handle_urb(
|
||||
&self,
|
||||
_interface: &UsbInterface,
|
||||
request: UrbRequest,
|
||||
) -> Result<UrbResponse> {
|
||||
let ep = request.ep.clone();
|
||||
let transfer_buffer_length = request.transfer_buffer_length;
|
||||
let setup = request.setup;
|
||||
let req = &request.data;
|
||||
debug!("To host device: ep={ep:?} setup={setup:?} req={req:?}",);
|
||||
let mut buffer = vec![0u8; transfer_buffer_length as usize];
|
||||
let timeout = std::time::Duration::new(1, 0);
|
||||
let handle = self.handle.lock().unwrap_or_else(|e| e.into_inner());
|
||||
if ep.transfer_type() == Some(EndpointAttributes::Control) {
|
||||
// control
|
||||
if let Direction::In = ep.direction() {
|
||||
// control in
|
||||
if let Ok(len) = handle.read_control(
|
||||
setup.request_type,
|
||||
setup.request,
|
||||
setup.value,
|
||||
setup.index,
|
||||
&mut buffer,
|
||||
timeout,
|
||||
) {
|
||||
return Ok(UrbResponse { data: Vec::from(&buffer[..len]), ..Default::default() });
|
||||
}
|
||||
} else {
|
||||
// control out
|
||||
handle
|
||||
.write_control(
|
||||
setup.request_type,
|
||||
setup.request,
|
||||
setup.value,
|
||||
setup.index,
|
||||
req,
|
||||
timeout,
|
||||
)
|
||||
.map_err(|e| {
|
||||
std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
format!("USB control OUT failed: {e}"),
|
||||
)
|
||||
})?;
|
||||
}
|
||||
} else if ep.transfer_type() == Some(EndpointAttributes::Interrupt) {
|
||||
// interrupt
|
||||
if let Direction::In = ep.direction() {
|
||||
// interrupt in
|
||||
if let Ok(len) = handle.read_interrupt(ep.address, &mut buffer, timeout) {
|
||||
info!("intr in {:?}", &buffer[..len]);
|
||||
return Ok(UrbResponse { data: Vec::from(&buffer[..len]), ..Default::default() });
|
||||
}
|
||||
} else {
|
||||
// interrupt out
|
||||
handle
|
||||
.write_interrupt(ep.address, req, timeout)
|
||||
.map_err(|e| {
|
||||
std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
format!("USB interrupt OUT failed: {e}"),
|
||||
)
|
||||
})?;
|
||||
}
|
||||
} else if ep.transfer_type() == Some(EndpointAttributes::Bulk) {
|
||||
// bulk
|
||||
if let Direction::In = ep.direction() {
|
||||
// bulk in
|
||||
if let Ok(len) = handle.read_bulk(ep.address, &mut buffer, timeout) {
|
||||
return Ok(UrbResponse { data: Vec::from(&buffer[..len]), ..Default::default() });
|
||||
}
|
||||
} else {
|
||||
// bulk out
|
||||
handle.write_bulk(ep.address, req, timeout).map_err(|e| {
|
||||
std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
format!("USB bulk OUT failed: {e}"),
|
||||
)
|
||||
})?;
|
||||
}
|
||||
} else if ep.transfer_type() == Some(EndpointAttributes::Isochronous) {
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Unsupported,
|
||||
"isochronous transfers not supported on rusb handler",
|
||||
));
|
||||
}
|
||||
Ok(UrbResponse::default())
|
||||
}
|
||||
|
||||
fn get_class_specific_descriptor(&self) -> Vec<u8> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// A handler to pass requests to device of a rusb USB device of the host
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct RusbUsbHostDeviceHandler {
|
||||
handle: Arc<Mutex<DeviceHandle<GlobalContext>>>,
|
||||
}
|
||||
|
||||
impl RusbUsbHostDeviceHandler {
|
||||
pub fn new(handle: Arc<Mutex<DeviceHandle<GlobalContext>>>) -> Self {
|
||||
Self { handle }
|
||||
}
|
||||
}
|
||||
|
||||
impl UsbDeviceHandler for RusbUsbHostDeviceHandler {
|
||||
fn handle_urb(
|
||||
&mut self,
|
||||
request: UrbRequest,
|
||||
) -> Result<UrbResponse> {
|
||||
let transfer_buffer_length = request.transfer_buffer_length;
|
||||
let setup = request.setup;
|
||||
let req = &request.data;
|
||||
debug!("To host device: setup={setup:?} req={req:?}");
|
||||
let mut buffer = vec![0u8; transfer_buffer_length as usize];
|
||||
let timeout = std::time::Duration::new(1, 0);
|
||||
let handle = self.handle.lock().unwrap_or_else(|e| e.into_inner());
|
||||
// control
|
||||
if setup.request_type & 0x80 == 0 {
|
||||
// control out
|
||||
handle
|
||||
.write_control(
|
||||
setup.request_type,
|
||||
setup.request,
|
||||
setup.value,
|
||||
setup.index,
|
||||
req,
|
||||
timeout,
|
||||
)
|
||||
.map_err(|e| {
|
||||
std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
format!("USB control OUT failed: {e}"),
|
||||
)
|
||||
})?;
|
||||
} else {
|
||||
// control in
|
||||
if let Ok(len) = handle.read_control(
|
||||
setup.request_type,
|
||||
setup.request,
|
||||
setup.value,
|
||||
setup.index,
|
||||
&mut buffer,
|
||||
timeout,
|
||||
) {
|
||||
return Ok(UrbResponse { data: Vec::from(&buffer[..len]), ..Default::default() });
|
||||
}
|
||||
}
|
||||
Ok(UrbResponse::default())
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// A handler to pass requests to interface of a nusb USB device of the host
|
||||
#[derive(Clone)]
|
||||
pub struct NusbUsbHostInterfaceHandler {
|
||||
|
|
|
|||
202
lib/src/lib.rs
202
lib/src/lib.rs
|
|
@ -4,7 +4,6 @@ use log::*;
|
|||
use num_derive::FromPrimitive;
|
||||
use num_traits::FromPrimitive;
|
||||
use nusb::MaybeFuture;
|
||||
use rusb::*;
|
||||
use std::any::Any;
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use std::io::{ErrorKind, Result};
|
||||
|
|
@ -187,210 +186,21 @@ impl UsbIpServer {
|
|||
devices
|
||||
}
|
||||
|
||||
/// Create a [UsbIpServer] with Vec<[rusb::DeviceHandle]> for sharing host devices
|
||||
pub fn with_rusb_device_handles(
|
||||
device_handles: Vec<DeviceHandle<GlobalContext>>,
|
||||
) -> Vec<UsbDevice> {
|
||||
let mut devices = vec![];
|
||||
for open_device in device_handles {
|
||||
let dev = open_device.device();
|
||||
let desc = match dev.device_descriptor() {
|
||||
Ok(desc) => desc,
|
||||
Err(err) => {
|
||||
warn!(
|
||||
"Impossible to get device descriptor for {dev:?}: {err}, ignoring device",
|
||||
);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let cfg = match dev.active_config_descriptor() {
|
||||
Ok(desc) => desc,
|
||||
Err(err) => {
|
||||
warn!(
|
||||
"Impossible to get config descriptor for {dev:?}: {err}, ignoring device",
|
||||
);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let handle = Arc::new(Mutex::new(open_device));
|
||||
let mut interface_states = vec![];
|
||||
handle
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_auto_detach_kernel_driver(true)
|
||||
.ok();
|
||||
for intf in cfg.interfaces() {
|
||||
// ignore alternate settings
|
||||
let intf_desc = intf.descriptors().next().unwrap();
|
||||
handle
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_auto_detach_kernel_driver(true)
|
||||
.ok();
|
||||
let mut endpoints = vec![];
|
||||
|
||||
for ep_desc in intf_desc.endpoint_descriptors() {
|
||||
endpoints.push(UsbEndpoint {
|
||||
address: ep_desc.address(),
|
||||
attributes: ep_desc.transfer_type() as u8,
|
||||
max_packet_size: ep_desc.max_packet_size(),
|
||||
interval: ep_desc.interval(),
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
|
||||
let handler: Arc<dyn UsbInterfaceHandler> = Arc::new(
|
||||
RusbUsbHostInterfaceHandler::new(handle.clone()),
|
||||
);
|
||||
interface_states.push(InterfaceState::new(UsbInterface {
|
||||
interface_class: intf_desc.class_code(),
|
||||
interface_subclass: intf_desc.sub_class_code(),
|
||||
interface_protocol: intf_desc.protocol_code(),
|
||||
endpoints,
|
||||
string_interface: intf_desc.description_string_index().unwrap_or(0),
|
||||
class_specific_descriptor: Vec::from(intf_desc.extra()),
|
||||
handler,
|
||||
}));
|
||||
}
|
||||
let mut device = UsbDevice {
|
||||
path: format!(
|
||||
"/sys/bus/{}/{}/{}",
|
||||
dev.bus_number(),
|
||||
dev.address(),
|
||||
dev.port_number()
|
||||
),
|
||||
bus_id: format!(
|
||||
"{}-{}-{}",
|
||||
dev.bus_number(),
|
||||
dev.address(),
|
||||
dev.port_number()
|
||||
),
|
||||
bus_num: dev.bus_number() as u32,
|
||||
dev_num: dev.port_number() as u32,
|
||||
speed: dev.speed() as u32,
|
||||
vendor_id: desc.vendor_id(),
|
||||
product_id: desc.product_id(),
|
||||
device_class: desc.class_code(),
|
||||
device_subclass: desc.sub_class_code(),
|
||||
device_protocol: desc.protocol_code(),
|
||||
device_bcd: desc.device_version().into(),
|
||||
configuration_value: cfg.number(),
|
||||
num_configurations: desc.num_configurations(),
|
||||
ep0_in: UsbEndpoint {
|
||||
address: 0x80,
|
||||
attributes: EndpointAttributes::Control as u8,
|
||||
max_packet_size: desc.max_packet_size() as u16,
|
||||
..Default::default()
|
||||
},
|
||||
ep0_out: UsbEndpoint {
|
||||
address: 0x00,
|
||||
attributes: EndpointAttributes::Control as u8,
|
||||
max_packet_size: desc.max_packet_size() as u16,
|
||||
..Default::default()
|
||||
},
|
||||
interface_states,
|
||||
device_handler: Some(Arc::new(Mutex::new(Box::new(
|
||||
RusbUsbHostDeviceHandler::new(handle.clone()),
|
||||
)))),
|
||||
usb_version: desc.usb_version().into(),
|
||||
..UsbDevice::default()
|
||||
};
|
||||
|
||||
// set strings
|
||||
if let Some(index) = desc.manufacturer_string_index() {
|
||||
match handle
|
||||
.lock()
|
||||
.unwrap()
|
||||
.read_string_descriptor_ascii(index)
|
||||
{
|
||||
Ok(s) => match device.new_string(&s) {
|
||||
Ok(idx) => device.string_manufacturer = idx,
|
||||
Err(err) => {
|
||||
warn!("Failed to set manufacturer string: {err}");
|
||||
continue;
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("Failed to read manufacturer string: {err}");
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(index) = desc.product_string_index() {
|
||||
match handle
|
||||
.lock()
|
||||
.unwrap()
|
||||
.read_string_descriptor_ascii(index)
|
||||
{
|
||||
Ok(s) => match device.new_string(&s) {
|
||||
Ok(idx) => device.string_product = idx,
|
||||
Err(err) => {
|
||||
warn!("Failed to set product string: {err}");
|
||||
continue;
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("Failed to read product string: {err}");
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(index) = desc.serial_number_string_index() {
|
||||
match handle
|
||||
.lock()
|
||||
.unwrap()
|
||||
.read_string_descriptor_ascii(index)
|
||||
{
|
||||
Ok(s) => match device.new_string(&s) {
|
||||
Ok(idx) => device.string_serial = idx,
|
||||
Err(err) => {
|
||||
warn!("Failed to set serial string: {err}");
|
||||
continue;
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("Failed to read serial string: {err}");
|
||||
}
|
||||
}
|
||||
}
|
||||
devices.push(device);
|
||||
}
|
||||
devices
|
||||
}
|
||||
|
||||
fn with_rusb_devices(device_list: Vec<Device<GlobalContext>>) -> Vec<UsbDevice> {
|
||||
let mut device_handles = vec![];
|
||||
|
||||
for dev in device_list {
|
||||
let open_device = match dev.open() {
|
||||
Ok(dev) => dev,
|
||||
Err(err) => {
|
||||
warn!("Impossible to share {dev:?}: {err}, ignoring device");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
device_handles.push(open_device);
|
||||
}
|
||||
Self::with_rusb_device_handles(device_handles)
|
||||
}
|
||||
|
||||
/// Create a [UsbIpServer] exposing devices in the host, and redirect all USB transfers to them using libusb
|
||||
/// Create a [UsbIpServer] exposing devices in the host using nusb
|
||||
pub fn new_from_host() -> Self {
|
||||
Self::new_from_host_with_filter(|_| true)
|
||||
}
|
||||
|
||||
/// Create a [UsbIpServer] exposing filtered devices in the host, and redirect all USB transfers to them using libusb
|
||||
/// Create a [UsbIpServer] exposing filtered devices in the host using nusb
|
||||
pub fn new_from_host_with_filter<F>(filter: F) -> Self
|
||||
where
|
||||
F: FnMut(&Device<GlobalContext>) -> bool,
|
||||
F: FnMut(&nusb::DeviceInfo) -> bool,
|
||||
{
|
||||
match rusb::devices() {
|
||||
match nusb::list_devices().wait() {
|
||||
Ok(list) => {
|
||||
let mut devs = vec![];
|
||||
for d in list.iter().filter(filter) {
|
||||
devs.push(d)
|
||||
}
|
||||
let devs: Vec<_> = list.filter(filter).collect();
|
||||
Self {
|
||||
available_devices: RwLock::new(Self::with_rusb_devices(devs)),
|
||||
available_devices: RwLock::new(Self::with_nusb_devices(devs)),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ pub const USBIP_RET_UNLINK: u16 = 0x0004;
|
|||
|
||||
/// USB/IP direction
|
||||
///
|
||||
/// NOTE: Must not be confused with rusb::Direction,
|
||||
/// NOTE: Must not be confused with the public Direction enum in consts.rs,
|
||||
/// which has the opposite enum values. This is only for
|
||||
/// internal use in the USB/IP protocol.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue