Skip to content

Commit 0712236

Browse files
committed
add libusb
1 parent d3f6c11 commit 0712236

8 files changed

Lines changed: 239 additions & 118 deletions

File tree

.vscode/settings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
// "rust-analyzer.cargo.target": "aarch64-unknown-none-softfloat",
33
"rust-analyzer.cargo.allTargets": false,
44
"rust-analyzer.cargo.features": [
5-
// "libusb"
5+
"libusb"
66
],
77
}
Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![cfg(test)]
22

3-
use crab_usb::Host;
3+
use crab_usb::USBHost;
44

55
#[tokio::test]
66
async fn test() {
@@ -9,12 +9,14 @@ async fn test() {
99
.is_test(true)
1010
.init();
1111

12-
let mut host = Host::new_libusb();
13-
let ls = host.probe().await.unwrap();
12+
let mut host = USBHost::new_libusb();
13+
let mut ls = host.device_list().await.unwrap();
1414

15-
println!("Found {} devices", ls.len());
15+
for device in ls {
16+
println!("Device: {:?}", device.descriptor().await.unwrap());
1617

17-
for device in &ls {
18-
println!("Device: {:?}", device.descriptor());
18+
for iface in device.interface_descriptors() {
19+
println!(" Interface: {iface:?}",);
20+
}
1921
}
2022
}

usb-host/src/host/common/mod.rs

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
use alloc::{boxed::Box, string::String, vec::Vec};
22
use core::{fmt::Display, ptr::NonNull};
3+
use std::collections::BTreeMap;
34

45
use usb_if::{
5-
descriptor::{EndpointDescriptor, InterfaceDescriptor},
6+
descriptor::{
7+
ConfigurationDescriptor, DeviceDescriptor, EndpointDescriptor, InterfaceDescriptor,
8+
},
69
host::{Controller, ResultTransfer, USBError},
710
};
811

@@ -22,17 +25,26 @@ impl USBHost {
2225
Self { raw: xhci }
2326
}
2427

28+
#[cfg(feature = "libusb")]
29+
pub fn new_libusb() -> Self {
30+
let libusb = crate::host::libusb::Libusb::new();
31+
Self {
32+
raw: Box::new(libusb),
33+
}
34+
}
35+
2536
pub async fn init(&mut self) -> Result<(), USBError> {
2637
self.raw.init().await
2738
}
2839

2940
pub async fn device_list(&self) -> Result<impl Iterator<Item = DeviceInfo>, USBError> {
30-
Ok(self
31-
.raw
32-
.device_list()
33-
.await?
34-
.into_iter()
35-
.map(DeviceInfo::from_box))
41+
let devices = self.raw.device_list().await?;
42+
let mut device_infos = Vec::with_capacity(devices.len());
43+
for device in devices {
44+
let device_info = DeviceInfo::from_box(device).await?;
45+
device_infos.push(device_info);
46+
}
47+
Ok(device_infos.into_iter())
3648
}
3749

3850
pub fn handle_event(&mut self) {
@@ -42,37 +54,48 @@ impl USBHost {
4254

4355
pub struct DeviceInfo {
4456
raw: Box<dyn usb_if::host::DeviceInfo>,
57+
pub descriptor: DeviceDescriptor,
58+
pub configurations: Vec<ConfigurationDescriptor>,
4559
}
4660

4761
impl DeviceInfo {
48-
fn from_box(raw: Box<dyn usb_if::host::DeviceInfo>) -> Self {
49-
DeviceInfo { raw }
62+
async fn from_box(mut raw: Box<dyn usb_if::host::DeviceInfo>) -> Result<Self, USBError> {
63+
let desc = raw.descriptor().await?;
64+
let mut configurations = Vec::with_capacity(desc.num_configurations as usize);
65+
for i in 0..desc.num_configurations {
66+
let config_desc = raw.configuration_descriptor(i).await?;
67+
68+
configurations.push(config_desc);
69+
}
70+
Ok(DeviceInfo {
71+
raw,
72+
descriptor: desc,
73+
configurations,
74+
})
5075
}
5176

5277
pub async fn open(&mut self) -> Result<Device, USBError> {
53-
let desc = self.raw.descriptor().await?;
5478
let mut device = self.raw.open().await?;
5579
device.set_configuration(1).await?; // Default to configuration 1
56-
let configurations = device.configuration_descriptors().await?;
5780

58-
let manufacturer_string = match desc.manufacturer_string_index {
81+
let manufacturer_string = match self.descriptor.manufacturer_string_index {
5982
Some(index) => device.string_descriptor(index.get(), 0).await?,
6083
None => String::new(),
6184
};
6285

63-
let product_string = match desc.product_string_index {
86+
let product_string = match self.descriptor.product_string_index {
6487
Some(index) => device.string_descriptor(index.get(), 0).await?,
6588
None => String::new(),
6689
};
6790

68-
let serial_number_string = match desc.serial_number_string_index {
91+
let serial_number_string = match self.descriptor.serial_number_string_index {
6992
Some(index) => device.string_descriptor(index.get(), 0).await?,
7093
None => String::new(),
7194
};
7295

7396
Ok(Device {
74-
descriptor: desc,
75-
configurations,
97+
descriptor: self.descriptor.clone(),
98+
configurations: self.configurations.clone(),
7699
raw: device,
77100
manufacturer_string,
78101
product_string,
@@ -84,10 +107,14 @@ impl DeviceInfo {
84107
self.raw.descriptor().await
85108
}
86109

87-
pub async fn configuration_descriptors(
88-
&self,
89-
) -> Result<Vec<usb_if::descriptor::ConfigurationDescriptor>, USBError> {
90-
self.raw.configuration_descriptors().await
110+
pub fn interface_descriptors(&self) -> Vec<usb_if::descriptor::InterfaceDescriptor> {
111+
let mut interfaces = BTreeMap::new();
112+
for config in &self.configurations {
113+
for iface in &config.interfaces {
114+
interfaces.insert(iface.interface_number, iface.first_alt_setting());
115+
}
116+
}
117+
interfaces.values().cloned().collect()
91118
}
92119
}
93120

usb-host/src/host/libusb/device.rs

Lines changed: 125 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
use core::{mem::MaybeUninit, num::NonZero};
22

3+
use futures::FutureExt;
34
use libusb1_sys::*;
4-
use usb_if::descriptor::DeviceDescriptor;
5-
6-
use crate::IDevice;
5+
use usb_if::descriptor::{ConfigurationDescriptor, DeviceDescriptor, InterfaceDescriptor, InterfaceDescriptors};
76

87
pub struct DeviceInfo {
98
pub(crate) raw: *mut libusb_device,
@@ -20,22 +19,6 @@ impl DeviceInfo {
2019
pub fn raw(&self) -> *mut libusb_device {
2120
self.raw
2221
}
23-
24-
pub fn open(&mut self) -> crate::err::Result<Device> {
25-
let mut handle = std::ptr::null_mut();
26-
usb!(libusb_open(self.raw, &mut handle))?;
27-
let desc = self.descriptor()?;
28-
Ok(Device::new(handle, desc))
29-
}
30-
31-
pub fn descriptor(&self) -> crate::err::Result<DeviceDescriptor> {
32-
let mut desc: MaybeUninit<libusb_device_descriptor> = MaybeUninit::uninit();
33-
usb!(libusb_get_device_descriptor(self.raw, desc.as_mut_ptr()))?;
34-
let desc = unsafe { desc.assume_init() };
35-
libusb_device_desc_to_desc(&desc)
36-
}
37-
38-
3922
}
4023

4124
impl Drop for DeviceInfo {
@@ -46,13 +29,88 @@ impl Drop for DeviceInfo {
4629
}
4730
}
4831

49-
impl IDevice for DeviceInfo {}
32+
impl usb_if::host::DeviceInfo for DeviceInfo {
33+
fn open(
34+
&mut self,
35+
) -> futures::future::LocalBoxFuture<
36+
'_,
37+
Result<Box<dyn usb_if::host::Device>, usb_if::host::USBError>,
38+
> {
39+
async move {
40+
let mut handle = std::ptr::null_mut();
41+
usb!(libusb_open(self.raw, &mut handle))?;
42+
let desc = self.descriptor().await?;
43+
let device = Device::new(handle, desc);
44+
45+
Ok(Box::new(device) as Box<dyn usb_if::host::Device>)
46+
}
47+
.boxed_local()
48+
}
49+
50+
fn descriptor(
51+
&self,
52+
) -> futures::future::LocalBoxFuture<'_, Result<DeviceDescriptor, usb_if::host::USBError>> {
53+
async move {
54+
let mut desc: MaybeUninit<libusb_device_descriptor> = MaybeUninit::uninit();
55+
usb!(libusb_get_device_descriptor(self.raw, desc.as_mut_ptr()))?;
56+
let desc = unsafe { desc.assume_init() };
57+
libusb_device_desc_to_desc(&desc)
58+
}
59+
.boxed_local()
60+
}
61+
62+
fn configuration_descriptor(
63+
&mut self,
64+
index: u8,
65+
) -> futures::future::LocalBoxFuture<'_, Result<ConfigurationDescriptor, usb_if::host::USBError>>
66+
{
67+
async move {
68+
let mut desc: MaybeUninit<*const libusb_config_descriptor> = MaybeUninit::uninit();
69+
usb!(libusb_get_config_descriptor(
70+
self.raw,
71+
index,
72+
desc.as_mut_ptr()
73+
))?;
74+
let desc = unsafe { desc.assume_init() };
75+
76+
if desc.is_null() {
77+
return Err(usb_if::host::USBError::Other(
78+
"Failed to get configuration descriptor".into(),
79+
));
80+
}
81+
82+
let desc = unsafe { &*desc };
83+
84+
let interface_num = desc.bNumInterfaces as usize;
85+
let mut interfaces = Vec::with_capacity(interface_num);
86+
87+
for iface_num in 0..interface_num {
88+
89+
}
90+
91+
let out = ConfigurationDescriptor {
92+
num_interfaces: desc.bNumInterfaces,
93+
configuration_value: desc.bConfigurationValue,
94+
attributes: desc.bmAttributes,
95+
max_power: desc.bMaxPower,
96+
string_index: NonZero::new(desc.iConfiguration),
97+
string: None,
98+
interfaces,
99+
};
100+
unsafe { libusb_free_config_descriptor(desc) };
101+
Ok(out)
102+
}
103+
.boxed_local()
104+
}
105+
}
50106

51107
pub struct Device {
52108
raw: *mut libusb_device_handle,
53109
desc: DeviceDescriptor,
54110
}
55111

112+
unsafe impl Send for Device {}
113+
56114
impl Device {
57115
pub(crate) fn new(raw: *mut libusb_device_handle, desc: DeviceDescriptor) -> Self {
58116
Self { raw, desc }
@@ -75,6 +133,53 @@ impl Drop for Device {
75133
}
76134
}
77135

136+
impl usb_if::host::Device for Device {
137+
fn set_configuration(
138+
&mut self,
139+
configuration: u8,
140+
) -> futures::future::LocalBoxFuture<'_, Result<(), usb_if::host::USBError>> {
141+
todo!()
142+
}
143+
144+
fn get_configuration(
145+
&mut self,
146+
) -> futures::future::LocalBoxFuture<'_, Result<u8, usb_if::host::USBError>> {
147+
todo!()
148+
}
149+
150+
fn claim_interface(
151+
&mut self,
152+
interface: u8,
153+
alternate: u8,
154+
) -> futures::future::LocalBoxFuture<
155+
'_,
156+
Result<Box<dyn usb_if::host::Interface>, usb_if::host::USBError>,
157+
> {
158+
todo!()
159+
}
160+
161+
fn string_descriptor(
162+
&mut self,
163+
index: u8,
164+
language_id: u16,
165+
) -> futures::future::LocalBoxFuture<'_, Result<String, usb_if::host::USBError>> {
166+
async move {
167+
let mut buf = vec![0u8; 256];
168+
let len = usb!(libusb_get_string_descriptor_ascii(
169+
self.raw,
170+
index,
171+
buf.as_mut_ptr(),
172+
buf.len() as _
173+
))?;
174+
buf.truncate(len as usize);
175+
String::from_utf8(buf).map_err(|_| {
176+
usb_if::host::USBError::Other("Failed to convert string descriptor to UTF-8".into())
177+
})
178+
}
179+
.boxed_local()
180+
}
181+
}
182+
78183
fn libusb_device_desc_to_desc(
79184
desc: &libusb_device_descriptor,
80185
) -> crate::err::Result<DeviceDescriptor> {
@@ -91,8 +196,5 @@ fn libusb_device_desc_to_desc(
91196
usb_version: desc.bcdUSB,
92197
max_packet_size_0: desc.bMaxPacketSize0,
93198
device_version: desc.bcdDevice,
94-
manufacturer_string: None,
95-
product_string: None,
96-
serial_number_string: None,
97199
})
98200
}

0 commit comments

Comments
 (0)