11/*
2- * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
2+ * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
33 *
44 * SPDX-License-Identifier: Apache-2.0
55 */
2626#define ENUM_WORST_CASE_MPS_FS_HS 64 // The worst case MPS of EP0 for a FS/HS device
2727#define ENUM_LANGID 0x409 // Current enumeration only supports English (United States) string descriptors
2828#define ENUM_MAX_ADDRESS (127) // Maximal device address value
29+ #define ENUM_PENDING_QUEUE_LEN (5)
2930
3031/**
3132 * @brief Stages of device enumeration listed in their order of execution
@@ -139,6 +140,11 @@ typedef struct {
139140 enum_device_params_t dev_params ; /**< Parameters of device under enumeration */
140141 int expect_num_bytes ; /**< Expected number of bytes for IN transfers stages. Set to 0 for OUT transfer */
141142 uint8_t next_dev_addr ; /**< Device address for device under enumeration */
143+ // Pending enumeration queue
144+ unsigned int pending_uids [ENUM_PENDING_QUEUE_LEN ];
145+ uint16_t pending_head ;
146+ uint16_t pending_tail ;
147+ uint16_t pending_count ;
142148 } single_thread ; /**< Single thread members don't require a critical section so long as they are never accessed from multiple threads */
143149
144150 struct {
@@ -203,6 +209,30 @@ static uint8_t get_next_free_dev_addr(void)
203209 return new_dev_addr ;
204210}
205211
212+ static bool pending_uid_enqueue (unsigned int uid )
213+ {
214+ if (p_enum_driver -> single_thread .pending_count >= ENUM_PENDING_QUEUE_LEN ) {
215+ return false;
216+ }
217+ p_enum_driver -> single_thread .pending_uids [p_enum_driver -> single_thread .pending_tail ] = uid ;
218+ p_enum_driver -> single_thread .pending_tail =
219+ (p_enum_driver -> single_thread .pending_tail + 1 ) % ENUM_PENDING_QUEUE_LEN ;
220+ p_enum_driver -> single_thread .pending_count ++ ;
221+ return true;
222+ }
223+
224+ static bool pending_uid_dequeue (unsigned int * uid )
225+ {
226+ if (p_enum_driver -> single_thread .pending_count == 0 ) {
227+ return false;
228+ }
229+ * uid = p_enum_driver -> single_thread .pending_uids [p_enum_driver -> single_thread .pending_head ];
230+ p_enum_driver -> single_thread .pending_head =
231+ (p_enum_driver -> single_thread .pending_head + 1 ) % ENUM_PENDING_QUEUE_LEN ;
232+ p_enum_driver -> single_thread .pending_count -- ;
233+ return true;
234+ }
235+
206236/**
207237 * @brief Get Configuration descriptor index
208238 *
@@ -1161,11 +1191,19 @@ esp_err_t enum_start(unsigned int uid)
11611191{
11621192 ENUM_CHECK (p_enum_driver != NULL , ESP_ERR_INVALID_STATE );
11631193
1194+ if (p_enum_driver -> single_thread .stage != ENUM_STAGE_IDLE ) {
1195+
1196+ // We are already enumerating a device, add the new device to the pending queue
1197+ if (!pending_uid_enqueue (uid )) {
1198+ return ESP_ERR_NO_MEM ;
1199+ }
1200+ return ESP_OK ;
1201+ }
11641202 esp_err_t ret = ESP_FAIL ;
11651203
11661204 // Open device and lock it for enumeration process
11671205 usb_device_handle_t dev_hdl ;
1168- ret = usbh_devs_open ( 0 , & dev_hdl );
1206+ ret = usbh_devs_open_uid ( uid , & dev_hdl );
11691207 if (ret != ESP_OK ) {
11701208 return ret ;
11711209 }
@@ -1176,7 +1214,7 @@ esp_err_t enum_start(unsigned int uid)
11761214 ESP_ERROR_CHECK (usbh_dev_get_info (dev_hdl , & dev_info ));
11771215
11781216 // Stage ENUM_STAGE_GET_SHORT_DEV_DESC
1179- ESP_LOGD (ENUM_TAG , "Start processing device with address %d" , 0 );
1217+ ESP_LOGD (ENUM_TAG , "Start processing device with uid %d" , uid );
11801218
11811219 p_enum_driver -> single_thread .stage = ENUM_STAGE_GET_SHORT_DEV_DESC ;
11821220 p_enum_driver -> single_thread .node_uid = uid ;
@@ -1322,5 +1360,17 @@ esp_err_t enum_process(void)
13221360 p_enum_driver -> constant .proc_req_cb (USB_PROC_REQ_SOURCE_ENUM , false, p_enum_driver -> constant .proc_req_cb_arg );
13231361 }
13241362
1363+ // If we are idle and there are pending devices, start the next one
1364+ while (p_enum_driver -> single_thread .pending_count > 0 &&
1365+ p_enum_driver -> single_thread .stage == ENUM_STAGE_IDLE ) {
1366+ unsigned int next_uid = 0 ;
1367+ if (!pending_uid_dequeue (& next_uid )) {
1368+ break ;
1369+ }
1370+ if (enum_start (next_uid ) == ESP_OK ) {
1371+ break ;
1372+ }
1373+ }
1374+
13251375 return ESP_OK ;
13261376}
0 commit comments