summaryrefslogtreecommitdiff
path: root/src/class/cdc/cdc_device.c
diff options
context:
space:
mode:
authorZixun LI <[email protected]>2025-11-27 12:01:33 +0100
committerZixun LI <[email protected]>2025-11-27 12:01:33 +0100
commit2e8d193c732bb211ebff8badff16a84775db42ff (patch)
tree9a3410e65711df25559524b760447ff68fdd316a /src/class/cdc/cdc_device.c
parentb997ec725812d2f6a573610ba0dd817f271eddea (diff)
parent5ef55bfa30d6f8cf175b3d327f621c76aae7b138 (diff)
Merge remote-tracking branch 'tinyusb/master' into hcd_fsdev
Signed-off-by: Zixun LI <[email protected]>
Diffstat (limited to 'src/class/cdc/cdc_device.c')
-rw-r--r--src/class/cdc/cdc_device.c91
1 files changed, 54 insertions, 37 deletions
diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c
index 9e62c6509..7ef8aa738 100644
--- a/src/class/cdc/cdc_device.c
+++ b/src/class/cdc/cdc_device.c
@@ -66,6 +66,8 @@ typedef struct {
#define ITF_MEM_RESET_SIZE offsetof(cdcd_interface_t, line_coding)
+// Skip local EP buffer if dedicated hw FIFO is supported
+ #if CFG_TUD_EDPT_DEDICATED_HWFIFO == 0
typedef struct {
TUD_EPBUF_DEF(epout, CFG_TUD_CDC_EP_BUFSIZE);
TUD_EPBUF_DEF(epin, CFG_TUD_CDC_EP_BUFSIZE);
@@ -75,6 +77,9 @@ typedef struct {
#endif
} cdcd_epbuf_t;
+CFG_TUD_MEM_SECTION static cdcd_epbuf_t _cdcd_epbuf[CFG_TUD_CDC];
+#endif
+
//--------------------------------------------------------------------+
// Weak stubs: invoked if no strong implementation is available
//--------------------------------------------------------------------+
@@ -115,7 +120,6 @@ TU_ATTR_WEAK void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms) {
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC];
-CFG_TUD_MEM_SECTION static cdcd_epbuf_t _cdcd_epbuf[CFG_TUD_CDC];
static tud_cdc_configure_t _cdcd_cfg = TUD_CDC_CONFIGURE_DEFAULT();
TU_ATTR_ALWAYS_INLINE static inline uint8_t find_cdc_itf(uint8_t ep_addr) {
@@ -166,40 +170,22 @@ void tud_cdc_n_get_line_coding(uint8_t itf, cdc_line_coding_t *coding) {
}
#if CFG_TUD_CDC_NOTIFY
-bool tud_cdc_n_notify_uart_state (uint8_t itf, const cdc_notify_uart_state_t *state) {
+bool tud_cdc_n_notify_msg(uint8_t itf, cdc_notify_msg_t *msg) {
TU_VERIFY(itf < CFG_TUD_CDC);
- cdcd_interface_t *p_cdc = &_cdcd_itf[itf];
- cdcd_epbuf_t *p_epbuf = &_cdcd_epbuf[itf];
+ const cdcd_interface_t *p_cdc = &_cdcd_itf[itf];
TU_VERIFY(tud_ready() && p_cdc->ep_notify != 0);
TU_VERIFY(usbd_edpt_claim(p_cdc->rhport, p_cdc->ep_notify));
- cdc_notify_msg_t* notify_msg = &p_epbuf->epnotify;
- 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 = p_cdc->itf_num;
- notify_msg->request.wLength = sizeof(cdc_notify_uart_state_t);
- notify_msg->serial_state = *state;
-
- return usbd_edpt_xfer(p_cdc->rhport, p_cdc->ep_notify, (uint8_t *)notify_msg, 8 + sizeof(cdc_notify_uart_state_t), false);
-}
-
-bool tud_cdc_n_notify_conn_speed_change(uint8_t itf, const cdc_notify_conn_speed_change_t* conn_speed_change) {
- TU_VERIFY(itf < CFG_TUD_CDC);
- cdcd_interface_t *p_cdc = &_cdcd_itf[itf];
- cdcd_epbuf_t *p_epbuf = &_cdcd_epbuf[itf];
- TU_VERIFY(tud_ready() && p_cdc->ep_notify != 0);
- TU_VERIFY(usbd_edpt_claim(p_cdc->rhport, p_cdc->ep_notify));
+ #if CFG_TUD_EDPT_DEDICATED_HWFIFO
+ cdc_notify_msg_t *msg_epbuf = msg;
+ #else
+ cdc_notify_msg_t *msg_epbuf = &_cdcd_epbuf[itf].epnotify;
+ *msg_epbuf = *msg;
+ #endif
- cdc_notify_msg_t* notify_msg = &p_epbuf->epnotify;
- 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 = p_cdc->itf_num;
- notify_msg->request.wLength = sizeof(cdc_notify_conn_speed_change_t);
- notify_msg->conn_speed_change = *conn_speed_change;
+ msg_epbuf->request.wIndex = p_cdc->itf_num;
- return usbd_edpt_xfer(p_cdc->rhport, p_cdc->ep_notify, (uint8_t *)notify_msg, 8 + sizeof(cdc_notify_conn_speed_change_t), false);
+ return usbd_edpt_xfer(p_cdc->rhport, p_cdc->ep_notify, (uint8_t *)msg_epbuf, 8 + msg_epbuf->request.wLength, false);
}
#endif
@@ -268,8 +254,6 @@ void cdcd_init(void) {
tu_memclr(_cdcd_itf, sizeof(_cdcd_itf));
for (uint8_t i = 0; i < CFG_TUD_CDC; i++) {
cdcd_interface_t *p_cdc = &_cdcd_itf[i];
- cdcd_epbuf_t *p_epbuf = &_cdcd_epbuf[i];
-
p_cdc->wanted_char = (char) -1;
// default line coding is : stop bit = 1, parity = none, data bits = 8
@@ -278,14 +262,23 @@ void cdcd_init(void) {
p_cdc->line_coding.parity = 0;
p_cdc->line_coding.data_bits = 8;
+ #if CFG_TUD_EDPT_DEDICATED_HWFIFO
+ uint8_t *epout_buf = NULL;
+ uint8_t *epin_buf = NULL;
+ #else
+ cdcd_epbuf_t *p_epbuf = &_cdcd_epbuf[i];
+ uint8_t *epout_buf = p_epbuf->epout;
+ uint8_t *epin_buf = p_epbuf->epin;
+ #endif
+
tu_edpt_stream_init(&p_cdc->stream.rx, false, false, false, p_cdc->stream.rx_ff_buf, CFG_TUD_CDC_RX_BUFSIZE,
- p_epbuf->epout, CFG_TUD_CDC_EP_BUFSIZE);
+ epout_buf, CFG_TUD_CDC_EP_BUFSIZE);
// TX fifo can be configured to change to overwritable if not connected (DTR bit not set). Without DTR we do not
// know if data is actually polled by terminal. This way the most current data is prioritized.
// Default: is overwritable
tu_edpt_stream_init(&p_cdc->stream.tx, false, true, _cdcd_cfg.tx_overwritabe_if_not_connected,
- p_cdc->stream.tx_ff_buf, CFG_TUD_CDC_TX_BUFSIZE, p_epbuf->epin, CFG_TUD_CDC_EP_BUFSIZE);
+ p_cdc->stream.tx_ff_buf, CFG_TUD_CDC_TX_BUFSIZE, epin_buf, CFG_TUD_CDC_EP_BUFSIZE);
}
}
@@ -481,11 +474,35 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_
if (ep_addr == stream_rx->ep_addr) {
tu_edpt_stream_read_xfer_complete(stream_rx, xferred_bytes);
- // Check for wanted char and invoke wanted callback (multiple times if multiple wanted received)
+ // Check for wanted char and invoke wanted callback
if (((signed char)p_cdc->wanted_char) != -1) {
- for (uint32_t i = 0; i < xferred_bytes; i++) {
- if ((p_cdc->wanted_char == (char)stream_rx->ep_buf[i]) && !tu_edpt_stream_empty(stream_rx)) {
- tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char);
+ tu_fifo_buffer_info_t buf_info;
+ tu_fifo_get_read_info(&stream_rx->ff, &buf_info);
+
+ // find backward
+ uint8_t *ptr;
+ if (buf_info.wrapped.len > 0) {
+ ptr = buf_info.wrapped.ptr + buf_info.wrapped.len - 1; // last byte of wrap buffer
+ } else if (buf_info.linear.len > 0) {
+ ptr = buf_info.linear.ptr + buf_info.linear.len - 1; // last byte of linear buffer
+ } else {
+ ptr = NULL; // no data
+ }
+
+ if (ptr != NULL) {
+ for (uint32_t i = 0; i < xferred_bytes; i++) {
+ if (p_cdc->wanted_char == (char)*ptr) {
+ tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char);
+ break; // only invoke once per transfer, even if multiple wanted chars are present
+ }
+
+ if (ptr == buf_info.wrapped.ptr) {
+ ptr = buf_info.linear.ptr + buf_info.linear.len - 1; // last byte of linear buffer
+ } else if (ptr == buf_info.linear.ptr) {
+ break; // reached the beginning
+ } else {
+ ptr--;
+ }
}
}
}