fix rx transfer length when high speed capable device/host working at full speed

Signed-off-by: HiFiPhile <admin@hifiphile.com>
This commit is contained in:
HiFiPhile
2026-02-11 22:04:44 +01:00
parent f5424c569d
commit 135a130ba5
9 changed files with 63 additions and 40 deletions

View File

@ -74,7 +74,7 @@ typedef struct {
} cdcd_epbuf_t;
CFG_TUD_MEM_SECTION static cdcd_epbuf_t _cdcd_epbuf[CFG_TUD_CDC];
#endif
#endif
//--------------------------------------------------------------------+
// Weak stubs: invoked if no strong implementation is available
@ -267,14 +267,13 @@ void cdcd_init(void) {
uint8_t *epin_buf = _cdcd_epbuf[i].epin;
#endif
tu_edpt_stream_init(&p_cdc->rx_stream, false, false, false, p_cdc->rx_ff_buf, CFG_TUD_CDC_RX_BUFSIZE, epout_buf,
CFG_TUD_CDC_EP_BUFSIZE);
tu_edpt_stream_init(&p_cdc->rx_stream, false, false, false, p_cdc->rx_ff_buf, CFG_TUD_CDC_RX_BUFSIZE, epout_buf);
// 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->tx_stream, false, true, _cdcd_cfg.tx_overwritabe_if_not_connected, p_cdc->tx_ff_buf,
CFG_TUD_CDC_TX_BUFSIZE, epin_buf, CFG_TUD_CDC_EP_BUFSIZE);
CFG_TUD_CDC_TX_BUFSIZE, epin_buf);
}
}
@ -349,7 +348,7 @@ uint16_t cdcd_open(uint8_t rhport, const tusb_desc_interface_t* itf_desc, uint16
if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) {
tu_edpt_stream_t *stream_tx = &p_cdc->tx_stream;
tu_edpt_stream_open(stream_tx, rhport, desc_ep);
tu_edpt_stream_open(stream_tx, rhport, desc_ep, CFG_TUD_CDC_EP_BUFSIZE);
if (_cdcd_cfg.tx_persistent) {
tu_edpt_stream_write_xfer(stream_tx); // flush pending data
} else {
@ -358,7 +357,8 @@ uint16_t cdcd_open(uint8_t rhport, const tusb_desc_interface_t* itf_desc, uint16
} else {
tu_edpt_stream_t *stream_rx = &p_cdc->rx_stream;
tu_edpt_stream_open(stream_rx, rhport, desc_ep);
tu_edpt_stream_open(stream_rx, rhport, desc_ep,
_cdcd_cfg.rx_multiple_packet_transfer ? CFG_TUD_CDC_EP_BUFSIZE : tu_edpt_packet_size(desc_ep));
if (!_cdcd_cfg.rx_persistent) {
tu_edpt_stream_clear(stream_rx);
}

View File

@ -64,6 +64,7 @@ typedef struct TU_ATTR_PACKED {
bool rx_persistent : 1; // keep rx fifo data even with bus reset or disconnect
bool tx_persistent : 1; // keep tx fifo data even with reset or disconnect
bool tx_overwritabe_if_not_connected : 1; // if not connected, tx fifo can be overwritten
bool rx_multiple_packet_transfer : 1; // allow transfer more than one packet in a single transfer, increase throughput but requires host sending ZLP at the end of transfer
} tud_cdc_configure_t;
TU_VERIFY_STATIC(sizeof(tud_cdc_configure_t) == 1, "size is not correct");
@ -71,6 +72,7 @@ TU_VERIFY_STATIC(sizeof(tud_cdc_configure_t) == 1, "size is not correct");
.rx_persistent = false, \
.tx_persistent = false, \
.tx_overwritabe_if_not_connected = true, \
.rx_multiple_packet_transfer = false, \
}
// Configure CDC driver behavior

View File

@ -648,10 +648,10 @@ bool cdch_init(void) {
for (size_t i = 0; i < CFG_TUH_CDC; i++) {
cdch_interface_t *p_cdc = &cdch_data[i];
cdch_epbuf_t *epbuf = &cdch_epbuf[i];
TU_ASSERT(tu_edpt_stream_init(&p_cdc->stream.tx, true, true, false, p_cdc->stream.tx_ff_buf, CFG_TUH_CDC_TX_BUFSIZE,
epbuf->tx, CFG_TUH_CDC_TX_EPSIZE));
TU_ASSERT(tu_edpt_stream_init(&p_cdc->stream.tx, true, true, false, p_cdc->stream.tx_ff_buf,
CFG_TUH_CDC_TX_BUFSIZE, epbuf->tx));
TU_ASSERT(tu_edpt_stream_init(&p_cdc->stream.rx, true, false, false, p_cdc->stream.rx_ff_buf,
CFG_TUH_CDC_RX_BUFSIZE, epbuf->rx, CFG_TUH_CDC_RX_EPSIZE));
CFG_TUH_CDC_RX_BUFSIZE, epbuf->rx));
}
return true;
@ -735,7 +735,7 @@ static bool open_ep_stream_pair(cdch_interface_t *p_cdc, tusb_desc_endpoint_t co
TU_ASSERT(tuh_edpt_open(p_cdc->daddr, desc_ep));
const uint8_t ep_dir = tu_edpt_dir(desc_ep->bEndpointAddress);
tu_edpt_stream_t *stream = (ep_dir == TUSB_DIR_IN) ? &p_cdc->stream.rx : &p_cdc->stream.tx;
tu_edpt_stream_open(stream, p_cdc->daddr, desc_ep);
tu_edpt_stream_open(stream, p_cdc->daddr, desc_ep, desc_ep->wMaxPacketSize);
tu_edpt_stream_clear(stream);
desc_ep = (const tusb_desc_endpoint_t *)tu_desc_next(desc_ep);

View File

@ -324,10 +324,10 @@ void midid_init(void) {
#endif
tu_edpt_stream_init(&p_midi->ep_stream.rx, false, false, false, p_midi->ep_stream.rx_ff_buf,
CFG_TUD_MIDI_RX_BUFSIZE, epout_buf, CFG_TUD_MIDI_EP_BUFSIZE);
CFG_TUD_MIDI_RX_BUFSIZE, epout_buf);
tu_edpt_stream_init(&p_midi->ep_stream.tx, false, true, false, p_midi->ep_stream.tx_ff_buf, CFG_TUD_MIDI_TX_BUFSIZE,
epin_buf, CFG_TUD_MIDI_EP_BUFSIZE);
epin_buf);
}
}
@ -408,11 +408,11 @@ uint16_t midid_open(uint8_t rhport, const tusb_desc_interface_t *desc_itf, uint1
if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) {
tu_edpt_stream_t *stream_tx = &p_midi->ep_stream.tx;
tu_edpt_stream_open(stream_tx, rhport, desc_ep);
tu_edpt_stream_open(stream_tx, rhport, desc_ep, CFG_TUD_MIDI_EP_BUFSIZE);
tu_edpt_stream_clear(stream_tx);
} else {
tu_edpt_stream_t *stream_rx = &p_midi->ep_stream.rx;
tu_edpt_stream_open(stream_rx, rhport, desc_ep);
tu_edpt_stream_open(stream_rx, rhport, desc_ep, tu_edpt_packet_size(desc_ep));
tu_edpt_stream_clear(stream_rx);
TU_ASSERT(tu_edpt_stream_read_xfer(stream_rx) > 0, 0); // prepare to receive data
}

