mirror of
https://github.com/espressif/esp-idf
synced 2025-03-31 03:41:07 -04:00
Merge branch 'feat/usb_disconnect_api_backport_v5.3' into 'release/v5.3'
refactor(usb): Update HCD tests to use port power off for disconnections backport v5.3 See merge request espressif/esp-idf!33527
This commit is contained in:
commit
a5ed03eb85
@ -62,7 +62,7 @@
|
|||||||
// FS: Must be 2-64. HS: Must be 8-256. See USB-OTG databook Table 5-47
|
// FS: Must be 2-64. HS: Must be 8-256. See USB-OTG databook Table 5-47
|
||||||
#define XFER_LIST_LEN_INTR FRAME_LIST_LEN
|
#define XFER_LIST_LEN_INTR FRAME_LIST_LEN
|
||||||
#define XFER_LIST_LEN_ISOC 64 // Implement longer ISOC transfer list to give us enough space for additional timing margin
|
#define XFER_LIST_LEN_ISOC 64 // Implement longer ISOC transfer list to give us enough space for additional timing margin
|
||||||
#define XFER_LIST_ISOC_MARGIN 2 // The 1st ISOC transfer is scheduled 2 (micro)frames later so we have enough timing margin
|
#define XFER_LIST_ISOC_MARGIN 3 // The 1st ISOC transfer is scheduled 3 (micro)frames later so we have enough timing margin
|
||||||
|
|
||||||
// ------------------------ Flags --------------------------
|
// ------------------------ Flags --------------------------
|
||||||
|
|
||||||
|
@ -369,8 +369,8 @@ reset_err:
|
|||||||
p_hub_driver_obj->dynamic.port_reqs |= PORT_REQ_RECOVER;
|
p_hub_driver_obj->dynamic.port_reqs |= PORT_REQ_RECOVER;
|
||||||
p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_ACTION_ROOT_REQ;
|
p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_ACTION_ROOT_REQ;
|
||||||
break;
|
break;
|
||||||
case ROOT_PORT_STATE_ENABLED:
|
case ROOT_PORT_STATE_NOT_POWERED: // The user turned off ports' power. Indicate to USBH that the device is gone
|
||||||
// There is an enabled (active) device. We need to indicate to USBH that the device is gone
|
case ROOT_PORT_STATE_ENABLED: // There is an enabled (active) device. Indicate to USBH that the device is gone
|
||||||
port_has_device = true;
|
port_has_device = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -408,10 +408,19 @@ static void root_port_req(hcd_port_handle_t root_port_hdl)
|
|||||||
if (port_reqs & PORT_REQ_RECOVER) {
|
if (port_reqs & PORT_REQ_RECOVER) {
|
||||||
ESP_LOGD(HUB_DRIVER_TAG, "Recovering root port");
|
ESP_LOGD(HUB_DRIVER_TAG, "Recovering root port");
|
||||||
ESP_ERROR_CHECK(hcd_port_recover(p_hub_driver_obj->constant.root_port_hdl));
|
ESP_ERROR_CHECK(hcd_port_recover(p_hub_driver_obj->constant.root_port_hdl));
|
||||||
ESP_ERROR_CHECK(hcd_port_command(p_hub_driver_obj->constant.root_port_hdl, HCD_PORT_CMD_POWER_ON));
|
|
||||||
|
// In case the port's power was turned off with usb_host_lib_set_root_port_power(false)
|
||||||
|
// we will not turn on the power during port recovery
|
||||||
HUB_DRIVER_ENTER_CRITICAL();
|
HUB_DRIVER_ENTER_CRITICAL();
|
||||||
p_hub_driver_obj->dynamic.root_port_state = ROOT_PORT_STATE_POWERED;
|
const root_port_state_t root_state = p_hub_driver_obj->dynamic.root_port_state;
|
||||||
HUB_DRIVER_EXIT_CRITICAL();
|
HUB_DRIVER_EXIT_CRITICAL();
|
||||||
|
|
||||||
|
if (root_state != ROOT_PORT_STATE_NOT_POWERED) {
|
||||||
|
ESP_ERROR_CHECK(hcd_port_command(p_hub_driver_obj->constant.root_port_hdl, HCD_PORT_CMD_POWER_ON));
|
||||||
|
HUB_DRIVER_ENTER_CRITICAL();
|
||||||
|
p_hub_driver_obj->dynamic.root_port_state = ROOT_PORT_STATE_POWERED;
|
||||||
|
HUB_DRIVER_EXIT_CRITICAL();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -570,15 +579,18 @@ esp_err_t hub_root_stop(void)
|
|||||||
{
|
{
|
||||||
HUB_DRIVER_ENTER_CRITICAL();
|
HUB_DRIVER_ENTER_CRITICAL();
|
||||||
HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj != NULL, ESP_ERR_INVALID_STATE);
|
HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj != NULL, ESP_ERR_INVALID_STATE);
|
||||||
HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj->dynamic.root_port_state != ROOT_PORT_STATE_NOT_POWERED, ESP_ERR_INVALID_STATE);
|
if (p_hub_driver_obj->dynamic.root_port_state == ROOT_PORT_STATE_NOT_POWERED) {
|
||||||
HUB_DRIVER_EXIT_CRITICAL();
|
// The HUB was already stopped by usb_host_lib_set_root_port_power(false)
|
||||||
esp_err_t ret;
|
|
||||||
ret = hcd_port_command(p_hub_driver_obj->constant.root_port_hdl, HCD_PORT_CMD_POWER_OFF);
|
|
||||||
if (ret == ESP_OK) {
|
|
||||||
HUB_DRIVER_ENTER_CRITICAL();
|
|
||||||
p_hub_driver_obj->dynamic.root_port_state = ROOT_PORT_STATE_NOT_POWERED;
|
|
||||||
HUB_DRIVER_EXIT_CRITICAL();
|
HUB_DRIVER_EXIT_CRITICAL();
|
||||||
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
p_hub_driver_obj->dynamic.root_port_state = ROOT_PORT_STATE_NOT_POWERED;
|
||||||
|
HUB_DRIVER_EXIT_CRITICAL();
|
||||||
|
|
||||||
|
// HCD_PORT_CMD_POWER_OFF will only fail if the port is already powered_off
|
||||||
|
// This should never happen, so we assert ret == ESP_OK
|
||||||
|
const esp_err_t ret = hcd_port_command(p_hub_driver_obj->constant.root_port_hdl, HCD_PORT_CMD_POWER_OFF);
|
||||||
|
assert(ret == ESP_OK);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,13 +101,16 @@ typedef void (*usb_host_client_event_cb_t)(const usb_host_client_event_msg_t *ev
|
|||||||
* Configuration structure of the USB Host Library. Provided in the usb_host_install() function
|
* Configuration structure of the USB Host Library. Provided in the usb_host_install() function
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool skip_phy_setup; /**< If set, the USB Host Library will not configure the USB PHY thus allowing the user
|
bool skip_phy_setup; /**< If set, the USB Host Library will not configure the USB PHY thus allowing
|
||||||
to manually configure the USB PHY before calling usb_host_install(). Users should
|
the user to manually configure the USB PHY before calling usb_host_install().
|
||||||
set this if they want to use an external USB PHY. Otherwise, the USB Host Library
|
Users should set this if they want to use an external USB PHY. Otherwise,
|
||||||
will automatically configure the internal USB PHY */
|
the USB Host Library will automatically configure the internal USB PHY */
|
||||||
int intr_flags; /**< Interrupt flags for the underlying ISR used by the USB Host stack */
|
bool root_port_unpowered; /**< If set, the USB Host Library will not power on the root port on installation.
|
||||||
usb_host_enum_filter_cb_t enum_filter_cb; /**< Enumeration filter callback. Enable CONFIG_USB_HOST_ENABLE_ENUM_FILTER_CALLBACK
|
This allows users to power on the root port manually by calling
|
||||||
to use this feature. Set to NULL otherwise. */
|
usb_host_lib_set_root_port_power(). */
|
||||||
|
int intr_flags; /**< Interrupt flags for the underlying ISR used by the USB Host stack */
|
||||||
|
usb_host_enum_filter_cb_t enum_filter_cb; /**< Enumeration filter callback. Enable CONFIG_USB_HOST_ENABLE_ENUM_FILTER_CALLBACK
|
||||||
|
to use this feature. Set to NULL otherwise. */
|
||||||
} usb_host_config_t;
|
} usb_host_config_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -187,6 +190,23 @@ esp_err_t usb_host_lib_unblock(void);
|
|||||||
*/
|
*/
|
||||||
esp_err_t usb_host_lib_info(usb_host_lib_info_t *info_ret);
|
esp_err_t usb_host_lib_info(usb_host_lib_info_t *info_ret);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Power the root port ON or OFF
|
||||||
|
*
|
||||||
|
* - Powering ON the root port will allow device connections to occur
|
||||||
|
* - Powering OFF the root port will disconnect all devices downstream off the root port and prevent
|
||||||
|
* any further device connections.
|
||||||
|
*
|
||||||
|
* @note If 'usb_host_config_t.root_port_unpowered' was set on USB Host Library installation, users must call this
|
||||||
|
* function to power ON the root port before any device connections can occur.
|
||||||
|
*
|
||||||
|
* @param[in] enable True to power the root port ON, false to power OFF
|
||||||
|
* @return
|
||||||
|
* - ESP_OK: Root port power enabled/disabled
|
||||||
|
* - ESP_ERR_INVALID_STATE: Root port already powered or HUB driver not installed
|
||||||
|
*/
|
||||||
|
esp_err_t usb_host_lib_set_root_port_power(bool enable);
|
||||||
|
|
||||||
// ------------------------------------------------ Client Functions ---------------------------------------------------
|
// ------------------------------------------------ Client Functions ---------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2,6 +2,5 @@ idf_component_register(SRCS "dev_hid.c"
|
|||||||
"dev_isoc.c"
|
"dev_isoc.c"
|
||||||
"dev_msc.c"
|
"dev_msc.c"
|
||||||
"mock_msc.c"
|
"mock_msc.c"
|
||||||
"test_usb_common.c"
|
|
||||||
INCLUDE_DIRS "."
|
INCLUDE_DIRS "."
|
||||||
REQUIRES usb unity)
|
REQUIRES usb unity)
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "esp_err.h"
|
|
||||||
#include "hal/usb_phy_types.h"
|
|
||||||
#include "esp_private/usb_phy.h"
|
|
||||||
#include "test_usb_common.h"
|
|
||||||
#include "unity.h"
|
|
||||||
|
|
||||||
static usb_phy_handle_t phy_hdl = NULL;
|
|
||||||
|
|
||||||
void test_usb_init_phy(void)
|
|
||||||
{
|
|
||||||
// Initialize the internal USB PHY to connect to the USB OTG peripheral
|
|
||||||
usb_phy_config_t phy_config = {
|
|
||||||
.controller = USB_PHY_CTRL_OTG,
|
|
||||||
.target = USB_PHY_TARGET_INT,
|
|
||||||
.otg_mode = USB_OTG_MODE_HOST,
|
|
||||||
.otg_speed = USB_PHY_SPEED_UNDEFINED, // In Host mode, the speed is determined by the connected device
|
|
||||||
.ext_io_conf = NULL,
|
|
||||||
.otg_io_conf = NULL,
|
|
||||||
};
|
|
||||||
TEST_ASSERT_EQUAL_MESSAGE(ESP_OK, usb_new_phy(&phy_config, &phy_hdl), "Failed to init USB PHY");
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_usb_deinit_phy(void)
|
|
||||||
{
|
|
||||||
// Deinitialize the internal USB PHY
|
|
||||||
TEST_ASSERT_EQUAL_MESSAGE(ESP_OK, usb_del_phy(phy_hdl), "Failed to delete PHY");
|
|
||||||
phy_hdl = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_usb_set_phy_state(bool connected, TickType_t delay_ticks)
|
|
||||||
{
|
|
||||||
if (delay_ticks > 0) {
|
|
||||||
// Delay of 0 ticks causes a yield. So skip if delay_ticks is 0.
|
|
||||||
vTaskDelay(delay_ticks);
|
|
||||||
}
|
|
||||||
ESP_ERROR_CHECK(usb_phy_action(phy_hdl, (connected) ? USB_PHY_ACTION_HOST_ALLOW_CONN : USB_PHY_ACTION_HOST_FORCE_DISCONN));
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Initialize the internal USB PHY and USB Controller for USB Host testing
|
|
||||||
*/
|
|
||||||
void test_usb_init_phy(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Deinitialize the internal USB PHY and USB Controller after USB Host testing
|
|
||||||
*/
|
|
||||||
void test_usb_deinit_phy(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief For the USB PHY into the connected or disconnected state
|
|
||||||
*
|
|
||||||
* @param connected For into connected state if true, disconnected if false
|
|
||||||
* @param delay_ticks Delay in ticks before forcing state
|
|
||||||
*/
|
|
||||||
void test_usb_set_phy_state(bool connected, TickType_t delay_ticks);
|
|
@ -53,7 +53,7 @@ Procedure:
|
|||||||
#define TEST_NUM_SECTORS_TOTAL 10
|
#define TEST_NUM_SECTORS_TOTAL 10
|
||||||
#define TEST_NUM_SECTORS_PER_XFER 2
|
#define TEST_NUM_SECTORS_PER_XFER 2
|
||||||
|
|
||||||
TEST_CASE("Test HCD bulk pipe URBs", "[bulk][full_speed]")
|
TEST_CASE("Test HCD bulk pipe URBs", "[bulk][full_speed][high_speed]")
|
||||||
{
|
{
|
||||||
usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); // Trigger a connection
|
usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); // Trigger a connection
|
||||||
vTaskDelay(pdMS_TO_TICKS(100)); // Short delay send of SOF (for FS) or EOPs (for LS)
|
vTaskDelay(pdMS_TO_TICKS(100)); // Short delay send of SOF (for FS) or EOPs (for LS)
|
||||||
|
@ -17,8 +17,8 @@
|
|||||||
#include "hcd.h"
|
#include "hcd.h"
|
||||||
#include "usb_private.h"
|
#include "usb_private.h"
|
||||||
#include "usb/usb_types_ch9.h"
|
#include "usb/usb_types_ch9.h"
|
||||||
|
#include "esp_private/usb_phy.h"
|
||||||
#include "test_hcd_common.h"
|
#include "test_hcd_common.h"
|
||||||
#include "test_usb_common.h"
|
|
||||||
#include "mock_msc.h"
|
#include "mock_msc.h"
|
||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
|
|
||||||
@ -38,6 +38,7 @@ typedef struct {
|
|||||||
} pipe_event_msg_t;
|
} pipe_event_msg_t;
|
||||||
|
|
||||||
hcd_port_handle_t port_hdl = NULL;
|
hcd_port_handle_t port_hdl = NULL;
|
||||||
|
static usb_phy_handle_t phy_hdl = NULL;
|
||||||
|
|
||||||
// ---------------------------------------------------- Private --------------------------------------------------------
|
// ---------------------------------------------------- Private --------------------------------------------------------
|
||||||
|
|
||||||
@ -144,7 +145,21 @@ int test_hcd_get_num_pipe_events(hcd_pipe_handle_t pipe_hdl)
|
|||||||
|
|
||||||
hcd_port_handle_t test_hcd_setup(void)
|
hcd_port_handle_t test_hcd_setup(void)
|
||||||
{
|
{
|
||||||
test_usb_init_phy(); // Initialize the internal USB PHY and USB Controller for testing
|
// Deinitialize PHY from previous failed test
|
||||||
|
if (phy_hdl != NULL) {
|
||||||
|
TEST_ASSERT_EQUAL_MESSAGE(ESP_OK, usb_del_phy(phy_hdl), "Failed to delete PHY");
|
||||||
|
phy_hdl = NULL;
|
||||||
|
}
|
||||||
|
// Initialize the internal USB PHY to connect to the USB OTG peripheral
|
||||||
|
usb_phy_config_t phy_config = {
|
||||||
|
.controller = USB_PHY_CTRL_OTG,
|
||||||
|
.target = USB_PHY_TARGET_INT,
|
||||||
|
.otg_mode = USB_OTG_MODE_HOST,
|
||||||
|
.otg_speed = USB_PHY_SPEED_UNDEFINED, // In Host mode, the speed is determined by the connected device
|
||||||
|
.ext_io_conf = NULL,
|
||||||
|
.otg_io_conf = NULL,
|
||||||
|
};
|
||||||
|
TEST_ASSERT_EQUAL_MESSAGE(ESP_OK, usb_new_phy(&phy_config, &phy_hdl), "Failed to init USB PHY");
|
||||||
// Create a queue for port callback to queue up port events
|
// Create a queue for port callback to queue up port events
|
||||||
QueueHandle_t port_evt_queue = xQueueCreate(EVENT_QUEUE_LEN, sizeof(port_event_msg_t));
|
QueueHandle_t port_evt_queue = xQueueCreate(EVENT_QUEUE_LEN, sizeof(port_event_msg_t));
|
||||||
TEST_ASSERT_NOT_NULL(port_evt_queue);
|
TEST_ASSERT_NOT_NULL(port_evt_queue);
|
||||||
@ -163,8 +178,6 @@ hcd_port_handle_t test_hcd_setup(void)
|
|||||||
hcd_port_handle_t port_hdl;
|
hcd_port_handle_t port_hdl;
|
||||||
TEST_ASSERT_EQUAL(ESP_OK, hcd_port_init(PORT_NUM, &port_config, &port_hdl));
|
TEST_ASSERT_EQUAL(ESP_OK, hcd_port_init(PORT_NUM, &port_config, &port_hdl));
|
||||||
TEST_ASSERT_NOT_NULL(port_hdl);
|
TEST_ASSERT_NOT_NULL(port_hdl);
|
||||||
TEST_ASSERT_EQUAL(HCD_PORT_STATE_NOT_POWERED, hcd_port_get_state(port_hdl));
|
|
||||||
test_usb_set_phy_state(false, 0); // Force disconnected state on PHY
|
|
||||||
return port_hdl;
|
return port_hdl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,17 +194,18 @@ void test_hcd_teardown(hcd_port_handle_t port_hdl)
|
|||||||
// Uninstall the HCD
|
// Uninstall the HCD
|
||||||
TEST_ASSERT_EQUAL(ESP_OK, hcd_uninstall());
|
TEST_ASSERT_EQUAL(ESP_OK, hcd_uninstall());
|
||||||
vQueueDelete(port_evt_queue);
|
vQueueDelete(port_evt_queue);
|
||||||
test_usb_deinit_phy(); // Deinitialize the internal USB PHY after testing
|
// Deinitialize the internal USB PHY
|
||||||
|
TEST_ASSERT_EQUAL_MESSAGE(ESP_OK, usb_del_phy(phy_hdl), "Failed to delete PHY");
|
||||||
|
phy_hdl = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
usb_speed_t test_hcd_wait_for_conn(hcd_port_handle_t port_hdl)
|
usb_speed_t test_hcd_wait_for_conn(hcd_port_handle_t port_hdl)
|
||||||
{
|
{
|
||||||
// Power ON the port
|
// Power ON the port. This should allow for connections to occur
|
||||||
TEST_ASSERT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_POWER_ON));
|
TEST_ASSERT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_POWER_ON));
|
||||||
TEST_ASSERT_EQUAL(HCD_PORT_STATE_DISCONNECTED, hcd_port_get_state(port_hdl));
|
TEST_ASSERT_EQUAL(HCD_PORT_STATE_DISCONNECTED, hcd_port_get_state(port_hdl));
|
||||||
// Wait for connection event
|
// Wait for connection event
|
||||||
printf("Waiting for connection\n");
|
printf("Waiting for connection\n");
|
||||||
test_usb_set_phy_state(true, pdMS_TO_TICKS(100)); // Allow for connected state on PHY
|
|
||||||
test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_CONNECTION);
|
test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_CONNECTION);
|
||||||
TEST_ASSERT_EQUAL(HCD_PORT_EVENT_CONNECTION, hcd_port_handle_event(port_hdl));
|
TEST_ASSERT_EQUAL(HCD_PORT_EVENT_CONNECTION, hcd_port_handle_event(port_hdl));
|
||||||
TEST_ASSERT_EQUAL(HCD_PORT_STATE_DISABLED, hcd_port_get_state(port_hdl));
|
TEST_ASSERT_EQUAL(HCD_PORT_STATE_DISABLED, hcd_port_get_state(port_hdl));
|
||||||
@ -217,9 +231,10 @@ void test_hcd_wait_for_disconn(hcd_port_handle_t port_hdl, bool already_disabled
|
|||||||
TEST_ASSERT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_DISABLE));
|
TEST_ASSERT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_DISABLE));
|
||||||
TEST_ASSERT_EQUAL(HCD_PORT_STATE_DISABLED, hcd_port_get_state(port_hdl));
|
TEST_ASSERT_EQUAL(HCD_PORT_STATE_DISABLED, hcd_port_get_state(port_hdl));
|
||||||
}
|
}
|
||||||
// Wait for a safe disconnect
|
|
||||||
printf("Waiting for disconnection\n");
|
printf("Waiting for disconnection\n");
|
||||||
test_usb_set_phy_state(false, pdMS_TO_TICKS(100)); // Force disconnected state on PHY
|
// Power-off the port to trigger a disconnection
|
||||||
|
TEST_ASSERT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_POWER_OFF));
|
||||||
|
// Wait for the port disconnection event
|
||||||
test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_DISCONNECTION);
|
test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_DISCONNECTION);
|
||||||
TEST_ASSERT_EQUAL(HCD_PORT_EVENT_DISCONNECTION, hcd_port_handle_event(port_hdl));
|
TEST_ASSERT_EQUAL(HCD_PORT_EVENT_DISCONNECTION, hcd_port_handle_event(port_hdl));
|
||||||
TEST_ASSERT_EQUAL(HCD_PORT_STATE_RECOVERY, hcd_port_get_state(port_hdl));
|
TEST_ASSERT_EQUAL(HCD_PORT_STATE_RECOVERY, hcd_port_get_state(port_hdl));
|
||||||
|
@ -53,6 +53,8 @@ int test_hcd_get_num_pipe_events(hcd_pipe_handle_t pipe_hdl);
|
|||||||
/**
|
/**
|
||||||
* @brief Sets up the HCD and initializes an HCD port.
|
* @brief Sets up the HCD and initializes an HCD port.
|
||||||
*
|
*
|
||||||
|
* The HCD port is left in the HCD_PORT_STATE_NOT_POWERED state
|
||||||
|
*
|
||||||
* @return hcd_port_handle_t Port handle
|
* @return hcd_port_handle_t Port handle
|
||||||
*/
|
*/
|
||||||
hcd_port_handle_t test_hcd_setup(void);
|
hcd_port_handle_t test_hcd_setup(void);
|
||||||
@ -67,7 +69,7 @@ void test_hcd_teardown(hcd_port_handle_t port_hdl);
|
|||||||
/**
|
/**
|
||||||
* @brief Wait for a connection on an HCD port
|
* @brief Wait for a connection on an HCD port
|
||||||
*
|
*
|
||||||
* @note This function will internally call test_usb_set_phy_state() to allow for a connection
|
* @note HCD_PORT_CMD_POWER_ON is called internally to allow connections
|
||||||
*
|
*
|
||||||
* @param port_hdl Port handle
|
* @param port_hdl Port handle
|
||||||
* @return usb_speed_t Speed of the connected device
|
* @return usb_speed_t Speed of the connected device
|
||||||
@ -77,7 +79,7 @@ usb_speed_t test_hcd_wait_for_conn(hcd_port_handle_t port_hdl);
|
|||||||
/**
|
/**
|
||||||
* @brief Wait for a disconnection on an HCD port
|
* @brief Wait for a disconnection on an HCD port
|
||||||
*
|
*
|
||||||
* @note This fucntion will internally call test_usb_set_phy_state() to force a disconnection
|
* @note HCD_PORT_CMD_POWER_OFF is called internally to force a disconnection
|
||||||
*
|
*
|
||||||
* @param port_hdl Port handle
|
* @param port_hdl Port handle
|
||||||
* @param already_disabled Whether the HCD port is already in the disabled state
|
* @param already_disabled Whether the HCD port is already in the disabled state
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@ -33,7 +33,7 @@ Procedure:
|
|||||||
- Expect URB to be USB_TRANSFER_STATUS_CANCELED or USB_TRANSFER_STATUS_COMPLETED
|
- Expect URB to be USB_TRANSFER_STATUS_CANCELED or USB_TRANSFER_STATUS_COMPLETED
|
||||||
- Teardown
|
- Teardown
|
||||||
*/
|
*/
|
||||||
TEST_CASE("Test HCD control pipe URBs", "[ctrl][low_speed][full_speed]")
|
TEST_CASE("Test HCD control pipe URBs", "[ctrl][low_speed][full_speed][high_speed]")
|
||||||
{
|
{
|
||||||
usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); // Trigger a connection
|
usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); // Trigger a connection
|
||||||
vTaskDelay(pdMS_TO_TICKS(100)); // Short delay send of SOF (for FS) or EOPs (for LS)
|
vTaskDelay(pdMS_TO_TICKS(100)); // Short delay send of SOF (for FS) or EOPs (for LS)
|
||||||
@ -110,7 +110,7 @@ TEST_CASE("Test HCD control pipe URBs", "[ctrl][low_speed][full_speed]")
|
|||||||
/*
|
/*
|
||||||
Test HCD control pipe STALL condition, abort, and clear
|
Test HCD control pipe STALL condition, abort, and clear
|
||||||
|
|
||||||
@todo this test is not passing with low-speed: test with bus analyzer
|
@todo this test is not passing with low-speed: test with bus analyzer IDF-10995
|
||||||
|
|
||||||
Purpose:
|
Purpose:
|
||||||
- Test that a control pipe can react to a STALL (i.e., a HCD_PIPE_EVENT_ERROR_STALL event)
|
- Test that a control pipe can react to a STALL (i.e., a HCD_PIPE_EVENT_ERROR_STALL event)
|
||||||
@ -128,7 +128,7 @@ Procedure:
|
|||||||
- Dequeue URBs
|
- Dequeue URBs
|
||||||
- Teardown
|
- Teardown
|
||||||
*/
|
*/
|
||||||
TEST_CASE("Test HCD control pipe STALL", "[ctrl][full_speed]")
|
TEST_CASE("Test HCD control pipe STALL", "[ctrl][full_speed][high_speed]")
|
||||||
{
|
{
|
||||||
usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); // Trigger a connection
|
usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); // Trigger a connection
|
||||||
vTaskDelay(pdMS_TO_TICKS(100)); // Short delay send of SOF (for FS) or EOPs (for LS)
|
vTaskDelay(pdMS_TO_TICKS(100)); // Short delay send of SOF (for FS) or EOPs (for LS)
|
||||||
@ -217,6 +217,8 @@ TEST_CASE("Test HCD control pipe STALL", "[ctrl][full_speed]")
|
|||||||
/*
|
/*
|
||||||
Test control pipe run-time halt and clear
|
Test control pipe run-time halt and clear
|
||||||
|
|
||||||
|
@todo this test is not passing on P4: test with bus analyzer IDF-10996
|
||||||
|
|
||||||
Purpose:
|
Purpose:
|
||||||
- Test that a control pipe can be halted with HCD_PIPE_CMD_HALT whilst there are ongoing URBs
|
- Test that a control pipe can be halted with HCD_PIPE_CMD_HALT whilst there are ongoing URBs
|
||||||
- Test that a control pipe can be un-halted with a HCD_PIPE_CMD_CLEAR
|
- Test that a control pipe can be un-halted with a HCD_PIPE_CMD_CLEAR
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
#include "dev_isoc.h"
|
#include "dev_isoc.h"
|
||||||
#include "usb/usb_types_ch9.h"
|
#include "usb/usb_types_ch9.h"
|
||||||
#include "test_usb_common.h"
|
|
||||||
#include "test_hcd_common.h"
|
#include "test_hcd_common.h"
|
||||||
|
|
||||||
#define NUM_URBS 3
|
#define NUM_URBS 3
|
||||||
@ -40,7 +39,7 @@ Procedure:
|
|||||||
- Teardown
|
- Teardown
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TEST_CASE("Test HCD isochronous pipe URBs", "[isoc][full_speed]")
|
TEST_CASE("Test HCD isochronous pipe URBs", "[isoc][full_speed][high_speed]")
|
||||||
{
|
{
|
||||||
usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); // Trigger a connection
|
usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); // Trigger a connection
|
||||||
// The MPS of the ISOC OUT pipe is quite large, so we need to bias the FIFO sizing
|
// The MPS of the ISOC OUT pipe is quite large, so we need to bias the FIFO sizing
|
||||||
@ -115,7 +114,7 @@ Procedure:
|
|||||||
- Deallocate URBs
|
- Deallocate URBs
|
||||||
- Teardown
|
- Teardown
|
||||||
*/
|
*/
|
||||||
TEST_CASE("Test HCD isochronous pipe URBs all", "[isoc][full_speed]")
|
TEST_CASE("Test HCD isochronous pipe URBs all", "[isoc][full_speed][high_speed]")
|
||||||
{
|
{
|
||||||
usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); // Trigger a connection
|
usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); // Trigger a connection
|
||||||
// The MPS of the ISOC OUT pipe is quite large, so we need to bias the FIFO sizing
|
// The MPS of the ISOC OUT pipe is quite large, so we need to bias the FIFO sizing
|
||||||
@ -164,7 +163,7 @@ TEST_CASE("Test HCD isochronous pipe URBs all", "[isoc][full_speed]")
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add a delay so we start scheduling the transactions at different time in USB frame
|
// Add a delay so we start scheduling the transactions at different time in USB frame
|
||||||
esp_rom_delay_us(ENQUEUE_DELAY * interval + ENQUEUE_DELAY * channel);
|
esp_rom_delay_us(ENQUEUE_DELAY * (interval - 1) + ENQUEUE_DELAY * channel);
|
||||||
|
|
||||||
// Enqueue URBs
|
// Enqueue URBs
|
||||||
for (int i = 0; i < NUM_URBS; i++) {
|
for (int i = 0; i < NUM_URBS; i++) {
|
||||||
@ -227,7 +226,7 @@ Procedure:
|
|||||||
- Free both pipes
|
- Free both pipes
|
||||||
- Teardown
|
- Teardown
|
||||||
*/
|
*/
|
||||||
TEST_CASE("Test HCD isochronous pipe sudden disconnect", "[isoc][full_speed]")
|
TEST_CASE("Test HCD isochronous pipe sudden disconnect", "[isoc][full_speed][high_speed]")
|
||||||
{
|
{
|
||||||
usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); // Trigger a connection
|
usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); // Trigger a connection
|
||||||
// The MPS of the ISOC OUT pipe is quite large, so we need to bias the FIFO sizing
|
// The MPS of the ISOC OUT pipe is quite large, so we need to bias the FIFO sizing
|
||||||
@ -261,7 +260,8 @@ TEST_CASE("Test HCD isochronous pipe sudden disconnect", "[isoc][full_speed]")
|
|||||||
}
|
}
|
||||||
// Add a short delay to let the transfers run for a bit
|
// Add a short delay to let the transfers run for a bit
|
||||||
esp_rom_delay_us(POST_ENQUEUE_DELAY_US);
|
esp_rom_delay_us(POST_ENQUEUE_DELAY_US);
|
||||||
test_usb_set_phy_state(false, 0);
|
// Power-off the port to trigger a disconnection
|
||||||
|
TEST_ASSERT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_POWER_OFF));
|
||||||
// Disconnect event should have occurred. Handle the port event
|
// Disconnect event should have occurred. Handle the port event
|
||||||
test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_DISCONNECTION);
|
test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_DISCONNECTION);
|
||||||
TEST_ASSERT_EQUAL(HCD_PORT_EVENT_DISCONNECTION, hcd_port_handle_event(port_hdl));
|
TEST_ASSERT_EQUAL(HCD_PORT_EVENT_DISCONNECTION, hcd_port_handle_event(port_hdl));
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
#include "freertos/semphr.h"
|
#include "freertos/semphr.h"
|
||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
#include "esp_rom_sys.h"
|
#include "esp_rom_sys.h"
|
||||||
#include "test_usb_common.h"
|
|
||||||
#include "test_hcd_common.h"
|
#include "test_hcd_common.h"
|
||||||
|
|
||||||
#define TEST_DEV_ADDR 0
|
#define TEST_DEV_ADDR 0
|
||||||
@ -31,7 +30,7 @@ Procedure:
|
|||||||
- Trigger the port disconnection event
|
- Trigger the port disconnection event
|
||||||
- Teardown port and HCD
|
- Teardown port and HCD
|
||||||
*/
|
*/
|
||||||
TEST_CASE("Test HCD port disconnect event, port enabled", "[port][low_speed][full_speed]")
|
TEST_CASE("Test HCD port disconnect event, port enabled", "[port][low_speed][full_speed][high_speed]")
|
||||||
{
|
{
|
||||||
usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); // Trigger a connection
|
usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); // Trigger a connection
|
||||||
printf("Connected %s speed device \n", (char*[]) {
|
printf("Connected %s speed device \n", (char*[]) {
|
||||||
@ -64,7 +63,7 @@ Procedure:
|
|||||||
- Teardown port and HCD
|
- Teardown port and HCD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TEST_CASE("Test HCD port sudden disconnect", "[port][low_speed][full_speed]")
|
TEST_CASE("Test HCD port sudden disconnect", "[port][low_speed][full_speed][high_speed]")
|
||||||
{
|
{
|
||||||
usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); // Trigger a connection
|
usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); // Trigger a connection
|
||||||
vTaskDelay(pdMS_TO_TICKS(100)); // Short delay send of SOF (for FS) or EOPs (for LS)
|
vTaskDelay(pdMS_TO_TICKS(100)); // Short delay send of SOF (for FS) or EOPs (for LS)
|
||||||
@ -87,7 +86,8 @@ TEST_CASE("Test HCD port sudden disconnect", "[port][low_speed][full_speed]")
|
|||||||
}
|
}
|
||||||
// Add a short delay to let the transfers run for a bit
|
// Add a short delay to let the transfers run for a bit
|
||||||
esp_rom_delay_us(POST_ENQUEUE_DELAY_US);
|
esp_rom_delay_us(POST_ENQUEUE_DELAY_US);
|
||||||
test_usb_set_phy_state(false, 0);
|
// Power-off the port to trigger a disconnection
|
||||||
|
TEST_ASSERT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_POWER_OFF));
|
||||||
// Disconnect event should have occurred. Handle the port event
|
// Disconnect event should have occurred. Handle the port event
|
||||||
test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_DISCONNECTION);
|
test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_DISCONNECTION);
|
||||||
TEST_ASSERT_EQUAL(HCD_PORT_EVENT_DISCONNECTION, hcd_port_handle_event(port_hdl));
|
TEST_ASSERT_EQUAL(HCD_PORT_EVENT_DISCONNECTION, hcd_port_handle_event(port_hdl));
|
||||||
@ -153,7 +153,7 @@ Procedure:
|
|||||||
- Cleanup default pipe
|
- Cleanup default pipe
|
||||||
- Trigger disconnection and teardown
|
- Trigger disconnection and teardown
|
||||||
*/
|
*/
|
||||||
TEST_CASE("Test HCD port suspend and resume", "[port][low_speed][full_speed]")
|
TEST_CASE("Test HCD port suspend and resume", "[port][low_speed][full_speed][high_speed]")
|
||||||
{
|
{
|
||||||
usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); // Trigger a connection
|
usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); // Trigger a connection
|
||||||
vTaskDelay(pdMS_TO_TICKS(100)); // Short delay send of SOF (for FS) or EOPs (for LS)
|
vTaskDelay(pdMS_TO_TICKS(100)); // Short delay send of SOF (for FS) or EOPs (for LS)
|
||||||
@ -207,7 +207,7 @@ Procedure:
|
|||||||
- Check that a disconnection still works after disable
|
- Check that a disconnection still works after disable
|
||||||
- Teardown
|
- Teardown
|
||||||
*/
|
*/
|
||||||
TEST_CASE("Test HCD port disable", "[port][low_speed][full_speed]")
|
TEST_CASE("Test HCD port disable", "[port][low_speed][full_speed][high_speed]")
|
||||||
{
|
{
|
||||||
usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); // Trigger a connection
|
usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); // Trigger a connection
|
||||||
vTaskDelay(pdMS_TO_TICKS(100)); // Short delay send of SOF (for FS) or EOPs (for LS)
|
vTaskDelay(pdMS_TO_TICKS(100)); // Short delay send of SOF (for FS) or EOPs (for LS)
|
||||||
@ -290,12 +290,12 @@ static void concurrent_task(void *arg)
|
|||||||
SemaphoreHandle_t sync_sem = (SemaphoreHandle_t) arg;
|
SemaphoreHandle_t sync_sem = (SemaphoreHandle_t) arg;
|
||||||
xSemaphoreTake(sync_sem, portMAX_DELAY);
|
xSemaphoreTake(sync_sem, portMAX_DELAY);
|
||||||
vTaskDelay(pdMS_TO_TICKS(10)); // Give a short delay let reset command start in main thread
|
vTaskDelay(pdMS_TO_TICKS(10)); // Give a short delay let reset command start in main thread
|
||||||
// Force a disconnection
|
// Power-off the port to trigger a disconnection
|
||||||
test_usb_set_phy_state(false, 0);
|
TEST_ASSERT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_POWER_OFF));
|
||||||
vTaskDelay(portMAX_DELAY); // Block forever and wait to be deleted
|
vTaskDelay(portMAX_DELAY); // Block forever and wait to be deleted
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Test HCD port command bailout", "[port][low_speed][full_speed]")
|
TEST_CASE("Test HCD port command bailout", "[port][low_speed][full_speed][high_speed]")
|
||||||
{
|
{
|
||||||
test_hcd_wait_for_conn(port_hdl); // Trigger a connection
|
test_hcd_wait_for_conn(port_hdl); // Trigger a connection
|
||||||
vTaskDelay(pdMS_TO_TICKS(100)); // Short delay send of SOF (for FS) or EOPs (for LS)
|
vTaskDelay(pdMS_TO_TICKS(100)); // Short delay send of SOF (for FS) or EOPs (for LS)
|
||||||
@ -314,7 +314,8 @@ TEST_CASE("Test HCD port command bailout", "[port][low_speed][full_speed]")
|
|||||||
// Attempt to resume the port. But the concurrent task should override this with a disconnection event
|
// Attempt to resume the port. But the concurrent task should override this with a disconnection event
|
||||||
printf("Attempting to resume\n");
|
printf("Attempting to resume\n");
|
||||||
xSemaphoreGive(sync_sem); // Trigger concurrent task
|
xSemaphoreGive(sync_sem); // Trigger concurrent task
|
||||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_RESPONSE, hcd_port_command(port_hdl, HCD_PORT_CMD_RESUME));
|
vTaskDelay(pdMS_TO_TICKS(20)); // Short delay for concurrent task to trigger disconnection
|
||||||
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, hcd_port_command(port_hdl, HCD_PORT_CMD_RESUME));
|
||||||
|
|
||||||
// Check that concurrent task triggered a sudden disconnection
|
// Check that concurrent task triggered a sudden disconnection
|
||||||
test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_DISCONNECTION);
|
test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_DISCONNECTION);
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "test_usb_common.h"
|
|
||||||
#include "dev_msc.h"
|
#include "dev_msc.h"
|
||||||
#include "ctrl_client.h"
|
#include "ctrl_client.h"
|
||||||
#include "usb/usb_host.h"
|
#include "usb/usb_host.h"
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "mock_msc.h"
|
#include "mock_msc.h"
|
||||||
#include "dev_msc.h"
|
#include "dev_msc.h"
|
||||||
#include "test_usb_common.h"
|
|
||||||
#include "msc_client.h"
|
#include "msc_client.h"
|
||||||
#include "usb/usb_types_ch9.h"
|
#include "usb/usb_types_ch9.h"
|
||||||
#include "usb/usb_host.h"
|
#include "usb/usb_host.h"
|
||||||
@ -89,8 +88,10 @@ static void msc_data_transfer_cb(usb_transfer_t *transfer)
|
|||||||
// The data stage should have either completed, or failed due to the disconnection.
|
// The data stage should have either completed, or failed due to the disconnection.
|
||||||
TEST_ASSERT(transfer->status == USB_TRANSFER_STATUS_COMPLETED || transfer->status == USB_TRANSFER_STATUS_NO_DEVICE);
|
TEST_ASSERT(transfer->status == USB_TRANSFER_STATUS_COMPLETED || transfer->status == USB_TRANSFER_STATUS_NO_DEVICE);
|
||||||
if (transfer->status == USB_TRANSFER_STATUS_COMPLETED) {
|
if (transfer->status == USB_TRANSFER_STATUS_COMPLETED) {
|
||||||
|
printf("Data transfer completed\n");
|
||||||
TEST_ASSERT_EQUAL(transfer->num_bytes, transfer->actual_num_bytes);
|
TEST_ASSERT_EQUAL(transfer->num_bytes, transfer->actual_num_bytes);
|
||||||
} else {
|
} else {
|
||||||
|
printf("Data transfer NOT completed: No device\n");
|
||||||
TEST_ASSERT_EQUAL(0, transfer->actual_num_bytes);
|
TEST_ASSERT_EQUAL(0, transfer->actual_num_bytes);
|
||||||
}
|
}
|
||||||
msc_client_obj_t *msc_obj = (msc_client_obj_t *)transfer->context;
|
msc_client_obj_t *msc_obj = (msc_client_obj_t *)transfer->context;
|
||||||
@ -239,7 +240,7 @@ void msc_client_async_dconn_task(void *arg)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TEST_STAGE_MSC_DATA_DCONN: {
|
case TEST_STAGE_MSC_DATA_DCONN: {
|
||||||
ESP_LOGD(MSC_CLIENT_TAG, "Data and disconnect");
|
ESP_LOGD(MSC_CLIENT_TAG, "Data (%d transfers) and disconnect", msc_obj.num_data_transfers);
|
||||||
// Setup the Data IN transfers
|
// Setup the Data IN transfers
|
||||||
const usb_ep_desc_t *in_ep_desc = dev_msc_get_in_ep_desc(msc_obj.dev_speed);
|
const usb_ep_desc_t *in_ep_desc = dev_msc_get_in_ep_desc(msc_obj.dev_speed);
|
||||||
const int bulk_ep_mps = USB_EP_DESC_GET_MPS(in_ep_desc);
|
const int bulk_ep_mps = USB_EP_DESC_GET_MPS(in_ep_desc);
|
||||||
@ -251,8 +252,8 @@ void msc_client_async_dconn_task(void *arg)
|
|||||||
for (int i = 0; i < msc_obj.num_data_transfers; i++) {
|
for (int i = 0; i < msc_obj.num_data_transfers; i++) {
|
||||||
TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_submit(xfer_in[i]));
|
TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_submit(xfer_in[i]));
|
||||||
}
|
}
|
||||||
// Trigger a disconnect
|
// Trigger a disconnect by powering OFF the root port
|
||||||
test_usb_set_phy_state(false, 0);
|
usb_host_lib_set_root_port_power(false);
|
||||||
// Next stage set from transfer callback
|
// Next stage set from transfer callback
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -260,12 +261,16 @@ void msc_client_async_dconn_task(void *arg)
|
|||||||
ESP_LOGD(MSC_CLIENT_TAG, "Close");
|
ESP_LOGD(MSC_CLIENT_TAG, "Close");
|
||||||
TEST_ASSERT_EQUAL(ESP_OK, usb_host_interface_release(msc_obj.client_hdl, msc_obj.dev_hdl, msc_obj.dev_info->bInterfaceNumber));
|
TEST_ASSERT_EQUAL(ESP_OK, usb_host_interface_release(msc_obj.client_hdl, msc_obj.dev_hdl, msc_obj.dev_info->bInterfaceNumber));
|
||||||
TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_close(msc_obj.client_hdl, msc_obj.dev_hdl));
|
TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_close(msc_obj.client_hdl, msc_obj.dev_hdl));
|
||||||
dconn_iter++;
|
vTaskDelay(10); // Yield to USB Host task so it can handle the disconnection
|
||||||
if (dconn_iter < TEST_DCONN_ITERATIONS) {
|
|
||||||
|
// The device has disconnected and it's disconnection has been handled
|
||||||
|
printf("Dconn iter %d done\n", dconn_iter);
|
||||||
|
if (++dconn_iter < TEST_DCONN_ITERATIONS) {
|
||||||
// Start the next test iteration by going back to TEST_STAGE_WAIT_CONN and reenabling connections
|
// Start the next test iteration by going back to TEST_STAGE_WAIT_CONN and reenabling connections
|
||||||
msc_obj.next_stage = TEST_STAGE_WAIT_CONN;
|
msc_obj.next_stage = TEST_STAGE_WAIT_CONN;
|
||||||
skip_event_handling = true; // Need to execute TEST_STAGE_WAIT_CONN
|
skip_event_handling = true; // Need to execute TEST_STAGE_WAIT_CONN
|
||||||
test_usb_set_phy_state(true, 0);
|
// Allow connections again by powering ON the root port
|
||||||
|
usb_host_lib_set_root_port_power(true);
|
||||||
} else {
|
} else {
|
||||||
exit_loop = true;
|
exit_loop = true;
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "dev_msc.h"
|
#include "dev_msc.h"
|
||||||
#include "mock_msc.h"
|
#include "mock_msc.h"
|
||||||
#include "test_usb_common.h"
|
|
||||||
#include "msc_client.h"
|
#include "msc_client.h"
|
||||||
#include "usb/usb_host.h"
|
#include "usb/usb_host.h"
|
||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
@ -177,8 +176,9 @@ void msc_client_async_enum_task(void *arg)
|
|||||||
enum_iter++;
|
enum_iter++;
|
||||||
if (enum_iter < TEST_ENUM_ITERATIONS) {
|
if (enum_iter < TEST_ENUM_ITERATIONS) {
|
||||||
// Start the next test iteration by disconnecting the device, then going back to TEST_STAGE_WAIT_CONN stage
|
// Start the next test iteration by disconnecting the device, then going back to TEST_STAGE_WAIT_CONN stage
|
||||||
test_usb_set_phy_state(false, 0);
|
usb_host_lib_set_root_port_power(false);
|
||||||
test_usb_set_phy_state(true, 0);
|
vTaskDelay(10); // Yield to USB Host task so it can handle the disconnection
|
||||||
|
usb_host_lib_set_root_port_power(true);
|
||||||
msc_obj.next_stage = TEST_STAGE_WAIT_CONN;
|
msc_obj.next_stage = TEST_STAGE_WAIT_CONN;
|
||||||
skip_event_handling = true; // Need to execute TEST_STAGE_WAIT_CONN
|
skip_event_handling = true; // Need to execute TEST_STAGE_WAIT_CONN
|
||||||
} else {
|
} else {
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "test_usb_common.h"
|
|
||||||
#include "mock_msc.h"
|
#include "mock_msc.h"
|
||||||
#include "dev_msc.h"
|
#include "dev_msc.h"
|
||||||
#include "msc_client.h"
|
#include "msc_client.h"
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
#include "freertos/semphr.h"
|
#include "freertos/semphr.h"
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "test_usb_common.h"
|
|
||||||
#include "multiconf_client.h"
|
#include "multiconf_client.h"
|
||||||
#include "mock_msc.h"
|
#include "mock_msc.h"
|
||||||
#include "dev_msc.h"
|
#include "dev_msc.h"
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
#include "unity_test_utils_memory.h"
|
#include "unity_test_utils_memory.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "test_usb_common.h"
|
|
||||||
#include "dev_msc.h"
|
#include "dev_msc.h"
|
||||||
#include "usb/usb_host.h"
|
#include "usb/usb_host.h"
|
||||||
|
|
||||||
@ -17,10 +16,10 @@ void setUp(void)
|
|||||||
{
|
{
|
||||||
unity_utils_record_free_mem();
|
unity_utils_record_free_mem();
|
||||||
dev_msc_init();
|
dev_msc_init();
|
||||||
test_usb_init_phy(); // Initialize the internal USB PHY and USB Controller for testing
|
|
||||||
// Install USB Host
|
// Install USB Host
|
||||||
usb_host_config_t host_config = {
|
usb_host_config_t host_config = {
|
||||||
.skip_phy_setup = true, // test_usb_init_phy() will already have setup the internal USB PHY for us
|
.skip_phy_setup = false,
|
||||||
|
.root_port_unpowered = false,
|
||||||
.intr_flags = ESP_INTR_FLAG_LEVEL1,
|
.intr_flags = ESP_INTR_FLAG_LEVEL1,
|
||||||
};
|
};
|
||||||
ESP_ERROR_CHECK(usb_host_install(&host_config));
|
ESP_ERROR_CHECK(usb_host_install(&host_config));
|
||||||
@ -32,10 +31,10 @@ void tearDown(void)
|
|||||||
// Short delay to allow task to be cleaned up
|
// Short delay to allow task to be cleaned up
|
||||||
vTaskDelay(10);
|
vTaskDelay(10);
|
||||||
// Clean up USB Host
|
// Clean up USB Host
|
||||||
|
printf("USB Host uninstall\n");
|
||||||
ESP_ERROR_CHECK(usb_host_uninstall());
|
ESP_ERROR_CHECK(usb_host_uninstall());
|
||||||
// Short delay to allow task to be cleaned up after client uninstall
|
// Short delay to allow task to be cleaned up after client uninstall
|
||||||
vTaskDelay(10);
|
vTaskDelay(10);
|
||||||
test_usb_deinit_phy(); // Deinitialize the internal USB PHY after testing
|
|
||||||
unity_utils_evaluate_leaks();
|
unity_utils_evaluate_leaks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
#include "freertos/semphr.h"
|
#include "freertos/semphr.h"
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "esp_intr_alloc.h"
|
#include "esp_intr_alloc.h"
|
||||||
#include "test_usb_common.h"
|
|
||||||
#include "dev_msc.h"
|
#include "dev_msc.h"
|
||||||
#include "msc_client.h"
|
#include "msc_client.h"
|
||||||
#include "ctrl_client.h"
|
#include "ctrl_client.h"
|
||||||
@ -182,7 +181,7 @@ static void test_async_client_cb(const usb_host_client_event_msg_t *event_msg, v
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Test USB Host async API", "[usb_host][full_speed][low_speed]")
|
TEST_CASE("Test USB Host async API", "[usb_host][low_speed][full_speed][high_speed]")
|
||||||
{
|
{
|
||||||
// Register two clients
|
// Register two clients
|
||||||
client_test_stage_t client0_stage = CLIENT_TEST_STAGE_NONE;
|
client_test_stage_t client0_stage = CLIENT_TEST_STAGE_NONE;
|
||||||
@ -252,8 +251,9 @@ TEST_CASE("Test USB Host async API", "[usb_host][full_speed][low_speed]")
|
|||||||
client0_dev_hdl,
|
client0_dev_hdl,
|
||||||
dev_info->bInterfaceNumber));
|
dev_info->bInterfaceNumber));
|
||||||
|
|
||||||
|
// Trigger a disconnect by powering OFF the root port
|
||||||
|
usb_host_lib_set_root_port_power(false);
|
||||||
// Wait until the device disconnects and the clients receive the event
|
// Wait until the device disconnects and the clients receive the event
|
||||||
test_usb_set_phy_state(false, 0);
|
|
||||||
while (!(client0_stage == CLIENT_TEST_STAGE_DCONN && client1_stage == CLIENT_TEST_STAGE_DCONN)) {
|
while (!(client0_stage == CLIENT_TEST_STAGE_DCONN && client1_stage == CLIENT_TEST_STAGE_DCONN)) {
|
||||||
usb_host_lib_handle_events(0, NULL);
|
usb_host_lib_handle_events(0, NULL);
|
||||||
usb_host_client_handle_events(client0_hdl, 0);
|
usb_host_client_handle_events(client0_hdl, 0);
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "esp_intr_alloc.h"
|
#include "esp_intr_alloc.h"
|
||||||
#include "test_usb_common.h"
|
|
||||||
#include "mock_msc.h"
|
#include "mock_msc.h"
|
||||||
#include "dev_msc.h"
|
#include "dev_msc.h"
|
||||||
#include "msc_client.h"
|
#include "msc_client.h"
|
||||||
@ -34,7 +33,7 @@ Procedure:
|
|||||||
|
|
||||||
#define TEST_DCONN_NO_CLIENT_ITERATIONS 3
|
#define TEST_DCONN_NO_CLIENT_ITERATIONS 3
|
||||||
|
|
||||||
TEST_CASE("Test USB Host sudden disconnection (no client)", "[usb_host][full_speed][low_speed]")
|
TEST_CASE("Test USB Host sudden disconnection (no client)", "[usb_host][low_speed][full_speed][high_speed]")
|
||||||
{
|
{
|
||||||
bool connected = false;
|
bool connected = false;
|
||||||
int dconn_iter = 0;
|
int dconn_iter = 0;
|
||||||
@ -49,7 +48,8 @@ TEST_CASE("Test USB Host sudden disconnection (no client)", "[usb_host][full_spe
|
|||||||
// We've just connected. Trigger a disconnect
|
// We've just connected. Trigger a disconnect
|
||||||
connected = true;
|
connected = true;
|
||||||
printf("Forcing Sudden Disconnect\n");
|
printf("Forcing Sudden Disconnect\n");
|
||||||
test_usb_set_phy_state(false, 0);
|
// Trigger a disconnect by powering OFF the root port
|
||||||
|
usb_host_lib_set_root_port_power(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) {
|
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) {
|
||||||
@ -58,7 +58,8 @@ TEST_CASE("Test USB Host sudden disconnection (no client)", "[usb_host][full_spe
|
|||||||
if (++dconn_iter < TEST_DCONN_NO_CLIENT_ITERATIONS) {
|
if (++dconn_iter < TEST_DCONN_NO_CLIENT_ITERATIONS) {
|
||||||
// Start next iteration
|
// Start next iteration
|
||||||
connected = false;
|
connected = false;
|
||||||
test_usb_set_phy_state(true, 0);
|
// Allow connections again by powering ON the root port
|
||||||
|
usb_host_lib_set_root_port_power(true);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -82,7 +83,7 @@ Procedure:
|
|||||||
#define TEST_FORCE_DCONN_NUM_TRANSFERS 3
|
#define TEST_FORCE_DCONN_NUM_TRANSFERS 3
|
||||||
#define TEST_MSC_SCSI_TAG 0xDEADBEEF
|
#define TEST_MSC_SCSI_TAG 0xDEADBEEF
|
||||||
|
|
||||||
TEST_CASE("Test USB Host sudden disconnection (single client)", "[usb_host][full_speed]")
|
TEST_CASE("Test USB Host sudden disconnection (single client)", "[usb_host][full_speed][high_speed]")
|
||||||
{
|
{
|
||||||
// Create task to run client that communicates with MSC SCSI interface
|
// Create task to run client that communicates with MSC SCSI interface
|
||||||
const dev_msc_info_t *dev_info = dev_msc_get_info();
|
const dev_msc_info_t *dev_info = dev_msc_get_info();
|
||||||
@ -131,7 +132,7 @@ Procedure:
|
|||||||
|
|
||||||
#define TEST_ENUM_ITERATIONS 3
|
#define TEST_ENUM_ITERATIONS 3
|
||||||
|
|
||||||
TEST_CASE("Test USB Host enumeration", "[usb_host][full_speed]")
|
TEST_CASE("Test USB Host enumeration", "[usb_host][full_speed][high_speed]")
|
||||||
{
|
{
|
||||||
// Create task to run client that checks the enumeration of the device
|
// Create task to run client that checks the enumeration of the device
|
||||||
TaskHandle_t task_hdl;
|
TaskHandle_t task_hdl;
|
||||||
|
@ -540,8 +540,11 @@ esp_err_t usb_host_install(const usb_host_config_t *config)
|
|||||||
p_host_lib_obj = host_lib_obj;
|
p_host_lib_obj = host_lib_obj;
|
||||||
HOST_EXIT_CRITICAL();
|
HOST_EXIT_CRITICAL();
|
||||||
|
|
||||||
// Start the root hub
|
if (!config->root_port_unpowered) {
|
||||||
ESP_ERROR_CHECK(hub_root_start());
|
// Start the root hub
|
||||||
|
ESP_ERROR_CHECK(hub_root_start());
|
||||||
|
}
|
||||||
|
|
||||||
ret = ESP_OK;
|
ret = ESP_OK;
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -694,6 +697,18 @@ esp_err_t usb_host_lib_info(usb_host_lib_info_t *info_ret)
|
|||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
esp_err_t usb_host_lib_set_root_port_power(bool enable)
|
||||||
|
{
|
||||||
|
esp_err_t ret;
|
||||||
|
if (enable) {
|
||||||
|
ret = hub_root_start();
|
||||||
|
} else {
|
||||||
|
ret = hub_root_stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------ Client Functions ---------------------------------------------------
|
// ------------------------------------------------ Client Functions ---------------------------------------------------
|
||||||
|
|
||||||
// ----------------------- Private -------------------------
|
// ----------------------- Private -------------------------
|
||||||
|
Loading…
x
Reference in New Issue
Block a user