@@ -275,6 +275,7 @@ typedef struct {
275275typedef struct {
276276 uint8_t controller_id ; // controller ID
277277 uint8_t enumerating_daddr ; // device address of the device being enumerated
278+ uint8_t attach_debouncing_bm ; // bitmask for roothub port attach debouncing
278279 tuh_bus_info_t dev0_bus ; // bus info for dev0 in enumeration
279280 usbh_ctrl_xfer_info_t ctrl_xfer_info ; // control transfer
280281} usbh_data_t ;
@@ -349,7 +350,7 @@ bool tuh_rhport_is_active(uint8_t rhport) {
349350
350351bool tuh_rhport_reset_bus (uint8_t rhport , bool active ) {
351352 TU_VERIFY (tuh_rhport_is_active (rhport ));
352- if ( active ) {
353+ if (active ) {
353354 hcd_port_reset (rhport );
354355 } else {
355356 hcd_port_reset_end (rhport );
@@ -512,28 +513,19 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) {
512513 case HCD_EVENT_DEVICE_ATTACH :
513514 // due to the shared control buffer, we must fully complete enumerating one device first.
514515 // TODO better to have an separated queue for newly attached devices
515- if (_usbh_data .enumerating_daddr != TUSB_INDEX_INVALID_8 ) {
516- if (event .rhport == _usbh_data .dev0_bus .rhport &&
517- event .connection .hub_addr == _usbh_data .dev0_bus .hub_addr && event .connection .hub_port == _usbh_data .dev0_bus .hub_port ) {
518- // Some device can cause multiple duplicated attach events
519- // drop current enumerating and start over for a proper port reset
520- // abort/cancel current enumeration and start new one
521- TU_LOG1 ("[%u:] USBH Device Attach (duplicated)\r\n" , event .rhport );
522- tuh_edpt_abort_xfer (0 , 0 );
523- enum_new_device (& event );
524- } else {
525- TU_LOG_USBH ("[%u:] USBH Defer Attach until current enumeration complete\r\n" , event .rhport );
526- bool is_empty = osal_queue_empty (_usbh_q );
527- queue_event (& event , in_isr );
528-
529- if (is_empty ) {
530- // Exit if this is the only event in the queue, otherwise we may loop forever
531- return ;
532- }
533- }
534- } else {
516+ if (_usbh_data .enumerating_daddr == TUSB_INDEX_INVALID_8 ) {
517+ // New device attached and we are ready
535518 TU_LOG1 ("[%u:] USBH Device Attach\r\n" , event .rhport );
519+ _usbh_data .enumerating_daddr = 0 ; // enumerate new device with address 0
536520 enum_new_device (& event );
521+ } else {
522+ // currently enumerating another device
523+ TU_LOG_USBH ("[%u:] USBH Defer Attach until current enumeration complete\r\n" , event .rhport );
524+ const bool is_empty = osal_queue_empty (_usbh_q );
525+ queue_event (& event , in_isr );
526+ if (is_empty ) {
527+ return ; // Exit if this is the only event in the queue, otherwise we loop forever
528+ }
537529 }
538530 break ;
539531
@@ -1021,10 +1013,18 @@ bool tuh_bus_info_get(uint8_t daddr, tuh_bus_info_t* bus_info) {
10211013TU_ATTR_FAST_FUNC void hcd_event_handler (hcd_event_t const * event , bool in_isr ) {
10221014 switch (event -> event_id ) {
10231015 case HCD_EVENT_DEVICE_ATTACH :
1024-
1025- break ;
1026-
10271016 case HCD_EVENT_DEVICE_REMOVE :
1017+ // Attach debouncing on roothub: skip attach/remove while debouncing delay
1018+ if (event -> connection .hub_addr == 0 ) {
1019+ if (tu_bit_test (_usbh_data .attach_debouncing_bm , event -> rhport )) {
1020+ return ;
1021+ }
1022+
1023+ if (event -> event_id == HCD_EVENT_DEVICE_ATTACH ) {
1024+ // No debouncing, set flag if attach event
1025+ _usbh_data .attach_debouncing_bm |= TU_BIT (event -> rhport );
1026+ }
1027+ }
10281028 break ;
10291029
10301030 default : break ;
@@ -1363,6 +1363,7 @@ enum { // USB 2.0 specs 7.1.7 for timing
13631363 ENUM_RESET_ROOT_DELAY_MS = 50 , // T(DRSTr) minimum 50 ms for reset from root port
13641364 ENUM_RESET_HUB_DELAY_MS = 20 , // T(DRST) 10-20 ms for hub reset
13651365 ENUM_RESET_RECOVERY_DELAY_MS = 10 , // T(RSTRCY) minimum 10 ms for reset recovery
1366+ ENUM_SET_ADDRESS_RECOVERY_DELAY_MS = 2 , // USB 2.0 Spec 9.2.6.3 min is 2 ms
13661367};
13671368
13681369enum {
@@ -1401,11 +1402,14 @@ static bool enum_new_device(hcd_event_t* event) {
14011402 dev0_bus -> hub_addr = event -> connection .hub_addr ;
14021403 dev0_bus -> hub_port = event -> connection .hub_port ;
14031404
1404- _usbh_data .enumerating_daddr = 0 ;
1405-
14061405 // wait until device connection is stable TODO non blocking
14071406 tusb_time_delay_ms_api (ENUM_DEBOUNCING_DELAY_MS );
14081407
1408+ // clear roothub debouncing delay
1409+ if (dev0_bus -> hub_addr == 0 ) {
1410+ _usbh_data .attach_debouncing_bm &= (uint8_t ) ~TU_BIT (dev0_bus -> rhport );
1411+ }
1412+
14091413 if (dev0_bus -> hub_addr == 0 ) {
14101414 // connected directly to roothub
14111415 // USB bus not active and frame number is not available yet.
@@ -1570,8 +1574,7 @@ static void process_enumeration(tuh_xfer_t* xfer) {
15701574 }
15711575
15721576 case ENUM_GET_DEVICE_DESC : {
1573- // Allow 2ms for address recovery time, Ref USB Spec 9.2.6.3
1574- tusb_time_delay_ms_api (2 );
1577+ tusb_time_delay_ms_api (ENUM_SET_ADDRESS_RECOVERY_DELAY_MS ); // set address recovery
15751578
15761579 const uint8_t new_addr = (uint8_t ) tu_le16toh (xfer -> setup -> wValue );
15771580 usbh_device_t * new_dev = get_device (new_addr );
0 commit comments