From a778baddca233ab8e6fdd4b687c982bb96a53adf Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 5 Oct 2026 16:56:10 -0500 Subject: [PATCH] [usb_uart] Only compile the vendor drivers that are configured (#20190) --- esphome/components/usb_uart/__init__.py | 21 +++++++++++++++++++ esphome/core/defines.h | 4 ++++ tests/component_tests/usb_uart/__init__.py | 0 .../usb_uart/test_source_filter.py | 19 +++++++++++++++++ .../usb_uart/test_usb_uart_ft232.yaml | 18 ++++++++++++++++ 5 files changed, 62 insertions(+) create mode 100644 tests/component_tests/usb_uart/__init__.py create mode 100644 tests/component_tests/usb_uart/test_source_filter.py create mode 100644 tests/component_tests/usb_uart/test_usb_uart_ft232.yaml diff --git a/esphome/components/usb_uart/__init__.py b/esphome/components/usb_uart/__init__.py index 5d0f8be165..af58c24d43 100644 --- a/esphome/components/usb_uart/__init__.py +++ b/esphome/components/usb_uart/__init__.py @@ -7,6 +7,7 @@ from esphome.components.usb_host import ( register_usb_client, usb_device_schema, ) +from esphome.config_helpers import filter_source_files_from_defines import esphome.config_validation as cv from esphome.const import ( CONF_BAUD_RATE, @@ -15,6 +16,7 @@ from esphome.const import ( CONF_DEBUG, CONF_DUMMY_RECEIVER, CONF_ID, + CONF_TYPE, ) from esphome.core import CORE from esphome.cpp_types import Component @@ -64,6 +66,8 @@ class Type: self.vid = vid self.pid = pid self.cls = usb_uart_ns.class_(f"USBUartType{cls}", USBUartComponent) + # CDC ACM lives in usb_uart.cpp; each vendor driver has its own .cpp + self.driver = None if cls == "CdcAcm" else cls self._max_channels = max_channels self.baud_rate_required = baud_rate_required self.max_baud = max_baud @@ -121,6 +125,21 @@ uart_types = ( ), ) +_TYPES_BY_NAME = {it.name: it for it in uart_types} + + +def _driver_define(driver: str) -> str: + return f"USE_USB_UART_{driver}" + + +FILTER_SOURCE_FILES = filter_source_files_from_defines( + { + f"{it.driver.lower()}.cpp": _driver_define(it.driver) + for it in uart_types + if it.driver is not None + } +) + def channel_schema(type_: "Type") -> cv.Schema: schema = cv.Schema( @@ -211,6 +230,8 @@ async def to_code(config: list[ConfigType]) -> None: cg.add_define("USB_UART_OUTPUT_CHUNK_COUNT", output_chunk_count) for device in config: + if (driver := _TYPES_BY_NAME[device[CONF_TYPE]].driver) is not None: + cg.add_define(_driver_define(driver)) var = await register_usb_client(device) # The C++ default is true; only emit the override if not device.get(CONF_CLAIM_COMM_INTERFACE, True): diff --git a/esphome/core/defines.h b/esphome/core/defines.h index be8d89c557..f701cd2919 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -459,6 +459,10 @@ #define USB_HOST_MAX_REQUESTS 16 #define USB_HOST_MAX_PACKET_SIZE 64 #define USB_UART_OUTPUT_CHUNK_COUNT 5 +#define USE_USB_UART_CH34X +#define USE_USB_UART_CP210X +#define USE_USB_UART_FT23XX +#define USE_USB_UART_PL2303 #ifdef USE_ARDUINO #define USE_ARDUINO_VERSION_CODE VERSION_CODE(3, 3, 7) diff --git a/tests/component_tests/usb_uart/__init__.py b/tests/component_tests/usb_uart/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/component_tests/usb_uart/test_source_filter.py b/tests/component_tests/usb_uart/test_source_filter.py new file mode 100644 index 0000000000..414640f821 --- /dev/null +++ b/tests/component_tests/usb_uart/test_source_filter.py @@ -0,0 +1,19 @@ +"""Tests for the usb_uart component's driver source filtering.""" + +from collections.abc import Callable + +from esphome.core import CORE + + +def test_only_configured_driver_compiled( + generate_main: Callable[[str], str], +) -> None: + generate_main("tests/component_tests/usb_uart/test_usb_uart_ft232.yaml") + from esphome.components.usb_uart import FILTER_SOURCE_FILES + + defines = {define.name for define in CORE.defines} + # cdc_acm is built into usb_uart.cpp and adds no driver define + assert {d for d in defines if d.startswith("USE_USB_UART_")} == { + "USE_USB_UART_FT23XX" + } + assert sorted(FILTER_SOURCE_FILES()) == ["ch34x.cpp", "cp210x.cpp", "pl2303.cpp"] diff --git a/tests/component_tests/usb_uart/test_usb_uart_ft232.yaml b/tests/component_tests/usb_uart/test_usb_uart_ft232.yaml new file mode 100644 index 0000000000..e68a6246bf --- /dev/null +++ b/tests/component_tests/usb_uart/test_usb_uart_ft232.yaml @@ -0,0 +1,18 @@ +esphome: + name: test + +esp32: + variant: esp32s3 + framework: + type: esp-idf + +usb_uart: + - type: ft232 + channels: + - id: ft_channel + baud_rate: 115200 + - type: cdc_acm + vid: 0x1234 + pid: 0x5678 + channels: + - id: cdc_channel