From 63f020f8e233d28b01d1f2018d4b976069839115 Mon Sep 17 00:00:00 2001 From: Tomas Rezucha Date: Tue, 3 Feb 2026 11:00:06 +0100 Subject: [PATCH] fix(host/usb): Fixed deadlock that prevented closing devices from high priority tasks If in usb_host_interface_release() the underlying pipe was halted while having an URB in-flight, usb_host_client_handle_events() may not have had a chance to process the URB yet. Check if there are any pending URBs on the pipe before attempting to free it. Closes https://github.com/espressif/esp-idf/issues/17707 --- components/usb/usb_host.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/components/usb/usb_host.c b/components/usb/usb_host.c index 98c04c4433c..10adaacdbab 100644 --- a/components/usb/usb_host.c +++ b/components/usb/usb_host.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -1480,6 +1480,18 @@ esp_err_t usb_host_interface_release(usb_host_client_handle_t client_hdl, usb_de // Take mux lock. This protects the client being released or other clients from claiming interfaces xSemaphoreTake(p_host_lib_obj->constant.mux_lock, portMAX_DELAY); + + // In case the underlying pipe was halted while having an URB in-flight, + // usb_host_client_handle_events() may not have had a chance to process the URB yet, + // in case it is handled from low priority task and we are calling this function from a high priority task. + HOST_ENTER_CRITICAL(); + const bool pending_ep = !TAILQ_EMPTY(&client_obj->dynamic.pending_ep_tailq); + HOST_EXIT_CRITICAL(); + if (pending_ep) { + // We wait 10 FreeRTOS ticks to give the class driver task chance to run and process the URB. + vTaskDelay(10); + } + esp_err_t ret = interface_release(client_obj, dev_hdl, bInterfaceNumber); xSemaphoreGive(p_host_lib_obj->constant.mux_lock);