mirror of
https://github.com/hathach/tinyusb.git
synced 2025-01-31 05:52:55 +08:00
Merge pull request #2550 from hathach/usbh-unroll-hub-remove
Usbh unroll hub removal
This commit is contained in:
commit
eaab04fefa
122
src/host/usbh.c
122
src/host/usbh.c
@ -1138,43 +1138,42 @@ bool tuh_interface_set(uint8_t daddr, uint8_t itf_num, uint8_t itf_alt,
|
||||
TU_VERIFY(_async_func(__VA_ARGS__, NULL, (uintptr_t) &result), XFER_RESULT_TIMEOUT); \
|
||||
return (uint8_t) result
|
||||
|
||||
uint8_t tuh_descriptor_get_sync(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len)
|
||||
{
|
||||
uint8_t tuh_descriptor_get_sync(uint8_t daddr, uint8_t type, uint8_t index,
|
||||
void* buffer, uint16_t len) {
|
||||
_CONTROL_SYNC_API(tuh_descriptor_get, daddr, type, index, buffer, len);
|
||||
}
|
||||
|
||||
uint8_t tuh_descriptor_get_device_sync(uint8_t daddr, void* buffer, uint16_t len)
|
||||
{
|
||||
uint8_t tuh_descriptor_get_device_sync(uint8_t daddr, void* buffer, uint16_t len) {
|
||||
_CONTROL_SYNC_API(tuh_descriptor_get_device, daddr, buffer, len);
|
||||
}
|
||||
|
||||
uint8_t tuh_descriptor_get_configuration_sync(uint8_t daddr, uint8_t index, void* buffer, uint16_t len)
|
||||
{
|
||||
uint8_t tuh_descriptor_get_configuration_sync(uint8_t daddr, uint8_t index,
|
||||
void* buffer, uint16_t len) {
|
||||
_CONTROL_SYNC_API(tuh_descriptor_get_configuration, daddr, index, buffer, len);
|
||||
}
|
||||
|
||||
uint8_t tuh_descriptor_get_hid_report_sync(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, uint8_t index, void* buffer, uint16_t len)
|
||||
{
|
||||
uint8_t tuh_descriptor_get_hid_report_sync(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, uint8_t index,
|
||||
void* buffer, uint16_t len) {
|
||||
_CONTROL_SYNC_API(tuh_descriptor_get_hid_report, daddr, itf_num, desc_type, index, buffer, len);
|
||||
}
|
||||
|
||||
uint8_t tuh_descriptor_get_string_sync(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len)
|
||||
{
|
||||
uint8_t tuh_descriptor_get_string_sync(uint8_t daddr, uint8_t index, uint16_t language_id,
|
||||
void* buffer, uint16_t len) {
|
||||
_CONTROL_SYNC_API(tuh_descriptor_get_string, daddr, index, language_id, buffer, len);
|
||||
}
|
||||
|
||||
uint8_t tuh_descriptor_get_manufacturer_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len)
|
||||
{
|
||||
uint8_t tuh_descriptor_get_manufacturer_string_sync(uint8_t daddr, uint16_t language_id,
|
||||
void* buffer, uint16_t len) {
|
||||
_CONTROL_SYNC_API(tuh_descriptor_get_manufacturer_string, daddr, language_id, buffer, len);
|
||||
}
|
||||
|
||||
uint8_t tuh_descriptor_get_product_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len)
|
||||
{
|
||||
uint8_t tuh_descriptor_get_product_string_sync(uint8_t daddr, uint16_t language_id,
|
||||
void* buffer, uint16_t len) {
|
||||
_CONTROL_SYNC_API(tuh_descriptor_get_product_string, daddr, language_id, buffer, len);
|
||||
}
|
||||
|
||||
uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len)
|
||||
{
|
||||
uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_id,
|
||||
void* buffer, uint16_t len) {
|
||||
_CONTROL_SYNC_API(tuh_descriptor_get_serial_string, daddr, language_id, buffer, len);
|
||||
}
|
||||
|
||||
@ -1210,57 +1209,60 @@ TU_ATTR_ALWAYS_INLINE static inline bool is_hub_addr(uint8_t daddr) {
|
||||
static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) {
|
||||
//------------- find the all devices (star-network) under port that is unplugged -------------//
|
||||
// TODO mark as disconnected in ISR, also handle dev0
|
||||
uint32_t removing_hubs = 0;
|
||||
do {
|
||||
for (uint8_t dev_id = 0; dev_id < TOTAL_DEVICES; dev_id++) {
|
||||
usbh_device_t* dev = &_usbh_devices[dev_id];
|
||||
uint8_t const daddr = dev_id + 1;
|
||||
|
||||
#if 0
|
||||
// index as hub addr, value is hub port (0xFF for invalid)
|
||||
uint8_t removing_hubs[CFG_TUH_HUB];
|
||||
memset(removing_hubs, TUSB_INDEX_INVALID_8, sizeof(removing_hubs));
|
||||
// hub_addr = 0 means roothub, hub_port = 0 means all devices of downstream hub
|
||||
if (dev->rhport == rhport && dev->connected &&
|
||||
(hub_addr == 0 || dev->hub_addr == hub_addr) &&
|
||||
(hub_port == 0 || dev->hub_port == hub_port)) {
|
||||
TU_LOG_USBH("[%u:%u:%u] unplugged address = %u\r\n", rhport, hub_addr, hub_port, daddr);
|
||||
|
||||
removing_hubs[hub_addr-CFG_TUH_DEVICE_MAX] = hub_port;
|
||||
if (is_hub_addr(daddr)) {
|
||||
TU_LOG_USBH(" is a HUB device %u\r\n", daddr);
|
||||
removing_hubs |= TU_BIT(dev_id - CFG_TUH_DEVICE_MAX);
|
||||
} else {
|
||||
// Invoke callback before closing driver (maybe call it later ?)
|
||||
if (tuh_umount_cb) tuh_umount_cb(daddr);
|
||||
}
|
||||
|
||||
// consecutive non-removing hub
|
||||
uint8_t nop_count = 0;
|
||||
#endif
|
||||
// Close class driver
|
||||
for (uint8_t drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) {
|
||||
usbh_class_driver_t const* driver = get_driver(drv_id);
|
||||
if (driver) driver->close(daddr);
|
||||
}
|
||||
|
||||
for (uint8_t dev_id = 0; dev_id < TOTAL_DEVICES; dev_id++) {
|
||||
usbh_device_t *dev = &_usbh_devices[dev_id];
|
||||
uint8_t const daddr = dev_id + 1;
|
||||
hcd_device_close(rhport, daddr);
|
||||
clear_device(dev);
|
||||
|
||||
// hub_addr = 0 means roothub, hub_port = 0 means all devices of downstream hub
|
||||
if (dev->rhport == rhport && dev->connected &&
|
||||
(hub_addr == 0 || dev->hub_addr == hub_addr) &&
|
||||
(hub_port == 0 || dev->hub_port == hub_port)) {
|
||||
TU_LOG_USBH("Device unplugged address = %u\r\n", daddr);
|
||||
|
||||
if (is_hub_addr(daddr)) {
|
||||
TU_LOG_USBH(" is a HUB device %u\r\n", daddr);
|
||||
|
||||
// Submit removed event If the device itself is a hub (un-rolled recursive)
|
||||
// TODO a better to unroll recursrive is using array of removing_hubs and mark it here
|
||||
hcd_event_t event;
|
||||
event.rhport = rhport;
|
||||
event.event_id = HCD_EVENT_DEVICE_REMOVE;
|
||||
event.connection.hub_addr = daddr;
|
||||
event.connection.hub_port = 0;
|
||||
|
||||
hcd_event_handler(&event, false);
|
||||
} else {
|
||||
// Invoke callback before closing driver (maybe call it later ?)
|
||||
if (tuh_umount_cb) tuh_umount_cb(daddr);
|
||||
// abort on-going control xfer on this device if any
|
||||
if (_ctrl_xfer.daddr == daddr) _set_control_xfer_stage(CONTROL_STAGE_IDLE);
|
||||
}
|
||||
|
||||
// Close class driver
|
||||
for (uint8_t drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) {
|
||||
usbh_class_driver_t const * driver = get_driver(drv_id);
|
||||
if ( driver ) driver->close(daddr);
|
||||
}
|
||||
|
||||
hcd_device_close(rhport, daddr);
|
||||
clear_device(dev);
|
||||
// abort on-going control xfer if any
|
||||
if (_ctrl_xfer.daddr == daddr) _set_control_xfer_stage(CONTROL_STAGE_IDLE);
|
||||
}
|
||||
}
|
||||
|
||||
// if removing a hub, we need to remove its downstream devices
|
||||
#if CFG_TUH_HUB
|
||||
if (removing_hubs == 0) break;
|
||||
|
||||
// find a marked hub to process
|
||||
for (uint8_t h_id = 0; h_id < CFG_TUH_HUB; h_id++) {
|
||||
if (tu_bit_test(removing_hubs, h_id)) {
|
||||
removing_hubs &= ~TU_BIT(h_id);
|
||||
|
||||
// update hub_addr and hub_port for next loop
|
||||
hub_addr = h_id + 1 + CFG_TUH_DEVICE_MAX;
|
||||
hub_port = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void) removing_hubs;
|
||||
break;
|
||||
#endif
|
||||
} while(1);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
|
Loading…
x
Reference in New Issue
Block a user