diff --git a/components/usb_device/README.md b/components/usb_device/README.md index 034633ed54..1bed6274fd 100644 --- a/components/usb_device/README.md +++ b/components/usb_device/README.md @@ -79,6 +79,10 @@ for back-compatibility. strings, plus the descriptor details some hosts check: `bcd_device` (device release), `max_power_ma` (bMaxPower, clamped to 500 mA and rounded up to the next 2 mA unit) and `remote_wakeup`. +- **Port selection** (`Config::port`): on targets with two USB-OTG + controllers (ESP32-P4) pick the full-speed or the high-speed port; boards do + not always route the high-speed port to a device-capable connector (the + M5Stack Tab5's USB-C carries the full-speed port). - **Idiomatic espp**: no exceptions; `initialize()` reports failures via `std::error_code`. - **Safe marshaling**: the TinyUSB RX callbacks (TinyUSB task context) are drained diff --git a/components/usb_device/include/usb_device.hpp b/components/usb_device/include/usb_device.hpp index ae5889481f..185db98732 100644 --- a/components/usb_device/include/usb_device.hpp +++ b/components/usb_device/include/usb_device.hpp @@ -347,6 +347,15 @@ class UsbDevice : public BaseComponent { * false to stay invisible to the host until connect() -- e.g. to finish * application file I/O on an MSC medium before a host can take it. */ bool connect_on_initialize{true}; + /** USB peripheral port to use, as esp_tinyusb's `tinyusb_port_t` (0 = the + * USB-OTG 1.1 full-speed port, 1 = the USB-OTG 2.0 high-speed port on + * targets that have one). -1 = TinyUSB's default for the target: the + * high-speed port on the ESP32-P4, the full-speed port elsewhere. Boards + * do not always route the high-speed port to a device-capable connector + * (the M5Stack Tab5 wires it to its USB-A host jack; its USB-C carries the + * full-speed port, shared with the USB-Serial-JTAG console), so this lets + * the application pick the connector. */ + int port{-1}; std::optional cdc{}; /**< Enable a CDC-ACM function. */ std::optional vendor{}; /**< Enable a vendor-specific / WebUSB function. */ diff --git a/components/usb_device/src/usb_device.cpp b/components/usb_device/src/usb_device.cpp index 3e301353ab..d384cf4951 100644 --- a/components/usb_device/src/usb_device.cpp +++ b/components/usb_device/src/usb_device.cpp @@ -1496,6 +1496,15 @@ bool UsbDevice::initialize(std::error_code &ec) { // --- Install the TinyUSB driver with our descriptors --- tinyusb_config_t tusb_cfg = TINYUSB_DEFAULT_CONFIG(); + if (config_.port >= 0) { + if (config_.port >= static_cast(TINYUSB_PORT_MAX)) { + logger_.error("Invalid USB port {} (this target has {} port(s))", config_.port, + static_cast(TINYUSB_PORT_MAX)); + ec = std::make_error_code(std::errc::invalid_argument); + return false; + } + tusb_cfg.port = static_cast(config_.port); + } tusb_cfg.descriptor.device = &impl_->device_desc; tusb_cfg.descriptor.string = impl_->strings.data(); tusb_cfg.descriptor.string_count = static_cast(impl_->strings.size());