Skip to content

Commit 792b2fb

Browse files
authored
Merge pull request hathach#1603 from Ryzee119/hub_improv
Host hub clear port and device interrupts
2 parents 585f37a + 2b2354d commit 792b2fb

File tree

1 file changed

+74
-14
lines changed

1 file changed

+74
-14
lines changed

src/host/hub.c

Lines changed: 74 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ typedef struct
4444
uint8_t status_change; // data from status change interrupt endpoint
4545

4646
hub_port_status_response_t port_status;
47+
hub_status_response_t hub_status;
4748
} hub_interface_t;
4849

4950
CFG_TUSB_MEM_SECTION static hub_interface_t hub_data[CFG_TUH_HUB];
@@ -85,7 +86,7 @@ bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature,
8586
{
8687
.bmRequestType_bit =
8788
{
88-
.recipient = TUSB_REQ_RCPT_OTHER,
89+
.recipient = (hub_port == 0) ? TUSB_REQ_RCPT_DEVICE : TUSB_REQ_RCPT_OTHER,
8990
.type = TUSB_REQ_TYPE_CLASS,
9091
.direction = TUSB_DIR_OUT
9192
},
@@ -117,7 +118,7 @@ bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature,
117118
{
118119
.bmRequestType_bit =
119120
{
120-
.recipient = TUSB_REQ_RCPT_OTHER,
121+
.recipient = (hub_port == 0) ? TUSB_REQ_RCPT_DEVICE : TUSB_REQ_RCPT_OTHER,
121122
.type = TUSB_REQ_TYPE_CLASS,
122123
.direction = TUSB_DIR_OUT
123124
},
@@ -149,7 +150,7 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp,
149150
{
150151
.bmRequestType_bit =
151152
{
152-
.recipient = TUSB_REQ_RCPT_OTHER,
153+
.recipient = (hub_port == 0) ? TUSB_REQ_RCPT_DEVICE : TUSB_REQ_RCPT_OTHER,
153154
.type = TUSB_REQ_TYPE_CLASS,
154155
.direction = TUSB_DIR_IN
155156
},
@@ -313,7 +314,8 @@ static void config_port_power_complete (tuh_xfer_t* xfer)
313314
// Connection Changes
314315
//--------------------------------------------------------------------+
315316

316-
static void connection_get_status_complete (tuh_xfer_t* xfer);
317+
static void hub_port_get_status_complete (tuh_xfer_t* xfer);
318+
static void hub_get_status_complete (tuh_xfer_t* xfer);
317319
static void connection_clear_conn_change_complete (tuh_xfer_t* xfer);
318320
static void connection_port_reset_complete (tuh_xfer_t* xfer);
319321

@@ -326,19 +328,31 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32
326328

327329
hub_interface_t* p_hub = get_itf(dev_addr);
328330

329-
TU_LOG2(" Port Status Change = 0x%02X\r\n", p_hub->status_change);
331+
TU_LOG2(" Hub Status Change = 0x%02X\r\n", p_hub->status_change);
330332

331-
// Hub ignore bit0 in status change
332-
for (uint8_t port=1; port <= p_hub->port_count; port++)
333+
// Hub bit 0 is for the hub device events
334+
if (tu_bit_test(p_hub->status_change, 0))
333335
{
334-
if ( tu_bit_test(p_hub->status_change, port) )
336+
if (hub_port_get_status(dev_addr, 0, &p_hub->hub_status, hub_get_status_complete, 0) == false)
335337
{
336-
if (hub_port_get_status(dev_addr, port, &p_hub->port_status, connection_get_status_complete, 0) == false)
338+
//Hub status control transfer failed, retry
339+
hub_edpt_status_xfer(dev_addr);
340+
}
341+
}
342+
else
343+
{
344+
// Hub bits 1 to n are hub port events
345+
for (uint8_t port=1; port <= p_hub->port_count; port++)
346+
{
347+
if ( tu_bit_test(p_hub->status_change, port) )
337348
{
338-
//Hub status control transfer failed, retry
339-
hub_edpt_status_xfer(dev_addr);
349+
if (hub_port_get_status(dev_addr, port, &p_hub->port_status, hub_port_get_status_complete, 0) == false)
350+
{
351+
//Hub status control transfer failed, retry
352+
hub_edpt_status_xfer(dev_addr);
353+
}
354+
break;
340355
}
341-
break;
342356
}
343357
}
344358

@@ -347,7 +361,36 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32
347361
return true;
348362
}
349363

350-
static void connection_get_status_complete (tuh_xfer_t* xfer)
364+
static void hub_clear_feature_complete_stub(tuh_xfer_t* xfer)
365+
{
366+
TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, );
367+
hub_edpt_status_xfer(xfer->daddr);
368+
}
369+
370+
static void hub_get_status_complete (tuh_xfer_t* xfer)
371+
{
372+
TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, );
373+
374+
uint8_t const daddr = xfer->daddr;
375+
hub_interface_t* p_hub = get_itf(daddr);
376+
uint8_t const port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex);
377+
TU_ASSERT(port_num == 0 , );
378+
379+
TU_LOG2("HUB Got hub status, addr = %u, status = %04x\r\n", daddr, p_hub->hub_status.change.value);
380+
381+
if (p_hub->hub_status.change.local_power_source)
382+
{
383+
TU_LOG2("HUB Local Power Change, addr = %u\r\n", daddr);
384+
hub_port_clear_feature(daddr, port_num, HUB_FEATURE_HUB_LOCAL_POWER_CHANGE, hub_clear_feature_complete_stub, 0);
385+
}
386+
else if (p_hub->hub_status.change.over_current)
387+
{
388+
TU_LOG1("HUB Over Current, addr = %u\r\n", daddr);
389+
hub_port_clear_feature(daddr, port_num, HUB_FEATURE_HUB_OVER_CURRENT_CHANGE, hub_clear_feature_complete_stub, 0);
390+
}
391+
}
392+
393+
static void hub_port_get_status_complete (tuh_xfer_t* xfer)
351394
{
352395
TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, );
353396

@@ -365,7 +408,24 @@ static void connection_get_status_complete (tuh_xfer_t* xfer)
365408
hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_CONNECTION_CHANGE, connection_clear_conn_change_complete, 0);
366409
}else
367410
{
368-
// Other changes are: Enable, Suspend, Over Current, Reset, L1 state
411+
// Clear other port status change interrupts. TODO Not currently handled - just cleared.
412+
if (p_hub->port_status.change.port_enable)
413+
{
414+
hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_ENABLE_CHANGE, hub_clear_feature_complete_stub, 0);
415+
}
416+
else if (p_hub->port_status.change.suspend)
417+
{
418+
hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_SUSPEND_CHANGE, hub_clear_feature_complete_stub, 0);
419+
}
420+
else if (p_hub->port_status.change.over_current)
421+
{
422+
hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_OVER_CURRENT_CHANGE, hub_clear_feature_complete_stub, 0);
423+
}
424+
else if (p_hub->port_status.change.reset)
425+
{
426+
hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_RESET_CHANGE, hub_clear_feature_complete_stub, 0);
427+
}
428+
// Other changes are: L1 state
369429
// TODO clear change
370430

371431
// prepare for next hub status

0 commit comments

Comments
 (0)