fix(uhci): rx fsm race condition and buffer size check

Closes https://github.com/espressif/esp-idf/issues/18819
Closes https://github.com/espressif/esp-idf/issues/18820
This commit is contained in:
Hu Rui
2026-07-27 11:48:52 +08:00
parent 281d61f131
commit e7eaad0eb8
7 changed files with 178 additions and 109 deletions
@@ -21,7 +21,7 @@ typedef struct {
size_t tx_trans_queue_depth; /*!< Depth of internal transfer queue, increase this value can support more transfers pending in the background */
size_t max_transmit_size; /*!< Maximum transfer size in one transaction, in bytes. Note that this is the total size of all buffers combined */
size_t max_transmit_buffer_count; /*!< Maximum number of buffers that can be transmitted together in one transaction, via `uhci_multi_buffer_transmit()`. Set to 0 or 1 if only single-buffer transmit (`uhci_transmit()`) is needed. */
size_t max_receive_internal_mem; /*!< Internal DMA usage memory. Each DMA node can point to a maximum of x bytes (depends on chip). This value determines the number of DMA nodes used for each transaction. When your transfer size is large enough, it is recommended to set this value greater than x to facilitate efficient ping-pong operations, such as 2 * x. */
size_t max_receive_internal_mem; /*!< Expected maximum buffer size for uhci_receive(). This value determines the number of descriptors in the receive DMA chain. Each DMA descriptor can reference a buffer of up to X bytes (depending on the chip). For large transfers, at least two descriptors are recommended for ping-pong operation. */
size_t dma_burst_size; /*!< DMA burst size, in bytes. Set to 0 to disable data burst. Otherwise, use a power of 2. */
size_t max_packet_receive; /*!< Max receive size, auto stop receiving after reach this value, only valid when `length_eof` set true */
@@ -79,15 +79,16 @@ esp_err_t uhci_new_controller(const uhci_controller_config_t *config, uhci_contr
* `uhci_new_controller()`.
* @param[out] read_buffer Pointer to the buffer where the received data will be stored.
* The buffer must be pre-allocated by the caller.
* @param[in] buffer_size The size of read buffer.
* @param[in] buffer_size The size of read buffer. Should generally not exceed `uhci_controller_config_t.max_receive_internal_mem`.
*
* @note The function is non-blocking, it just mounts the user buffer to the DMA.
* The return from the function doesn't mean a finished receive. You need to register corresponding
* callback function to get notification.
*
* @return
* - `ESP_OK`: Data successfully received and written to the buffer.
* - `ESP_ERR_INVALID_ARG`: Invalid arguments (e.g., null buffer or invalid controller handle).
* - `ESP_OK`: The driver is ready for data reception.
* - `ESP_ERR_INVALID_STATE`: The controller is not in enable state.
* - `ESP_ERR_INVALID_ARG`: Invalid arguments (e.g., invalid controller handle, null buffer, invalid buffer size).
*/
esp_err_t uhci_receive(uhci_controller_handle_t uhci_ctrl, uint8_t *read_buffer, size_t buffer_size);