@@ -3,6 +3,7 @@ use rand::prelude::*;
33use rusb:: { request_type, Direction , Recipient , RequestType , TransferType } ;
44use std:: cmp:: max;
55use std:: fmt:: Write ;
6+ use std:: thread;
67use std:: time:: { Duration , Instant } ;
78use usb_device:: test_class;
89
@@ -367,6 +368,62 @@ fn bench_bulk_read(context, out) {
367368 } ) ;
368369}
369370
371+ fn enumerates_promptly( context, out) {
372+ // Time measured between issuance of the hard reset command, to the device
373+ // successfully enumerating. This approach might need to be improved on,
374+ // since the time might depend on USB host implementation details,
375+ // bootloaders in the device, etc.
376+ const MAX_TIME : Duration = Duration :: from_secs( 2 ) ;
377+
378+ let dev = match context. device_for_test( ) {
379+ Ok ( dev) => dev,
380+ Err ( err) => {
381+ assert!( false , "Failed to prepare for test: {}" , err) ;
382+ return ;
383+ }
384+ } ;
385+
386+ // Ensure we've got a device by doing a dummy read
387+ let mut response = [ 0u8 ; 8 ] ;
388+ dev. read_control(
389+ request_type( Direction :: In , RequestType :: Vendor , Recipient :: Device ) ,
390+ test_class:: REQ_READ_BUFFER , 0 , 0 , & mut response, TIMEOUT )
391+ . expect( "control read" ) ;
392+
393+ // Since the write_control() may have a timeout, measure from the point when
394+ // the request is sent
395+ let reset_started = Instant :: now( ) ;
396+
397+ // This is expected to fail since the device immediately restarts
398+ let res = dev. write_control(
399+ request_type( Direction :: Out , RequestType :: Vendor , Recipient :: Device ) ,
400+ test_class:: REQ_HARD_RESET , 0 , 0 , & [ ] , TIMEOUT ) ;
401+
402+ if res. is_ok( ) {
403+ panic!( "Hard reset request succeeded, implies the device didn't reset" ) ;
404+ }
405+
406+ loop {
407+ thread:: sleep( Duration :: from_millis( 100 ) ) ;
408+
409+ if reset_started. elapsed( ) > MAX_TIME {
410+ eprintln!( " Didn't enumerate in {:?}" , MAX_TIME ) ;
411+ // Note this hoses the rest of the test suite, since the loop in
412+ // main.rs expects tests to leave the test interface claimed.
413+ panic!( "Enumeration timed out" ) ;
414+ }
415+ if context. reopen_device( None ) . is_ok( ) {
416+ let enumeration_duration = reset_started. elapsed( ) ;
417+
418+ if let Ok ( _) = context. device_for_test( ) {
419+ writeln!( out, " enumerated in {:?}" , enumeration_duration) . expect( "write failed" ) ;
420+ }
421+
422+ break ;
423+ }
424+ }
425+ }
426+
370427} // end tests! {
371428
372429fn run_bench ( dev : & DeviceHandles , out : & mut String , f : impl Fn ( & mut [ u8 ] ) ) {
0 commit comments