Skip to content

Commit 623f8c4

Browse files
feat(usb_host): Apply review comments, add dconn test
1 parent 025f3a1 commit 623f8c4

File tree

10 files changed

+100
-14
lines changed

10 files changed

+100
-14
lines changed

host/usb/private_include/hub.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ esp_err_t hub_uninstall(void);
112112
* @note This function should only be called from the Host Library task
113113
*
114114
* @return
115-
* - ESP_OK: Hub driver started successfully
115+
* - ESP_OK: Root port has been powered on
116116
* - ESP_ERR_INVALID_STATE: Hub driver is not installed, or root port is in other state than not powered
117117
*/
118118
esp_err_t hub_root_start(void);
@@ -123,7 +123,7 @@ esp_err_t hub_root_start(void);
123123
* This will power OFF the root port
124124
*
125125
* @return
126-
* - ESP_OK: Hub driver stopped successfully
126+
* - ESP_OK: Root port has been powered off
127127
* - ESP_ERR_INVALID_STATE: Hub driver is not installed, or root port is in not powered state
128128
*/
129129
esp_err_t hub_root_stop(void);

host/usb/src/hcd_dwc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1344,6 +1344,7 @@ static esp_err_t _port_cmd_bus_suspend(port_t *port)
13441344
// Here we are calling ll directly instead of hal, to allow the suspend/resume feature to be used as a managed usb
13451345
// component in all active IDF releases (Currently IDF 5.4.x, IDF 5.5.x and IDF 6.0) and all it's minor releases
13461346
// because the hal function usb_dwc_hal_port_check_if_suspended(port->hal) starts to be supported in IDF 5.5.2, (and IDF 5.4.2)
1347+
// TODO: use usb_dwc_hal_hprt_get_port_suspend() instead of usb_dwc_ll_hprt_get_port_suspend() when IDF 5.5 is EOL
13471348

13481349
// Sanity check, the root port should have entered the suspended state after the SUSPEND_ENTRY_MS delay
13491350
if (!usb_dwc_ll_hprt_get_port_suspend(port->hal->dev)) {

host/usb/src/usbh.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,7 @@ static inline void handle_prop_resume_event(device_t *dev_obj)
633633

634634
static inline void handle_prop_all_idle_event(void)
635635
{
636-
ESP_LOGD(USBH_TAG, "ALl devices idle");
636+
ESP_LOGD(USBH_TAG, "All devices idle");
637637
usbh_event_data_t event_data = {
638638
.event = USBH_EVENT_ALL_IDLE,
639639
};

host/usb/test/target_test/common/dev_msc.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -99,7 +99,7 @@ static const dev_msc_info_t dev_info = {
9999
.bInterfaceNumber = 0x00,
100100
.bAlternateSetting = 0x00,
101101
.in_ep_addr = 0x81,
102-
.out_up_addr = 0x02,
102+
.out_ep_addr = 0x02,
103103
.scsi_sector_size = 512,
104104
};
105105

host/usb/test/target_test/common/dev_msc.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -34,7 +34,7 @@ typedef struct {
3434
uint8_t bInterfaceNumber;
3535
uint8_t bAlternateSetting;
3636
uint8_t in_ep_addr;
37-
uint8_t out_up_addr;
37+
uint8_t out_ep_addr;
3838
unsigned int scsi_sector_size;
3939
} dev_msc_info_t;
4040

host/usb/test/target_test/usb_host/main/msc_client_async_dconn.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ void msc_client_async_dconn_task(void *arg)
234234
msc_obj.dev_info->scsi_sector_size,
235235
msc_obj.test_param.msc_scsi_xfer_tag);
236236
xfer_out->num_bytes = sizeof(mock_msc_bulk_cbw_t);
237-
xfer_out->bEndpointAddress = msc_obj.dev_info->out_up_addr;
237+
xfer_out->bEndpointAddress = msc_obj.dev_info->out_ep_addr;
238238
TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_submit(xfer_out));
239239
// Next stage set from transfer callback
240240
break;

host/usb/test/target_test/usb_host/main/msc_client_async_seq.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ void msc_client_async_seq_task(void *arg)
236236
msc_obj.dev_info->scsi_sector_size,
237237
msc_obj.test_param.msc_scsi_xfer_tag);
238238
xfer_out->num_bytes = sizeof(mock_msc_bulk_cbw_t);
239-
xfer_out->bEndpointAddress = msc_obj.dev_info->out_up_addr;
239+
xfer_out->bEndpointAddress = msc_obj.dev_info->out_ep_addr;
240240
TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_submit(xfer_out));
241241
// Test that an inflight transfer cannot be resubmitted
242242
TEST_ASSERT_EQUAL(ESP_ERR_NOT_FINISHED, usb_host_transfer_submit(xfer_out));

host/usb/test/target_test/usb_host/main/msc_client_suspend.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ void msc_client_async_suspend_resume_task(void *arg)
318318
msc_obj.dev_info->scsi_sector_size,
319319
msc_obj.test_param.msc_scsi_xfer_tag);
320320
xfer_out->num_bytes = sizeof(mock_msc_bulk_cbw_t);
321-
xfer_out->bEndpointAddress = msc_obj.dev_info->out_up_addr;
321+
xfer_out->bEndpointAddress = msc_obj.dev_info->out_ep_addr;
322322
TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_submit(xfer_out));
323323
// Next stage set from transfer callback
324324
break;

