From c18ed05e782c44e5b9bf0e817d25ce942b9dd42a Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Tue, 21 Nov 2023 00:49:48 +0000 Subject: [PATCH] Port LUNA/Cynthion analyzer capture backend from rusb to nusb. --- Cargo.lock | 213 +++++++++++++++++++++++++++++++++++--------- Cargo.toml | 5 +- src/backend/luna.rs | 211 +++++++++++++++++++++++++------------------ src/ui.rs | 10 +-- 4 files changed, 301 insertions(+), 138 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a4903ff9..49833cab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -38,6 +38,12 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "autocfg" version = "1.1.0" @@ -172,6 +178,22 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + [[package]] name = "derive-into-owned" version = "0.2.0" @@ -215,7 +237,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -266,6 +288,19 @@ version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" +[[package]] +name = "futures-lite" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445ba825b27408685aaecefd65178908c36c6e96aaf6d8599419d46e624192ba" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + [[package]] name = "futures-macro" version = "0.3.21" @@ -399,7 +434,7 @@ dependencies = [ "gobject-sys", "libc", "system-deps", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -597,6 +632,16 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "io-kit-sys" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4769cb30e5dcf1710fc6730d3e94f78c47723a014a567de385e113c737394640" +dependencies = [ + "core-foundation-sys", + "mach2", +] + [[package]] name = "itertools" version = "0.12.1" @@ -624,30 +669,33 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" -[[package]] -name = "libusb1-sys" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d0e2afce4245f2c9a418511e5af8718bcaf2fa408aefb259504d1a9cb25f27" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "linux-raw-sys" version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + [[package]] name = "lrumap" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1251ce8e8f9909600e127dcbe74ac50d8464e6685cf5953d37df7a741dbf9e9d" +[[package]] +name = "mach2" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" +dependencies = [ + "libc", +] + [[package]] name = "memchr" version = "2.7.1" @@ -712,6 +760,23 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "nusb" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5f8adce0565ec457ca66a47721a20c72d180be44f444b6cf9539c47b52c653e" +dependencies = [ + "atomic-waker", + "core-foundation", + "core-foundation-sys", + "io-kit-sys", + "log", + "once_cell", + "rustix", + "slab", + "windows-sys 0.48.0", +] + [[package]] name = "object" version = "0.30.4" @@ -739,6 +804,9 @@ dependencies = [ "bytemuck", "bytemuck_derive", "derive_more", + "futures-channel", + "futures-lite", + "futures-util", "gtk4", "humansize", "itertools", @@ -746,12 +814,12 @@ dependencies = [ "memmap2", "num-format", "num_enum", + "nusb", "once_cell", "page_size", "pcap-file", "rand", "rand_xorshift", - "rusb", "serde", "serde_json", "tempfile", @@ -791,6 +859,12 @@ dependencies = [ "system-deps", ] +[[package]] +name = "parking" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" + [[package]] name = "pcap-file" version = "2.0.0" @@ -934,16 +1008,6 @@ dependencies = [ "bitflags 1.3.2", ] -[[package]] -name = "rusb" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45fff149b6033f25e825cbb7b2c625a11ee8e6dac09264d49beb125e39aa97bf" -dependencies = [ - "libc", - "libusb1-sys", -] - [[package]] name = "rustc-demangle" version = "0.1.23" @@ -978,7 +1042,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -1044,9 +1108,12 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.5" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] [[package]] name = "smallvec" @@ -1099,7 +1166,7 @@ dependencies = [ "fastrand", "redox_syscall", "rustix", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -1166,12 +1233,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - [[package]] name = "version-compare" version = "0.1.0" @@ -1212,13 +1273,37 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.0", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -1227,51 +1312,93 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.0" diff --git a/Cargo.toml b/Cargo.toml index 140903fe..09e6aee8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,10 @@ num-format = "0.4.4" humansize = "2.1.3" bisection = "0.1.0" derive_more = "0.99.17" -rusb = "0.9.3" +nusb = "0.1.6" +futures-lite = "2.0.1" +futures-channel = "0.3.21" +futures-util = "0.3.21" serde = { version = "1.0.196", optional = true, features = ["derive"] } serde_json = { version = "1.0.113", optional = true } itertools = "0.12.1" diff --git a/src/backend/luna.rs b/src/backend/luna.rs index 60c1db92..157fd7d4 100644 --- a/src/backend/luna.rs +++ b/src/backend/luna.rs @@ -1,27 +1,36 @@ use std::collections::VecDeque; use std::thread::{spawn, JoinHandle}; -use std::sync::mpsc::{channel, Sender, Receiver}; use std::time::Duration; +use std::sync::mpsc; use anyhow::{Context as ErrorContext, Error, bail}; +use futures_channel::oneshot; +use futures_lite::future::block_on; +use futures_util::{select_biased, FutureExt}; use num_enum::{FromPrimitive, IntoPrimitive}; -use rusb::{ - Context, - Device, - DeviceHandle, - UsbContext, - Version +use nusb::{ + self, + transfer::{ + Control, + ControlType, + Recipient, + RequestBuffer, + TransferError, + }, + DeviceInfo, + Interface }; const VID: u16 = 0x1d50; const PID: u16 = 0x615b; -const MIN_SUPPORTED: Version = Version(0, 0, 2); -const NOT_SUPPORTED: Version = Version(0, 0, 3); +const MIN_SUPPORTED: u16 = 0x0002; +const NOT_SUPPORTED: u16 = 0x0003; const ENDPOINT: u8 = 0x81; const READ_LEN: usize = 0x4000; +const NUM_TRANSFERS: usize = 4; #[derive(Copy, Clone, FromPrimitive, IntoPrimitive)] #[repr(u8)] @@ -73,37 +82,47 @@ impl State { /// A Luna device attached to the system. pub struct LunaDevice { - usb_device: Device, + device_info: DeviceInfo, pub description: String, pub speeds: Vec, } /// A handle to an open Luna device. pub struct LunaHandle { - usb_handle: DeviceHandle, + interface: Interface, } pub struct LunaStream { - receiver: Receiver, rusb::Error>>, + receiver: mpsc::Receiver, TransferError>>, } pub struct LunaStop { - stop_request: Sender<()>, + stop_request: oneshot::Sender<()>, worker: JoinHandle::>, } impl LunaDevice { - pub fn scan(context: &mut Context) -> Result, Error> { - let devices = context.devices()?; - let mut result = Vec::with_capacity(devices.len()); - for usb_device in devices.iter() { - let desc = usb_device.device_descriptor()?; - if desc.vendor_id() == VID && desc.product_id() == PID { - let handle = LunaHandle::new(usb_device.open()?)?; - let description = handle.description()?; + pub fn scan() -> Result, Error> { + let mut result = Vec::new(); + for device_info in nusb::list_devices()? { + if device_info.vendor_id() == VID && + device_info.product_id() == PID + { + let version = device_info.device_version(); + if !(MIN_SUPPORTED..=NOT_SUPPORTED).contains(version) { + continue; + } + let manufacturer = device_info + .manufacturer_string() + .unwrap_or("Unknown"); + let product = device_info + .product_string() + .unwrap_or("Device"); + let description = format!("{} {}", manufacturer, product); + let handle = LunaHandle::new(&device_info)?; let speeds = handle.speeds()?; result.push(LunaDevice{ - usb_device, + device_info, description, speeds, }) @@ -113,45 +132,35 @@ impl LunaDevice { } pub fn open(&self) -> Result { - LunaHandle::new(self.usb_device.open()?) + LunaHandle::new(&self.device_info) } } impl LunaHandle { - fn new(usb_handle: DeviceHandle) -> Result { - let version = usb_handle - .device() - .device_descriptor()? - .device_version(); - if version >= MIN_SUPPORTED && version < NOT_SUPPORTED { - Ok(Self { usb_handle }) - } else { - bail!("Unsupported analyzer version: Gateware version is {version}. \ - Supported range is {MIN_SUPPORTED} or higher, \ - but not {NOT_SUPPORTED} or higher") - } - } - - pub fn description(&self) -> Result { - let desc = self.usb_handle.device().device_descriptor()?; - let manufacturer = self.usb_handle.read_manufacturer_string_ascii(&desc)?; - let product = self.usb_handle.read_product_string_ascii(&desc)?; - Ok(format!("{} {}", manufacturer, product)) + fn new(device_info: &DeviceInfo) -> Result { + let device = device_info.open()?; + let interface = device.claim_interface(0)?; + Ok(LunaHandle { interface }) } pub fn speeds(&self) -> Result, Error> { - use rusb::{Direction, RequestType, Recipient, request_type}; - let mut buf = [0u8]; - self.usb_handle.read_control( - request_type(Direction::In, RequestType::Vendor, Recipient::Device), - 2, - 0, - 0, - &mut buf, - Duration::from_secs(5), - )?; - let mut speeds = vec![]; use Speed::*; + let control = Control { + control_type: ControlType::Vendor, + recipient: Recipient::Device, + request: 2, + value: 0, + index: 0, + }; + let mut buf = [0; 64]; + let timeout = Duration::from_secs(1); + let size = self.interface + .control_in_blocking(control, &mut buf, timeout) + .context("Failed retrieving supported speeds from device")?; + if size != 1 { + bail!("Expected 1-byte response to speed request, got {size}"); + } + let mut speeds = Vec::new(); for speed in [Auto, High, Full, Low] { if buf[0] & speed.mask() != 0 { speeds.push(speed); @@ -163,39 +172,67 @@ impl LunaHandle { pub fn start(mut self, speed: Speed) -> Result<(LunaStream, LunaStop), Error> { - self.usb_handle.claim_interface(0)?; - let (tx, rx) = channel(); - let (stop_tx, stop_rx) = channel(); - let worker = spawn(move || { - let mut buffer = [0u8; READ_LEN]; + // Channel to pass captured packets or errors to the decoder thread. + let (tx, rx) = mpsc::channel(); + // Channel to stop the capture thread on request. + let (stop_tx, mut stop_rx) = oneshot::channel(); + // The task to be run by the capture thread. + let capture_task = async move { + // Set up a queue of bulk transfer requests on the capture endpoint. + let mut transfer_queue = self.interface.bulk_in_queue(ENDPOINT); + // Pre-fill the queue with transfer requests. + while transfer_queue.pending() < NUM_TRANSFERS { + transfer_queue.submit(RequestBuffer::new(READ_LEN)); + } + // Local queue to store bytes not yet divided into packets. let mut packet_queue = PacketQueue::new(); + // Start the capture. let mut state = State::new(true, speed); self.write_state(state)?; println!("Capture enabled, speed: {}", speed.description()); - while stop_rx.try_recv().is_err() { - let result = self.usb_handle.read_bulk( - ENDPOINT, &mut buffer, Duration::from_millis(100)); - match result { - Ok(count) => { - packet_queue.extend(&buffer[..count]); - while let Some(packet) = packet_queue.next() { - tx.send(Ok(packet)) - .context("Failed sending packet to channel")?; - }; + // Main capture loop: + loop { + select_biased! { + _ = stop_rx => { + // Signalled to stop capture. Cancel all transfers. + transfer_queue.cancel_all(); + break; }, - Err(rusb::Error::Timeout) => continue, - Err(usb_error) => { - tx.send(Err(usb_error)) - .context("Failed sending error to channel")?; - return Err(Error::from(usb_error)); + completion = transfer_queue.next_complete().fuse() => { + // The next bulk transfer completed. + match completion.status { + Ok(()) => { + // Transfer successful. Queue the data for packetization. + packet_queue.extend(&completion.data); + // Having done so, reuse the buffer. + let buffer = RequestBuffer::reuse( + completion.data, READ_LEN); + // Submit a new transfer to keep the queue full. + transfer_queue.submit(buffer); + // Send all complete packets to decoder thread. + while let Some(packet) = packet_queue.next() { + tx.send(Ok(packet)) + .context("Failed sending packet to channel")?; + } + }, + Err(usb_error) => { + // Transfer failed. Send error to decoder thread. + tx.send(Err(usb_error)) + .context("Failed sending error to channel")?; + return Err(Error::from(usb_error)); + } + } } } } + // Stop capture. state.set_enable(false); self.write_state(state)?; println!("Capture disabled"); Ok(()) - }); + }; + // Spawn worker thread to run capture task. + let worker = spawn(|| block_on(capture_task)); Ok(( LunaStream { receiver: rx, @@ -208,21 +245,24 @@ impl LunaHandle { } fn write_state(&mut self, state: State) -> Result<(), Error> { - use rusb::{Direction, RequestType, Recipient, request_type}; - self.usb_handle.write_control( - request_type(Direction::Out, RequestType::Vendor, Recipient::Device), - 1, - u16::from(state.0), - 0, - &[], - Duration::from_secs(5), - )?; + let control = Control { + control_type: ControlType::Vendor, + recipient: Recipient::Device, + request: 1, + value: u16::from(state.0), + index: 0, + }; + let data = &[]; + let timeout = Duration::from_secs(1); + self.interface + .control_out_blocking(control, data, timeout) + .context("Failed writing state to device")?; Ok(()) } } impl LunaStream { - pub fn next(&mut self) -> Option, rusb::Error>> { + pub fn next(&mut self) -> Option, TransferError>> { self.receiver.recv().ok() } } @@ -230,7 +270,8 @@ impl LunaStream { impl LunaStop { pub fn stop(self) -> Result<(), Error> { println!("Requesting capture stop"); - self.stop_request.send(()).context("Failed sending stop request")?; + self.stop_request.send(()) + .or_else(|_| bail!("Failed sending stop request"))?; match self.worker.join() { Ok(result) => result, Err(panic) => { diff --git a/src/ui.rs b/src/ui.rs index e11c0bde..ae827f70 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -46,8 +46,6 @@ use pcap_file::{ pcap::{PcapReader, PcapWriter, PcapHeader, RawPcapPacket}, }; -use rusb::Context; - use crate::backend::luna::{LunaDevice, LunaHandle, LunaStop, Speed}; use crate::capture::{ create_capture, @@ -94,7 +92,6 @@ enum FileAction { } struct DeviceSelector { - usb_context: Option, devices: Vec, dev_strings: Vec, dev_speeds: Vec>, @@ -106,7 +103,6 @@ struct DeviceSelector { impl DeviceSelector { fn new() -> Result { let selector = DeviceSelector { - usb_context: Context::new().ok(), devices: vec![], dev_strings: vec![], dev_speeds: vec![], @@ -143,11 +139,7 @@ impl DeviceSelector { } fn scan(&mut self) -> Result { - self.devices = if let Some(context) = self.usb_context.as_mut() { - LunaDevice::scan(context)? - } else { - vec![] - }; + self.devices = LunaDevice::scan()?; self.dev_strings = Vec::with_capacity(self.devices.len()); self.dev_speeds = Vec::with_capacity(self.devices.len()); for device in self.devices.iter() {