This repository has been archived on 2026-08-31. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
donglora/vendor/usb-device/tests/test_class_host/device.rs
T
swaitsandClaude Opus 4.6 3102fc747a feat: add display UI with splash screen, dashboard, and RSSI sparkline
Implement full SSD1306 OLED display support:
- Splash screen on boot (1.5s) with project name, version, board
- Dashboard showing radio state, config, counters, RSSI/SNR
- RSSI history sparkline (64-sample ring buffer, 2px-wide bars)
- DisplayOn/DisplayOff host commands routed via dedicated channel
- Pure render functions against generic DrawTarget (no hardware coupling)
- Display on/off control bypasses radio task entirely

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 20:42:54 -06:00

88 lines
2.6 KiB
Rust

use rusb::{ConfigDescriptor, Context, DeviceDescriptor, DeviceHandle, Language, UsbContext as _};
use std::time::Duration;
use usb_device::test_class;
pub const TIMEOUT: Duration = Duration::from_secs(1);
pub const EN_US: u16 = 0x0409;
pub struct DeviceHandles {
pub device_descriptor: DeviceDescriptor,
pub config_descriptor: ConfigDescriptor,
pub handle: DeviceHandle<Context>,
pub en_us: Language,
}
impl DeviceHandles {
/// Indicates if this device is (true) or isn't (false) a
/// high-speed device.
pub fn is_high_speed(&self) -> bool {
self.handle.device().speed() == rusb::Speed::High
}
/// Returns the max packet size for the `TestClass` bulk endpoint(s).
pub fn bulk_max_packet_size(&self) -> u16 {
self.config_descriptor
.interfaces()
.flat_map(|intf| intf.descriptors())
.flat_map(|desc| {
desc.endpoint_descriptors()
.find(|ep| {
// Assumes that IN and OUT endpoint MPSes are the same.
ep.transfer_type() == rusb::TransferType::Bulk
})
.map(|ep| ep.max_packet_size())
})
.next()
.expect("TestClass has at least one bulk endpoint")
}
}
impl ::std::ops::Deref for DeviceHandles {
type Target = DeviceHandle<Context>;
fn deref(&self) -> &DeviceHandle<Context> {
&self.handle
}
}
impl ::std::ops::DerefMut for DeviceHandles {
fn deref_mut(&mut self) -> &mut DeviceHandle<Context> {
&mut self.handle
}
}
pub fn open_device(ctx: &Context) -> rusb::Result<DeviceHandles> {
for device in ctx.devices()?.iter() {
let device_descriptor = device.device_descriptor()?;
if !(device_descriptor.vendor_id() == test_class::VID
&& device_descriptor.product_id() == test_class::PID)
{
continue;
}
let mut handle = device.open()?;
let langs = handle.read_languages(TIMEOUT)?;
if langs.is_empty() || langs[0].lang_id() != EN_US {
continue;
}
let prod = handle.read_product_string(langs[0], &device_descriptor, TIMEOUT)?;
if prod == test_class::PRODUCT {
handle.reset()?;
let config_descriptor = device.config_descriptor(0)?;
return Ok(DeviceHandles {
device_descriptor,
config_descriptor,
handle,
en_us: langs[0],
});
}
}
Err(rusb::Error::NoDevice)
}