From 3c7b5dcaffb9ccc81e700d5b0b212e897b4b9b0d Mon Sep 17 00:00:00 2001 From: Ryzee119 Date: Mon, 15 Aug 2022 17:39:32 +0930 Subject: [PATCH] Hub: Handle hub device status change interrupt --- src/host/hub.c | 59 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 8 deletions(-) diff --git a/src/host/hub.c b/src/host/hub.c index dc2e4e759..99c629071 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -44,6 +44,7 @@ typedef struct uint8_t status_change; // data from status change interrupt endpoint hub_port_status_response_t port_status; + hub_status_response_t hub_status; } hub_interface_t; CFG_TUSB_MEM_SECTION static hub_interface_t hub_data[CFG_TUH_HUB]; @@ -314,6 +315,7 @@ static void config_port_power_complete (tuh_xfer_t* xfer) //--------------------------------------------------------------------+ static void hub_port_get_status_complete (tuh_xfer_t* xfer); +static void hub_get_status_complete (tuh_xfer_t* xfer); static void connection_clear_conn_change_complete (tuh_xfer_t* xfer); static void connection_port_reset_complete (tuh_xfer_t* xfer); @@ -326,19 +328,31 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32 hub_interface_t* p_hub = get_itf(dev_addr); - TU_LOG2(" Port Status Change = 0x%02X\r\n", p_hub->status_change); + TU_LOG2(" Hub Status Change = 0x%02X\r\n", p_hub->status_change); - // Hub ignore bit0 in status change - for (uint8_t port=1; port <= p_hub->port_count; port++) + // Hub bit 0 is for the hub device events + if (tu_bit_test(p_hub->status_change, 0)) { - if ( tu_bit_test(p_hub->status_change, port) ) + if (hub_port_get_status(dev_addr, 0, &p_hub->hub_status, hub_get_status_complete, 0) == false) { - if (hub_port_get_status(dev_addr, port, &p_hub->port_status, hub_port_get_status_complete, 0) == false) + //Hub status control transfer failed, retry + hub_edpt_status_xfer(dev_addr); + } + } + else + { + // Hub bits 1 to n are hub port events + for (uint8_t port=1; port <= p_hub->port_count; port++) + { + if ( tu_bit_test(p_hub->status_change, port) ) { - //Hub status control transfer failed, retry - hub_edpt_status_xfer(dev_addr); + if (hub_port_get_status(dev_addr, port, &p_hub->port_status, hub_port_get_status_complete, 0) == false) + { + //Hub status control transfer failed, retry + hub_edpt_status_xfer(dev_addr); + } + break; } - break; } } @@ -347,6 +361,35 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32 return true; } +static void hub_clear_feature_complete_stub(tuh_xfer_t* xfer) +{ + TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); + hub_edpt_status_xfer(xfer->daddr); +} + +static void hub_get_status_complete (tuh_xfer_t* xfer) +{ + TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); + + uint8_t const daddr = xfer->daddr; + hub_interface_t* p_hub = get_itf(daddr); + uint8_t const port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); + TU_ASSERT(port_num == 0 , ); + + TU_LOG2("HUB Got hub status, addr = %u, status = %04x\r\n", daddr, p_hub->hub_status.change.value); + + if (p_hub->hub_status.change.local_power_source) + { + TU_LOG2("HUB Local Power Change, addr = %u\r\n", daddr); + hub_port_clear_feature(daddr, port_num, HUB_FEATURE_HUB_LOCAL_POWER_CHANGE, hub_clear_feature_complete_stub, 0); + } + else if (p_hub->hub_status.change.over_current) + { + TU_LOG1("HUB Over Current, addr = %u\r\n", daddr); + hub_port_clear_feature(daddr, port_num, HUB_FEATURE_HUB_OVER_CURRENT_CHANGE, hub_clear_feature_complete_stub, 0); + } +} + static void hub_port_get_status_complete (tuh_xfer_t* xfer) { TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, );