host/usb/test/target_test/usb_host/main/msc_client_transfer_resume.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ void msc_client_async_resume_by_transfer_task(void *arg)
278278
msc_obj.dev_info->scsi_sector_size,
279279
msc_obj.test_param.msc_scsi_xfer_tag);
280280
xfer_out->num_bytes = sizeof(mock_msc_bulk_cbw_t);
281-
xfer_out->bEndpointAddress = msc_obj.dev_info->out_up_addr;
281+
xfer_out->bEndpointAddress = msc_obj.dev_info->out_ep_addr;
282282
TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_submit(xfer_out));
283283
// Test that pending transfers can't be resubmitted
284284
TEST_ASSERT_EQUAL(ESP_ERR_NOT_FINISHED, usb_host_transfer_submit(xfer_out));

host/usb/test/target_test/usb_host/main/test_usb_host_plugging.c

Lines changed: 88 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -49,7 +49,7 @@ TEST_CASE("Test USB Host sudden disconnection (no client)", "[usb_host][low_spee
4949
connected = true;
5050
printf("Forcing Sudden Disconnect\n");
5151
// Trigger a disconnect by powering OFF the root port
52-
usb_host_lib_set_root_port_power(false);
52+
TEST_ASSERT_EQUAL(ESP_OK, usb_host_lib_set_root_port_power(false));
5353
}
5454
}
5555
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) {
@@ -59,7 +59,92 @@ TEST_CASE("Test USB Host sudden disconnection (no client)", "[usb_host][low_spee
5959
// Start next iteration
6060
connected = false;
6161
// Allow connections again by powering ON the root port
62-
usb_host_lib_set_root_port_power(true);
62+
TEST_ASSERT_EQUAL(ESP_OK, usb_host_lib_set_root_port_power(true));
63+
} else {
64+
break;
65+
}
66+
}
67+
}
68+
}
69+
70+
/*
71+
Test USB Host Library root port suspend with Sudden Disconnection Handling (no clients)
72+
Purpose:
73+
- Test that sudden disconnections after suspending are handled properly when there are no clients
74+
- Test that devices can reconnect after suspending with a sudden disconnection has been handled by the USB Host Library
75+
76+
Procedure:
77+
- Install USB Host Library:
78+
- Wait for connection to occur and suspend the root port
79+
- Let the usb_host lib to handle events caused by root port suspend call
80+
- Force a disconnection, then wait for disconnection to be handled (USB_HOST_LIB_EVENT_FLAGS_ALL_FREE)
81+
- Allow connections again, and repeat test for multiple iterations
82+
- Wait for connection to occur and suspend the root port
83+
- Don't handle events (just mark the root port for suspending)
84+
- Force a disconnection, then wait for disconnection to be handled (USB_HOST_LIB_EVENT_FLAGS_ALL_FREE)
85+
- Allow connections again, and repeat test for multiple iterations
86+
*/
87+
88+
#define TEST_DCONN_SUSPEND_ITERATIONS 6
89+
90+
TEST_CASE("Test USB Host suspend + disconnection (no client)", "[usb_host][low_speed][full_speed][high_speed]")
91+
{
92+
bool connected = false;
93+
bool suspended = false;
94+
int dconn_iter = 0;
95+
while (1) {
96+
// Start handling system events
97+
uint32_t event_flags;
98+
usb_host_lib_handle_events(portMAX_DELAY, &event_flags);
99+
100+
if (!connected) {
101+
usb_host_lib_info_t lib_info_connected;
102+
TEST_ASSERT_EQUAL(ESP_OK, usb_host_lib_info(&lib_info_connected));
103+
if (lib_info_connected.num_devices == 1) {
104+
// We've just connected. Trigger root port suspend
105+
connected = true;
106+
107+
printf("Suspending the root port\n");
108+
// Suspend the root port
109+
TEST_ASSERT_EQUAL(ESP_OK, usb_host_lib_root_port_suspend());
110+
111+
// In first test variation, continue to the end of the loop, to handle events connected to the port suspend
112+
// In second variation don't handle port suspend, disconnect immediately
113+
if (dconn_iter < TEST_DCONN_SUSPEND_ITERATIONS / 2) {
114+
continue;
115+
}
116+
}
117+
}
118+
119+
if (!suspended) {
120+
usb_host_lib_info_t lib_info;
121+
TEST_ASSERT_EQUAL(ESP_OK, usb_host_lib_info(&lib_info));
122+
if (lib_info.num_devices == 1) {
123+
// We've started suspend sequence. Trigger a disconnect
124+
suspended = true;
125+
126+
if (dconn_iter < TEST_DCONN_SUSPEND_ITERATIONS / 2) {
127+
// Port suspend call has been handled, expect the port to be suspended
128+
TEST_ASSERT_MESSAGE(lib_info.root_port_suspended, "Root port should be suspended");
129+
} else {
130+
// Port suspend call has not been handled, expect the port not to be suspended
131+
TEST_ASSERT_MESSAGE(!lib_info.root_port_suspended, "Root port should not be suspended");
132+
}
133+
printf("Forcing Sudden Disconnect\n");
134+
// Trigger a disconnect by powering OFF the root port
135+
TEST_ASSERT_EQUAL(ESP_OK, usb_host_lib_set_root_port_power(false));
136+
}
137+
}
138+
139+
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) {
140+
// The device has disconnected and it's disconnection has been handled
141+
printf("Dconn iter %d done\n", dconn_iter);
142+
if (++dconn_iter < TEST_DCONN_SUSPEND_ITERATIONS) {
143+
// Start next iteration
144+
connected = false;
145+
suspended = false;
146+
// Allow connections again by powering ON the root port
147+
TEST_ASSERT_EQUAL(ESP_OK, usb_host_lib_set_root_port_power(true));
63148
} else {
64149
break;
65150
}

0 commit comments

Comments
 (0)