1
1
use rusb:: { ConfigDescriptor , Context , DeviceDescriptor , DeviceHandle , Language , UsbContext as _} ;
2
2
use std:: thread;
3
- use std:: time:: Duration ;
3
+ use std:: time:: { Duration , Instant } ;
4
4
use usb_device:: device:: CONFIGURATION_VALUE ;
5
5
use usb_device:: test_class;
6
6
@@ -100,7 +100,7 @@ impl UsbContext {
100
100
}
101
101
102
102
/// 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 > {
104
104
for device in self . inner . devices ( ) ?. iter ( ) {
105
105
let device_descriptor = device. device_descriptor ( ) ?;
106
106
@@ -136,15 +136,31 @@ impl UsbContext {
136
136
Err ( rusb:: Error :: NoDevice )
137
137
}
138
138
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 > {
141
141
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
+ }
146
163
}
147
- thread:: sleep ( Duration :: from_millis ( 100 ) ) ;
148
164
}
149
165
}
150
166
@@ -154,9 +170,19 @@ impl UsbContext {
154
170
}
155
171
}
156
172
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
+
157
183
/// Attempts to open (if necessary) and (re-)initialize a device for a test
158
184
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 ) ) ) {
160
186
Ok ( dev) => dev,
161
187
Err ( err) => {
162
188
println ! ( "Did not find a TestClass device. Make sure the device is correctly programmed and plugged in. Last error: {}" , err) ;
0 commit comments