|
1 | 1 | /* |
2 | | - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD |
| 2 | + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD |
3 | 3 | * |
4 | 4 | * SPDX-License-Identifier: Apache-2.0 |
5 | 5 | */ |
@@ -28,7 +28,6 @@ implement the bare minimum to control the root HCD port. |
28 | 28 | */ |
29 | 29 |
|
30 | 30 | #define HUB_ROOT_PORT_NUM 1 // HCD only supports one port |
31 | | -#define HUB_ROOT_DEV_UID 1 // Unique device ID |
32 | 31 |
|
33 | 32 | #ifdef CONFIG_USB_HOST_HW_BUFFER_BIAS_IN |
34 | 33 | #define HUB_ROOT_HCD_PORT_FIFO_BIAS HCD_PORT_FIFO_BIAS_RX |
@@ -93,7 +92,6 @@ typedef struct { |
93 | 92 |
|
94 | 93 | struct { |
95 | 94 | TAILQ_HEAD(tailhead_devs, dev_tree_node_s) dev_nodes_tailq; /**< Tailq of attached devices */ |
96 | | - unsigned int next_uid; /**< Unique ID for next upcoming device */ |
97 | 95 | } single_thread; /**< Single thread members don't require a critical section so long as they are never accessed from multiple threads */ |
98 | 96 |
|
99 | 97 | struct { |
@@ -153,53 +151,52 @@ static bool root_port_callback(hcd_port_handle_t port_hdl, hcd_port_event_t port |
153 | 151 | * |
154 | 152 | * @return esp_err_t |
155 | 153 | */ |
156 | | -static esp_err_t new_dev_tree_node(usb_device_handle_t parent_dev_hdl, uint8_t parent_port_num, usb_speed_t speed) |
| 154 | +static esp_err_t dev_tree_node_new(usb_device_handle_t parent_dev_hdl, uint8_t parent_port_num, usb_speed_t speed) |
157 | 155 | { |
158 | 156 | esp_err_t ret; |
159 | | - unsigned int node_uid = p_hub_driver_obj->single_thread.next_uid; |
160 | | - |
| 157 | + // Allocate memory for a new device tree node |
161 | 158 | dev_tree_node_t *dev_tree_node = heap_caps_calloc(1, sizeof(dev_tree_node_t), MALLOC_CAP_DEFAULT); |
162 | 159 | if (dev_tree_node == NULL) { |
163 | 160 | return ESP_ERR_NO_MEM; |
164 | 161 | } |
| 162 | + // Assign initial UID based on the current number of registered devices |
| 163 | + int device_num = 0; |
| 164 | + ESP_ERROR_CHECK(usbh_devs_num(&device_num)); |
| 165 | + dev_tree_node->uid = device_num + 1; |
| 166 | + // Ensure the UID is unique |
| 167 | + while (usbh_devs_is_uid_in_use(dev_tree_node->uid)) { |
| 168 | + dev_tree_node->uid++; |
| 169 | + assert(dev_tree_node->uid != 0); // No overflow possible |
| 170 | + } |
| 171 | + |
| 172 | + dev_tree_node->parent_dev_hdl = parent_dev_hdl; |
| 173 | + dev_tree_node->parent_port_num = parent_port_num; |
165 | 174 |
|
166 | | - // Allocate a new USBH device |
| 175 | + // Initialize and register a new USBH Device with the assigned UID |
167 | 176 | usbh_dev_params_t params = { |
168 | | - .uid = node_uid, |
| 177 | + .uid = dev_tree_node->uid, |
169 | 178 | .speed = speed, |
170 | 179 | .root_port_hdl = p_hub_driver_obj->constant.root_port_hdl, // Always the same for all devices |
171 | | - // TODO: IDF-10023 Move responsibility of parent-child tree building to Hub Driver instead of USBH |
| 180 | + // TODO: IDF-10023 Move parent-child tree management responsibility to Hub Driver |
172 | 181 | .parent_dev_hdl = parent_dev_hdl, |
173 | 182 | .parent_port_num = parent_port_num, |
174 | 183 | }; |
175 | 184 |
|
176 | 185 | ret = usbh_devs_add(¶ms); |
177 | 186 | if (ret != ESP_OK) { |
178 | | - // USBH devs add could failed due to lack of free hcd channels |
179 | | - // TODO: IDF-10044 Hub should recover after running out of hcd channels |
| 187 | + // Device registration may fail if there are no available HCD channels. |
| 188 | + // TODO: IDF-10044 Implement hub recovery mechanism for running out of HCD channels. |
180 | 189 | goto fail; |
181 | 190 | } |
182 | 191 |
|
183 | | - dev_tree_node->uid = node_uid; |
184 | | - dev_tree_node->parent_dev_hdl = parent_dev_hdl; |
185 | | - dev_tree_node->parent_port_num = parent_port_num; |
186 | 192 | TAILQ_INSERT_TAIL(&p_hub_driver_obj->single_thread.dev_nodes_tailq, dev_tree_node, tailq_entry); |
187 | 193 |
|
188 | | - p_hub_driver_obj->single_thread.next_uid++; |
189 | | - if (p_hub_driver_obj->single_thread.next_uid == 0) { |
190 | | - ESP_LOGW(HUB_DRIVER_TAG, "Counter overflowed, possibility of uid collisions"); |
191 | | - p_hub_driver_obj->single_thread.next_uid = HUB_ROOT_DEV_UID; |
192 | | - } |
193 | | - // Verify presence of a device with newly prepared uid in USBH |
194 | | - // TODO: IDF-10022 Provide a mechanism to request presence status of a device with uid in USBH device object list |
195 | | - // Return if device uid is not in USBH device object list, repeat until uid will be founded |
196 | | - |
197 | | - ESP_LOGD(HUB_DRIVER_TAG, "Device tree node (uid=%d): new", node_uid); |
| 194 | + ESP_LOGD(HUB_DRIVER_TAG, "Device tree node (uid=%d): new", dev_tree_node->uid); |
198 | 195 |
|
199 | 196 | hub_event_data_t event_data = { |
200 | 197 | .event = HUB_EVENT_CONNECTED, |
201 | 198 | .connected = { |
202 | | - .uid = node_uid, |
| 199 | + .uid = dev_tree_node->uid, |
203 | 200 | }, |
204 | 201 | }; |
205 | 202 | p_hub_driver_obj->constant.event_cb(&event_data, p_hub_driver_obj->constant.event_cb_arg); |
@@ -364,7 +361,7 @@ static void ext_port_event_callback(ext_port_event_data_t *event_data, void *arg |
364 | 361 | } |
365 | 362 | #endif // CONFIG_USB_HOST_EXT_PORT_SUPPORT_LS |
366 | 363 |
|
367 | | - if (new_dev_tree_node(event_data->connected.parent_dev_hdl, event_data->connected.parent_port_num, port_speed) != ESP_OK) { |
| 364 | + if (dev_tree_node_new(event_data->connected.parent_dev_hdl, event_data->connected.parent_port_num, port_speed) != ESP_OK) { |
368 | 365 | ESP_LOGE(HUB_DRIVER_TAG, "Failed to add new downstream device"); |
369 | 366 | goto new_ds_dev_err; |
370 | 367 | } |
@@ -406,7 +403,7 @@ static void root_port_handle_events(hcd_port_handle_t root_port_hdl) |
406 | 403 | goto new_dev_err; |
407 | 404 | } |
408 | 405 |
|
409 | | - if (new_dev_tree_node(NULL, 0, speed) != ESP_OK) { |
| 406 | + if (dev_tree_node_new(NULL, 0, speed) != ESP_OK) { |
410 | 407 | ESP_LOGE(HUB_DRIVER_TAG, "Failed to add new device"); |
411 | 408 | goto new_dev_err; |
412 | 409 | } |
@@ -589,7 +586,6 @@ esp_err_t hub_install(hub_config_t *hub_config, void **client_ret) |
589 | 586 | hub_driver_obj->constant.proc_req_cb_arg = hub_config->proc_req_cb_arg; |
590 | 587 | hub_driver_obj->constant.event_cb = hub_config->event_cb; |
591 | 588 | hub_driver_obj->constant.event_cb_arg = hub_config->event_cb_arg; |
592 | | - hub_driver_obj->single_thread.next_uid = HUB_ROOT_DEV_UID; |
593 | 589 | TAILQ_INIT(&hub_driver_obj->single_thread.dev_nodes_tailq); |
594 | 590 | // Driver is not installed, we can modify dynamic section outside of the critical section |
595 | 591 | hub_driver_obj->dynamic.root_port_state = ROOT_PORT_STATE_NOT_POWERED; |
|
0 commit comments