Skip to content

Commit e901d76

Browse files
committed
Add test_class_host reopen_device()
Needed for testing enumeration time
1 parent 8480215 commit e901d76

File tree

1 file changed

+36
-10
lines changed

1 file changed

+36
-10
lines changed

tests/test_class_host/device.rs

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use rusb::{ConfigDescriptor, Context, DeviceDescriptor, DeviceHandle, Language, UsbContext as _};
22
use std::thread;
3-
use std::time::Duration;
3+
use std::time::{Duration, Instant};
44
use usb_device::device::CONFIGURATION_VALUE;
55
use usb_device::test_class;
66

@@ -100,7 +100,7 @@ impl UsbContext {
100100
}
101101

102102
/// Attempt to open the test device once
103-
fn try_open_device(&self) -> rusb::Result<DeviceHandles> {
103+
fn open_device_immediate(&self) -> rusb::Result<DeviceHandles> {
104104
for device in self.inner.devices()?.iter() {
105105
let device_descriptor = device.device_descriptor()?;
106106

@@ -136,15 +136,31 @@ impl UsbContext {
136136
Err(rusb::Error::NoDevice)
137137
}
138138

139-
/// Look for the device for about 5 seconds in case it hasn't finished enumerating yet
140-
pub fn open_device(&mut self) -> rusb::Result<&mut DeviceHandles> {
139+
/// Look for the device, retry until timeout expires
140+
pub fn open_device(&mut self, timeout: Option<Duration>) -> rusb::Result<&mut DeviceHandles> {
141141
if self.device.is_none() {
142-
for _ in 0..50 {
143-
if let Ok(dev) = self.try_open_device() {
144-
self.device = Some(dev);
145-
break;
142+
match timeout {
143+
Some(timeout) => {
144+
let deadline = Instant::now() + timeout;
145+
loop {
146+
if let Ok(dev) = self.open_device_immediate() {
147+
self.device = Some(dev);
148+
break;
149+
}
150+
let now = Instant::now();
151+
if now >= deadline {
152+
break;
153+
} else {
154+
let dur = Duration::from_millis(100).min(deadline - now);
155+
thread::sleep(dur);
156+
}
157+
}
158+
}
159+
None => {
160+
if let Ok(dev) = self.open_device_immediate() {
161+
self.device = Some(dev);
162+
}
146163
}
147-
thread::sleep(Duration::from_millis(100));
148164
}
149165
}
150166

@@ -154,9 +170,19 @@ impl UsbContext {
154170
}
155171
}
156172

173+
/// Closes device if it was open (handling errors), attempts to reopen
174+
pub fn reopen_device(&mut self, timeout: Option<Duration>) -> rusb::Result<&mut DeviceHandles> {
175+
// This is expected to fail in tests where device was asked to reset
176+
let _ = self.cleanup_after_test();
177+
178+
self.device = None;
179+
180+
self.open_device(timeout)
181+
}
182+
157183
/// Attempts to open (if necessary) and (re-)initialize a device for a test
158184
pub fn device_for_test(&mut self) -> rusb::Result<&mut DeviceHandles> {
159-
let dev = match self.open_device() {
185+
let dev = match self.open_device(Some(Duration::from_secs(5))) {
160186
Ok(dev) => dev,
161187
Err(err) => {
162188
println!("Did not find a TestClass device. Make sure the device is correctly programmed and plugged in. Last error: {}", err);

0 commit comments

Comments
 (0)