From 76eb8f697f43b4777dffa66a327024b027a46d0e Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Wed, 22 Apr 2026 16:16:14 -0500 Subject: [PATCH] [usb_uart] Derive TX output chunk count from `buffer_size` config (#15909) --- esphome/components/usb_uart/__init__.py | 13 ++++++++++++- esphome/components/usb_uart/usb_uart.h | 5 +++-- esphome/core/defines.h | 1 + 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/esphome/components/usb_uart/__init__.py b/esphome/components/usb_uart/__init__.py index 0e8994a3ed..d542788fb9 100644 --- a/esphome/components/usb_uart/__init__.py +++ b/esphome/components/usb_uart/__init__.py @@ -116,12 +116,23 @@ CONFIG_SCHEMA = cv.ensure_list( async def to_code(config): + # The output chunk pool/queue are compile-time-sized templates shared by all + # USBUartChannel instances, so use the largest buffer_size across every channel + # of every device. Each chunk is 64 bytes (USB FS MPS); add one extra slot + # because LockFreeQueue is a ring buffer that wastes one entry. + max_buffer_size = max( + channel[CONF_BUFFER_SIZE] + for device in config + for channel in device[CONF_CHANNELS] + ) + output_chunk_count = max_buffer_size // 64 + 1 + cg.add_define("USB_UART_OUTPUT_CHUNK_COUNT", output_chunk_count) + for device in config: var = await register_usb_client(device) for index, channel in enumerate(device[CONF_CHANNELS]): chvar = cg.new_Pvariable(channel[CONF_ID], index, channel[CONF_BUFFER_SIZE]) await cg.register_parented(chvar, var) - cg.add(chvar.set_rx_buffer_size(channel[CONF_BUFFER_SIZE])) cg.add(chvar.set_stop_bits(channel[CONF_STOP_BITS])) cg.add(chvar.set_data_bits(channel[CONF_DATA_BITS])) cg.add(chvar.set_parity(channel[CONF_PARITY])) diff --git a/esphome/components/usb_uart/usb_uart.h b/esphome/components/usb_uart/usb_uart.h index 8e8e65032d..f9648b795b 100644 --- a/esphome/components/usb_uart/usb_uart.h +++ b/esphome/components/usb_uart/usb_uart.h @@ -132,8 +132,9 @@ class USBUartChannel : public uart::UARTComponent, public Parented