ESPHome 2026.1.5
Loading...
Searching...
No Matches
usb_cdc_acm.h
Go to the documentation of this file.
1#pragma once
2#if defined(USE_ESP32_VARIANT_ESP32P4) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)
3
8
9#include <functional>
10#include "freertos/ringbuf.h"
11#include "tusb_cdc_acm.h"
12
13namespace esphome::usb_cdc_acm {
14
15static const uint8_t EVENT_QUEUE_SIZE = 12;
16
17// Callback types for line coding and line state changes
18using LineCodingCallback = std::function<void(uint32_t bit_rate, uint8_t stop_bits, uint8_t parity, uint8_t data_bits)>;
19using LineStateCallback = std::function<void(bool dtr, bool rts)>;
20
21// Event types
26
27// Event structure for the queue
28struct CDCEvent {
30 union {
31 struct {
32 bool dtr;
33 bool rts;
35 struct {
36 uint32_t bit_rate;
37 uint8_t stop_bits;
38 uint8_t parity;
39 uint8_t data_bits;
42
43 // Required by EventPool - called before returning to pool
44 void release() {
45 // No dynamic memory to clean up, data is stored inline
46 }
47};
48
49// Forward declaration
50class USBCDCACMComponent;
51
53class USBCDCACMInstance : public uart::UARTComponent, public Parented<USBCDCACMComponent> {
54 public:
55 void setup();
56 void loop();
57 void dump_config();
58
59 void set_interface_number(uint8_t itf) { this->itf_ = itf; }
60 // Get the CDC port number for this instance
61 uint8_t get_itf() const { return this->itf_; }
62 // Ring buffer accessors for bridge components
63 RingbufHandle_t get_tx_ringbuf() const { return this->usb_tx_ringbuf_; }
64 RingbufHandle_t get_rx_ringbuf() const { return this->usb_rx_ringbuf_; }
65
66 // Task handle accessor for notifying TX task
67 TaskHandle_t get_tx_task_handle() const { return this->usb_tx_task_handle_; }
68
69 // Callback registration for line coding and line state changes
70 void set_line_coding_callback(LineCodingCallback callback) { this->line_coding_callback_ = std::move(callback); }
71 void set_line_state_callback(LineStateCallback callback) { this->line_state_callback_ = std::move(callback); }
72
73 // Called from USB core task context queues event for processing in main loop
74 void queue_line_coding_event(uint32_t bit_rate, uint8_t stop_bits, uint8_t parity, uint8_t data_bits);
75 void queue_line_state_event(bool dtr, bool rts);
76
77 static void usb_tx_task_fn(void *arg);
78 void usb_tx_task();
79
80 // UARTComponent interface implementation
81 void write_array(const uint8_t *data, size_t len) override;
82 bool peek_byte(uint8_t *data) override;
83 bool read_array(uint8_t *data, size_t len) override;
84 int available() override;
85 void flush() override;
86
87 protected:
88 void check_logger_conflict() override;
89
90 // Process queued events and invoke callbacks (called from main loop)
91 void process_events_();
92 TaskHandle_t usb_tx_task_handle_{nullptr};
93
94 RingbufHandle_t usb_tx_ringbuf_{nullptr};
95 RingbufHandle_t usb_rx_ringbuf_{nullptr};
96 // RX buffer for peek functionality
97 uint8_t peek_buffer_{0};
98 bool has_peek_{false};
99 uint8_t itf_{0};
100 // User-registered callbacks (called from main loop)
103
104 // Lock-free queue and event pool for cross-task event passing
107};
108
111 public:
113
114 void setup() override;
115 void loop() override;
116 void dump_config() override;
117 float get_setup_priority() const override { return setup_priority::IO; }
118
119 // Interface management
120 void add_interface(USBCDCACMInstance *interface);
122
123 protected:
124 std::array<USBCDCACMInstance *, ESPHOME_MAX_USB_CDC_INSTANCES> interfaces_{};
125};
126
127extern USBCDCACMComponent *global_usb_cdc_component; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
128
129} // namespace esphome::usb_cdc_acm
130#endif
Helper class to easily give an object a parent of type T.
Definition helpers.h:1246
Main USB CDC ACM component that manages the USB device and all CDC interfaces.
void add_interface(USBCDCACMInstance *interface)
std::array< USBCDCACMInstance *, ESPHOME_MAX_USB_CDC_INSTANCES > interfaces_
USBCDCACMInstance * get_interface_by_number(uint8_t itf)
float get_setup_priority() const override
Represents a single CDC ACM interface instance.
Definition usb_cdc_acm.h:53
RingbufHandle_t get_rx_ringbuf() const
Definition usb_cdc_acm.h:64
bool read_array(uint8_t *data, size_t len) override
EventPool< CDCEvent, EVENT_QUEUE_SIZE > event_pool_
RingbufHandle_t get_tx_ringbuf() const
Definition usb_cdc_acm.h:63
void set_line_state_callback(LineStateCallback callback)
Definition usb_cdc_acm.h:71
LockFreeQueue< CDCEvent, EVENT_QUEUE_SIZE > event_queue_
void queue_line_coding_event(uint32_t bit_rate, uint8_t stop_bits, uint8_t parity, uint8_t data_bits)
TaskHandle_t get_tx_task_handle() const
Definition usb_cdc_acm.h:67
void set_line_coding_callback(LineCodingCallback callback)
Definition usb_cdc_acm.h:70
void write_array(const uint8_t *data, size_t len) override
void queue_line_state_event(bool dtr, bool rts)
const float IO
For components that represent GPIO pins like PCF8573.
Definition component.cpp:79
std::function< void(uint32_t bit_rate, uint8_t stop_bits, uint8_t parity, uint8_t data_bits)> LineCodingCallback
Definition usb_cdc_acm.h:18
USBCDCACMComponent * global_usb_cdc_component
std::function< void(bool dtr, bool rts)> LineStateCallback
Definition usb_cdc_acm.h:19
std::string size_t len
Definition helpers.h:595
union esphome::usb_cdc_acm::CDCEvent::@159 data
struct esphome::usb_cdc_acm::CDCEvent::@159::@160 line_state
struct esphome::usb_cdc_acm::CDCEvent::@159::@161 line_coding