mirror of
https://github.com/espressif/esp-idf
synced 2025-03-10 01:29:21 -04:00
Merge branch 'feature/usb_host_ext_hub_driver' into 'master'
feat(ext_hub): Added External Hub Driver Closes IDF-9697, IDF-9205, IDF-10073, and IDF-10100 See merge request espressif/esp-idf!30391
This commit is contained in:
commit
d4f0b77d29
@ -29,6 +29,10 @@ if(CONFIG_SOC_USB_OTG_SUPPORTED)
|
||||
list(APPEND priv_includes "private_include")
|
||||
endif()
|
||||
|
||||
if(CONFIG_USB_HOST_HUBS_SUPPORTED)
|
||||
list(APPEND srcs "ext_hub.c")
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS ${srcs}
|
||||
INCLUDE_DIRS ${include}
|
||||
PRIV_INCLUDE_DIRS ${priv_includes}
|
||||
|
@ -46,73 +46,85 @@ menu "USB-OTG"
|
||||
bool "Periodic OUT"
|
||||
endchoice
|
||||
|
||||
menu "Root Hub configuration"
|
||||
menu "Hub Driver Configuration"
|
||||
|
||||
config USB_HOST_DEBOUNCE_DELAY_MS
|
||||
int "Debounce delay in ms"
|
||||
default 250
|
||||
menu "Root Port configuration"
|
||||
|
||||
config USB_HOST_DEBOUNCE_DELAY_MS
|
||||
int "Debounce delay in ms"
|
||||
default 250
|
||||
help
|
||||
On connection of a USB device, the USB 2.0 specification requires
|
||||
a "debounce interval with a minimum duration of 100ms" to allow the connection to stabilize
|
||||
(see USB 2.0 chapter 7.1.7.3 for more details).
|
||||
During the debounce interval, no new connection/disconnection events are registered.
|
||||
|
||||
The default value is set to 250 ms to be safe.
|
||||
|
||||
config USB_HOST_RESET_HOLD_MS
|
||||
int "Reset hold in ms"
|
||||
default 30
|
||||
help
|
||||
The reset signaling can be generated on any Hub or Host Controller port by request from
|
||||
the USB System Software. The USB 2.0 specification requires that "the reset signaling must
|
||||
be driven for a minimum of 10ms" (see USB 2.0 chapter 7.1.7.5 for more details).
|
||||
After the reset, the hub port will transition to the Enabled state (refer to Section 11.5).
|
||||
|
||||
The default value is set to 30 ms to be safe.
|
||||
|
||||
config USB_HOST_RESET_RECOVERY_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_SET_ADDR_RECOVERY_MS
|
||||
int "SetAddress() recovery time in ms"
|
||||
default 10
|
||||
help
|
||||
"After successful completion of the Status stage, the device is allowed a SetAddress()
|
||||
recovery interval of 2 ms. At the end of this interval, the device must be able to accept
|
||||
Setup packets addressed to the new address. Also, at the end of the recovery interval, the
|
||||
device must not respond to tokens sent to the old address (unless, of course, the old and new
|
||||
address is the same)." See USB 2.0 chapter 9.2.6.3 for more details.
|
||||
|
||||
The default value is set to 10 ms to be safe.
|
||||
|
||||
endmenu #Root Hub configuration
|
||||
|
||||
config USB_HOST_HUBS_SUPPORTED
|
||||
bool "Support Hubs"
|
||||
default n
|
||||
help
|
||||
On connection of a USB device, the USB 2.0 specification requires a "debounce interval with a minimum
|
||||
duration of 100ms" to allow the connection to stabilize (see USB 2.0 chapter 7.1.7.3 for more details).
|
||||
During the debounce interval, no new connection/disconnection events are registered.
|
||||
Enables support of external Hubs.
|
||||
|
||||
The default value is set to 250 ms to be safe.
|
||||
|
||||
config USB_HOST_RESET_HOLD_MS
|
||||
int "Reset hold in ms"
|
||||
default 30
|
||||
config USB_HOST_HUB_MULTI_LEVEL
|
||||
depends on USB_HOST_HUBS_SUPPORTED
|
||||
bool "Support multiple Hubs"
|
||||
default y
|
||||
help
|
||||
The reset signaling can be generated on any Hub or Host Controller port by request from the USB System
|
||||
Software. The USB 2.0 specification requires that "the reset signaling must be driven for a minimum of
|
||||
10ms" (see USB 2.0 chapter 7.1.7.5 for more details). After the reset, the hub port will transition to
|
||||
the Enabled state (refer to Section 11.5).
|
||||
Enables support for connecting multiple Hubs simultaneously.
|
||||
|
||||
The default value is set to 30 ms to be safe.
|
||||
|
||||
config USB_HOST_RESET_RECOVERY_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_SET_ADDR_RECOVERY_MS
|
||||
int "SetAddress() recovery time in ms"
|
||||
default 10
|
||||
help
|
||||
"After successful completion of the Status stage, the device is allowed a SetAddress() recovery
|
||||
interval of 2 ms. At the end of this interval, the device must be able to accept Setup packets
|
||||
addressed to the new address. Also, at the end of the recovery interval, the device must not respond to
|
||||
tokens sent to the old address (unless, of course, the old and new address is the same)." See USB 2.0
|
||||
chapter 9.2.6.3 for more details.
|
||||
|
||||
The default value is set to 10 ms to be safe.
|
||||
|
||||
endmenu #Root Hub configuration
|
||||
endmenu #Hub Driver Configuration
|
||||
|
||||
config USB_HOST_ENABLE_ENUM_FILTER_CALLBACK
|
||||
bool "Enable enumeration filter callback"
|
||||
default n
|
||||
help
|
||||
The enumeration filter callback is called before enumeration of each newly attached device. This callback
|
||||
allows users to control whether a device should be enumerated, and what configuration number to use when
|
||||
enumerating a device.
|
||||
The enumeration filter callback is called before enumeration of each newly attached device.
|
||||
This callback allows users to control whether a device should be enumerated, and what configuration
|
||||
number to use when enumerating a device.
|
||||
|
||||
If enabled, the enumeration filter callback can be set via 'usb_host_config_t' when calling
|
||||
'usb_host_install()'.
|
||||
|
||||
config USB_HOST_EXT_HUB_SUPPORT
|
||||
depends on IDF_EXPERIMENTAL_FEATURES
|
||||
bool "Support USB HUB (Experimental)"
|
||||
default n
|
||||
help
|
||||
Feature is under development.
|
||||
|
||||
# Hidden or compatibility options
|
||||
config USB_OTG_SUPPORTED
|
||||
# Invisible config kept for compatibility
|
||||
|
1598
components/usb/ext_hub.c
Normal file
1598
components/usb/ext_hub.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -19,6 +19,10 @@
|
||||
#include "hub.h"
|
||||
#include "usb/usb_helpers.h"
|
||||
|
||||
#if ENABLE_USB_HUBS
|
||||
#include "ext_hub.h"
|
||||
#endif // ENABLE_USB_HUBS
|
||||
|
||||
/*
|
||||
Implementation of the HUB driver that only supports the Root Hub with a single port. Therefore, we currently don't
|
||||
implement the bare minimum to control the root HCD port.
|
||||
@ -35,13 +39,21 @@ implement the bare minimum to control the root HCD port.
|
||||
#define HUB_ROOT_HCD_PORT_FIFO_BIAS HCD_PORT_FIFO_BIAS_BALANCED
|
||||
#endif
|
||||
|
||||
// Hub driver action flags. LISTED IN THE ORDER THEY SHOULD BE HANDLED IN within hub_process(). Some actions are mutually exclusive
|
||||
#define HUB_DRIVER_FLAG_ACTION_ROOT_EVENT 0x01
|
||||
#define HUB_DRIVER_FLAG_ACTION_PORT_REQ 0x02
|
||||
|
||||
#define PORT_REQ_DISABLE 0x01
|
||||
#define PORT_REQ_RECOVER 0x02
|
||||
|
||||
/**
|
||||
* @brief Hub driver action flags
|
||||
*/
|
||||
typedef enum {
|
||||
HUB_DRIVER_ACTION_ROOT_EVENT = (1 << 0),
|
||||
HUB_DRIVER_ACTION_ROOT_REQ = (1 << 1),
|
||||
#if ENABLE_USB_HUBS
|
||||
HUB_DRIVER_ACTION_EXT_HUB = (1 << 6),
|
||||
HUB_DRIVER_ACTION_EXT_PORT = (1 << 7)
|
||||
#endif // ENABLE_USB_HUBS
|
||||
} hub_flag_action_t;
|
||||
|
||||
/**
|
||||
* @brief Root port states
|
||||
*/
|
||||
@ -57,7 +69,6 @@ typedef enum {
|
||||
* @brief Hub device tree node
|
||||
*
|
||||
* Object type of a node in the USB device tree that is maintained by the Hub driver
|
||||
*
|
||||
*/
|
||||
struct dev_tree_node_s {
|
||||
TAILQ_ENTRY(dev_tree_node_s) tailq_entry; /**< Entry for the device tree node object tailq */
|
||||
@ -72,11 +83,11 @@ typedef struct {
|
||||
struct {
|
||||
union {
|
||||
struct {
|
||||
uint32_t actions: 8;
|
||||
uint32_t reserved24: 24;
|
||||
hub_flag_action_t actions: 8; /**< Hub actions */
|
||||
uint32_t reserved24: 24; /**< Reserved */
|
||||
};
|
||||
uint32_t val; /**< Root port flag value */
|
||||
} flags; /**< Root port flags */
|
||||
uint32_t val; /**< Hub flag action value */
|
||||
} flags; /**< Hub flags */
|
||||
root_port_state_t root_port_state; /**< Root port state */
|
||||
unsigned int port_reqs; /**< Root port request flag */
|
||||
} dynamic; /**< Dynamic members. Require a critical section */
|
||||
@ -145,7 +156,7 @@ static bool root_port_callback(hcd_port_handle_t port_hdl, hcd_port_event_t port
|
||||
*/
|
||||
static esp_err_t new_dev_tree_node(usb_device_handle_t parent_dev_hdl, uint8_t parent_port_num, usb_speed_t speed)
|
||||
{
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
esp_err_t ret;
|
||||
unsigned int node_uid = p_hub_driver_obj->single_thread.next_uid;
|
||||
|
||||
dev_tree_node_t *dev_tree_node = heap_caps_calloc(1, sizeof(dev_tree_node_t), MALLOC_CAP_DEFAULT);
|
||||
@ -165,6 +176,8 @@ static esp_err_t new_dev_tree_node(usb_device_handle_t parent_dev_hdl, uint8_t p
|
||||
|
||||
ret = usbh_devs_add(¶ms);
|
||||
if (ret != ESP_OK) {
|
||||
// USBH devs add could failed due to lack of free hcd channels
|
||||
// TODO: IDF-10044 Hub should recover after running out of hcd channels
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -293,12 +306,22 @@ static esp_err_t dev_tree_node_remove_by_parent(usb_device_handle_t parent_dev_h
|
||||
static bool root_port_callback(hcd_port_handle_t port_hdl, hcd_port_event_t port_event, void *user_arg, bool in_isr)
|
||||
{
|
||||
HUB_DRIVER_ENTER_CRITICAL_SAFE();
|
||||
p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_ROOT_EVENT;
|
||||
p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_ACTION_ROOT_EVENT;
|
||||
HUB_DRIVER_EXIT_CRITICAL_SAFE();
|
||||
assert(in_isr); // Currently, this callback should only ever be called from an ISR context
|
||||
return p_hub_driver_obj->constant.proc_req_cb(USB_PROC_REQ_SOURCE_HUB, in_isr, p_hub_driver_obj->constant.proc_req_cb_arg);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_USB_HUBS
|
||||
static bool ext_hub_callback(bool in_isr, void *user_arg)
|
||||
{
|
||||
HUB_DRIVER_ENTER_CRITICAL_SAFE();
|
||||
p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_ACTION_EXT_HUB;
|
||||
HUB_DRIVER_EXIT_CRITICAL_SAFE();
|
||||
return p_hub_driver_obj->constant.proc_req_cb(USB_PROC_REQ_SOURCE_HUB, in_isr, p_hub_driver_obj->constant.proc_req_cb_arg);
|
||||
}
|
||||
#endif // ENABLE_USB_HUBS
|
||||
|
||||
// ---------------------- Handlers -------------------------
|
||||
static void root_port_handle_events(hcd_port_handle_t root_port_hdl)
|
||||
{
|
||||
@ -344,7 +367,7 @@ reset_err:
|
||||
case ROOT_PORT_STATE_DISABLED: // This occurred after the device has already been disabled
|
||||
// Therefore, there's no device object to clean up, and we can go straight to port recovery
|
||||
p_hub_driver_obj->dynamic.port_reqs |= PORT_REQ_RECOVER;
|
||||
p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_PORT_REQ;
|
||||
p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_ACTION_ROOT_REQ;
|
||||
break;
|
||||
case ROOT_PORT_STATE_ENABLED:
|
||||
// There is an enabled (active) device. We need to indicate to USBH that the device is gone
|
||||
@ -409,7 +432,7 @@ static esp_err_t root_port_recycle(void)
|
||||
abort(); // Should never occur
|
||||
break;
|
||||
}
|
||||
p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_PORT_REQ;
|
||||
p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_ACTION_ROOT_REQ;
|
||||
HUB_DRIVER_EXIT_CRITICAL();
|
||||
|
||||
ESP_ERROR_CHECK(dev_tree_node_remove_by_parent(NULL, 0));
|
||||
@ -434,7 +457,20 @@ esp_err_t hub_install(hub_config_t *hub_config, void **client_ret)
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
#if ENABLE_USB_HUBS
|
||||
// Install External HUB driver
|
||||
ext_hub_config_t ext_hub_config = {
|
||||
.proc_req_cb = ext_hub_callback,
|
||||
.port_driver = NULL,
|
||||
};
|
||||
ret = ext_hub_install(&ext_hub_config);
|
||||
if (ret != ESP_OK) {
|
||||
goto err_ext_hub;
|
||||
}
|
||||
*client_ret = ext_hub_get_client();
|
||||
#else
|
||||
*client_ret = NULL;
|
||||
#endif // ENABLE_USB_HUBS
|
||||
|
||||
// Install HCD port
|
||||
hcd_port_config_t port_config = {
|
||||
@ -474,6 +510,10 @@ esp_err_t hub_install(hub_config_t *hub_config, void **client_ret)
|
||||
assign_err:
|
||||
ESP_ERROR_CHECK(hcd_port_deinit(root_port_hdl));
|
||||
err:
|
||||
#if ENABLE_USB_HUBS
|
||||
ext_hub_uninstall();
|
||||
err_ext_hub:
|
||||
#endif // ENABLE_USB_HUBS
|
||||
heap_caps_free(hub_driver_obj);
|
||||
return ret;
|
||||
}
|
||||
@ -487,6 +527,10 @@ esp_err_t hub_uninstall(void)
|
||||
p_hub_driver_obj = NULL;
|
||||
HUB_DRIVER_EXIT_CRITICAL();
|
||||
|
||||
#if ENABLE_USB_HUBS
|
||||
ESP_ERROR_CHECK(ext_hub_uninstall());
|
||||
#endif // ENABLE_USB_HUBS
|
||||
|
||||
ESP_ERROR_CHECK(hcd_port_deinit(hub_driver_obj->constant.root_port_hdl));
|
||||
// Free Hub driver resources
|
||||
heap_caps_free(hub_driver_obj);
|
||||
@ -531,14 +575,19 @@ esp_err_t hub_port_recycle(usb_device_handle_t parent_dev_hdl, uint8_t parent_po
|
||||
HUB_DRIVER_ENTER_CRITICAL();
|
||||
HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj != NULL, ESP_ERR_INVALID_STATE);
|
||||
HUB_DRIVER_EXIT_CRITICAL();
|
||||
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
esp_err_t ret;
|
||||
|
||||
if (parent_port_num == 0) {
|
||||
ret = root_port_recycle();
|
||||
} else {
|
||||
ESP_LOGW(HUB_DRIVER_TAG, "Recycling External Port has not been implemented yet");
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
#if ENABLE_USB_HUBS
|
||||
ext_hub_handle_t ext_hub_hdl = NULL;
|
||||
ext_hub_get_handle(parent_dev_hdl, &ext_hub_hdl);
|
||||
ret = ext_hub_port_recycle(ext_hub_hdl, parent_port_num);
|
||||
#else
|
||||
ESP_LOGW(HUB_DRIVER_TAG, "Recycling External Port is not available (External Hub support disabled)");
|
||||
ret = ESP_ERR_NOT_SUPPORTED;
|
||||
#endif // ENABLE_USB_HUBS
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -549,8 +598,7 @@ esp_err_t hub_port_reset(usb_device_handle_t parent_dev_hdl, uint8_t parent_port
|
||||
HUB_DRIVER_ENTER_CRITICAL();
|
||||
HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj != NULL, ESP_ERR_INVALID_STATE);
|
||||
HUB_DRIVER_EXIT_CRITICAL();
|
||||
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
esp_err_t ret;
|
||||
|
||||
if (parent_port_num == 0) {
|
||||
ret = hcd_port_command(p_hub_driver_obj->constant.root_port_hdl, HCD_PORT_CMD_RESET);
|
||||
@ -559,13 +607,68 @@ esp_err_t hub_port_reset(usb_device_handle_t parent_dev_hdl, uint8_t parent_port
|
||||
}
|
||||
ret = dev_tree_node_reset_completed(NULL, 0);
|
||||
} else {
|
||||
ESP_LOGW(HUB_DRIVER_TAG, "Reset External Port has not been implemented yet");
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
#if ENABLE_USB_HUBS
|
||||
ext_hub_handle_t ext_hub_hdl = NULL;
|
||||
ext_hub_get_handle(parent_dev_hdl, &ext_hub_hdl);
|
||||
ret = ext_hub_port_reset(ext_hub_hdl, parent_port_num);
|
||||
#else
|
||||
ESP_LOGW(HUB_DRIVER_TAG, "Resetting External Port is not available (External Hub support disabled)");
|
||||
ret = ESP_ERR_NOT_SUPPORTED;
|
||||
#endif // ENABLE_USB_HUBS
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t hub_port_active(usb_device_handle_t parent_dev_hdl, uint8_t parent_port_num)
|
||||
{
|
||||
esp_err_t ret;
|
||||
|
||||
if (parent_port_num == 0) {
|
||||
// Root port no need to be activated
|
||||
ret = ESP_OK;
|
||||
} else {
|
||||
#if ENABLE_USB_HUBS
|
||||
// External Hub port
|
||||
ext_hub_handle_t ext_hub_hdl = NULL;
|
||||
ext_hub_get_handle(parent_dev_hdl, &ext_hub_hdl);
|
||||
ret = ext_hub_port_active(ext_hub_hdl, parent_port_num);
|
||||
#else
|
||||
ESP_LOGW(HUB_DRIVER_TAG, "Activating External Port is not available (External Hub support disabled)");
|
||||
ret = ESP_ERR_NOT_SUPPORTED;
|
||||
#endif // ENABLE_USB_HUBS
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if ENABLE_USB_HUBS
|
||||
esp_err_t hub_notify_new_dev(uint8_t dev_addr)
|
||||
{
|
||||
HUB_DRIVER_ENTER_CRITICAL();
|
||||
HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj != NULL, ESP_ERR_INVALID_STATE);
|
||||
HUB_DRIVER_EXIT_CRITICAL();
|
||||
|
||||
return ext_hub_new_dev(dev_addr);
|
||||
}
|
||||
|
||||
esp_err_t hub_notify_dev_gone(uint8_t dev_addr)
|
||||
{
|
||||
HUB_DRIVER_ENTER_CRITICAL();
|
||||
HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj != NULL, ESP_ERR_INVALID_STATE);
|
||||
HUB_DRIVER_EXIT_CRITICAL();
|
||||
|
||||
return ext_hub_dev_gone(dev_addr);
|
||||
}
|
||||
|
||||
esp_err_t hub_notify_all_free(void)
|
||||
{
|
||||
HUB_DRIVER_ENTER_CRITICAL();
|
||||
HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj != NULL, ESP_ERR_INVALID_STATE);
|
||||
HUB_DRIVER_EXIT_CRITICAL();
|
||||
|
||||
return ext_hub_all_free();
|
||||
}
|
||||
#endif // ENABLE_USB_HUBS
|
||||
|
||||
esp_err_t hub_process(void)
|
||||
{
|
||||
HUB_DRIVER_ENTER_CRITICAL();
|
||||
@ -574,10 +677,21 @@ esp_err_t hub_process(void)
|
||||
HUB_DRIVER_EXIT_CRITICAL();
|
||||
|
||||
while (action_flags) {
|
||||
if (action_flags & HUB_DRIVER_FLAG_ACTION_ROOT_EVENT) {
|
||||
#if ENABLE_USB_HUBS
|
||||
if (action_flags & HUB_DRIVER_ACTION_EXT_PORT) {
|
||||
ESP_LOGW(HUB_DRIVER_TAG, "ext_port_process() has not been implemented yet");
|
||||
/*
|
||||
ESP_ERROR_CHECK(ext_port_process());
|
||||
*/
|
||||
}
|
||||
if (action_flags & HUB_DRIVER_ACTION_EXT_HUB) {
|
||||
ESP_ERROR_CHECK(ext_hub_process());
|
||||
}
|
||||
#endif // ENABLE_USB_HUBS
|
||||
if (action_flags & HUB_DRIVER_ACTION_ROOT_EVENT) {
|
||||
root_port_handle_events(p_hub_driver_obj->constant.root_port_hdl);
|
||||
}
|
||||
if (action_flags & HUB_DRIVER_FLAG_ACTION_PORT_REQ) {
|
||||
if (action_flags & HUB_DRIVER_ACTION_ROOT_REQ) {
|
||||
root_port_req(p_hub_driver_obj->constant.root_port_hdl);
|
||||
}
|
||||
|
||||
@ -586,5 +700,6 @@ esp_err_t hub_process(void)
|
||||
p_hub_driver_obj->dynamic.flags.actions = 0;
|
||||
HUB_DRIVER_EXIT_CRITICAL();
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
@ -66,7 +66,34 @@ typedef enum {
|
||||
} usb_hub_port_feature_t;
|
||||
|
||||
/**
|
||||
* @brief Size of a USB Hub Port Status and Hub Change results
|
||||
* @brief USB Hub characteristics
|
||||
*
|
||||
* See USB 2.0 spec Table 11-13, offset 3
|
||||
*/
|
||||
#define USB_W_HUB_CHARS_PORT_PWR_CTRL_ALL (0) /**< All ports power control at once */
|
||||
#define USB_W_HUB_CHARS_PORT_PWR_CTRL_INDV (1) /**< Individual port power control */
|
||||
#define USB_W_HUB_CHARS_PORT_PWR_CTRL_NO (2) /**< No power switching */
|
||||
|
||||
#define USB_W_HUB_CHARS_PORT_OVER_CURR_ALL (0) /**< All ports Over-Current reporting */
|
||||
#define USB_W_HUB_CHARS_PORT_OVER_CURR_INDV (1) /**< Individual port Over-current reporting */
|
||||
#define USB_W_HUB_CHARS_PORT_OVER_CURR_NO (2) /**< No Over-current Protection support */
|
||||
|
||||
#define USB_W_HUB_CHARS_TTTT_8_BITS (0) /**< TT requires at most 8 FS bit times of inter transaction gap on a full-/low-speed downstream bus */
|
||||
#define USB_W_HUB_CHARS_TTTT_16_BITS (1) /**< TT requires at most 16 FS bit times */
|
||||
#define USB_W_HUB_CHARS_TTTT_24_BITS (2) /**< TT requires at most 24 FS bit times */
|
||||
#define USB_W_HUB_CHARS_TTTT_32_BITS (3) /**< TT requires at most 32 FS bit times */
|
||||
|
||||
/**
|
||||
* @brief USB Hub bDeviceProtocol
|
||||
*/
|
||||
#define USB_B_DEV_PROTOCOL_HUB_FS (0) /**< Full speed hub */
|
||||
#define USB_B_DEV_PROTOCOL_HUB_HS_NO_TT (0) /**< Hi-speed hub without TT */
|
||||
#define USB_B_DEV_PROTOCOL_HUB_HS_SINGLE_TT (1) /**< Hi-speed hub with single TT */
|
||||
#define USB_B_DEV_PROTOCOL_HUB_HS_MULTI_TT (2) /**< Hi-speed hub with multiple TT */
|
||||
#define USB_B_DEV_PROTOCOL_HUB_SS (3) /**< Super speed hub */
|
||||
|
||||
/**
|
||||
* @brief USB Hub Port Status and Hub Change results size
|
||||
*/
|
||||
#define USB_PORT_STATUS_SIZE 4
|
||||
|
||||
@ -148,7 +175,17 @@ typedef struct {
|
||||
uint8_t bDescLength; /**< Number of bytes in this descriptor, including this byte */
|
||||
uint8_t bDescriptorType; /**< Descriptor Type, value: 29H for Hub descriptor */
|
||||
uint8_t bNbrPorts; /**< Number of downstream facing ports that this Hub supports */
|
||||
uint16_t wHubCharacteristics; /**< Logical Power Switching Mode, Compound Device, Over-current Protection Mode, TT Think Time, Port Indicators Supported */
|
||||
union {
|
||||
struct {
|
||||
uint16_t power_switching: 2;
|
||||
uint16_t compound: 1;
|
||||
uint16_t ovr_current_protect: 2;
|
||||
uint16_t tt_think_time: 2;
|
||||
uint16_t indicator_support: 1;
|
||||
uint16_t reserved: 8;
|
||||
};
|
||||
uint16_t val; /**< Hub Characteristics value */
|
||||
} wHubCharacteristics; /**< Hub Characteristics */
|
||||
uint8_t bPwrOn2PwrGood; /**< Time (in 2 ms intervals) from the time the power-on sequence begins on a port until power is good on that port */
|
||||
uint8_t bHubContrCurrent; /**< Maximum current requirements of the Hub Controller electronics in mA. */
|
||||
} __attribute__((packed)) usb_hub_descriptor_t;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -101,6 +101,21 @@ typedef union {
|
||||
} usb_setup_packet_t;
|
||||
ESP_STATIC_ASSERT(sizeof(usb_setup_packet_t) == USB_SETUP_PACKET_SIZE, "Size of usb_setup_packet_t incorrect");
|
||||
|
||||
/**
|
||||
* @brief Structure representing a USB device status
|
||||
*
|
||||
* See Figures 9-4 Information Returned by a GetStatus() Request to a Device of USB2.0 specification for more details
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint16_t self_powered: 1; /**< 1 - Device is currently self-powered, 0 - bus powered */
|
||||
uint16_t remote_wakeup: 1; /**< 1 - the ability of the device to signal remote wakeup is enabled, 0 - the ability of the device to signal remote wakeup is disabled. */
|
||||
uint16_t reserved: 14; /**< reserved */
|
||||
} USB_DESC_ATTR; /**< Packed */
|
||||
uint16_t val; /**< Device status value */
|
||||
} usb_device_status_t;
|
||||
ESP_STATIC_ASSERT(sizeof(usb_device_status_t) == sizeof(uint16_t), "Size of usb_device_status_t incorrect");
|
||||
|
||||
/**
|
||||
* @brief Bit masks belonging to the bmRequestType field of a setup packet
|
||||
*/
|
||||
@ -144,6 +159,19 @@ ESP_STATIC_ASSERT(sizeof(usb_setup_packet_t) == USB_SETUP_PACKET_SIZE, "Size of
|
||||
#define USB_W_VALUE_DT_OTHER_SPEED_CONFIG 0x07
|
||||
#define USB_W_VALUE_DT_INTERFACE_POWER 0x08
|
||||
|
||||
/**
|
||||
* @brief Initializer for a GET_STATUS request
|
||||
*
|
||||
* Sets the address of a connected device
|
||||
*/
|
||||
#define USB_SETUP_PACKET_INIT_GET_STATUS(setup_pkt_ptr) ({ \
|
||||
(setup_pkt_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_IN | USB_BM_REQUEST_TYPE_TYPE_STANDARD | USB_BM_REQUEST_TYPE_RECIP_DEVICE; \
|
||||
(setup_pkt_ptr)->bRequest = USB_B_REQUEST_GET_STATUS; \
|
||||
(setup_pkt_ptr)->wValue = 0; \
|
||||
(setup_pkt_ptr)->wIndex = 0; \
|
||||
(setup_pkt_ptr)->wLength = 2; \
|
||||
})
|
||||
|
||||
/**
|
||||
* @brief Initializer for a SET_ADDRESS request
|
||||
*
|
||||
|
248
components/usb/private_include/ext_hub.h
Normal file
248
components/usb/private_include/ext_hub.h
Normal file
@ -0,0 +1,248 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
#include "hcd.h"
|
||||
#include "usbh.h"
|
||||
#include "usb/usb_types_stack.h"
|
||||
#include "usb/usb_types_ch9.h"
|
||||
#include "usb/usb_types_ch11.h"
|
||||
|
||||
#if CONFIG_USB_HOST_HUB_MULTI_LEVEL
|
||||
#define ENABLE_MULTIPLE_HUBS 1
|
||||
#endif // CONFIG_USB_HOST_HUB_MULTI_LEVEL
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// ----------------------------- Handles ---------------------------------------
|
||||
|
||||
typedef struct ext_hub_s *ext_hub_handle_t;
|
||||
|
||||
// ---------------------------- Callbacks --------------------------------------
|
||||
|
||||
/**
|
||||
* @brief Callback used to indicate that the External Hub Driver requires process callback
|
||||
* For Hub Driver only
|
||||
*/
|
||||
typedef bool (*ext_hub_cb_t)(bool in_isr, void *user_arg);
|
||||
|
||||
// ------------------------ External Port API typedefs -------------------------
|
||||
|
||||
/**
|
||||
* @brief External Hub Port driver
|
||||
*/
|
||||
typedef struct {
|
||||
esp_err_t (*new)(void *port_cfg, void **port_hdl);
|
||||
esp_err_t (*reset)(void *port_hdl);
|
||||
esp_err_t (*recycle)(void *port_hdl);
|
||||
esp_err_t (*active)(void *port_hdl);
|
||||
esp_err_t (*disable)(void *port_hdl);
|
||||
esp_err_t (*gone)(void *port_hdl);
|
||||
esp_err_t (*free)(void *port_hdl);
|
||||
esp_err_t (*get_speed)(void *por_hdl, usb_speed_t *speed);
|
||||
esp_err_t (*get_status)(void *port_hdl);
|
||||
esp_err_t (*set_status)(void *port_hdl, const usb_port_status_t *status);
|
||||
} ext_hub_port_driver_t;
|
||||
|
||||
/**
|
||||
* @brief External Hub Driver configuration
|
||||
*/
|
||||
typedef struct {
|
||||
ext_hub_cb_t proc_req_cb; /**< External Hub process callback */
|
||||
void *proc_req_cb_arg; /**< External Hub process callback argument */
|
||||
const ext_hub_port_driver_t* port_driver; /**< External Port Driver */
|
||||
} ext_hub_config_t;
|
||||
|
||||
// ------------------------------ Driver ---------------------------------------
|
||||
|
||||
/**
|
||||
* @brief Install External Hub Driver
|
||||
*
|
||||
* Entry:
|
||||
* - should be called within Hub Driver
|
||||
*
|
||||
* @param[in] config External Hub driver configuration
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t ext_hub_install(const ext_hub_config_t* config);
|
||||
|
||||
/**
|
||||
* @brief Uninstall External Hub Driver
|
||||
*
|
||||
* Entry:
|
||||
* - should be called within Hub Driver
|
||||
*
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t ext_hub_uninstall(void);
|
||||
|
||||
/**
|
||||
* @brief External Hub Driver get client pointer
|
||||
*
|
||||
* Entry:
|
||||
* - should be called within Hub Driver
|
||||
*
|
||||
* @param[in] config External Hub driver configuration
|
||||
* @return Unique pointer to identify the External Hub as a USB Host client
|
||||
*/
|
||||
void *ext_hub_get_client(void);
|
||||
|
||||
// -------------------------- External Hub API ---------------------------------
|
||||
|
||||
/**
|
||||
* @brief Get External Hub device handle by USBH device handle
|
||||
*
|
||||
* @param[in] dev_hdl USBH device handle
|
||||
* @param[out] ext_hub_hdl External Hub device handle
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t ext_hub_get_handle(usb_device_handle_t dev_hdl, ext_hub_handle_t *ext_hub_hdl);
|
||||
|
||||
/**
|
||||
* @brief Add new device
|
||||
*
|
||||
* After attaching new device:
|
||||
* - configure it's parameters (requesting hub descriptor)
|
||||
*
|
||||
* @param[in] dev_addr Device bus address
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t ext_hub_new_dev(uint8_t dev_addr);
|
||||
|
||||
/**
|
||||
* @brief Device gone
|
||||
*
|
||||
* After device were detached:
|
||||
* - prepare the device to be freed
|
||||
*
|
||||
* @param[in] dev_addr Device bus address
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t ext_hub_dev_gone(uint8_t dev_addr);
|
||||
|
||||
/**
|
||||
* @brief Marks all devices to be freed
|
||||
*
|
||||
* Entry:
|
||||
* - should be called within Hub Driver when USB Host library need to be uninstalled
|
||||
*
|
||||
* @param[in] dev_addr Device bus address
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t ext_hub_all_free(void);
|
||||
|
||||
/**
|
||||
* @brief The External Hub or Ports statuses change completed
|
||||
*
|
||||
* Enables Interrupt IN endpoint to get information about Hub or Ports statuses change
|
||||
*
|
||||
* @param[in] ext_hub_hdl External Hub device handle
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t ext_hub_status_handle_complete(ext_hub_handle_t ext_hub_hdl);
|
||||
|
||||
/**
|
||||
* @brief External Hub driver's process function
|
||||
*
|
||||
* External Hub driver process function that must be called repeatedly to process the driver's actions and events.
|
||||
* If blocking, the caller can block on the notification callback of source USB_PROC_REQ_SOURCE_HUB
|
||||
* to run this function.
|
||||
*/
|
||||
esp_err_t ext_hub_process(void);
|
||||
|
||||
// -------------------- External Hub - Port related ----------------------------
|
||||
|
||||
/**
|
||||
* @brief Indicate to the External Hub driver that a device's port can be recycled
|
||||
*
|
||||
* The device connected to the port has been freed. The Hub driver can now
|
||||
* recycle the port.
|
||||
*
|
||||
* @param[in] ext_hub_hdl External Hub handle
|
||||
* @param[in] port_num Port number
|
||||
* @retval ESP_OK: Success
|
||||
*/
|
||||
esp_err_t ext_hub_port_recycle(ext_hub_handle_t ext_hub_hdl, uint8_t port_num);
|
||||
|
||||
/**
|
||||
* @brief Indicate to the External Hub driver that a device's port need a reset
|
||||
*
|
||||
* @param[in] ext_hub_hdl External Hub handle
|
||||
* @param[in] port_num Port number
|
||||
* @retval ESP_OK: Success
|
||||
*/
|
||||
esp_err_t ext_hub_port_reset(ext_hub_handle_t ext_hub_hdl, uint8_t port_num);
|
||||
|
||||
/**
|
||||
* @brief Indicate to the External Hub driver that a device's port has a device and device has been enumerated
|
||||
*
|
||||
* @param[in] ext_hub_hdl External Hub handle
|
||||
* @param[in] port_num Port number
|
||||
* @retval ESP_OK: Success
|
||||
*/
|
||||
esp_err_t ext_hub_port_active(ext_hub_handle_t ext_hub_hdl, uint8_t port_num);
|
||||
|
||||
/**
|
||||
* @brief Indicate to the External Hub driver that a device's port should be disabled
|
||||
*
|
||||
* @param[in] ext_hub_hdl External Hub handle
|
||||
* @param[in] port_num Port number
|
||||
* @retval ESP_OK: Success
|
||||
*/
|
||||
esp_err_t ext_hub_port_disable(ext_hub_handle_t ext_hub_hdl, uint8_t port_num);
|
||||
|
||||
/**
|
||||
* @brief Returns device speed of the device, attached to the port
|
||||
*
|
||||
* @param[in] ext_hub_hdl External Hub handle
|
||||
* @param[in] port_num Port number
|
||||
* @param[out] speed Devices' speed
|
||||
* @retval ESP_OK: Success
|
||||
*/
|
||||
esp_err_t ext_hub_port_get_speed(ext_hub_handle_t ext_hub_hdl, uint8_t port_num, usb_speed_t *speed);
|
||||
|
||||
// --------------------------- USB Chapter 11 ----------------------------------
|
||||
|
||||
/**
|
||||
* @brief Set Port Feature request
|
||||
*
|
||||
* @param[in] ext_hub_hdl External Hub device handle
|
||||
* @param[in] port_num Port number
|
||||
* @param[in] feature Port Feature to set
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t ext_hub_set_port_feature(ext_hub_handle_t ext_hub_hdl, uint8_t port_num, uint8_t feature);
|
||||
|
||||
/**
|
||||
* @brief Clear Port Feature request
|
||||
*
|
||||
* @param[in] ext_hub_hdl External Hub device handle
|
||||
* @param[in] port_num Port number
|
||||
* @param[in] feature Port Feature to clear
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t ext_hub_clear_port_feature(ext_hub_handle_t ext_hub_hdl, uint8_t port_num, uint8_t feature);
|
||||
|
||||
/**
|
||||
* @brief Get Port Status request
|
||||
*
|
||||
* Sends the request to retrieve port status data.
|
||||
* Actual port status data could be requested by calling ext_hub_get_port_status() after request completion.
|
||||
*
|
||||
* @param[in] ext_hub_hdl External Hub device handle
|
||||
* @param[in] port_num Port number
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t ext_hub_get_port_status(ext_hub_handle_t ext_hub_hdl, uint8_t port_num);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -8,10 +8,15 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
#include "usb_private.h"
|
||||
#include "usbh.h"
|
||||
|
||||
#if CONFIG_USB_HOST_HUBS_SUPPORTED
|
||||
#define ENABLE_USB_HUBS 1
|
||||
#endif // CONFIG_USB_HOST_HUBS_SUPPORTED
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -138,6 +143,50 @@ esp_err_t hub_port_recycle(usb_device_handle_t parent_dev_hdl, uint8_t parent_po
|
||||
*/
|
||||
esp_err_t hub_port_reset(usb_device_handle_t parent_dev_hdl, uint8_t parent_port_num);
|
||||
|
||||
/**
|
||||
* @brief Activate the port
|
||||
*
|
||||
* @note This function should only be called from the Host Library task
|
||||
*
|
||||
* @param[in] parent_dev_hdl Parent device handle (is used to get the External Hub handle)
|
||||
* @param[in] parent_port_num Parent number (is used to specify the External Port)
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
*/
|
||||
esp_err_t hub_port_active(usb_device_handle_t parent_dev_hdl, uint8_t parent_port_num);
|
||||
|
||||
#if ENABLE_USB_HUBS
|
||||
/**
|
||||
* @brief Notify Hub driver that new device has been attached
|
||||
*
|
||||
* If device is has a HUB class, then it will be added as External Hub to Hub Driver.
|
||||
*
|
||||
* @param[in] dev_addr Device bus address
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
*/
|
||||
esp_err_t hub_notify_new_dev(uint8_t dev_addr);
|
||||
|
||||
/**
|
||||
* @brief Notify Hub driver that device has been removed
|
||||
*
|
||||
* If the device was an External Hub, then it will be removed from the Hub Driver.
|
||||
*
|
||||
* @param[in] dev_addr Device bus address
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
*/
|
||||
esp_err_t hub_notify_dev_gone(uint8_t dev_addr);
|
||||
|
||||
/**
|
||||
* @brief Notify Hub driver that all devices should be freed
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
*/
|
||||
esp_err_t hub_notify_all_free(void);
|
||||
#endif // ENABLE_USB_HUBS
|
||||
|
||||
/**
|
||||
* @brief Hub driver's processing function
|
||||
*
|
||||
|
@ -227,6 +227,11 @@ static inline bool _is_internal_client(void *client)
|
||||
if (p_host_lib_obj->constant.enum_client && (client == p_host_lib_obj->constant.enum_client)) {
|
||||
return true;
|
||||
}
|
||||
#if ENABLE_USB_HUBS
|
||||
if (p_host_lib_obj->constant.hub_client && (client == p_host_lib_obj->constant.hub_client)) {
|
||||
return true;
|
||||
}
|
||||
#endif // ENABLE_USB_HUBS
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -311,9 +316,15 @@ static void usbh_event_callback(usbh_event_data_t *event_data, void *arg)
|
||||
.new_dev.address = event_data->new_dev_data.dev_addr,
|
||||
};
|
||||
send_event_msg_to_clients(&event_msg, true, 0);
|
||||
#if ENABLE_USB_HUBS
|
||||
hub_notify_new_dev(event_data->new_dev_data.dev_addr);
|
||||
#endif // ENABLE_USB_HUBS
|
||||
break;
|
||||
}
|
||||
case USBH_EVENT_DEV_GONE: {
|
||||
#if ENABLE_USB_HUBS
|
||||
hub_notify_dev_gone(event_data->new_dev_data.dev_addr);
|
||||
#endif // ENABLE_USB_HUBS
|
||||
// Prepare event msg, send only to clients that have opened the device
|
||||
usb_host_client_event_msg_t event_msg = {
|
||||
.event = USB_HOST_CLIENT_EVENT_DEV_GONE,
|
||||
@ -324,9 +335,10 @@ static void usbh_event_callback(usbh_event_data_t *event_data, void *arg)
|
||||
}
|
||||
case USBH_EVENT_DEV_FREE: {
|
||||
// Let the Hub driver know that the device is free and its port can be recycled
|
||||
ESP_ERROR_CHECK(hub_port_recycle(event_data->dev_free_data.parent_dev_hdl,
|
||||
event_data->dev_free_data.port_num,
|
||||
event_data->dev_free_data.dev_uid));
|
||||
// Port could be absent, no need to verify
|
||||
hub_port_recycle(event_data->dev_free_data.parent_dev_hdl,
|
||||
event_data->dev_free_data.port_num,
|
||||
event_data->dev_free_data.dev_uid);
|
||||
break;
|
||||
}
|
||||
case USBH_EVENT_ALL_FREE: {
|
||||
@ -378,6 +390,8 @@ static void enum_event_callback(enum_event_data_t *event_data, void *arg)
|
||||
hub_port_reset(event_data->reset_req.parent_dev_hdl, event_data->reset_req.parent_port_num);
|
||||
break;
|
||||
case ENUM_EVENT_COMPLETED:
|
||||
// Notify port that device completed enumeration
|
||||
hub_port_active(event_data->complete.parent_dev_hdl, event_data->complete.parent_port_num);
|
||||
// Propagate a new device event
|
||||
ESP_ERROR_CHECK(usbh_devs_new_dev_event(event_data->complete.dev_hdl));
|
||||
break;
|
||||
@ -995,6 +1009,9 @@ esp_err_t usb_host_device_free_all(void)
|
||||
HOST_CHECK_FROM_CRIT(p_host_lib_obj->dynamic.flags.num_clients == 0, ESP_ERR_INVALID_STATE); // All clients must have been deregistered
|
||||
HOST_EXIT_CRITICAL();
|
||||
esp_err_t ret;
|
||||
#if ENABLE_USB_HUBS
|
||||
hub_notify_all_free();
|
||||
#endif // ENABLE_USB_HUBS
|
||||
ret = usbh_devs_mark_all_free();
|
||||
// If ESP_ERR_NOT_FINISHED is returned, caller must wait for USB_HOST_LIB_EVENT_FLAGS_ALL_FREE to confirm all devices are free
|
||||
return ret;
|
||||
|
@ -117,7 +117,8 @@ USB_DOCS = ['api-reference/peripherals/usb_device.rst',
|
||||
'api-reference/peripherals/usb_host/usb_host_notes_dwc_otg.rst',
|
||||
'api-reference/peripherals/usb_host/usb_host_notes_index.rst',
|
||||
'api-reference/peripherals/usb_host/usb_host_notes_usbh.rst',
|
||||
'api-reference/peripherals/usb_host/usb_host_notes_enum.rst']
|
||||
'api-reference/peripherals/usb_host/usb_host_notes_enum.rst',
|
||||
'api-reference/peripherals/usb_host/usb_host_notes_ext_hub.rst']
|
||||
|
||||
I80_LCD_DOCS = ['api-reference/peripherals/lcd/i80_lcd.rst']
|
||||
RGB_LCD_DOCS = ['api-reference/peripherals/lcd/rgb_lcd.rst']
|
||||
|
@ -86,6 +86,7 @@ api-reference/peripherals/usb_host/usb_host_notes_dwc_otg.rst
|
||||
api-reference/peripherals/usb_host/usb_host_notes_design.rst
|
||||
api-reference/peripherals/usb_host/usb_host_notes_usbh.rst
|
||||
api-reference/peripherals/usb_host/usb_host_notes_enum.rst
|
||||
api-reference/peripherals/usb_host/usb_host_notes_ext_hub.rst
|
||||
api-reference/peripherals/usb_device.rst
|
||||
api-reference/peripherals/sdspi_host.rst
|
||||
api-reference/peripherals/spi_slave.rst
|
||||
|
@ -18,6 +18,7 @@ api-reference/peripherals/usb_host/usb_host_notes_dwc_otg.rst
|
||||
api-reference/peripherals/usb_host/usb_host_notes_design.rst
|
||||
api-reference/peripherals/usb_host/usb_host_notes_usbh.rst
|
||||
api-reference/peripherals/usb_host/usb_host_notes_enum.rst
|
||||
api-reference/peripherals/usb_host/usb_host_notes_ext_hub.rst
|
||||
api-reference/peripherals/usb_device.rst
|
||||
api-reference/peripherals/touch_element.rst
|
||||
api-reference/peripherals/spi_flash/xip_from_psram.inc
|
||||
|
@ -0,0 +1,65 @@
|
||||
USB Host External Hub Driver (Ext Hub)
|
||||
======================================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
The External Hub Driver (henceforth referred to as Ext Hub Driver)
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
USB Specification Requirements
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Chapter 11 of the USB 2.0 specification outlines some aspects, when a USB Hub device is attached to a powered port.
|
||||
|
||||
The design of the Ext Driver takes into consideration the following:
|
||||
|
||||
- **Connectivity behavior**
|
||||
- **Power management**
|
||||
- **Device connect/disconnect detection**
|
||||
- **Bus fault detection and recovery**
|
||||
- **High-, full-, and low-speed device support**
|
||||
|
||||
.. note::
|
||||
|
||||
For more detailed information, please refer to `USB 2.0 Specification <https://www.usb.org/document-library/usb-20-specification>`_ > Chapter 11.1 **Overview**.
|
||||
|
||||
Host Stack Requirements
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
In addition to the USB 2.0 specification requirements, the Ext Hub Driver also takes into consideration the requirements set for the overall Host Stack (see :doc:`./usb_host_notes_design`):
|
||||
|
||||
- Ext Hub Driver must not instantiate any tasks/threads
|
||||
- Ext Hub Driver must be event driven, providing event callbacks and an event processing function
|
||||
- Ext Hub Driver must use only API from underlying layer (USBH)
|
||||
|
||||
Implementation & Usage
|
||||
----------------------
|
||||
|
||||
Host Stack Interaction
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The Ext Hub Driver takes place between USB Host layer and USBH layer, next to the Hub Driver. The Hub Driver and the Ext Hub Driver were split into two Drivers to achieve the goal of logic distinguishing between root Hub and external Hub.
|
||||
|
||||
Device handling
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
The Ext Hub Driver can be installed via ``ext_hub_install()`` call and uninstalled via ``ext_hub_uninstall()`` call. After installation the Ext Hub provides the following APIs for external Hub addition and removal:
|
||||
|
||||
- ``ext_hub_new_dev()`` which will verify the device class (`HUB_CLASSCODE (09H)`) and, if the device has the Hub class, the Ext Hub Driver:
|
||||
|
||||
- allocates a new device object
|
||||
- adds it to the external device pool
|
||||
- starts the process of Hub configuration (retrieving Hub Descriptor, Device status and Hub status)
|
||||
|
||||
- ``ext_hub_dev_gone()`` which will verify the device in the Ext Hub Driver list and start the process of external Hub device removing.
|
||||
|
||||
Events & Processing
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The Ext Hub Driver is completely event driven and all event handling is done via the ``ext_hub_process()`` function. The ``ext_hub_config_t.proc_req_cb`` callback provided on the Ext Hub Driver installation will be called when processing is required. Typically, ``ext_hub_process()`` will be called from the Hub Driver ``hub_process()`` processing function.
|
||||
|
||||
The Ext Hub Driver does not expose any event callback.
|
||||
|
@ -23,6 +23,7 @@ This document is split into the following sections:
|
||||
usb_host_notes_dwc_otg
|
||||
usb_host_notes_usbh
|
||||
usb_host_notes_enum
|
||||
usb_host_notes_ext_hub
|
||||
|
||||
Todo:
|
||||
|
||||
@ -45,6 +46,10 @@ Features & Limitations
|
||||
|
||||
**The Host Stack currently supports the following notable features:**
|
||||
|
||||
.. only:: esp32p4
|
||||
|
||||
- Supports HS (High Speed)
|
||||
|
||||
- Supports FS (Full Speed) and LS (Low Speed) devices
|
||||
- Supports all transfer types (Control, Bulk, Isochronous, and Interrupt)
|
||||
- Automatically enumerates connected devices
|
||||
@ -52,5 +57,4 @@ Features & Limitations
|
||||
|
||||
**The Host Stack currently has the following notable limitations:**
|
||||
|
||||
- No HS (High Speed) support
|
||||
- No Hub support (currently only supports a single device)
|
||||
|
@ -0,0 +1 @@
|
||||
.. include:: ../../../../en/api-reference/peripherals/usb_host/usb_host_notes_ext_hub.rst
|
@ -1,56 +1 @@
|
||||
USB 主机维护者注意事项(简介)
|
||||
==============================
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
本文档包含有关 USB 主机协议栈实现细节的信息,面向 USB 主机协议栈的维护者和第三方贡献者。USB 主机协议栈的用户请参考 :doc:`../usb_host`。
|
||||
|
||||
.. warning::
|
||||
|
||||
USB 主机协议栈的实现细节属于私有 API,因此,除 USB 主机库外的所有层均不遵循 :ref:`ESP-IDF 版本简介 <versioning-scheme>`,即允许进行重大更改。
|
||||
|
||||
.. figure:: ../../../../_static/usb_host/stack-overview.png
|
||||
:align: center
|
||||
:alt: 主机协议栈层次结构图
|
||||
|
||||
本文档分为以下几个部分:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
usb_host_notes_design
|
||||
usb_host_notes_arch
|
||||
usb_host_notes_dwc_otg
|
||||
usb_host_notes_usbh
|
||||
usb_host_notes_enum
|
||||
|
||||
待写章节:
|
||||
|
||||
- USB 主机维护者注意事项(HAL 和 LL)
|
||||
- USB 主机维护者注意事项(HCD)
|
||||
- USB 主机维护者注意事项(Hub)
|
||||
- USB 主机维护者注意事项(USB Host Library)
|
||||
|
||||
.. -------------------------------------------------- Introduction -----------------------------------------------------
|
||||
|
||||
简介
|
||||
----
|
||||
|
||||
ESP-IDF USB 主机协议栈允许 {IDF_TARGET_NAME} 作为 USB 主机运行,此时,{IDF_TARGET_NAME} 能够与各种 USB 设备通信。然而,大多数 USB 主机协议栈实现都不运行在嵌入式硬件上(即在电脑和手机端运行),因此,相对来说具有更多的资源(即,具有更高内存和 CPU 速度)。
|
||||
|
||||
ESP-IDF USB 主机协议栈(以下简称为主机协议栈)的实现考虑到了 {IDF_TARGET_NAME} 的嵌入式特性,这体现在主机协议栈设计的各个方面。
|
||||
|
||||
特性和局限性
|
||||
^^^^^^^^^^^^
|
||||
|
||||
**主机协议栈目前支持以下显著特性:**
|
||||
|
||||
- 支持 FS(全速)和 LS(低速)设备
|
||||
- 支持所有传输类型(控制传输、批量传输、同步传输和中断传输)
|
||||
- 自动枚举已连接设备
|
||||
- 允许多个类驱动程序(即 USB 主机库的客户端)同时运行并共享同一设备(即组合设备)
|
||||
|
||||
**主机协议栈目前存在以下显著局限:**
|
||||
|
||||
- 不支持 HS(高速)设备
|
||||
- 不支持集线器(当前仅支持单个设备)
|
||||
.. include:: ../../../../en/api-reference/peripherals/usb_host/usb_host_notes_index.rst
|
||||
|
Loading…
x
Reference in New Issue
Block a user