@@ -307,6 +307,37 @@ TU_ATTR_ALWAYS_INLINE static inline bool queue_event(hcd_event_t const * event,
307
307
return true;
308
308
}
309
309
310
+ TU_ATTR_ALWAYS_INLINE static inline void _control_set_xfer_stage (uint8_t stage ) {
311
+ if (_usbh_data .ctrl_xfer_info .stage != stage ) {
312
+ (void ) osal_mutex_lock (_usbh_mutex , OSAL_TIMEOUT_WAIT_FOREVER );
313
+ _usbh_data .ctrl_xfer_info .stage = stage ;
314
+ (void ) osal_mutex_unlock (_usbh_mutex );
315
+ }
316
+ }
317
+
318
+ TU_ATTR_ALWAYS_INLINE static inline bool usbh_setup_send (uint8_t daddr , const uint8_t setup_packet [8 ]) {
319
+ const uint8_t rhport = usbh_get_rhport (daddr );
320
+ const bool ret = hcd_setup_send (rhport , daddr , setup_packet );
321
+ if (!ret ) {
322
+ _control_set_xfer_stage (CONTROL_STAGE_IDLE );
323
+ }
324
+ return ret ;
325
+ }
326
+
327
+ TU_ATTR_ALWAYS_INLINE static inline void usbh_device_close (uint8_t rhport , uint8_t daddr ) {
328
+ hcd_device_close (rhport , daddr );
329
+
330
+ // abort any ongoing control transfer
331
+ if (daddr == _usbh_data .ctrl_xfer_info .daddr ) {
332
+ _control_set_xfer_stage (CONTROL_STAGE_IDLE );
333
+ }
334
+
335
+ // invalidate if enumerating
336
+ if (daddr == _usbh_data .enumerating_daddr ) {
337
+ _usbh_data .enumerating_daddr = TUSB_INDEX_INVALID_8 ;
338
+ }
339
+ }
340
+
310
341
//--------------------------------------------------------------------+
311
342
// Device API
312
343
//--------------------------------------------------------------------+
@@ -530,8 +561,17 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) {
530
561
break ;
531
562
532
563
case HCD_EVENT_DEVICE_REMOVE :
533
- TU_LOG_USBH ("[%u:%u:%u] USBH DEVICE REMOVED\r\n" , event .rhport , event .connection .hub_addr , event .connection .hub_port );
534
- process_removed_device (event .rhport , event .connection .hub_addr , event .connection .hub_port );
564
+ TU_LOG1 ("[%u:%u:%u] USBH DEVICE REMOVED\r\n" , event .rhport , event .connection .hub_addr , event .connection .hub_port );
565
+
566
+ if (_usbh_data .enumerating_daddr == 0 &&
567
+ event .rhport == _usbh_data .dev0_bus .rhport &&
568
+ event .connection .hub_addr == _usbh_data .dev0_bus .hub_addr &&
569
+ event .connection .hub_port == _usbh_data .dev0_bus .hub_port ) {
570
+ // dev0 is unplugged while enumerating (not yet assigned an address)
571
+ usbh_device_close (_usbh_data .dev0_bus .rhport , 0 );
572
+ } else {
573
+ process_removed_device (event .rhport , event .connection .hub_addr , event .connection .hub_port );
574
+ }
535
575
536
576
#if CFG_TUH_HUB
537
577
// TODO remove
@@ -623,23 +663,6 @@ static void _control_blocking_complete_cb(tuh_xfer_t* xfer) {
623
663
* ((xfer_result_t * ) xfer -> user_data ) = xfer -> result ;
624
664
}
625
665
626
- TU_ATTR_ALWAYS_INLINE static inline void _control_set_xfer_stage (uint8_t stage ) {
627
- if (_usbh_data .ctrl_xfer_info .stage != stage ) {
628
- (void ) osal_mutex_lock (_usbh_mutex , OSAL_TIMEOUT_WAIT_FOREVER );
629
- _usbh_data .ctrl_xfer_info .stage = stage ;
630
- (void ) osal_mutex_unlock (_usbh_mutex );
631
- }
632
- }
633
-
634
- TU_ATTR_ALWAYS_INLINE static inline bool usbh_setup_send (uint8_t daddr , const uint8_t setup_packet [8 ]) {
635
- const uint8_t rhport = usbh_get_rhport (daddr );
636
- const bool ret = hcd_setup_send (rhport , daddr , setup_packet );
637
- if (!ret ) {
638
- _control_set_xfer_stage (CONTROL_STAGE_IDLE );
639
- }
640
- return ret ;
641
- }
642
-
643
666
// TODO timeout_ms is not supported yet
644
667
bool tuh_control_xfer (tuh_xfer_t * xfer ) {
645
668
TU_VERIFY (xfer -> ep_addr == 0 && xfer -> setup ); // EP0 with setup packet
@@ -1270,21 +1293,8 @@ TU_ATTR_ALWAYS_INLINE static inline bool is_hub_addr(uint8_t daddr) {
1270
1293
1271
1294
// a device unplugged from rhport:hub_addr:hub_port
1272
1295
static void process_removed_device (uint8_t rhport , uint8_t hub_addr , uint8_t hub_port ) {
1273
- // if dev0 is unplugged while enumerating (not yet assigned an address)
1274
- if (_usbh_data .enumerating_daddr == 0 ) {
1275
- const tuh_bus_info_t * dev0_bus = & _usbh_data .dev0_bus ;
1276
- if ((rhport == dev0_bus -> rhport ) && (hub_addr == dev0_bus -> hub_addr ) && (hub_port == dev0_bus -> hub_port )) {
1277
- hcd_device_close (dev0_bus -> rhport , 0 );
1278
- if (_usbh_data .ctrl_xfer_info .daddr == 0 ) {
1279
- _control_set_xfer_stage (CONTROL_STAGE_IDLE );
1280
- }
1281
- _usbh_data .enumerating_daddr = TUSB_INDEX_INVALID_8 ;
1282
- return ;
1283
- }
1284
- }
1285
-
1286
- //------------- find the all devices (star-network) under port that is unplugged -------------//
1287
- uint32_t removing_hubs = 0 ;
1296
+ // Find the all devices (star-network) under port that is unplugged
1297
+ uint32_t removing_hubs_bm = 0 ;
1288
1298
do {
1289
1299
for (uint8_t dev_id = 0 ; dev_id < TOTAL_DEVICES ; dev_id ++ ) {
1290
1300
usbh_device_t * dev = & _usbh_devices [dev_id ];
@@ -1298,7 +1308,7 @@ static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub
1298
1308
1299
1309
if (is_hub_addr (daddr )) {
1300
1310
TU_LOG_USBH (" is a HUB device %u\r\n" , daddr );
1301
- removing_hubs |= TU_BIT (dev_id - CFG_TUH_DEVICE_MAX );
1311
+ removing_hubs_bm |= TU_BIT (dev_id - CFG_TUH_DEVICE_MAX );
1302
1312
} else {
1303
1313
// Invoke callback before closing driver (maybe call it later ?)
1304
1314
if (tuh_umount_cb ) {
@@ -1314,30 +1324,21 @@ static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub
1314
1324
}
1315
1325
}
1316
1326
1317
- hcd_device_close (rhport , daddr );
1327
+ usbh_device_close (rhport , daddr );
1318
1328
clear_device (dev );
1319
-
1320
- // abort ongoing control xfer on this device if any
1321
- if (daddr == _usbh_data .ctrl_xfer_info .daddr ) {
1322
- _control_set_xfer_stage (CONTROL_STAGE_IDLE );
1323
- }
1324
-
1325
- if (daddr == _usbh_data .enumerating_daddr ) {
1326
- _usbh_data .enumerating_daddr = TUSB_INDEX_INVALID_8 ;
1327
- }
1328
1329
}
1329
1330
}
1330
1331
1331
1332
// if removing a hub, we need to remove all of its downstream devices
1332
1333
#if CFG_TUH_HUB
1333
- if (removing_hubs == 0 ) {
1334
+ if (removing_hubs_bm == 0 ) {
1334
1335
break ;
1335
1336
}
1336
1337
1337
1338
// find a marked hub to process
1338
1339
for (uint8_t h_id = 0 ; h_id < CFG_TUH_HUB ; h_id ++ ) {
1339
- if (tu_bit_test (removing_hubs , h_id )) {
1340
- removing_hubs &= ~TU_BIT (h_id );
1340
+ if (tu_bit_test (removing_hubs_bm , h_id )) {
1341
+ removing_hubs_bm &= ~TU_BIT (h_id );
1341
1342
1342
1343
// update hub_addr and hub_port for next loop
1343
1344
hub_addr = h_id + 1 + CFG_TUH_DEVICE_MAX ;
@@ -1560,6 +1561,10 @@ static void process_enumeration(tuh_xfer_t* xfer) {
1560
1561
}
1561
1562
1562
1563
case ENUM_SET_ADDR : {
1564
+ // Due to physical debouncing, some devices can cause multiple attaches (actually reset) without detach event
1565
+ // Force remove currently mounted with the same bus info (rhport, hub addr, hub port) if exists
1566
+ process_removed_device (dev0_bus -> rhport , dev0_bus -> hub_addr , dev0_bus -> hub_port );
1567
+
1563
1568
const tusb_desc_device_t * desc_device = (const tusb_desc_device_t * ) _usbh_epbuf .ctrl ;
1564
1569
const uint8_t new_addr = enum_get_new_address (desc_device -> bDeviceClass == TUSB_CLASS_HUB );
1565
1570
TU_ASSERT (new_addr != 0 ,);
@@ -1582,7 +1587,7 @@ static void process_enumeration(tuh_xfer_t* xfer) {
1582
1587
new_dev -> addressed = 1 ;
1583
1588
_usbh_data .enumerating_daddr = new_addr ;
1584
1589
1585
- hcd_device_close (dev0_bus -> rhport , 0 ); // close dev0
1590
+ usbh_device_close (dev0_bus -> rhport , 0 ); // close dev0
1586
1591
1587
1592
TU_ASSERT (usbh_edpt_control_open (new_addr , new_dev -> ep0_size ),); // open new control endpoint
1588
1593
0 commit comments