ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
usb_uart.h
Go to the documentation of this file.
1#pragma once
2
3#if defined(USE_ESP32_VARIANT_ESP32P4) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) || \
4 defined(USE_ESP32_VARIANT_ESP32S31) || defined(USE_ESP32_VARIANT_ESP32H4)
12#include "esphome/core/log.h"
13#include <array>
14#include <atomic>
15#include <functional>
16
17namespace esphome::usb_uart {
18
19class USBUartTypeCdcAcm;
20class USBUartComponent;
21class USBUartChannelBase;
22class USBUartTypePL2303;
23
24ESPHOME_LOG_TAG(TAG, "usb_uart");
25
26static constexpr uint8_t USB_CDC_SUBCLASS_ACM = 0x02;
27static constexpr uint8_t USB_SUBCLASS_COMMON = 0x02;
28static constexpr uint8_t USB_SUBCLASS_NULL = 0x00;
29static constexpr uint8_t USB_PROTOCOL_NULL = 0x00;
30static constexpr uint8_t USB_DEVICE_PROTOCOL_IAD = 0x01;
31static constexpr uint8_t USB_VENDOR_IFC = usb_host::USB_TYPE_VENDOR | usb_host::USB_RECIP_INTERFACE;
32static constexpr uint8_t USB_VENDOR_DEV = usb_host::USB_TYPE_VENDOR | usb_host::USB_RECIP_DEVICE;
33
34struct CdcEps {
35 const usb_ep_desc_t *notify_ep;
36 const usb_ep_desc_t *in_ep;
37 const usb_ep_desc_t *out_ep;
38 // 0xFF marks a channel that was never matched to a CDC function on the device
39 uint8_t bulk_interface_number{0xFF};
40 // Also the wIndex target for CDC class requests (SET_LINE_CODING etc.), so it
41 // must remain valid even when the interface itself is not claimed.
44 // bInterfaceClass of each interface above, which decides how a host binds the port
47};
48
78
79// 1 and 2 are the stop bit count the uart component uses, so a count set through the
80// UARTComponent API (as serial_proxy does) means the same here. 1.5 has no count.
86
87// Stop bits and parity as adapters take them on the wire: CDC SET_LINE_CODING, and the
88// CP210x, FTDI and PL2303 requests, all use these values
89enum class LineStopBits : uint8_t {
93};
94
95enum class LineParity : uint8_t {
101};
102
103// Indexed by LineParity
104static const char *const PARITY_NAMES[] = {"NONE", "ODD", "EVEN", "MARK", "SPACE"};
105// Indexed by LineStopBits
106static const char *const STOP_BITS_NAMES[] = {"1", "1.5", "2"};
107
109enum class ConfigMode : uint8_t {
113};
114
116 public:
117 RingBuffer(uint16_t buffer_size) : buffer_size_(buffer_size), buffer_(new uint8_t[buffer_size]) {}
118 bool is_empty() const { return this->read_pos_ == this->insert_pos_; }
119 size_t get_available() const {
120 return (this->insert_pos_ + this->buffer_size_ - this->read_pos_) % this->buffer_size_;
121 };
122 size_t get_free_space() const { return this->buffer_size_ - 1 - this->get_available(); }
123 uint8_t peek() const { return this->buffer_[this->read_pos_]; }
124 void push(uint8_t item);
125 void push(const uint8_t *data, size_t len);
126 uint8_t pop();
127 size_t pop(uint8_t *data, size_t len);
128 void clear() { this->read_pos_ = this->insert_pos_ = 0; }
129
130 protected:
131 uint16_t insert_pos_ = 0;
132 uint16_t read_pos_ = 0;
133 uint16_t buffer_size_;
134 uint8_t *buffer_;
135};
136
137// Structure for queuing received USB data chunks
139 uint8_t data[usb_host::USB_MAX_PACKET_SIZE];
140 uint16_t length;
142
143 // Required for EventPool - no cleanup needed for POD types
144 void release() {}
145};
146
147// Structure for queuing outgoing USB data chunks (one per USB packet)
149 static constexpr size_t MAX_CHUNK_SIZE = usb_host::USB_MAX_PACKET_SIZE;
151 uint16_t length;
152
153 // Required for EventPool - no cleanup needed for POD types
154 void release() {}
155};
156
157// Common, non-final base for all USB UART channel implementations.
158// Concrete channel types (USBUartChannel for CDC-style devices, vendor-specific
159// multiplexed channels like CH934X) derive from this and are themselves final,
160// per the "configurable classes are final" convention.
161class USBUartChannelBase : public uart::UARTComponent, public Parented<USBUartComponent> {
162 friend class USBUartComponent;
163 friend class USBUartTypeCdcAcm;
164 friend class USBUartTypeCP210X;
165 friend class USBUartTypeCH34X;
166 friend class USBUartTypeFT23XX;
167 friend class USBUartTypePL2303;
168
169 public:
170 // Number of output chunk slots per channel, derived from buffer_size config.
171 // Computed as ceil(buffer_size / 64) + 1 in Python codegen; defaults to 5 (256 / 64 + 1).
172 static constexpr uint8_t USB_OUTPUT_CHUNK_COUNT = USB_UART_OUTPUT_CHUNK_COUNT;
173
174 void write_array(const uint8_t *data, size_t len) override;
175 bool peek_byte(uint8_t *data) override;
176 bool read_array(uint8_t *data, size_t len) override;
177 size_t available() override { return this->input_buffer_.get_available(); }
178 bool is_connected() override { return this->initialised_.load(); }
179 uart::UARTFlushResult flush() override;
180 // Re-apply the current line settings (baud, parity, etc) to this already-open channel.
181 void load_settings(bool dump_config) override;
182 using UARTComponent::load_settings; // also bring in the no-arg overload for convenience
183 void set_debug(bool debug) { this->debug_ = debug; }
184 void set_dummy_receiver(bool dummy_receiver) { this->dummy_receiver_ = dummy_receiver; }
185 void set_debug_prefix(const char *prefix) { this->debug_prefix_ = StringRef(prefix); }
186 void set_flush_timeout(uint32_t flush_timeout_ms) override { this->flush_timeout_ms_ = flush_timeout_ms; }
187
192 void set_rx_callback(std::function<void()> cb) { this->rx_callback_ = std::move(cb); }
193
200
206
209 uint8_t get_port_number() const { return 0; }
210
212 bool set_modem_control(bool dtr, bool rts);
213 bool get_dtr() const { return this->dtr_; }
214 bool get_rts() const { return this->rts_; }
215
216 protected:
217 // Not directly instantiable; construct a concrete channel type instead.
218 USBUartChannelBase(uint8_t index, uint16_t buffer_size) : input_buffer_(RingBuffer(buffer_size)), index_(index) {}
219 void check_logger_conflict() override {}
221 LineParity line_parity_() const;
222 // Larger structures first (8+ bytes)
225 // Pool sized to queue capacity (SIZE-1) because LockFreeQueue<T,N> is a ring
226 // buffer that holds N-1 elements. This guarantees allocate() returns nullptr
227 // before push() can fail, preventing a pool slot leak.
229 std::function<void()> rx_callback_{};
232 // 4-byte fields
234 // 1-byte fields (no padding between groups)
235 std::atomic<bool> input_started_{true};
236 std::atomic<bool> output_started_{true};
237 std::atomic<bool> initialised_{false};
238 const uint8_t index_;
239 bool debug_{};
241 // Asserted whenever a device connects, as a host driver does when it opens the port
242 bool dtr_{true};
243 bool rts_{true};
244 // Line settings or DTR/RTS changed while the config machine was busy; sent once it is idle
245 bool reload_pending_{false};
246 bool modem_pending_{false};
247};
248
249// Concrete channel type for CDC-style USB serial devices (2 bulk endpoints per
250// channel). All shared behavior lives in USBUartChannelBase.
251class USBUartChannel final : public USBUartChannelBase {
252 public:
253 USBUartChannel(uint8_t index, uint16_t buffer_size) : USBUartChannelBase(index, buffer_size) {}
254};
255
257 public:
258 USBUartComponent(uint16_t vid, uint16_t pid) : usb_host::USBClient(vid, pid) {}
259 void setup() override;
260 void loop() override;
261 void dump_config() override;
262 std::vector<USBUartChannelBase *> get_channels() { return this->channels_; }
263
264 void add_channel(USBUartChannelBase *channel) { this->channels_.push_back(channel); }
265
266 virtual void start_input(USBUartChannelBase *channel);
267 void start_output(USBUartChannelBase *channel);
268
269 // Begin configuring all channels (full initialisation). Called from on_connected().
270 void enable_channels();
271 // Re-apply line settings to a single, already-open channel (used by
272 // USBUartChannelBase::load_settings()).
274 // Apply the DTR/RTS state of a single, already-open channel (used by
275 // USBUartChannelBase::set_modem_control()).
277
278 // Called from loop() when input_buffer_ has insufficient space for the incoming chunk.
279 // Default is a no-op; override in device-specific subclasses that need resync on overflow.
280 virtual void on_rx_overflow(USBUartChannelBase *channel) {}
281
282 // Lock-free data transfer from USB task to main loop
283 static constexpr int USB_DATA_QUEUE_SIZE = 32;
285 // Pool sized to queue capacity (SIZE-1) — see USBUartChannelBase::output_pool_ comment.
287
288 protected:
289 // Issue one control transfer as part of the setup state machine. The completion
290 // callback (USB-task context) records the result/IN data, marks the step done and
291 // wakes the loop so run_config_machine_() advances on the loop thread. Call exactly
292 // once from config_step_()/config_device_step_() when issuing a step.
293 // An IN reply goes to cfg_response_, or to `dest` when set. A `dest` reply must be
294 // exactly data.size() bytes, else the step fails.
295 void config_transfer_(uint8_t type, uint8_t request, uint16_t value, uint16_t index,
296 const std::vector<uint8_t> &data = {}, uint8_t *dest = nullptr);
297 // (Re)start the config state machine. INIT runs over all channels; the other modes act
298 // on cfg_single_ only.
300 // Advance the config state machine; called from loop(). Returns true if it did work.
301 bool run_config_machine_();
302
303 // Per-subclass per-channel settings sequence. For the given zero-based step, issue the
304 // next control transfer via config_transfer_() and return true, or return false when the
305 // channel has no more steps. reload=true ⇒ apply only baud/parity/stop/data (skip
306 // enable/reset/DTR-RTS). ok/response carry the previous step's result and IN data.
307 virtual bool config_step(USBUartChannelBase *channel, uint8_t step, bool reload, bool ok,
308 const uint8_t *response) = 0;
309 // Optional one-time device-level setup run before the per-channel phase on init only
310 // (e.g. CH34x chip detection). Same contract as config_step_(). Default: no steps.
311 virtual bool config_device_step(uint8_t step, bool ok, const uint8_t *response) { return false; }
312 // Issue the one control transfer, via config_transfer_(), that puts the channel's dtr_
313 // and rts_ on the wire.
314 virtual void modem_control_transfer(USBUartChannelBase *channel) = 0;
315
316 // The device is only usable once the config machine has applied every channel's line
317 // settings, so the connected report waits for run_config_machine_() to finish the init
318 bool reports_connection_itself() const override { return true; }
319
320 std::vector<USBUartChannelBase *> channels_{};
321
322 // Config state machine
323 USBUartChannelBase *cfg_single_{nullptr}; // non-null: single-channel run (RELOAD or MODEM)
324 uint8_t *cfg_read_dest_{nullptr}; // where the step in flight stores its reply, if not cfg_response_
325 size_t cfg_read_len_{0}; // and the exact length it then expects
326 // synchronizes cfg_ok_/cfg_response_ across threads; a byte, since atomic<bool> does not inline on Xtensa
327 std::atomic<uint8_t> cfg_done_{0};
328 uint8_t cfg_response_[8]{}; // last IN transfer payload
330 uint8_t cfg_step_{0};
332 bool cfg_active_{false};
333 bool cfg_device_phase_{false};
334 bool cfg_in_flight_{false};
335 bool cfg_ok_{true};
336};
337
339 public:
340 USBUartTypeCdcAcm(uint16_t vid, uint16_t pid) : USBUartComponent(vid, pid) {}
341 void set_claim_comm_interface(bool claim) { this->claim_comm_interface_ = claim; }
342
343 protected:
344 virtual std::vector<CdcEps> parse_descriptors(usb_device_handle_t dev_hdl);
345 void on_connected() override;
346 void on_disconnected() override;
347 bool config_step(USBUartChannelBase *channel, uint8_t step, bool reload, bool ok, const uint8_t *response) override;
348 void modem_control_transfer(USBUartChannelBase *channel) override;
349 // Each claimed interface pins one host hardware channel per endpoint; skipping
350 // the comm (interrupt) interface frees one on channel-poor hosts (ESP32-S3: 8).
352};
353
354// The block GET_FLOW and SET_FLOW transfer, little-endian on the wire as in memory
361
363 public:
364 USBUartTypeCP210X(uint16_t vid, uint16_t pid) : USBUartTypeCdcAcm(vid, pid) {}
365
366 protected:
367 // Matches max_channels of the CP210X type in __init__.py
368 static constexpr uint8_t MAX_CHANNELS = 3;
369
370 std::vector<CdcEps> parse_descriptors(usb_device_handle_t dev_hdl) override;
371 bool config_step(USBUartChannelBase *channel, uint8_t step, bool reload, bool ok, const uint8_t *response) override;
372 void modem_control_transfer(USBUartChannelBase *channel) override;
373 bool config_device_step(uint8_t step, bool ok, const uint8_t *response) override;
375
376 // The block last read for each channel, so a DTR/RTS change under RTS/CTS is a single SET_FLOW
377 std::array<CP210xFlowBlock, MAX_CHANNELS> flow_blocks_{};
378 // A CP2102N whose firmware has erratum E104
379 bool no_flow_control_{false};
380};
382 public:
383 USBUartTypeCH34X(uint16_t vid, uint16_t pid) : USBUartTypeCdcAcm(vid, pid) {
384 // ch34x doesn't use the interrupt endpoint, and we don't have endpoints to spare. The
385 // comm interface is left in place unclaimed: on the CDC-style chips it is still the
386 // interface a host binds, and so the one the port is identified by.
387 this->claim_comm_interface_ = false;
388 }
389 void dump_config() override;
390
391 protected:
392 bool config_step(USBUartChannelBase *channel, uint8_t step, bool reload, bool ok, const uint8_t *response) override;
393 void modem_control_transfer(USBUartChannelBase *channel) override;
394 bool config_device_step(uint8_t step, bool ok, const uint8_t *response) override;
395
396 private:
397 CH34xChipType chiptype_{CHIP_UNKNOWN};
398 const char *chip_name_{"unknown"};
399 uint8_t num_ports_{1};
400};
401
403 public:
404 USBUartTypeFT23XX(uint16_t vid, uint16_t pid) : USBUartTypeCdcAcm(vid, pid) {}
405
406 void start_input(USBUartChannelBase *channel) override;
407 void on_rx_overflow(USBUartChannelBase *channel) override;
408
409 protected:
410 std::vector<CdcEps> parse_descriptors(usb_device_handle_t dev_hdl) override;
411 bool config_step(USBUartChannelBase *channel, uint8_t step, bool reload, bool ok, const uint8_t *response) override;
412 void modem_control_transfer(USBUartChannelBase *channel) override;
413
414 uint8_t chip_type_{255};
415};
416
417enum Pl2303ChipType : uint8_t {
418 PL2303_TYPE_H = 0, // Legacy, max 1.2Mbaud
419 PL2303_TYPE_HX, // max 6Mbaud, divisor encoding
420 PL2303_TYPE_TA, // max 6Mbaud, alt divisor encoding
421 PL2303_TYPE_TB, // max 12Mbaud, alt divisor encoding
422 PL2303_TYPE_HXD, // max 12Mbaud, divisor encoding
423 PL2303_TYPE_HXN, // G-series, max 12Mbaud, direct encoding only
425};
426
428 friend class USBUartChannelBase;
429
430 public:
431 USBUartTypePL2303(uint16_t vid, uint16_t pid) : USBUartTypeCdcAcm(vid, pid) {}
432
433 protected:
434 std::vector<CdcEps> parse_descriptors(usb_device_handle_t dev_hdl) override;
435 bool config_step(USBUartChannelBase *channel, uint8_t step, bool reload, bool ok, const uint8_t *response) override;
436 void modem_control_transfer(USBUartChannelBase *channel) override;
437
439};
440
441} // namespace esphome::usb_uart
442
443#endif // USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3 ||
444 // USE_ESP32_VARIANT_ESP32S31 || USE_ESP32_VARIANT_ESP32H4
BedjetMode mode
BedJet operating mode.
Helper class to easily give an object a parent of type T.
Definition helpers.h:2073
StringRef is a reference to a string owned by something else.
Definition string_ref.h:31
void load_settings()
Load the UART settings.
USBClient(uint16_t vid, uint16_t pid)
Definition usb_host.h:154
void push(uint8_t item)
Definition usb_uart.cpp:111
RingBuffer(uint16_t buffer_size)
Definition usb_uart.h:117
size_t get_free_space() const
Definition usb_uart.h:122
size_t get_available() const
Definition usb_uart.h:119
uint8_t get_interface_class() const
bInterfaceClass of the interface get_interface_number() names
Definition usb_uart.h:202
uart::UARTFlushResult flush() override
Definition usb_uart.cpp:174
bool read_array(uint8_t *data, size_t len) override
Definition usb_uart.cpp:197
EventPool< UsbOutputChunk, USB_OUTPUT_CHUNK_COUNT - 1 > output_pool_
Definition usb_uart.h:228
bool peek_byte(uint8_t *data) override
Definition usb_uart.cpp:190
std::function< void()> rx_callback_
Definition usb_uart.h:229
void set_rx_callback(std::function< void()> cb)
Register a callback invoked immediately after data is pushed to the input ring buffer.
Definition usb_uart.h:192
USBUartChannelBase(uint8_t index, uint16_t buffer_size)
Definition usb_uart.h:218
LockFreeQueue< UsbOutputChunk, USB_OUTPUT_CHUNK_COUNT > output_queue_
Definition usb_uart.h:224
uint8_t get_port_number() const
Index of this port among the ports on its interface.
Definition usb_uart.h:209
static constexpr uint8_t USB_OUTPUT_CHUNK_COUNT
Definition usb_uart.h:172
std::atomic< bool > input_started_
Definition usb_uart.h:235
uint8_t get_interface_number() const
USB interface number a host driver binds to for this channel: the communication interface of a CDC AC...
Definition usb_uart.h:196
void set_dummy_receiver(bool dummy_receiver)
Definition usb_uart.h:184
void set_debug_prefix(const char *prefix)
Definition usb_uart.h:185
std::atomic< bool > output_started_
Definition usb_uart.h:236
void set_flush_timeout(uint32_t flush_timeout_ms) override
Definition usb_uart.h:186
void write_array(const uint8_t *data, size_t len) override
Definition usb_uart.cpp:140
bool set_modem_control(bool dtr, bool rts)
Store DTR/RTS and send them to the device. False when not connected.
Definition usb_uart.cpp:775
LineStopBits line_stop_bits_() const
Definition usb_uart.cpp:744
USBUartChannel(uint8_t index, uint16_t buffer_size)
Definition usb_uart.h:253
USBUartChannelBase * cfg_single_
Definition usb_uart.h:323
std::atomic< uint8_t > cfg_done_
Definition usb_uart.h:327
std::vector< USBUartChannelBase * > channels_
Definition usb_uart.h:320
void start_config_(ConfigMode mode)
Definition usb_uart.cpp:593
USBUartComponent(uint16_t vid, uint16_t pid)
Definition usb_uart.h:258
bool reports_connection_itself() const override
Definition usb_uart.h:318
LockFreeQueue< UsbDataChunk, USB_DATA_QUEUE_SIZE > usb_data_queue_
Definition usb_uart.h:284
virtual void on_rx_overflow(USBUartChannelBase *channel)
Definition usb_uart.h:280
virtual void modem_control_transfer(USBUartChannelBase *channel)=0
std::vector< USBUartChannelBase * > get_channels()
Definition usb_uart.h:262
void config_transfer_(uint8_t type, uint8_t request, uint16_t value, uint16_t index, const std::vector< uint8_t > &data={}, uint8_t *dest=nullptr)
Definition usb_uart.cpp:604
virtual bool config_device_step(uint8_t step, bool ok, const uint8_t *response)
Definition usb_uart.h:311
virtual void start_input(USBUartChannelBase *channel)
Definition usb_uart.cpp:282
void apply_modem_control(USBUartChannelBase *channel)
Definition usb_uart.cpp:582
void apply_channel_settings(USBUartChannelBase *channel)
Definition usb_uart.cpp:569
void start_output(USBUartChannelBase *channel)
Definition usb_uart.cpp:351
void add_channel(USBUartChannelBase *channel)
Definition usb_uart.h:264
static constexpr int USB_DATA_QUEUE_SIZE
Definition usb_uart.h:283
EventPool< UsbDataChunk, USB_DATA_QUEUE_SIZE - 1 > chunk_pool_
Definition usb_uart.h:286
virtual bool config_step(USBUartChannelBase *channel, uint8_t step, bool reload, bool ok, const uint8_t *response)=0
void modem_control_transfer(USBUartChannelBase *channel) override
Definition ch34x.cpp:185
bool config_device_step(uint8_t step, bool ok, const uint8_t *response) override
Definition ch34x.cpp:68
USBUartTypeCH34X(uint16_t vid, uint16_t pid)
Definition usb_uart.h:383
bool config_step(USBUartChannelBase *channel, uint8_t step, bool reload, bool ok, const uint8_t *response) override
Definition ch34x.cpp:113
void modem_control_transfer(USBUartChannelBase *channel) override
Definition cp210x.cpp:260
bool config_device_step(uint8_t step, bool ok, const uint8_t *response) override
Definition cp210x.cpp:153
USBUartTypeCP210X(uint16_t vid, uint16_t pid)
Definition usb_uart.h:364
void set_flow_transfer_(USBUartChannelBase *channel)
Definition cp210x.cpp:274
std::vector< CdcEps > parse_descriptors(usb_device_handle_t dev_hdl) override
Definition cp210x.cpp:99
bool config_step(USBUartChannelBase *channel, uint8_t step, bool reload, bool ok, const uint8_t *response) override
Definition cp210x.cpp:188
std::array< CP210xFlowBlock, MAX_CHANNELS > flow_blocks_
Definition usb_uart.h:377
static constexpr uint8_t MAX_CHANNELS
Definition usb_uart.h:368
bool config_step(USBUartChannelBase *channel, uint8_t step, bool reload, bool ok, const uint8_t *response) override
Definition usb_uart.cpp:510
USBUartTypeCdcAcm(uint16_t vid, uint16_t pid)
Definition usb_uart.h:340
void set_claim_comm_interface(bool claim)
Definition usb_uart.h:341
virtual std::vector< CdcEps > parse_descriptors(usb_device_handle_t dev_hdl)
Definition usb_uart.cpp:65
void modem_control_transfer(USBUartChannelBase *channel) override
Definition usb_uart.cpp:548
USBUartTypeFT23XX(uint16_t vid, uint16_t pid)
Definition usb_uart.h:404
void modem_control_transfer(USBUartChannelBase *channel) override
Definition ft23xx.cpp:411
bool config_step(USBUartChannelBase *channel, uint8_t step, bool reload, bool ok, const uint8_t *response) override
Definition ft23xx.cpp:359
void on_rx_overflow(USBUartChannelBase *channel) override
Definition ft23xx.cpp:354
std::vector< CdcEps > parse_descriptors(usb_device_handle_t dev_hdl) override
Definition ft23xx.cpp:238
void start_input(USBUartChannelBase *channel) override
Definition ft23xx.cpp:288
USBUartTypePL2303(uint16_t vid, uint16_t pid)
Definition usb_uart.h:431
std::vector< CdcEps > parse_descriptors(usb_device_handle_t dev_hdl) override
Definition pl2303.cpp:159
bool config_step(USBUartChannelBase *channel, uint8_t step, bool reload, bool ok, const uint8_t *response) override
Definition pl2303.cpp:275
void modem_control_transfer(USBUartChannelBase *channel) override
Definition pl2303.cpp:352
uint8_t type
UARTFlushResult
Result of a flush() call.
ConfigMode
What the config state machine is applying.
Definition usb_uart.h:109
@ CONFIG_MODE_RELOAD
Re-apply the line settings of one already-open channel.
@ CONFIG_MODE_MODEM
Apply the DTR/RTS state of one already-open channel.
@ CONFIG_MODE_INIT
Full initialisation of every channel after the device connected.
ESPHOME_LOG_TAG(TAG, "usb_uart")
@ UART_CONFIG_STOP_BITS_1_5
Definition usb_uart.h:84
const void size_t len
Definition hal.h:68
static void uint32_t
const usb_ep_desc_t * out_ep
Definition usb_uart.h:37
uint8_t interrupt_interface_class
Definition usb_uart.h:46
const usb_ep_desc_t * notify_ep
Definition usb_uart.h:35
const usb_ep_desc_t * in_ep
Definition usb_uart.h:36
uint8_t interrupt_interface_number
Definition usb_uart.h:42
uint8_t data[usb_host::USB_MAX_PACKET_SIZE]
Definition usb_uart.h:139
USBUartChannelBase * channel
Definition usb_uart.h:141
uint8_t data[MAX_CHUNK_SIZE]
Definition usb_uart.h:150
static constexpr size_t MAX_CHUNK_SIZE
Definition usb_uart.h:149