11use rusb:: { ConfigDescriptor , Context , DeviceDescriptor , DeviceHandle , Language , UsbContext as _} ;
22use std:: thread;
3- use std:: time:: Duration ;
3+ use std:: time:: { Duration , Instant } ;
44use usb_device:: device:: CONFIGURATION_VALUE ;
55use 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