View File

@ -121,9 +121,9 @@ bool midih_init(void) {
for (int inst = 0; inst < CFG_TUH_MIDI; inst++) {
midih_interface_t *p_midi_host = &_midi_host[inst];
tu_edpt_stream_init(&p_midi_host->ep_stream.rx, true, false, false,
p_midi_host->ep_stream.rx_ff_buf, CFG_TUH_MIDI_RX_BUFSIZE, _midi_epbuf->rx, TUH_EPSIZE_BULK_MPS);
p_midi_host->ep_stream.rx_ff_buf, CFG_TUH_MIDI_RX_BUFSIZE, _midi_epbuf->rx);
tu_edpt_stream_init(&p_midi_host->ep_stream.tx, true, true, false,
p_midi_host->ep_stream.tx_ff_buf, CFG_TUH_MIDI_TX_BUFSIZE, _midi_epbuf->tx, TUH_EPSIZE_BULK_MPS);
p_midi_host->ep_stream.tx_ff_buf, CFG_TUH_MIDI_TX_BUFSIZE, _midi_epbuf->tx);
}
return true;
}
@ -306,7 +306,7 @@ uint16_t midih_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_interface_
ep_stream = &p_midi->ep_stream.rx;
}
TU_ASSERT(tuh_edpt_open(dev_addr, p_ep), 0);
tu_edpt_stream_open(ep_stream, dev_addr, p_ep);
tu_edpt_stream_open(ep_stream, dev_addr, p_ep, p_ep->wMaxPacketSize);
tu_edpt_stream_clear(ep_stream);
break;

