Skip to content

Commit

Permalink
Merge branch 'feature/usb_host_hub_support_collective_backport_p3_v5.…
Browse files Browse the repository at this point in the history
…3' into 'release/v5.3'

feat(usb_host): Hub Support Collective backport part 3/3 (v5.3)

See merge request espressif/esp-idf!33987
  • Loading branch information
Jiang Jiang Jian committed Nov 14, 2024
2 parents 6639e72 + b15e83f commit 96a795d
Show file tree
Hide file tree
Showing 22 changed files with 2,013 additions and 187 deletions.
2 changes: 2 additions & 0 deletions Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -655,3 +655,5 @@ mainmenu "Espressif IoT Development Framework Configuration"
- CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH
- CONFIG_ESP_WIFI_EAP_TLS1_3
- CONFIG_ESP_WIFI_ENABLE_ROAMING_APP
- CONFIG_USB_HOST_EXT_PORT_SUPPORT_LS
- CONFIG_USB_HOST_EXT_PORT_RESET_ATTEMPTS
3 changes: 2 additions & 1 deletion components/usb/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ if(CONFIG_SOC_USB_OTG_SUPPORTED)
endif()

if(CONFIG_USB_HOST_HUBS_SUPPORTED)
list(APPEND srcs "ext_hub.c")
list(APPEND srcs "ext_hub.c"
"ext_port.c")
endif()

