11#include "freertos/FreeRTOS.h"
12#include "freertos/task.h"
13#include "freertos/ringbuf.h"
19#define RX_UNREADBUF_SZ_DEFAULT 64
20#define MIN(x, y) (((x) < (y)) ? (x) : (y))
34static const char *
TAG =
"tusb_cdc_acm";
39 if (cdc_inst == NULL) {
55 ESP_LOGV(
TAG,
"Host connected to CDC no.%d.", itf);
57 ESP_LOGW(
TAG,
"Host is connected to CDC no.%d, but it is not initialized. Initialize it using `tinyusb_cdc_init`.", itf);
62 ESP_LOGV(
TAG,
"Serial device is ready to connect to CDC no.%d", itf);
72 .line_state_changed_data = {
88 ESP_LOGE(
TAG,
"There is no RX buffer created");
92 tud_cdc_n_read_flush(itf);
95 while (tud_cdc_n_available(itf)) {
96 int read_res = tud_cdc_n_read( itf,
98 CONFIG_TINYUSB_CDC_RX_BUFSIZE );
103 ESP_LOGW(
TAG,
"The unread buffer is too small, the data has been lost");
105 ESP_LOGV(
TAG,
"Sent %d bytes to the buffer", read_res);
128 .line_coding_changed_data = {
129 .p_line_coding = p_line_coding,
148 .rx_wanted_char_data = {
149 .wanted_char = wanted_char,
165 switch (event_type) {
179 ESP_LOGE(
TAG,
"Wrong event type");
180 return ESP_ERR_INVALID_ARG;
183 ESP_LOGE(
TAG,
"CDC-ACM is not initialized");
184 return ESP_ERR_INVALID_STATE;
193 ESP_LOGE(
TAG,
"Interface is not initialized. Use `tinyusb_cdc_init` for initialization");
194 return ESP_ERR_INVALID_STATE;
196 switch (event_type) {
210 ESP_LOGE(
TAG,
"Wrong event type");
211 return ESP_ERR_INVALID_ARG;
221 uint8_t *buf = xRingbufferReceiveUpTo(acm->
rx_unread_buf, read_bytes, 0, req_bytes);
223 memcpy(out_buf, buf, *read_bytes);
227 return ESP_ERR_NO_MEM;
234 ESP_LOGW(
TAG,
"Read error: ACM is busy");
235 return ESP_ERR_INVALID_STATE;
243 assert(ret == pdTRUE);
250 ESP_RETURN_ON_FALSE(acm, ESP_ERR_INVALID_STATE,
TAG,
"Interface is not initialized. Use `tinyusb_cdc_init` for initialization");
262 *rx_data_size = read_sz;
265 *rx_data_size += read_sz;
277 return tud_cdc_n_write_char(itf, ch);
285 const uint32_t size_available = tud_cdc_n_write_available(itf);
286 return tud_cdc_n_write(itf, in_buf,
MIN(in_size, size_available));
300 if (!timeout_ticks) {
301 int res = tud_cdc_n_write_flush(itf);
303 ESP_LOGW(
TAG,
"flush failed (res: %d)", res);
307 ESP_LOGW(
TAG,
"remained data to flush!");
314 uint32_t ticks_start = xTaskGetTickCount();
315 uint32_t ticks_now = ticks_start;
317 ticks_now = xTaskGetTickCount();
321 if (tud_cdc_n_write_flush(itf)) {
324 if ( (ticks_now - ticks_start) > timeout_ticks ) {
325 ESP_LOGW(
TAG,
"Flush failed");
326 return ESP_ERR_TIMEOUT;
359 .cdc_class = TUSB_CLASS_CDC,
360 .cdc_subclass.comm_subclass = CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL
364 ESP_GOTO_ON_FALSE(!
alloc_obj(itf), ESP_FAIL, out4,
TAG,
"alloc_obj failed");
384 ESP_GOTO_ON_FALSE(acm->
ringbuf_read_mux, ESP_ERR_NO_MEM, out3,
TAG,
"Creation of a ringbuf mutex failed");
386 acm->
rx_tfbuf = malloc(CONFIG_TINYUSB_CDC_RX_BUFSIZE);
387 ESP_GOTO_ON_FALSE(acm->
rx_tfbuf, ESP_ERR_NO_MEM, out2,
TAG,
"Creation buffer error");
391 ESP_GOTO_ON_FALSE(acm->
rx_unread_buf, ESP_ERR_NO_MEM, out1,
TAG,
"Creation buffer error");
#define ESP_RETURN_ON_ERROR(x, log_tag, format,...)
esp_err_t tinyusb_cdc_deinit(int itf)
De-initializing CDC. Clean its objects.
esp_tusb_cdc_t * tinyusb_cdc_get_intf(int itf_num)
Return interface of a CDC device.
esp_err_t tinyusb_cdc_init(int itf, const tinyusb_config_cdc_t *cfg)
Initializing CDC basic object.
Describes an event passing to the input of a callbacks.
tusb_cdcacm_callback_t callback_line_coding_changed
tusb_cdcacm_callback_t callback_line_state_changed
SemaphoreHandle_t ringbuf_read_mux
tusb_cdcacm_callback_t callback_rx
RingbufHandle_t rx_unread_buf
tusb_cdcacm_callback_t callback_rx_wanted_char
Configuration structure for CDC-ACM.
tusb_cdcacm_callback_t callback_rx_wanted_char
tusb_cdcacm_callback_t callback_line_coding_changed
tusb_cdcacm_callback_t callback_rx
tusb_cdcacm_callback_t callback_line_state_changed
tinyusb_cdcacm_itf_t cdc_port
static esp_err_t ringbuf_mux_give(esp_tusb_cdcacm_t *acm)
static esp_err_t ringbuf_mux_take(esp_tusb_cdcacm_t *acm)
size_t tinyusb_cdcacm_write_queue(tinyusb_cdcacm_itf_t itf, const uint8_t *in_buf, size_t in_size)
Write data to write buffer from a byte array.
void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char)
esp_err_t tinyusb_cdcacm_register_callback(tinyusb_cdcacm_itf_t itf, cdcacm_event_type_t event_type, tusb_cdcacm_callback_t callback)
Register a callback invoking on CDC event. If the callback had been already registered,...
static esp_err_t read_from_rx_unread_to_buffer(esp_tusb_cdcacm_t *acm, uint8_t *out_buf, size_t req_bytes, size_t *read_bytes)
void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts)
bool tusb_cdc_acm_initialized(tinyusb_cdcacm_itf_t itf)
Check if the ACM initialized.
static esp_err_t alloc_obj(tinyusb_cdcacm_itf_t itf)
static void free_obj(tinyusb_cdcacm_itf_t itf)
void tud_cdc_rx_cb(uint8_t itf)
void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const *p_line_coding)
esp_err_t tinyusb_cdcacm_read(tinyusb_cdcacm_itf_t itf, uint8_t *out_buf, size_t out_buf_sz, size_t *rx_data_size)
Read a content to the array, and defines it's size to the sz_store.
esp_err_t tusb_cdc_acm_init(const tinyusb_config_cdcacm_t *cfg)
Initialize CDC ACM. Initialization will be finished with the tud_cdc_line_state_cb callback.
static esp_tusb_cdcacm_t * get_acm(tinyusb_cdcacm_itf_t itf)
esp_err_t tinyusb_cdcacm_unregister_callback(tinyusb_cdcacm_itf_t itf, cdcacm_event_type_t event_type)
Unregister a callback invoking on CDC event.
size_t tinyusb_cdcacm_write_queue_char(tinyusb_cdcacm_itf_t itf, char ch)
Sent one character to a write buffer.
#define RX_UNREADBUF_SZ_DEFAULT
esp_err_t tinyusb_cdcacm_write_flush(tinyusb_cdcacm_itf_t itf, uint32_t timeout_ticks)
Send all data from a write buffer. Use tinyusb_cdcacm_write_queue to add data to the buffer.
static uint32_t tud_cdc_n_write_occupied(tinyusb_cdcacm_itf_t itf)
cdcacm_event_type_t
Types of CDC ACM events.
@ CDC_EVENT_LINE_STATE_CHANGED
@ CDC_EVENT_RX_WANTED_CHAR
@ CDC_EVENT_LINE_CODING_CHANGED
void(* tusb_cdcacm_callback_t)(int itf, cdcacm_event_t *event)
CDC-ACM callback type.
tinyusb_cdcacm_itf_t
CDC ports available to setup.
#define CFG_TUD_CDC_TX_BUFSIZE