From 8fb0366f70e87f93a73e8f74abc04b9ac0df8a76 Mon Sep 17 00:00:00 2001 From: Tomas Rezucha Date: Tue, 3 Dec 2024 08:52:48 +0100 Subject: [PATCH 1/2] feat(usb/host): Add option to choose peripheral for USB host library Starting with ESP32-P4 we can have targets that have more than 1 USB-OTG peripheral. This commit adds an option to choose which peripherals will be used by USB Host lib. Internally, we will still have only 1 Root HUB but with multiple Root ports. --- components/soc/include/soc/usb_dwc_periph.h | 2 +- components/usb/hcd_dwc.c | 125 +++++++++++------- components/usb/hub.c | 13 +- components/usb/include/usb/usb_host.h | 7 + components/usb/private_include/hcd.h | 10 +- components/usb/private_include/hub.h | 1 + components/usb/usb_host.c | 24 +++- .../en/api-reference/peripherals/usb_host.rst | 2 +- .../usb_host_lib/main/usb_host_lib_main.c | 2 + 9 files changed, 122 insertions(+), 64 deletions(-) diff --git a/components/soc/include/soc/usb_dwc_periph.h b/components/soc/include/soc/usb_dwc_periph.h index 185a6bdb37..f35664d0c9 100644 --- a/components/soc/include/soc/usb_dwc_periph.h +++ b/components/soc/include/soc/usb_dwc_periph.h @@ -106,9 +106,9 @@ extern const usb_dwc_info_t usb_dwc_info; /* ------------------------------- Deprecated ------------------------------- */ /* Todo: Remove in ESP-IDF v6.0 (IDF-9052) */ #include -#include "soc/periph_defs.h" #if SOC_USB_OTG_SUPPORTED +#include "soc/periph_defs.h" /* Stores a bunch of USB-peripheral data. diff --git a/components/usb/hcd_dwc.c b/components/usb/hcd_dwc.c index 94c63a20be..e051e282df 100644 --- a/components/usb/hcd_dwc.c +++ b/components/usb/hcd_dwc.c @@ -43,7 +43,7 @@ #define CTRL_EP_MAX_MPS_LS 8 // Largest Maximum Packet Size for Low Speed control endpoints #define CTRL_EP_MAX_MPS_HSFS 64 // Largest Maximum Packet Size for High & Full Speed control endpoints -#define NUM_PORTS 1 // The controller only has one port. +#define NUM_PORTS SOC_USB_OTG_PERIPH_NUM // Each peripheral is a root port // ----------------------- Configs ------------------------- @@ -108,7 +108,6 @@ DEFINE_CRIT_SECTION_LOCK_STATIC(hcd_lock); * For other SOCs this is no-operation */ #if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE -#define ALIGN_UP_BY(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) #define CACHE_SYNC_FRAME_LIST(frame_list) cache_sync_frame_list(frame_list) #define CACHE_SYNC_XFER_DESCRIPTOR_LIST_M2C(buffer) cache_sync_xfer_descriptor_list(buffer, true) #define CACHE_SYNC_XFER_DESCRIPTOR_LIST_C2M(buffer) cache_sync_xfer_descriptor_list(buffer, false) @@ -257,15 +256,15 @@ struct port_obj { void *callback_arg; SemaphoreHandle_t port_mux; void *context; + intr_handle_t isr_hdl; // Interrupt handle for this root port (USB-OTG peripheral) }; /** * @brief Object representing the HCD */ typedef struct { - // Ports (Hardware only has one) - port_t *port_obj; - intr_handle_t isr_hdl; + // Ports: Each peripheral is a root port + port_t *port_obj[NUM_PORTS]; } hcd_obj_t; static hcd_obj_t *s_hcd_obj = NULL; // Note: "s_" is for the static pointer @@ -1041,52 +1040,66 @@ esp_err_t hcd_install(const hcd_config_t *config) HCD_CHECK_FROM_CRIT(s_hcd_obj == NULL, ESP_ERR_INVALID_STATE); HCD_EXIT_CRITICAL(); + // Check if peripheral_map does not have bits set outside of valid range. Valid bits are BIT0 - BIT(NUM_PORTS - 1) + HCD_CHECK((config->peripheral_map != 0) && (config->peripheral_map < BIT(NUM_PORTS)), ESP_ERR_INVALID_ARG); + esp_err_t err_ret; + // Allocate memory for the driver object hcd_obj_t *p_hcd_obj_dmy = calloc(1, sizeof(hcd_obj_t)); if (p_hcd_obj_dmy == NULL) { return ESP_ERR_NO_MEM; } - // Allocate each port object (the hardware currently only has one port) - p_hcd_obj_dmy->port_obj = port_obj_alloc(); - if (p_hcd_obj_dmy->port_obj == NULL) { - err_ret = ESP_ERR_NO_MEM; - goto port_alloc_err; - } - // Allocate interrupt - err_ret = esp_intr_alloc(usb_dwc_info.controllers[0].irq, - config->intr_flags | ESP_INTR_FLAG_INTRDISABLED, // The interrupt must be disabled until the port is initialized - intr_hdlr_main, - (void *)p_hcd_obj_dmy->port_obj, - &p_hcd_obj_dmy->isr_hdl); - if (err_ret != ESP_OK) { - ESP_LOGE(HCD_DWC_TAG, "Interrupt alloc error: %s", esp_err_to_name(err_ret)); - goto intr_alloc_err; - } - // Apply custom FIFO config if provided, otherwise mark as default (all zeros) - memset(&p_hcd_obj_dmy->port_obj->fifo_config, 0, sizeof(p_hcd_obj_dmy->port_obj->fifo_config)); - if (config->fifo_config != NULL) { - // Convert and validate user-provided config - err_ret = convert_fifo_config_to_hal_config(config->fifo_config, &p_hcd_obj_dmy->port_obj->fifo_config); - if (err_ret != ESP_OK) { - goto assign_err; + + // Allocate each port object + for (int i = 0; i < NUM_PORTS; i++) { + if (BIT(i) & config->peripheral_map) { + p_hcd_obj_dmy->port_obj[i] = port_obj_alloc(); + if (p_hcd_obj_dmy->port_obj[i] == NULL) { + err_ret = ESP_ERR_NO_MEM; + goto clean_up; + } + // Allocate interrupt + const int irq_index = usb_dwc_info.controllers[i].irq; + err_ret = esp_intr_alloc(irq_index, + config->intr_flags | ESP_INTR_FLAG_INTRDISABLED, // The interrupt must be disabled until the port is initialized + intr_hdlr_main, + (void *)p_hcd_obj_dmy->port_obj[i], + &p_hcd_obj_dmy->port_obj[i]->isr_hdl); + if (err_ret != ESP_OK) { + ESP_LOGE(HCD_DWC_TAG, "Interrupt alloc error: %s", esp_err_to_name(err_ret)); + goto clean_up; + } + + // Apply custom FIFO config if provided + if (config->fifo_config != NULL) { + // Convert and validate user-provided config + err_ret = convert_fifo_config_to_hal_config(config->fifo_config, &p_hcd_obj_dmy->port_obj[i]->fifo_config); + if (err_ret != ESP_OK) { + goto clean_up; + } + } } } + HCD_ENTER_CRITICAL(); if (s_hcd_obj != NULL) { HCD_EXIT_CRITICAL(); err_ret = ESP_ERR_INVALID_STATE; - goto assign_err; + goto clean_up; } s_hcd_obj = p_hcd_obj_dmy; HCD_EXIT_CRITICAL(); return ESP_OK; -assign_err: - esp_intr_free(p_hcd_obj_dmy->isr_hdl); -intr_alloc_err: - port_obj_free(p_hcd_obj_dmy->port_obj); -port_alloc_err: +clean_up: + // Free resources + for (int i = 0; i < NUM_PORTS; i++) { + if (p_hcd_obj_dmy->port_obj[i]) { + esp_intr_free(p_hcd_obj_dmy->port_obj[i]->isr_hdl); + port_obj_free(p_hcd_obj_dmy->port_obj[i]); + } + } free(p_hcd_obj_dmy); return err_ret; } @@ -1094,8 +1107,14 @@ port_alloc_err: esp_err_t hcd_uninstall(void) { HCD_ENTER_CRITICAL(); - // Check that all ports have been disabled (there's only one port) - if (s_hcd_obj == NULL || s_hcd_obj->port_obj->initialized) { + // Check that all ports have been disabled + bool all_ports_disabled = true; + for (int i = 0; i < NUM_PORTS; i++) { + if (s_hcd_obj->port_obj[i]) { + all_ports_disabled = all_ports_disabled && !(s_hcd_obj->port_obj[i]->initialized); + } + } + if (s_hcd_obj == NULL || !all_ports_disabled) { HCD_EXIT_CRITICAL(); return ESP_ERR_INVALID_STATE; } @@ -1104,8 +1123,12 @@ esp_err_t hcd_uninstall(void) HCD_EXIT_CRITICAL(); // Free resources - port_obj_free(p_hcd_obj_dmy->port_obj); - esp_intr_free(p_hcd_obj_dmy->isr_hdl); + for (int i = 0; i < NUM_PORTS; i++) { + if (p_hcd_obj_dmy->port_obj[i]) { + esp_intr_free(p_hcd_obj_dmy->port_obj[i]->isr_hdl); + port_obj_free(p_hcd_obj_dmy->port_obj[i]); + } + } free(p_hcd_obj_dmy); return ESP_OK; } @@ -1366,13 +1389,13 @@ exit: esp_err_t hcd_port_init(int port_number, const hcd_port_config_t *port_config, hcd_port_handle_t *port_hdl) { - HCD_CHECK(port_number > 0 && port_config != NULL && port_hdl != NULL, ESP_ERR_INVALID_ARG); - HCD_CHECK(port_number <= NUM_PORTS, ESP_ERR_NOT_FOUND); + HCD_CHECK(port_number >= 0 && port_config != NULL && port_hdl != NULL, ESP_ERR_INVALID_ARG); + HCD_CHECK(port_number < NUM_PORTS, ESP_ERR_NOT_FOUND); HCD_ENTER_CRITICAL(); - HCD_CHECK_FROM_CRIT(s_hcd_obj != NULL && !s_hcd_obj->port_obj->initialized, ESP_ERR_INVALID_STATE); + HCD_CHECK_FROM_CRIT(s_hcd_obj != NULL && !s_hcd_obj->port_obj[port_number]->initialized, ESP_ERR_INVALID_STATE); // Port object memory and resources (such as the mutex) already be allocated. Just need to initialize necessary fields only - port_t *port_obj = s_hcd_obj->port_obj; + port_t *port_obj = s_hcd_obj->port_obj[port_number]; TAILQ_INIT(&port_obj->pipes_idle_tailq); TAILQ_INIT(&port_obj->pipes_active_tailq); port_obj->state = HCD_PORT_STATE_NOT_POWERED; @@ -1380,18 +1403,24 @@ esp_err_t hcd_port_init(int port_number, const hcd_port_config_t *port_config, h port_obj->callback = port_config->callback; port_obj->callback_arg = port_config->callback_arg; port_obj->context = port_config->context; - usb_dwc_hal_init(port_obj->hal, 0); + + // USB-HAL's size is dependent on its configuration, namely on number of channels in the configuration + // We must first initialize the HAL, to get the number of channels and then allocate memory for the channels + ESP_COMPILER_DIAGNOSTIC_PUSH_IGNORE("-Wanalyzer-malloc-leak") // False positive + usb_dwc_hal_init(port_obj->hal, port_number); port_obj->hal->channels.hdls = calloc(port_obj->hal->constant_config.chan_num_total, sizeof(usb_dwc_hal_chan_t*)); HCD_CHECK_FROM_CRIT(port_obj->hal->channels.hdls != NULL, ESP_ERR_NO_MEM); + ESP_COMPILER_DIAGNOSTIC_POP("-Wanalyzer-malloc-leak") + port_obj->initialized = true; - // Clear the frame list. We set the frame list register and enable periodic scheduling after a successful reset + // Clear the frame list. We will set the frame list register and enable periodic scheduling after a successful reset memset(port_obj->frame_list, 0, FRAME_LIST_LEN * sizeof(uint32_t)); // If FIFO config is zeroed -> calculate from bias if (_is_fifo_config_by_bias(&port_obj->fifo_config)) { // Calculate default FIFO sizes based on Kconfig bias settings _calculate_fifo_from_bias(port_obj, port_obj->hal); } - esp_intr_enable(s_hcd_obj->isr_hdl); + esp_intr_enable(port_obj->isr_hdl); *port_hdl = (hcd_port_handle_t)port_obj; HCD_EXIT_CRITICAL(); ESP_LOGD(HCD_DWC_TAG, "FIFO config lines: RX=%" PRIu32 ", PTX=%" PRIu32 ", NPTX=%" PRIu32, @@ -1413,7 +1442,7 @@ esp_err_t hcd_port_deinit(hcd_port_handle_t port_hdl) && port->task_waiting_port_notif == NULL, ESP_ERR_INVALID_STATE); port->initialized = false; - esp_intr_disable(s_hcd_obj->isr_hdl); + esp_intr_disable(port->isr_hdl); free(port->hal->channels.hdls); usb_dwc_hal_deinit(port->hal); HCD_EXIT_CRITICAL(); @@ -1529,7 +1558,7 @@ esp_err_t hcd_port_recover(hcd_port_handle_t port_hdl) ESP_ERR_INVALID_STATE); // We are about to do a soft reset on the peripheral. Disable the peripheral throughout - esp_intr_disable(s_hcd_obj->isr_hdl); + esp_intr_disable(port->isr_hdl); usb_dwc_hal_core_soft_reset(port->hal); port->state = HCD_PORT_STATE_NOT_POWERED; port->last_event = HCD_PORT_EVENT_NONE; @@ -1537,7 +1566,7 @@ esp_err_t hcd_port_recover(hcd_port_handle_t port_hdl) // Clear the frame list. We set the frame list register and enable periodic scheduling after a successful reset memset(port->frame_list, 0, FRAME_LIST_LEN * sizeof(uint32_t)); - esp_intr_enable(s_hcd_obj->isr_hdl); + esp_intr_enable(port->isr_hdl); HCD_EXIT_CRITICAL(); return ESP_OK; } diff --git a/components/usb/hub.c b/components/usb/hub.c index d9a2c2b038..dccd92ba44 100644 --- a/components/usb/hub.c +++ b/components/usb/hub.c @@ -11,6 +11,7 @@ #include #include "esp_err.h" #include "esp_heap_caps.h" +#include "esp_bit_defs.h" #include "esp_private/critical_section.h" #include "esp_log.h" #include "usb_private.h" @@ -27,8 +28,6 @@ Implementation of the HUB driver that only supports the Root Hub with a single p implement the bare minimum to control the root HCD port. */ -#define HUB_ROOT_PORT_NUM 1 // HCD only supports one port - #ifdef CONFIG_USB_HOST_HW_BUFFER_BIAS_IN #define HUB_ROOT_HCD_PORT_FIFO_BIAS HCD_PORT_FIFO_BIAS_RX #elif CONFIG_USB_HOST_HW_BUFFER_BIAS_PERIODIC_OUT @@ -60,7 +59,6 @@ typedef enum { ROOT_PORT_STATE_POWERED, /**< Root port is powered, device is not connected */ ROOT_PORT_STATE_DISABLED, /**< A device is connected but is disabled (i.e., not reset, no SOFs are sent) */ ROOT_PORT_STATE_ENABLED, /**< A device is connected, port has been reset, SOFs are sent */ - ROOT_PORT_STATE_RECOVERY, /**< Root port encountered an error and needs to be recovered */ } root_port_state_t; /** @@ -566,7 +564,14 @@ esp_err_t hub_install(hub_config_t *hub_config, void **client_ret) .context = NULL, }; hcd_port_handle_t root_port_hdl; - ret = hcd_port_init(HUB_ROOT_PORT_NUM, &port_config, &root_port_hdl); + + // Right now we support only one root port, can be extended in future + int root_port_index = 0; + if (hub_config->port_map & BIT1) { + root_port_index = 1; + } + + ret = hcd_port_init(root_port_index, &port_config, &root_port_hdl); if (ret != ESP_OK) { ESP_LOGE(HUB_DRIVER_TAG, "HCD Port init error: %s", esp_err_to_name(ret)); goto err; diff --git a/components/usb/include/usb/usb_host.h b/components/usb/include/usb/usb_host.h index 001327d809..992d783dea 100644 --- a/components/usb/include/usb/usb_host.h +++ b/components/usb/include/usb/usb_host.h @@ -121,6 +121,13 @@ typedef struct { } fifo_settings_custom; /**< Optional custom FIFO configuration (advanced use). RX and NPTX must be > 0. If all fields are zero, a default configuration will be selected based on Kconfig bias. */ + unsigned peripheral_map; /**< Selects the USB peripheral(s) to use. + - On targets with multiple USB peripherals, this field can be used to specify which ones to enable. + - Set to 0 to use the default peripheral. + - On High-Speed capable targets, the default is the High-Speed peripheral. + - On Full-Speed only targets, the default is the Full-Speed peripheral. + - Example: peripheral_map = BIT1; installs USB host on peripheral 1. + - The mapping of bits to specific peripherals is defined in the USB_DWC_LL_GET_HW() macro. */ } usb_host_config_t; /** diff --git a/components/usb/private_include/hcd.h b/components/usb/private_include/hcd.h index 2920a11b99..eeb1f22709 100644 --- a/components/usb/private_include/hcd.h +++ b/components/usb/private_include/hcd.h @@ -154,9 +154,10 @@ typedef struct { * @brief HCD configuration structure */ typedef struct { - int intr_flags; /**< Interrupt flags for HCD interrupt */ - const hcd_fifo_settings_t *fifo_config;/**< Optional pointer to custom FIFO config. - If NULL, default configuration is used. */ + int intr_flags; /**< Interrupt flags for HCD interrupt */ + const hcd_fifo_settings_t *fifo_config; /**< Optional pointer to custom FIFO config. + If NULL, default configuration is used. */ + unsigned peripheral_map; /**< Bit map of USB-OTG peripherals that belong to HCD. Set to zero to use default */ } hcd_config_t; /** @@ -166,6 +167,7 @@ typedef struct { hcd_port_callback_t callback; /**< HCD port event callback */ void *callback_arg; /**< User argument for HCD port callback */ void *context; /**< Context variable used to associate the port with upper layer object */ + unsigned peripheral_idx; /**< Index of USB peripheral this port belongs to. Index numbers are defined in USB_DWC_LL_GET_HW */ } hcd_port_config_t; /** @@ -225,8 +227,6 @@ esp_err_t hcd_uninstall(void); * * After a port is initialized, it will be put into the HCD_PORT_STATE_NOT_POWERED state. * - * @note The host controller only has one port, thus the only valid port_number is 1 - * * @param[in] port_number Port number * @param[in] port_config Port configuration * @param[out] port_hdl Port handle diff --git a/components/usb/private_include/hub.h b/components/usb/private_include/hub.h index c5ca0aec88..e47e11c189 100644 --- a/components/usb/private_include/hub.h +++ b/components/usb/private_include/hub.h @@ -60,6 +60,7 @@ typedef void (*hub_event_cb_t)(hub_event_data_t *event_data, void *arg); * @brief Hub driver configuration */ typedef struct { + unsigned port_map; /**< Bitmap of root ports to enable */ usb_proc_req_cb_t proc_req_cb; /**< Processing request callback */ void *proc_req_cb_arg; /**< Processing request callback argument */ hub_event_cb_t event_cb; /**< Hub event callback */ diff --git a/components/usb/usb_host.c b/components/usb/usb_host.c index f75459d64e..98c04c4433 100644 --- a/components/usb/usb_host.c +++ b/components/usb/usb_host.c @@ -17,9 +17,11 @@ Warning: The USB Host Library API is still a beta version and may be subject to #include "freertos/queue.h" #include "freertos/semphr.h" #include "esp_private/critical_section.h" +#include "soc/usb_dwc_periph.h" #include "esp_err.h" #include "esp_log.h" #include "esp_heap_caps.h" +#include "esp_bit_defs.h" #include "hub.h" #include "enum.h" #include "usbh.h" @@ -466,16 +468,26 @@ esp_err_t usb_host_install(const usb_host_config_t *config) - Hub */ + // For backward compatibility accept 0 too + const unsigned peripheral_map = config->peripheral_map == 0 ? BIT0 : config->peripheral_map; + // Install USB PHY (if necessary). USB PHY driver will also enable the underlying Host Controller if (!config->skip_phy_setup) { + bool init_utmi_phy = false; // Default value for Linux simulation + +#if SOC_USB_OTG_SUPPORTED // In case we run on a real target, select the PHY from usb_dwc_info description structure + // Right now we support only one peripheral, can be extended in future + int peripheral_index = 0; + if (peripheral_map & BIT1) { + peripheral_index = 1; + } + init_utmi_phy = (usb_dwc_info.controllers[peripheral_index].supported_phys == USB_PHY_INST_UTMI_0); +#endif // SOC_USB_OTG_SUPPORTED + // Host Library defaults to internal PHY usb_phy_config_t phy_config = { .controller = USB_PHY_CTRL_OTG, -#if CONFIG_IDF_TARGET_ESP32P4 // ESP32-P4 has 2 USB-DWC peripherals, each with its dedicated PHY. We support HS+UTMI only ATM. - .target = USB_PHY_TARGET_UTMI, -#else - .target = USB_PHY_TARGET_INT, -#endif + .target = init_utmi_phy ? USB_PHY_TARGET_UTMI : 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, @@ -493,6 +505,7 @@ esp_err_t usb_host_install(const usb_host_config_t *config) hcd_fifo_settings_t user_fifo_config; hcd_config_t hcd_config = { .intr_flags = config->intr_flags, + .peripheral_map = peripheral_map, .fifo_config = NULL, // Default: use bias strategy from Kconfig }; @@ -547,6 +560,7 @@ esp_err_t usb_host_install(const usb_host_config_t *config) // Install Hub hub_config_t hub_config = { + .port_map = peripheral_map, // Each USB-OTG peripheral maps to a root port .proc_req_cb = proc_req_callback, .proc_req_cb_arg = NULL, .event_cb = hub_event_callback, diff --git a/docs/en/api-reference/peripherals/usb_host.rst b/docs/en/api-reference/peripherals/usb_host.rst index d90b6dc819..9446d3a306 100644 --- a/docs/en/api-reference/peripherals/usb_host.rst +++ b/docs/en/api-reference/peripherals/usb_host.rst @@ -33,6 +33,7 @@ The Host Library has the following features: :esp32p4: - Supports High Speed (HS), Full Speed (FS) and Low Speed (LS) Devices. - Supports all four transfer types: Control, Bulk, Interrupt, and Isochronous. :esp32p4: - Supports High-Bandwidth Isochronous endpoints. + :esp32p4: - {IDF_TARGET_NAME} includes two USB 2.0 OTG peripherals: one High-Speed and one Full-Speed. Both support USB Host functionality; however, due to a current software limitation, only one can operate as a USB Host at a time. Support for dual USB Host operation is planned for a future update. - Allows multiple class drivers to run simultaneously, i.e., multiple clients of the Host Library. - A single device can be used by multiple clients simultaneously, e.g., composite devices. - The Host Library itself and the underlying Host Stack does not internally instantiate any OS tasks. The number of tasks is entirely controlled by how the Host Library interface is used. However, a general rule of thumb regarding the number of tasks is ``(the number of host class drivers running + 1)``. @@ -46,7 +47,6 @@ Currently, the Host Library and the underlying Host Stack has the following limi - Only supports Asynchronous transfers. - Only supports using one configuration. Changing to other configurations after enumeration is not supported yet. - Transfer timeouts are not supported yet. - :esp32p4: - {IDF_TARGET_NAME} contains two USB-OTG peripherals USB 2.0 OTG High-Speed and USB 2.0 OTG Full-Speed. Only the High-Speed instance is supported now. - The External Hub Driver: Remote Wakeup feature is not supported (External Hubs are active, even if there are no devices inserted). - The External Hub Driver: Doesn't handle error cases (overcurrent handling, errors during initialization etc. are not implemented yet). - The External Hub Driver: No Interface selection. The Driver uses the first available Interface with Hub Class code (09h). diff --git a/examples/peripherals/usb/host/usb_host_lib/main/usb_host_lib_main.c b/examples/peripherals/usb/host/usb_host_lib/main/usb_host_lib_main.c index f1a2dc348a..a7da50caac 100644 --- a/examples/peripherals/usb/host/usb_host_lib/main/usb_host_lib_main.c +++ b/examples/peripherals/usb/host/usb_host_lib/main/usb_host_lib_main.c @@ -113,8 +113,10 @@ static void usb_host_lib_task(void *arg) # ifdef ENABLE_ENUM_FILTER_CALLBACK .enum_filter_cb = set_config_cb, # endif // ENABLE_ENUM_FILTER_CALLBACK + .peripheral_map = BIT0, }; ESP_ERROR_CHECK(usb_host_install(&host_config)); + ESP_LOGI(TAG, "USB Host installed with peripheral map 0x%x", host_config.peripheral_map); //Signalize the app_main, the USB host library has been installed xTaskNotifyGive(arg); From e48a920176f27cfabe84803302cca2ad5b1edfe6 Mon Sep 17 00:00:00 2001 From: Zhang Shuxian Date: Thu, 8 May 2025 14:21:46 +0800 Subject: [PATCH 2/2] docs: Update CN for usb_host.rst --- docs/en/api-reference/peripherals/usb_host.rst | 2 +- docs/zh_CN/api-reference/peripherals/usb_host.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/en/api-reference/peripherals/usb_host.rst b/docs/en/api-reference/peripherals/usb_host.rst index 9446d3a306..b81613bcc0 100644 --- a/docs/en/api-reference/peripherals/usb_host.rst +++ b/docs/en/api-reference/peripherals/usb_host.rst @@ -33,7 +33,7 @@ The Host Library has the following features: :esp32p4: - Supports High Speed (HS), Full Speed (FS) and Low Speed (LS) Devices. - Supports all four transfer types: Control, Bulk, Interrupt, and Isochronous. :esp32p4: - Supports High-Bandwidth Isochronous endpoints. - :esp32p4: - {IDF_TARGET_NAME} includes two USB 2.0 OTG peripherals: one High-Speed and one Full-Speed. Both support USB Host functionality; however, due to a current software limitation, only one can operate as a USB Host at a time. Support for dual USB Host operation is planned for a future update. + :esp32p4: - {IDF_TARGET_NAME} includes two USB 2.0 OTG peripherals: one High-Speed and one Full-Speed. Both support USB Host functionality. However, due to a current software limitation, only one can operate as a USB Host at a time. Support for dual USB Host operation is planned for a future update. - Allows multiple class drivers to run simultaneously, i.e., multiple clients of the Host Library. - A single device can be used by multiple clients simultaneously, e.g., composite devices. - The Host Library itself and the underlying Host Stack does not internally instantiate any OS tasks. The number of tasks is entirely controlled by how the Host Library interface is used. However, a general rule of thumb regarding the number of tasks is ``(the number of host class drivers running + 1)``. diff --git a/docs/zh_CN/api-reference/peripherals/usb_host.rst b/docs/zh_CN/api-reference/peripherals/usb_host.rst index 61350c9c5d..871203d9fa 100644 --- a/docs/zh_CN/api-reference/peripherals/usb_host.rst +++ b/docs/zh_CN/api-reference/peripherals/usb_host.rst @@ -33,6 +33,7 @@ USB 主机库(以下简称主机库)是 USB 主机栈的最底层,提供 :esp32p4: - 支持高速 (HS)、全速 (FS) 和低速 (LS) 设备。 - 支持四种传输类型,即控制传输、块传输、中断传输和同步传输。 :esp32p4: - 支持高带宽等时性端点。 + :esp32p4: - {IDF_TARGET_NAME} 包含两个 USB 2.0 OTG 外设:USB 2.0 OTG 高速和 USB 2.0 OTG 全速,二者均支持 USB 主机功能。但由于当前软件的限制,同一时间仅能有一个作为 USB 主机工作。未来版本计划支持两个 USB 主机同时运行。 - 支持多个 Class 驱动程序同时运行,即主机的多个客户端同时运行。 - 单个设备可以由多个客户端同时使用,如复合设备。 - 主机库及其底层主机栈不会在内部自动创建操作系统任务,任务数量完全由主机库接口的使用方式决定。一般来说,任务数量为 ``(运行中的主机 Class 驱动程序数量 + 1)``。 @@ -46,7 +47,6 @@ USB 主机库(以下简称主机库)是 USB 主机栈的最底层,提供 - 仅支持异步传输。 - 仅支持使用发现的首个配置,尚不支持变更为其他配置。 - 尚不支持传输超时。 - :esp32p4: - {IDF_TARGET_NAME} 包含两个 USB-OTG 外设:USB 2.0 OTG 高速和 USB 2.0 OTG 全速。目前仅支持高速实例。 - 外部 Hub 驱动:不支持远程唤醒功能(即使没有设备插入,外部 Hub 也处于工作状态)。 - 外部 Hub 驱动:不处理错误用例(尚未实现过流处理、初始化错误等功能)。 - 外部 Hub 驱动:不支持接口选择。驱动程序使用具有 Hub 类代码 (09h) 的第一个可用接口。