diff --git a/esphome/components/usb_uart/cp210x.cpp b/esphome/components/usb_uart/cp210x.cpp index 67fd03a813..2c341313db 100644 --- a/esphome/components/usb_uart/cp210x.cpp +++ b/esphome/components/usb_uart/cp210x.cpp @@ -120,6 +120,32 @@ void USBUartTypeCP210X::enable_channels() { } this->start_channels_(); } + +void USBUartTypeCP210X::load_settings(USBUartChannel *channel, bool dump_config) { + if (channel == nullptr || !channel->initialised_.load()) + return; + + usb_host::transfer_cb_t callback = [channel](const usb_host::TransferStatus &status) { + if (!status.success) { + ESP_LOGE(TAG, "Control transfer failed, status=%s", esp_err_to_name(status.error_code)); + channel->initialised_.store(false); + } + }; + + uint16_t line_control = channel->stop_bits_; + line_control |= static_cast(channel->parity_) << 4; + line_control |= channel->data_bits_ << 8; + this->control_transfer(USB_VENDOR_IFC | usb_host::USB_DIR_OUT, SET_LINE_CTL, line_control, channel->index_, + callback); + + auto baud = ByteBuffer::wrap(channel->baud_rate_, LITTLE); + this->control_transfer(USB_VENDOR_IFC | usb_host::USB_DIR_OUT, SET_BAUDRATE, 0, channel->index_, callback, + baud.get_data()); + + if (dump_config) { + ESP_LOGCONFIG(TAG, "UART settings reloaded for CP210X channel %u", channel->index_); + } +} } // namespace esphome::usb_uart #endif // USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3 diff --git a/esphome/components/usb_uart/usb_uart.cpp b/esphome/components/usb_uart/usb_uart.cpp index 3fdf35a472..7388484fcd 100644 --- a/esphome/components/usb_uart/usb_uart.cpp +++ b/esphome/components/usb_uart/usb_uart.cpp @@ -209,7 +209,21 @@ bool USBUartChannel::read_array(uint8_t *data, size_t len) { this->parent_->start_input(this); return status; } +#if defined(USE_ESP8266) || defined(USE_ESP32) +void USBUartChannel::load_settings(bool dump_config) { + if (this->parent_ == nullptr || !this->initialised_.load()) + return; + this->parent_->load_settings(this, dump_config); +} + +void USBUartChannel::load_settings() { this->load_settings(true); } +#endif + void USBUartComponent::setup() { USBClient::setup(); } +void USBUartComponent::load_settings(USBUartChannel *channel, bool dump_config) { + (void) channel; + (void) dump_config; +} void USBUartComponent::loop() { bool had_work = this->process_usb_events_(); diff --git a/esphome/components/usb_uart/usb_uart.h b/esphome/components/usb_uart/usb_uart.h index 41dc2c546d..345eec2664 100644 --- a/esphome/components/usb_uart/usb_uart.h +++ b/esphome/components/usb_uart/usb_uart.h @@ -149,6 +149,10 @@ class USBUartChannel : public uart::UARTComponent, public Parenteddummy_receiver_ = dummy_receiver; } void set_debug_prefix(const char *prefix) { this->debug_prefix_ = StringRef(prefix); } void set_flush_timeout(uint32_t flush_timeout_ms) override { this->flush_timeout_ms_ = flush_timeout_ms; } +#if defined(USE_ESP8266) || defined(USE_ESP32) + void load_settings(bool dump_config) override; + void load_settings() override; +#endif /// Register a callback invoked immediately after data is pushed to the input ring buffer. /// Called from USBUartComponent::loop() in the main loop context. @@ -188,6 +192,7 @@ class USBUartComponent : public usb_host::USBClient { std::vector get_channels() { return this->channels_; } void add_channel(USBUartChannel *channel) { this->channels_.push_back(channel); } + virtual void load_settings(USBUartChannel *channel, bool dump_config); void start_input(USBUartChannel *channel); void start_output(USBUartChannel *channel); @@ -224,6 +229,7 @@ class USBUartTypeCP210X : public USBUartTypeCdcAcm { protected: std::vector parse_descriptors(usb_device_handle_t dev_hdl) override; void enable_channels() override; + void load_settings(USBUartChannel *channel, bool dump_config) override; }; class USBUartTypeCH34X : public USBUartTypeCdcAcm { public: