@@ -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
4950CFG_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 );
317319static void connection_clear_conn_change_complete (tuh_xfer_t * xfer );
318320static 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