idf_component_register(SRCS ${srcs}
Expand Down
57 changes: 57 additions & 0 deletions components/usb/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,63 @@ menu "USB-OTG"
help
Enables support for connecting multiple Hubs simultaneously.

menu "Downstream Port configuration"
depends on USB_HOST_HUBS_SUPPORTED

config USB_HOST_EXT_PORT_SUPPORT_LS
depends on IDF_EXPERIMENTAL_FEATURES
bool "Support LS"
default n
help
Enables support of Low-speed devices, connected through the external Hub.

config USB_HOST_EXT_PORT_RESET_ATTEMPTS
depends on IDF_EXPERIMENTAL_FEATURES
# Invisible config option
# Todo: IDF-11283
int
default 1
help
Amount of attempts to reset the device.

The default value is 1.

config USB_HOST_EXT_PORT_RESET_RECOVERY_DELAY_MS
int "Reset recovery delay in ms"
default 30
help
After a port stops driving the reset signal, the USB 2.0 specification requires that
the "USB System Software guarantees a minimum of 10 ms for reset recovery" before the
attached device is expected to respond to data transfers (see USB 2.0 chapter 7.1.7.3 for
more details).
The device may ignore any data transfers during the recovery interval.

The default value is set to 30 ms to be safe.

config USB_HOST_EXT_PORT_CUSTOM_POWER_ON_DELAY_ENABLE
bool "Custom bPwrOn2PwrGood value"
default n
help
Enables the possibility to configure custom time for the power-on sequence on a port
until power is good on that port.

When enabled, applies the custom PwrOn2PwrGood delay.
When disabled, applies the PwrOn2PwrGood value from the Hub Descriptor.

config USB_HOST_EXT_PORT_CUSTOM_POWER_ON_DELAY_MS
depends on USB_HOST_EXT_PORT_CUSTOM_POWER_ON_DELAY_ENABLE
int "PwrOn2PwrGood delay in ms"
default 100
range 0 5000
help
Custom value of delay from the time the power-on sequence begins on a port
until power is good on that port.
Value 0 is used for a hub with no power switches.

The default value is 100 ms.

endmenu #Downstream Port configuration

endmenu #Hub Driver Configuration

config USB_HOST_ENABLE_ENUM_FILTER_CALLBACK
Expand Down
20 changes: 13 additions & 7 deletions components/usb/enum.c
Original file line number Diff line number Diff line change
Expand Up @@ -765,9 +765,15 @@ static esp_err_t control_response_handling(enum_stage_t stage)
usb_transfer_t *ctrl_xfer = &p_enum_driver->constant.urb->transfer;

if (ctrl_xfer->status != USB_TRANSFER_STATUS_COMPLETED) {
ESP_LOGE(ENUM_TAG, "Bad transfer status %d: %s",
ctrl_xfer->status,
enum_stage_strings[stage]);
if (ctrl_xfer->status == USB_TRANSFER_STATUS_STALL &&
stage >= ENUM_STAGE_CHECK_SHORT_LANGID_TABLE &&
stage <= ENUM_STAGE_CHECK_FULL_SER_STR_DESC) {
// String Descriptor request could be STALLed, if the device doesn't have them
} else {
ESP_LOGE(ENUM_TAG, "Bad transfer status %d: %s",
ctrl_xfer->status,
enum_stage_strings[stage]);
}
return ret;
}

Expand Down Expand Up @@ -1015,10 +1021,6 @@ static bool set_next_stage(bool last_stage_pass)
next_stage = last_stage + 1;
}
} else {
ESP_LOGE(ENUM_TAG, "[%d:%d] %s FAILED",
p_enum_driver->single_thread.parent_dev_addr,
p_enum_driver->single_thread.parent_port_num,
enum_stage_strings[last_stage]);
// These stages cannot fail
assert(last_stage != ENUM_STAGE_SET_ADDR_RECOVERY &&
last_stage != ENUM_STAGE_SELECT_CONFIG &&
Expand Down Expand Up @@ -1055,6 +1057,10 @@ static bool set_next_stage(bool last_stage_pass)
break;
default:
// Stage is not allowed to failed. Cancel enumeration.
ESP_LOGE(ENUM_TAG, "[%d:%d] %s FAILED",
p_enum_driver->single_thread.parent_dev_addr,
p_enum_driver->single_thread.parent_port_num,
enum_stage_strings[last_stage]);
next_stage = ENUM_STAGE_CANCEL;
break;
}
Expand Down
29 changes: 16 additions & 13 deletions components/usb/ext_hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,17 @@
*/
#include <string.h>
#include <stdint.h>
#include "sdkconfig.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp_heap_caps.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "usb_private.h"
#include "ext_hub.h"
#include "ext_port.h"
#include "usb/usb_helpers.h"

typedef struct ext_port_s *ext_port_hdl_t; /* This will be implemented during ext_port driver implementation */

#define EXT_HUB_MAX_STATUS_BYTES_SIZE (sizeof(uint32_t))
#define EXT_HUB_STATUS_CHANGE_FLAG (1 << 0)
#define EXT_HUB_STATUS_PORT1_CHANGE_FLAG (1 << 1)
Expand Down Expand Up @@ -396,8 +395,15 @@ static void device_error(ext_hub_dev_t *ext_hub_dev)

static esp_err_t device_port_new(ext_hub_dev_t *ext_hub_dev, uint8_t port_idx)
{
ext_port_config_t port_config = {
.ext_hub_hdl = (ext_hub_handle_t) ext_hub_dev,
.parent_dev_hdl = ext_hub_dev->constant.dev_hdl,
.parent_port_num = port_idx + 1,
.port_power_delay_ms = ext_hub_dev->constant.hub_desc->bPwrOn2PwrGood * 2,
};

assert(p_ext_hub_driver->constant.port_driver);
esp_err_t ret = p_ext_hub_driver->constant.port_driver->new (NULL, (void**) &ext_hub_dev->constant.ports[port_idx]);
esp_err_t ret = p_ext_hub_driver->constant.port_driver->new (&port_config, (void**) &ext_hub_dev->constant.ports[port_idx]);
if (ret != ESP_OK) {
ESP_LOGE(EXT_HUB_TAG, "[%d:%d] Port allocation error: %s", ext_hub_dev->constant.dev_addr, port_idx + 1, esp_err_to_name(ret));
goto fail;
Expand All @@ -418,7 +424,7 @@ static esp_err_t device_port_free(ext_hub_dev_t *ext_hub_dev, uint8_t port_idx)

assert(ext_hub_dev->single_thread.maxchild != 0);
assert(p_ext_hub_driver->constant.port_driver);
esp_err_t ret = p_ext_hub_driver->constant.port_driver->free(ext_hub_dev->constant.ports[port_idx]);
esp_err_t ret = p_ext_hub_driver->constant.port_driver->del(ext_hub_dev->constant.ports[port_idx]);

if (ret != ESP_OK) {
ESP_LOGE(EXT_HUB_TAG, "[%d:%d] Unable to free port: %s", ext_hub_dev->constant.dev_addr, port_idx + 1, esp_err_to_name(ret));
Expand Down Expand Up @@ -1038,6 +1044,7 @@ static void handle_device(ext_hub_dev_t *ext_hub_dev)
// FSM for external Hub
switch (ext_hub_dev->single_thread.stage) {
case EXT_HUB_STAGE_IDLE:
stage_pass = true;
break;
case EXT_HUB_STAGE_GET_DEVICE_STATUS:
case EXT_HUB_STAGE_GET_HUB_DESCRIPTOR:
Expand Down Expand Up @@ -1118,8 +1125,7 @@ esp_err_t ext_hub_install(const ext_hub_config_t *config)
{
esp_err_t ret;
ext_hub_driver_t *ext_hub_drv = heap_caps_calloc(1, sizeof(ext_hub_driver_t), MALLOC_CAP_DEFAULT);
SemaphoreHandle_t mux_lock = xSemaphoreCreateMutex();
if (ext_hub_drv == NULL || mux_lock == NULL) {
if (ext_hub_drv == NULL) {
ret = ESP_ERR_NO_MEM;
goto err;
}
Expand Down Expand Up @@ -1151,9 +1157,6 @@ esp_err_t ext_hub_install(const ext_hub_config_t *config)
return ESP_OK;

err:
if (mux_lock != NULL) {
vSemaphoreDelete(mux_lock);
}
heap_caps_free(ext_hub_drv);
return ret;
}
Expand Down Expand Up @@ -1672,7 +1675,7 @@ esp_err_t ext_hub_port_get_speed(ext_hub_handle_t ext_hub_hdl, uint8_t port_num,
esp_err_t ext_hub_set_port_feature(ext_hub_handle_t ext_hub_hdl, uint8_t port_num, uint8_t feature)
{
EXT_HUB_ENTER_CRITICAL();
EXT_HUB_CHECK_FROM_CRIT(p_ext_hub_driver != NULL, ESP_ERR_INVALID_STATE);
EXT_HUB_CHECK_FROM_CRIT(p_ext_hub_driver != NULL, ESP_ERR_NOT_ALLOWED);
EXT_HUB_EXIT_CRITICAL();

esp_err_t ret;
Expand Down Expand Up @@ -1701,7 +1704,7 @@ esp_err_t ext_hub_set_port_feature(ext_hub_handle_t ext_hub_hdl, uint8_t port_nu
esp_err_t ext_hub_clear_port_feature(ext_hub_handle_t ext_hub_hdl, uint8_t port_num, uint8_t feature)
{
EXT_HUB_ENTER_CRITICAL();
EXT_HUB_CHECK_FROM_CRIT(p_ext_hub_driver != NULL, ESP_ERR_INVALID_STATE);
EXT_HUB_CHECK_FROM_CRIT(p_ext_hub_driver != NULL, ESP_ERR_NOT_ALLOWED);
EXT_HUB_EXIT_CRITICAL();

esp_err_t ret;
Expand Down Expand Up @@ -1730,7 +1733,7 @@ esp_err_t ext_hub_clear_port_feature(ext_hub_handle_t ext_hub_hdl, uint8_t port_
esp_err_t ext_hub_get_port_status(ext_hub_handle_t ext_hub_hdl, uint8_t port_num)
{
EXT_HUB_ENTER_CRITICAL();
EXT_HUB_CHECK_FROM_CRIT(p_ext_hub_driver != NULL, ESP_ERR_INVALID_STATE);
EXT_HUB_CHECK_FROM_CRIT(p_ext_hub_driver != NULL, ESP_ERR_NOT_ALLOWED);
EXT_HUB_EXIT_CRITICAL();

esp_err_t ret;
Expand Down
Loading

0 comments on commit 96a795d

Please sign in to comment.