View File

@ -49,8 +49,7 @@ typedef struct {
#else
uint8_t ep_in;
uint8_t ep_out;
uint16_t ep_in_mps;
uint16_t ep_out_mps;
uint16_t rx_xfer_len;
#endif
} vendord_interface_t;
@ -72,6 +71,8 @@ typedef struct {
CFG_TUD_MEM_SECTION static vendord_epbuf_t _vendord_epbuf[CFG_TUD_VENDOR];
#endif
static tud_vendor_configure_t _vendord_cfg = TUD_VENDOR_CONFIGURE_DEFAULT();
//--------------------------------------------------------------------+
// Weak stubs: invoked if no strong implementation is available
//--------------------------------------------------------------------+
@ -89,6 +90,12 @@ TU_ATTR_WEAK void tud_vendor_tx_cb(uint8_t idx, uint32_t sent_bytes) {
//--------------------------------------------------------------------
// Application API
//--------------------------------------------------------------------
bool tud_vendor_configure(const tud_vendor_configure_t* driver_cfg) {
TU_VERIFY(driver_cfg != NULL);
_vendord_cfg = *driver_cfg;
return true;
}
bool tud_vendor_n_mounted(uint8_t idx) {
TU_VERIFY(idx < CFG_TUD_VENDOR);
vendord_interface_t *p_itf = &_vendord_itf[idx];
@ -128,9 +135,9 @@ void tud_vendor_n_read_flush(uint8_t idx) {
tu_edpt_stream_clear(&p_itf->rx_stream);
tu_edpt_stream_read_xfer(&p_itf->rx_stream);
}
#endif
#endif
#if CFG_TUD_VENDOR_RX_MANUAL_XFER
#if CFG_TUD_VENDOR_RX_MANUAL_XFER
bool tud_vendor_n_read_xfer(uint8_t idx) {
TU_VERIFY(idx < CFG_TUD_VENDOR);
vendord_interface_t *p_itf = &_vendord_itf[idx];
@ -141,7 +148,7 @@ bool tud_vendor_n_read_xfer(uint8_t idx) {
#else
// Non-FIFO mode
TU_VERIFY(usbd_edpt_claim(p_itf->rhport, p_itf->ep_out));
return usbd_edpt_xfer(p_itf->rhport, p_itf->ep_out, _vendord_epbuf[idx].epout, CFG_TUD_VENDOR_EPSIZE, false);
return usbd_edpt_xfer(p_itf->rhport, p_itf->ep_out, _vendord_epbuf[idx].epout, p_itf->rx_xfer_len, false);
#endif
}
#endif
@ -215,12 +222,10 @@ void vendord_init(void) {
#endif
uint8_t *rx_ff_buf = p_itf->rx_ff_buf;
tu_edpt_stream_init(&p_itf->rx_stream, false, false, false, rx_ff_buf, CFG_TUD_VENDOR_RX_BUFSIZE, epout_buf,
CFG_TUD_VENDOR_EPSIZE);
tu_edpt_stream_init(&p_itf->rx_stream, false, false, false, rx_ff_buf, CFG_TUD_VENDOR_RX_BUFSIZE, epout_buf);
uint8_t *tx_ff_buf = p_itf->tx_ff_buf;
tu_edpt_stream_init(&p_itf->tx_stream, false, true, false, tx_ff_buf, CFG_TUD_VENDOR_TX_BUFSIZE, epin_buf,
CFG_TUD_VENDOR_EPSIZE);
tu_edpt_stream_init(&p_itf->tx_stream, false, true, false, tx_ff_buf, CFG_TUD_VENDOR_TX_BUFSIZE, epin_buf);
}
#endif
}
@ -302,30 +307,31 @@ uint16_t vendord_open(uint8_t rhport, const tusb_desc_interface_t *desc_itf, uin
const tusb_desc_endpoint_t* desc_ep = (const tusb_desc_endpoint_t*) p_desc;
TU_ASSERT(usbd_edpt_open(rhport, desc_ep));
uint16_t rx_xfer_len = _vendord_cfg.rx_multiple_packet_transfer ? CFG_TUD_VENDOR_EPSIZE : tu_edpt_packet_size(desc_ep);
#if CFG_TUD_VENDOR_TXRX_BUFFERED
// open endpoint stream
if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) {
tu_edpt_stream_t *tx_stream = &p_vendor->tx_stream;
tu_edpt_stream_open(tx_stream, rhport, desc_ep);
tu_edpt_stream_open(tx_stream, rhport, desc_ep, CFG_TUD_VENDOR_EPSIZE);
tu_edpt_stream_write_xfer(tx_stream); // flush pending data
} else {
tu_edpt_stream_t *rx_stream = &p_vendor->rx_stream;
tu_edpt_stream_open(rx_stream, rhport, desc_ep);
tu_edpt_stream_open(rx_stream, rhport, desc_ep, rx_xfer_len);
#if CFG_TUD_VENDOR_RX_MANUAL_XFER == 0
TU_ASSERT(tu_edpt_stream_read_xfer(rx_stream) > 0, 0); // prepare for incoming data
#endif
}
#else
p_vendor->rx_xfer_len = rx_xfer_len;
// Non-FIFO mode: store endpoint info
if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) {
p_vendor->ep_in = desc_ep->bEndpointAddress;
p_vendor->ep_in_mps = tu_edpt_packet_size(desc_ep);
} else {
p_vendor->ep_out = desc_ep->bEndpointAddress;
p_vendor->ep_out_mps = tu_edpt_packet_size(desc_ep);
#if CFG_TUD_VENDOR_RX_MANUAL_XFER == 0
// Prepare for incoming data
TU_ASSERT(usbd_edpt_xfer(rhport, p_vendor->ep_out, _vendord_epbuf[idx].epout, CFG_TUD_VENDOR_EPSIZE, false), 0);
TU_ASSERT(usbd_edpt_xfer(rhport, p_vendor->ep_out, _vendord_epbuf[idx].epout, rx_xfer_len, false), 0);
#endif
}
#endif
@ -367,7 +373,7 @@ bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint
// Non-FIFO mode: invoke callback with buffer
tud_vendor_rx_cb(idx, _vendord_epbuf[idx].epout, xferred_bytes);
#if CFG_TUD_VENDOR_RX_MANUAL_XFER == 0
usbd_edpt_xfer(rhport, p_vendor->ep_out, _vendord_epbuf[idx].epout, CFG_TUD_VENDOR_EPSIZE, false);
usbd_edpt_xfer(rhport, p_vendor->ep_out, _vendord_epbuf[idx].epout, p_vendor->rx_xfer_len, false);
#endif
} else if (ep_addr == p_vendor->ep_in) {
// Send complete

View File

@ -37,7 +37,7 @@ extern "C" {
// Configuration
//--------------------------------------------------------------------+
#ifndef CFG_TUD_VENDOR_EPSIZE
#define CFG_TUD_VENDOR_EPSIZE 64
#define CFG_TUD_VENDOR_EPSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
#endif
// RX FIFO can be disabled by setting this value to 0
@ -62,6 +62,21 @@ extern "C" {
#define CFG_TUD_VENDOR_RX_MANUAL_XFER 0
#endif
//--------------------------------------------------------------------+
// Driver Configuration
//--------------------------------------------------------------------+
typedef struct TU_ATTR_PACKED {
bool rx_multiple_packet_transfer : 1; // allow transfer more than one packet in a single transfer, increase throughput but requires host sending ZLP at the end of transfer
} tud_vendor_configure_t;
TU_VERIFY_STATIC(sizeof(tud_vendor_configure_t) == 1, "size is not correct");
#define TUD_VENDOR_CONFIGURE_DEFAULT() { \
.rx_multiple_packet_transfer = false, \
}
// Configure CDC driver behavior
bool tud_vendor_configure(const tud_vendor_configure_t* driver_cfg);
//--------------------------------------------------------------------+
// Application API (Multiple Interfaces) i.e CFG_TUD_VENDOR > 1
//--------------------------------------------------------------------+

View File

@ -62,7 +62,7 @@ typedef struct {
uint8_t ep_addr;
uint16_t mps;
uint16_t ep_bufsize;
uint16_t xfer_len;
uint8_t *ep_buf; // set to NULL to use xfer_fifo when CFG_TUD_EDPT_DEDICATED_HWFIFO = 1
tu_fifo_t ff;
@ -101,7 +101,7 @@ bool tu_edpt_release(tu_edpt_state_t* ep_state, osal_mutex_t mutex);
// Init an endpoint stream
bool tu_edpt_stream_init(tu_edpt_stream_t *s, bool is_host, bool is_tx, bool overwritable, void *ff_buf,
uint16_t ff_bufsize, uint8_t *ep_buf, uint16_t ep_bufsize);
uint16_t ff_bufsize, uint8_t *ep_buf);
// Deinit an endpoint stream
TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_deinit(tu_edpt_stream_t *s) {
@ -118,10 +118,11 @@ TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_deinit(tu_edpt_stream_t
// Open an endpoint stream
TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_open(tu_edpt_stream_t *s, uint8_t hwid,
const tusb_desc_endpoint_t *desc_ep) {
const tusb_desc_endpoint_t *desc_ep, uint16_t xfer_len) {
s->hwid = hwid;
s->ep_addr = desc_ep->bEndpointAddress;
s->mps = tu_edpt_packet_size(desc_ep);
s->xfer_len = xfer_len;
}
TU_ATTR_ALWAYS_INLINE static inline bool tu_edpt_stream_is_opened(const tu_edpt_stream_t *s) {

View File

@ -306,7 +306,7 @@ bool tu_bind_driver_to_ep_itf(uint8_t driver_id, uint8_t ep2drv[][2], uint8_t it
//--------------------------------------------------------------------+
bool tu_edpt_stream_init(tu_edpt_stream_t *s, bool is_host, bool is_tx, bool overwritable, void *ff_buf,
uint16_t ff_bufsize, uint8_t *ep_buf, uint16_t ep_bufsize) {
uint16_t ff_bufsize, uint8_t *ep_buf) {
(void) is_tx;
if (ff_buf == NULL || ff_bufsize == 0) {
@ -324,7 +324,6 @@ bool tu_edpt_stream_init(tu_edpt_stream_t *s, bool is_host, bool is_tx, bool ove
#endif
s->ep_buf = ep_buf;
s->ep_bufsize = ep_bufsize;
return true;
}
@ -394,7 +393,7 @@ uint32_t tu_edpt_stream_write_xfer(tu_edpt_stream_t *s) {
if (s->ep_buf == NULL) {
count = tu_fifo_count(&s->ff); // re-get count since fifo can be changed
} else {
count = tu_fifo_read_n(&s->ff, s->ep_buf, s->ep_bufsize);
count = tu_fifo_read_n(&s->ff, s->ep_buf, s->xfer_len);
}
if (count > 0) {
@ -441,7 +440,7 @@ uint32_t tu_edpt_stream_read_xfer(tu_edpt_stream_t *s) {
if (available >= s->mps) {
// multiple of packet size limit by ep bufsize
uint16_t count = (uint16_t) (available & ~(s->mps - 1));
count = tu_min16(count, s->ep_bufsize);
count = tu_min16(count, s->xfer_len);
TU_ASSERT(stream_xfer(s, count), 0);
return count;
} else {