@@ -1100,6 +1100,12 @@ uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_i
1100
1100
//
1101
1101
//--------------------------------------------------------------------+
1102
1102
1103
+ TU_ATTR_ALWAYS_INLINE
1104
+ static inline bool is_hub_addr (uint8_t daddr )
1105
+ {
1106
+ return (CFG_TUH_HUB > 0 ) && (daddr > CFG_TUH_DEVICE_MAX );
1107
+ }
1108
+
1103
1109
// a device unplugged from rhport:hub_addr:hub_port
1104
1110
static void process_device_unplugged (uint8_t rhport , uint8_t hub_addr , uint8_t hub_port )
1105
1111
{
@@ -1112,14 +1118,23 @@ static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t h
1112
1118
1113
1119
// TODO Hub multiple level
1114
1120
if (dev -> rhport == rhport &&
1115
- (hub_addr == 0 || dev -> hub_addr == hub_addr ) && // hub_addr == 0 & hub_port == 0 means roothub
1116
- (hub_port == 0 || dev -> hub_port == hub_port ) &&
1121
+ (hub_addr == 0 || dev -> hub_addr == hub_addr ) && // hub_addr = 0 means roothub
1122
+ (hub_port == 0 || dev -> hub_port == hub_port ) && // hub_port = 0 means all devices of downstream hub
1117
1123
dev -> connected )
1118
1124
{
1119
1125
TU_LOG2 (" Address = %u\r\n" , dev_addr );
1120
1126
1121
- // Invoke callback before close driver
1122
- if (tuh_umount_cb ) tuh_umount_cb (dev_addr );
1127
+ if (is_hub_addr (dev_addr ))
1128
+ {
1129
+ TU_LOG (USBH_DBG_LVL , "HUB address = %u is unmounted\r\n" , dev_addr );
1130
+ // If the device itself is a usb hub, unplug downstream devices.
1131
+ // FIXME un-roll recursive calls to prevent potential stack overflow
1132
+ process_device_unplugged (rhport , dev_addr , 0 );
1133
+ }else
1134
+ {
1135
+ // Invoke callback before closing driver
1136
+ if (tuh_umount_cb ) tuh_umount_cb (dev_addr );
1137
+ }
1123
1138
1124
1139
// Close class driver
1125
1140
for (uint8_t drv_id = 0 ; drv_id < USBH_CLASS_DRIVER_COUNT ; drv_id ++ )
@@ -1402,12 +1417,6 @@ static bool enum_new_device(hcd_event_t* event)
1402
1417
return true;
1403
1418
}
1404
1419
1405
- TU_ATTR_ALWAYS_INLINE
1406
- static inline bool is_hub_addr (uint8_t daddr )
1407
- {
1408
- return daddr > CFG_TUH_DEVICE_MAX ;
1409
- }
1410
-
1411
1420
static uint8_t get_new_address (bool is_hub )
1412
1421
{
1413
1422
uint8_t start ;
@@ -1520,40 +1529,31 @@ static bool _parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configur
1520
1529
uint16_t const drv_len = tu_desc_get_interface_total_len (desc_itf , assoc_itf_count , desc_end - p_desc );
1521
1530
TU_ASSERT (drv_len >= sizeof (tusb_desc_interface_t ));
1522
1531
1523
- if (desc_itf -> bInterfaceClass == TUSB_CLASS_HUB && dev -> hub_addr != 0 )
1532
+ // Find driver for this interface
1533
+ uint8_t drv_id ;
1534
+ for (drv_id = 0 ; drv_id < USBH_CLASS_DRIVER_COUNT ; drv_id ++ )
1524
1535
{
1525
- // TODO Attach hub to Hub is not currently supported
1526
- // skip this interface
1527
- TU_LOG (USBH_DBG_LVL , "Only 1 level of HUB is supported\r\n" );
1528
- }
1529
- else
1530
- {
1531
- // Find driver for this interface
1532
- uint8_t drv_id ;
1533
- for (drv_id = 0 ; drv_id < USBH_CLASS_DRIVER_COUNT ; drv_id ++ )
1536
+ usbh_class_driver_t const * driver = & usbh_class_drivers [drv_id ];
1537
+
1538
+ if ( driver -> open (dev -> rhport , dev_addr , desc_itf , drv_len ) )
1534
1539
{
1535
- usbh_class_driver_t const * driver = & usbh_class_drivers [drv_id ];
1540
+ // open successfully
1541
+ TU_LOG2 (" %s opened\r\n" , driver -> name );
1536
1542
1537
- if ( driver -> open (dev -> rhport , dev_addr , desc_itf , drv_len ) )
1543
+ // bind (associated) interfaces to found driver
1544
+ for (uint8_t i = 0 ; i < assoc_itf_count ; i ++ )
1538
1545
{
1539
- // open successfully
1540
- TU_LOG2 (" %s opened\r\n" , driver -> name );
1541
-
1542
- // bind (associated) interfaces to found driver
1543
- for (uint8_t i = 0 ; i < assoc_itf_count ; i ++ )
1544
- {
1545
- uint8_t const itf_num = desc_itf -> bInterfaceNumber + i ;
1546
+ uint8_t const itf_num = desc_itf -> bInterfaceNumber + i ;
1546
1547
1547
- // Interface number must not be used already
1548
- TU_ASSERT ( DRVID_INVALID == dev -> itf2drv [itf_num ] );
1549
- dev -> itf2drv [itf_num ] = drv_id ;
1550
- }
1548
+ // Interface number must not be used already
1549
+ TU_ASSERT ( DRVID_INVALID == dev -> itf2drv [itf_num ] );
1550
+ dev -> itf2drv [itf_num ] = drv_id ;
1551
+ }
1551
1552
1552
- // bind all endpoints to found driver
1553
- tu_edpt_bind_driver (dev -> ep2drv , desc_itf , drv_len , drv_id );
1553
+ // bind all endpoints to found driver
1554
+ tu_edpt_bind_driver (dev -> ep2drv , desc_itf , drv_len , drv_id );
1554
1555
1555
- break ; // exit driver find loop
1556
- }
1556
+ break ; // exit driver find loop
1557
1557
}
1558
1558
1559
1559
if ( drv_id >= USBH_CLASS_DRIVER_COUNT )
@@ -1593,10 +1593,10 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num)
1593
1593
{
1594
1594
enum_full_complete ();
1595
1595
1596
- # if CFG_TUH_HUB
1597
- // skip device mount callback for hub
1598
- if ( ! is_hub_addr ( dev_addr ) )
1599
- #endif
1596
+ if ( is_hub_addr ( dev_addr ))
1597
+ {
1598
+ TU_LOG ( USBH_DBG_LVL , "HUB address = %u is mounted\r\n" , dev_addr );
1599
+ } else
1600
1600
{
1601
1601
// Invoke callback if available
1602
1602
if (tuh_mount_cb ) tuh_mount_cb (dev_addr );
0 commit comments