Skip to content

Commit

Permalink
Expose nusb support
Browse files Browse the repository at this point in the history
  • Loading branch information
jiegec committed Oct 26, 2024
1 parent 9c1efa1 commit 0e896b2
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 17 deletions.
11 changes: 11 additions & 0 deletions src/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,17 @@ impl From<Version> for rusbVersion {
}
}

/// bcdDevice
impl From<u16> for Version {
fn from(value: u16) -> Self {
Self {
major: (value >> 8) as u8,
minor: ((value >> 4) & 0xF) as u8,
patch: (value & 0xF) as u8,
}
}
}

/// Represent a USB device
#[derive(Clone, Default)]
#[cfg_attr(feature = "serde", derive(Serialize))]
Expand Down
138 changes: 121 additions & 17 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,123 @@ impl UsbIpServer {
}
}

/// Create a [UsbIpServer] with Vec<[nusb::DeviceInfo]> for sharing host devices
pub fn with_nusb_devices(nusb_device_infos: Vec<nusb::DeviceInfo>) -> Vec<UsbDevice> {
let mut devices = vec![];
for device_info in nusb_device_infos {
let dev = match device_info.open() {
Ok(dev) => dev,
Err(err) => {
warn!(
"Impossible to open device {:?}: {}, ignoring device",
device_info, err
);
continue;
}
};
let cfg = match dev.active_configuration() {
Ok(cfg) => cfg,
Err(err) => {
warn!(
"Impossible to get active configuration {:?}: {}, ignoring device",
device_info, err
);
continue;
}
};
let mut interfaces = vec![];
for intf in cfg.interfaces() {
// ignore alternate settings
let intf_num = intf.interface_number();
let intf = dev.claim_interface(intf_num).unwrap();
let alt_setting = intf.descriptors().next().unwrap();
let mut endpoints = vec![];

for ep_desc in alt_setting.endpoints() {
endpoints.push(UsbEndpoint {
address: ep_desc.address(),
attributes: ep_desc.transfer_type() as u8,
max_packet_size: ep_desc.max_packet_size() as u16,
interval: ep_desc.interval(),
});
}

let handler = Arc::new(Mutex::new(Box::new(NusbUsbHostInterfaceHandler::new(
Arc::new(Mutex::new(intf.clone())),
))
as Box<dyn UsbInterfaceHandler + Send>));
interfaces.push(UsbInterface {
interface_class: alt_setting.class(),
interface_subclass: alt_setting.subclass(),
interface_protocol: alt_setting.protocol(),
endpoints,
string_interface: alt_setting.string_index().unwrap_or(0),
class_specific_descriptor: Vec::new(),
handler,
});
}
let mut device = UsbDevice {
path: format!(
"/sys/bus/{}/{}/{}",
device_info.bus_number(),
device_info.device_address(),
0
),
bus_id: format!(
"{}-{}-{}",
device_info.bus_number(),
device_info.device_address(),
0,
),
bus_num: device_info.bus_number() as u32,
dev_num: 0,
speed: device_info.speed().unwrap() as u32,
vendor_id: device_info.vendor_id(),
product_id: device_info.product_id(),
device_class: device_info.class(),
device_subclass: device_info.subclass(),
device_protocol: device_info.protocol(),
device_bcd: device_info.device_version().into(),
configuration_value: cfg.configuration_value(),
num_configurations: dev.configurations().count() as u8,
ep0_in: UsbEndpoint {
address: 0x80,
attributes: EndpointAttributes::Control as u8,
max_packet_size: 16,
interval: 0,
},
ep0_out: UsbEndpoint {
address: 0x00,
attributes: EndpointAttributes::Control as u8,
max_packet_size: 16,
interval: 0,
},
interfaces,
device_handler: Some(Arc::new(Mutex::new(Box::new(
NusbUsbHostDeviceHandler::new(Arc::new(Mutex::new(dev))),
)))),
..UsbDevice::default()
};

// set strings
if let Some(s) = device_info.manufacturer_string() {
device.string_manufacturer = device.new_string(s)
}
if let Some(s) = device_info.product_string() {
device.string_product = device.new_string(s)
}
if let Some(s) = device_info.serial_number() {
device.string_serial = device.new_string(s)
}
devices.push(device);
}
devices
}

/// Create a [UsbIpServer] with Vec<[rusb::DeviceHandle]> for sharing host devices
pub fn with_device_handles(device_handles: Vec<DeviceHandle<GlobalContext>>) -> Vec<UsbDevice> {
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();
Expand Down Expand Up @@ -197,7 +312,7 @@ impl UsbIpServer {
devices
}

fn with_devices(device_list: Vec<Device<GlobalContext>>) -> Vec<UsbDevice> {
fn with_rusb_devices(device_list: Vec<Device<GlobalContext>>) -> Vec<UsbDevice> {
let mut device_handles = vec![];

for dev in device_list {
Expand All @@ -210,26 +325,15 @@ impl UsbIpServer {
};
device_handles.push(open_device);
}
Self::with_device_handles(device_handles)
Self::with_rusb_device_handles(device_handles)
}

/// Create a [UsbIpServer] exposing devices in the host, and redirect all USB transfers to them using libusb
pub fn new_from_host() -> Self {
match rusb::devices() {
Ok(list) => {
let mut devs = vec![];
for d in list.iter() {
devs.push(d)
}
Self {
available_devices: RwLock::new(Self::with_devices(devs)),
..Default::default()
}
}
Err(_) => Default::default(),
}
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
pub fn new_from_host_with_filter<F>(filter: F) -> Self
where
F: FnMut(&Device<GlobalContext>) -> bool,
Expand All @@ -241,7 +345,7 @@ impl UsbIpServer {
devs.push(d)
}
Self {
available_devices: RwLock::new(Self::with_devices(devs)),
available_devices: RwLock::new(Self::with_rusb_devices(devs)),
..Default::default()
}
}
Expand Down

0 comments on commit 0e896b2

Please sign in to comment.