| /* | |
| * SPDX-FileCopyrightText: Copyright (c) 2019 Ha Thach (tinyusb.org) | |
| * SPDX-License-Identifier: MIT | |
| * | |
| * This file is part of the TinyUSB stack. | |
| */ | |
| #ifndef TUSB_CDC_DEVICE_H_ | |
| #define TUSB_CDC_DEVICE_H_ | |
| #include "cdc.h" | |
| #ifdef __cplusplus | |
| extern "C" { | |
| #endif | |
| //--------------------------------------------------------------------+ | |
| // Class Driver Configuration | |
| //--------------------------------------------------------------------+ | |
| #ifndef CFG_TUD_CDC_NOTIFY | |
| #define CFG_TUD_CDC_NOTIFY 0 | |
| #endif | |
| #ifndef CFG_TUD_CDC_TX_BUFSIZE | |
| #define CFG_TUD_CDC_TX_BUFSIZE TUD_EPSIZE_BULK_MAX | |
| #endif | |
| #ifndef CFG_TUD_CDC_RX_BUFSIZE | |
| #define CFG_TUD_CDC_RX_BUFSIZE TUD_EPSIZE_BULK_MAX | |
| #endif | |
| // EP_BUFSIZE is separated to RX_EPSIZE and TX_EPSIZE | |
| #ifndef CFG_TUD_CDC_RX_EPSIZE | |
| #ifdef CFG_TUD_CDC_EP_BUFSIZE | |
| #define CFG_TUD_CDC_RX_EPSIZE CFG_TUD_CDC_EP_BUFSIZE | |
| #else | |
| #define CFG_TUD_CDC_RX_EPSIZE TUD_EPSIZE_BULK_MAX | |
| #endif | |
| #endif | |
| #ifndef CFG_TUD_CDC_TX_EPSIZE | |
| #ifdef CFG_TUD_CDC_EP_BUFSIZE | |
| #define CFG_TUD_CDC_TX_EPSIZE CFG_TUD_CDC_EP_BUFSIZE | |
| #else | |
| #define CFG_TUD_CDC_TX_EPSIZE TUD_EPSIZE_BULK_MAX | |
| #endif | |
| #endif | |
| // Enable multi-packet RX transfer with ZLP termination for better throughput. Requires host support for ZLP. | |
| #ifndef CFG_TUD_CDC_RX_NEED_ZLP | |
| #define CFG_TUD_CDC_RX_NEED_ZLP 0 | |
| #endif | |
| // Keep rx fifo data even with bus reset or disconnect | |
| #ifndef CFG_TUD_CDC_RX_PERSISTENT | |
| #define CFG_TUD_CDC_RX_PERSISTENT 0 | |
| #endif | |
| // Keep tx fifo data even with bus reset or disconnect | |
| #ifndef CFG_TUD_CDC_TX_PERSISTENT | |
| #define CFG_TUD_CDC_TX_PERSISTENT 0 | |
| #endif | |
| // If not connected, tx fifo can be overwritten | |
| #ifndef CFG_TUD_CDC_TX_OVERWRITABLE_IF_NOT_CONNECTED | |
| #define CFG_TUD_CDC_TX_OVERWRITABLE_IF_NOT_CONNECTED 1 | |
| #endif | |
| // Backward compatible: tud_cdc_configure_t and tud_cdc_configure() are no longer used. | |
| // Configuration is now done via compile-time macros above. | |
| typedef struct { | |
| bool rx_persistent; | |
| bool tx_persistent; | |
| bool tx_overwritabe_if_not_connected; | |
| } tud_cdc_configure_t; | |
| #define tud_cdc_configure(_cfg) ((void)(_cfg)) | |
| #define tud_cdc_configure_fifo_t tud_cdc_configure_t | |
| #define tud_cdc_configure_fifo(_cfg) ((void)(_cfg)) | |
| //--------------------------------------------------------------------+ | |
| // Application API (Multiple Ports) i.e. CFG_TUD_CDC > 1 | |
| //--------------------------------------------------------------------+ | |
| // Check if the interface is ready | |
| bool tud_cdc_n_ready(uint8_t itf); | |
| // Check if the terminal is connected to this port | |
| bool tud_cdc_n_connected(uint8_t itf); | |
| // Get the current line state. Bit 0: DTR (Data Terminal Ready), Bit 1: RTS (Request to Send) | |
| uint8_t tud_cdc_n_get_line_state(uint8_t itf); | |
| // Get current line encoding: bit rate, stop bits parity etc .. | |
| void tud_cdc_n_get_line_coding(uint8_t itf, cdc_line_coding_t* coding); | |
| // Set special character that will trigger tud_cdc_rx_wanted_cb() callback on receiving | |
| void tud_cdc_n_set_wanted_char(uint8_t itf, char wanted); | |
| // Get the number of bytes available for reading | |
| uint32_t tud_cdc_n_available(uint8_t itf); | |
| // Read received bytes | |
| uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize); | |
| // Read a byte, return -1 if there is none | |
| TU_ATTR_ALWAYS_INLINE static inline int32_t tud_cdc_n_read_char(uint8_t itf) { | |
| uint8_t ch; | |
| return tud_cdc_n_read(itf, &ch, 1) ? (int32_t) ch : -1; | |
| } | |
| // Clear the received FIFO | |
| void tud_cdc_n_read_flush(uint8_t itf); | |
| // Get a byte from FIFO without removing it | |
| bool tud_cdc_n_peek(uint8_t itf, uint8_t* ui8); | |
| // Write bytes to TX FIFO, data may remain in the FIFO for a while | |
| uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize); | |
| // Write a byte | |
| TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_cdc_n_write_char(uint8_t itf, char ch) { | |
| return tud_cdc_n_write(itf, &ch, 1); | |
| } | |
| // Write a null-terminated string | |
| TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_cdc_n_write_str(uint8_t itf, char const* str) { | |
| return tud_cdc_n_write(itf, str, strlen(str)); | |
| } | |
| // Force sending data if possible, return number of forced bytes | |
| uint32_t tud_cdc_n_write_flush(uint8_t itf); | |
| // Return the number of bytes (characters) available for writing to TX FIFO buffer in a single n_write operation. | |
| uint32_t tud_cdc_n_write_available(uint8_t itf); | |
| // Clear the TX FIFO | |
| bool tud_cdc_n_write_clear(uint8_t itf); | |
| #if CFG_TUD_CDC_NOTIFY | |
| bool tud_cdc_n_notify_msg(uint8_t itf, cdc_notify_msg_t *msg); | |
| // Send UART status notification: DCD, DSR etc .. | |
| TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_n_notify_uart_state(uint8_t itf, | |
| const cdc_notify_uart_state_t *state) { | |
| cdc_notify_msg_t notify_msg; | |
| notify_msg.request.bmRequestType = CDC_REQ_TYPE_NOTIF; | |
| notify_msg.request.bRequest = CDC_NOTIF_SERIAL_STATE; | |
| notify_msg.request.wValue = 0; | |
| notify_msg.request.wIndex = 0; // filled later | |
| notify_msg.request.wLength = sizeof(cdc_notify_uart_state_t); | |
| notify_msg.serial_state = *state; | |
| return tud_cdc_n_notify_msg(itf, ¬ify_msg); | |
| } | |
| // Send connection speed change notification | |
| TU_ATTR_ALWAYS_INLINE static inline bool | |
| tud_cdc_n_notify_conn_speed_change(uint8_t itf, const cdc_notify_conn_speed_change_t *conn_speed_change) { | |
| cdc_notify_msg_t notify_msg; | |
| notify_msg.request.bmRequestType = CDC_REQ_TYPE_NOTIF; | |
| notify_msg.request.bRequest = CDC_NOTIF_CONNECTION_SPEED_CHANGE; | |
| notify_msg.request.wValue = 0; | |
| notify_msg.request.wIndex = 0; // filled later | |
| notify_msg.request.wLength = sizeof(cdc_notify_conn_speed_change_t); | |
| notify_msg.conn_speed_change = *conn_speed_change; | |
| return tud_cdc_n_notify_msg(itf, ¬ify_msg); | |
| } | |
| TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_notify_msg(cdc_notify_msg_t *msg) { | |
| return tud_cdc_n_notify_msg(0, msg); | |
| } | |
| TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_notify_uart_state(const cdc_notify_uart_state_t* state) { | |
| return tud_cdc_n_notify_uart_state(0, state); | |
| } | |
| TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_notify_conn_speed_change(const cdc_notify_conn_speed_change_t* conn_speed_change) { | |
| return tud_cdc_n_notify_conn_speed_change(0, conn_speed_change); | |
| } | |
| #endif | |
| //--------------------------------------------------------------------+ | |
| // Application API (Single Port) | |
| //--------------------------------------------------------------------+ | |
| TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_ready(void) { | |
| return tud_cdc_n_ready(0); | |
| } | |
| TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_connected(void) { | |
| return tud_cdc_n_connected(0); | |
| } | |
| TU_ATTR_ALWAYS_INLINE static inline uint8_t tud_cdc_get_line_state(void) { | |
| return tud_cdc_n_get_line_state(0); | |
| } | |
| TU_ATTR_ALWAYS_INLINE static inline void tud_cdc_get_line_coding(cdc_line_coding_t* coding) { | |
| tud_cdc_n_get_line_coding(0, coding); | |
| } | |
| TU_ATTR_ALWAYS_INLINE static inline void tud_cdc_set_wanted_char(char wanted) { | |
| tud_cdc_n_set_wanted_char(0, wanted); | |
| } | |
| TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_cdc_available(void) { | |
| return tud_cdc_n_available(0); | |
| } | |
| TU_ATTR_ALWAYS_INLINE static inline int32_t tud_cdc_read_char(void) { | |
| return tud_cdc_n_read_char(0); | |
| } | |
| TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_cdc_read(void* buffer, uint32_t bufsize) { | |
| return tud_cdc_n_read(0, buffer, bufsize); | |
| } | |
| TU_ATTR_ALWAYS_INLINE static inline void tud_cdc_read_flush(void) { | |
| tud_cdc_n_read_flush(0); | |
| } | |
| TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_peek(uint8_t* ui8) { | |
| return tud_cdc_n_peek(0, ui8); | |
| } | |
| TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_cdc_write_char(char ch) { | |
| return tud_cdc_n_write_char(0, ch); | |
| } | |
| TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_cdc_write(void const* buffer, uint32_t bufsize) { | |
| return tud_cdc_n_write(0, buffer, bufsize); | |
| } | |
| TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_cdc_write_str(char const* str) { | |
| return tud_cdc_n_write_str(0, str); | |
| } | |
| TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_cdc_write_flush(void) { | |
| return tud_cdc_n_write_flush(0); | |
| } | |
| TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_cdc_write_available(void) { | |
| return tud_cdc_n_write_available(0); | |
| } | |
| TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_write_clear(void) { | |
| return tud_cdc_n_write_clear(0); | |
| } | |
| //--------------------------------------------------------------------+ | |
| // Application Callback API | |
| //--------------------------------------------------------------------+ | |
| // Invoked when received new data | |
| void tud_cdc_rx_cb(uint8_t itf); | |
| // Invoked when received `wanted_char` | |
| void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char); | |
| // Invoked when a TX is complete and therefore space becomes available in TX buffer | |
| void tud_cdc_tx_complete_cb(uint8_t itf); | |
| // Invoked when a notification is sent to host | |
| void tud_cdc_notify_complete_cb(uint8_t itf); | |
| // Invoked when line state DTR & RTS are changed via SET_CONTROL_LINE_STATE | |
| void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts); | |
| // Invoked when line coding is change via SET_LINE_CODING | |
| void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding); | |
| // Invoked when received send break | |
| // \param[in] itf interface for which send break was received. | |
| // \param[in] duration_ms the length of time, in milliseconds, of the break signal. If a value of FFFFh, then the | |
| // device will send a break until another SendBreak request is received with value 0000h. | |
| void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms); | |
| //--------------------------------------------------------------------+ | |
| // INTERNAL USBD-CLASS DRIVER API | |
| //--------------------------------------------------------------------+ | |
| void cdcd_init (void); | |
| bool cdcd_deinit (void); | |
| void cdcd_reset (uint8_t rhport); | |
| uint16_t cdcd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); | |
| bool cdcd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); | |
| bool cdcd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); | |
| #ifdef __cplusplus | |
| } | |
| #endif | |
| #endif /* TUSB_CDC_DEVICE_H_ */ |