@@ -3,6 +3,7 @@ use rand::prelude::*;
3
3
use rusb:: { request_type, Direction , Recipient , RequestType , TransferType } ;
4
4
use std:: cmp:: max;
5
5
use std:: fmt:: Write ;
6
+ use std:: thread;
6
7
use std:: time:: { Duration , Instant } ;
7
8
use usb_device:: test_class;
8
9
@@ -367,6 +368,62 @@ fn bench_bulk_read(context, out) {
367
368
} ) ;
368
369
}
369
370
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
+
370
427
} // end tests! {
371
428
372
429
fn run_bench ( dev : & DeviceHandles , out : & mut String , f : impl Fn ( & mut [ u8 ] ) ) {
0 commit comments