summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyzee119 <[email protected]>2022-08-15 17:39:32 +0930
committerRyan Wendland <[email protected]>2022-08-16 18:25:43 +0930
commit3c7b5dcaffb9ccc81e700d5b0b212e897b4b9b0d (patch)
tree7f39622266a531a3e15b2d5a5f271c5f462e18e3
parentaafea8ef5d6f329d66c6c1e903b8a6b33d769ad5 (diff)
Hub: Handle hub device status change interrupt
-rw-r--r--src/host/hub.c59
1 files 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, );