Skip to content

Commit df6c6f9

Browse files
Dazza0espressif-bot
authored andcommitted
refactor(usb/hub): Update Hub driver port request logic
1 parent 3358f3e commit df6c6f9

File tree

1 file changed

+51
-28
lines changed

1 file changed

+51
-28
lines changed

components/usb/hub.c

Lines changed: 51 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,12 @@ implement the bare minimum to control the root HCD port.
5050

5151
// Hub driver action flags. LISTED IN THE ORDER THEY SHOULD BE HANDLED IN within hub_process(). Some actions are mutually exclusive
5252
#define HUB_DRIVER_FLAG_ACTION_ROOT_EVENT 0x01
53-
#define HUB_DRIVER_FLAG_ACTION_PORT 0x02
53+
#define HUB_DRIVER_FLAG_ACTION_PORT_REQ 0x02
5454
#define HUB_DRIVER_FLAG_ACTION_ENUM_EVENT 0x04
5555

56+
#define PORT_REQ_DISABLE 0x01
57+
#define PORT_REQ_RECOVER 0x02
58+
5659
/**
5760
* @brief Root port states
5861
*
@@ -185,6 +188,7 @@ typedef struct {
185188
uint32_t val;
186189
} flags;
187190
root_port_state_t root_port_state;
191+
unsigned int port_reqs;
188192
} dynamic;
189193
// Single thread members don't require a critical section so long as they are never accessed from multiple threads
190194
struct {
@@ -679,7 +683,8 @@ static void enum_stage_cleanup_failed(enum_ctrl_t *enum_ctrl)
679683
HUB_DRIVER_ENTER_CRITICAL();
680684
// Enum could have failed due to a port error. If so, we need to trigger a port recovery
681685
if (p_hub_driver_obj->dynamic.root_port_state == ROOT_PORT_STATE_RECOVERY) {
682-
p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_PORT;
686+
p_hub_driver_obj->dynamic.port_reqs |= PORT_REQ_RECOVER;
687+
p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_PORT_REQ;
683688
} else {
684689
// Otherwise, we move to the enum failed state and wait for the device to disconnect
685690
p_hub_driver_obj->dynamic.root_port_state = ROOT_PORT_STATE_ENUM_FAILED;
@@ -839,7 +844,8 @@ static void root_port_handle_events(hcd_port_handle_t root_port_hdl)
839844
case ROOT_PORT_STATE_POWERED: // This occurred before enumeration
840845
case ROOT_PORT_STATE_ENUM_FAILED: // This occurred after a failed enumeration.
841846
// Therefore, there's no device and we can go straight to port recovery
842-
p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_PORT;
847+
p_hub_driver_obj->dynamic.port_reqs |= PORT_REQ_RECOVER;
848+
p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_PORT_REQ;
843849
break;
844850
case ROOT_PORT_STATE_ENUM:
845851
// This occurred during enumeration. Therefore, we need to cleanup the failed enumeration
@@ -867,6 +873,30 @@ static void root_port_handle_events(hcd_port_handle_t root_port_hdl)
867873
}
868874
}
869875

876+
static void root_port_req(hcd_port_handle_t root_port_hdl)
877+
{
878+
unsigned int port_reqs;
879+
880+
HUB_DRIVER_ENTER_CRITICAL();
881+
port_reqs = p_hub_driver_obj->dynamic.port_reqs;
882+
p_hub_driver_obj->dynamic.port_reqs = 0;
883+
HUB_DRIVER_EXIT_CRITICAL();
884+
885+
if (port_reqs & PORT_REQ_DISABLE) {
886+
ESP_LOGD(HUB_DRIVER_TAG, "Disabling root port");
887+
// We allow this to fail in case a disconnect/port error happens while disabling.
888+
hcd_port_command(p_hub_driver_obj->constant.root_port_hdl, HCD_PORT_CMD_DISABLE);
889+
}
890+
if (port_reqs & PORT_REQ_RECOVER) {
891+
ESP_LOGD(HUB_DRIVER_TAG, "Recovering root port");
892+
ESP_ERROR_CHECK(hcd_port_recover(p_hub_driver_obj->constant.root_port_hdl));
893+
ESP_ERROR_CHECK(hcd_port_command(p_hub_driver_obj->constant.root_port_hdl, HCD_PORT_CMD_POWER_ON));
894+
HUB_DRIVER_ENTER_CRITICAL();
895+
p_hub_driver_obj->dynamic.root_port_state = ROOT_PORT_STATE_POWERED;
896+
HUB_DRIVER_EXIT_CRITICAL();
897+
}
898+
}
899+
870900
static void enum_handle_events(void)
871901
{
872902
bool stage_pass;
@@ -1055,10 +1085,24 @@ esp_err_t hub_dev_is_free(uint8_t dev_addr)
10551085
{
10561086
assert(dev_addr == ENUM_DEV_ADDR);
10571087
assert(p_hub_driver_obj->single_thread.root_dev_hdl);
1058-
p_hub_driver_obj->single_thread.root_dev_hdl = NULL;
10591088
// Device is free, we can now request its port be recycled
1089+
hcd_port_state_t port_state = hcd_port_get_state(p_hub_driver_obj->constant.root_port_hdl);
1090+
p_hub_driver_obj->single_thread.root_dev_hdl = NULL;
1091+
10601092
HUB_DRIVER_ENTER_CRITICAL();
1061-
p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_PORT;
1093+
// How the port is recycled will depend on the port's state
1094+
switch (port_state) {
1095+
case HCD_PORT_STATE_ENABLED:
1096+
p_hub_driver_obj->dynamic.port_reqs |= PORT_REQ_DISABLE;
1097+
break;
1098+
case HCD_PORT_STATE_RECOVERY:
1099+
p_hub_driver_obj->dynamic.port_reqs |= PORT_REQ_RECOVER;
1100+
break;
1101+
default:
1102+
abort(); // Should never occur
1103+
break;
1104+
}
1105+
p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_PORT_REQ;
10621106
HUB_DRIVER_EXIT_CRITICAL();
10631107

10641108
p_hub_driver_obj->constant.proc_req_cb(USB_PROC_REQ_SOURCE_HUB, false, p_hub_driver_obj->constant.proc_req_cb_arg);
@@ -1076,29 +1120,8 @@ esp_err_t hub_process(void)
10761120
if (action_flags & HUB_DRIVER_FLAG_ACTION_ROOT_EVENT) {
10771121
root_port_handle_events(p_hub_driver_obj->constant.root_port_hdl);
10781122
}
1079-
if (action_flags & HUB_DRIVER_FLAG_ACTION_PORT) {
1080-
// Check current state of port
1081-
hcd_port_state_t port_state = hcd_port_get_state(p_hub_driver_obj->constant.root_port_hdl);
1082-
switch (port_state) {
1083-
case HCD_PORT_STATE_ENABLED:
1084-
// Port is still enabled with a connect device. Disable it.
1085-
ESP_LOGD(HUB_DRIVER_TAG, "Disabling root port");
1086-
// We allow this to fail in case a disconnect/port error happens while disabling.
1087-
hcd_port_command(p_hub_driver_obj->constant.root_port_hdl, HCD_PORT_CMD_DISABLE);
1088-
break;
1089-
case HCD_PORT_STATE_RECOVERY:
1090-
// Port is in recovery after a disconnect/error. Recover it.
1091-
ESP_LOGD(HUB_DRIVER_TAG, "Recovering root port");
1092-
ESP_ERROR_CHECK(hcd_port_recover(p_hub_driver_obj->constant.root_port_hdl));
1093-
ESP_ERROR_CHECK(hcd_port_command(p_hub_driver_obj->constant.root_port_hdl, HCD_PORT_CMD_POWER_ON));
1094-
HUB_DRIVER_ENTER_CRITICAL();
1095-
p_hub_driver_obj->dynamic.root_port_state = ROOT_PORT_STATE_POWERED;
1096-
HUB_DRIVER_EXIT_CRITICAL();
1097-
break;
1098-
default:
1099-
abort(); // Should never occur
1100-
break;
1101-
}
1123+
if (action_flags & HUB_DRIVER_FLAG_ACTION_PORT_REQ) {
1124+
root_port_req(p_hub_driver_obj->constant.root_port_hdl);
11021125
}
11031126
if (action_flags & HUB_DRIVER_FLAG_ACTION_ENUM_EVENT) {
11041127
enum_handle_events();

0 commit comments

Comments
 (0)