change tud_vendor_rx_cb() behavior, buffer and bufsize only available when CFG_TUD_VENDOR_RX_BUFSIZE = 0

update vendor device to omit ep buf when dedicated hwfifo is supported
This commit is contained in:
hathach
2025-11-27 18:41:57 +07:00
parent f3dc2186ae
commit 9a9bf0fd7b
6 changed files with 73 additions and 37 deletions

View File

@ -211,15 +211,16 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ
return false;
}
void tud_vendor_rx_cb(uint8_t idx, const uint8_t *buffer, uint16_t bufsize) {
void tud_vendor_rx_cb(uint8_t idx, const uint8_t *buffer, uint32_t bufsize) {
(void)idx;
(void)buffer;
(void)bufsize;
// since we used data without pulling it from RX FIFO, we need to discard number of items used
#if CFG_TUD_VENDOR_RX_BUFSIZE > 0
tud_vendor_read_discard(bufsize);
#endif
echo_all(buffer, bufsize);
while (tud_vendor_available()) {
uint8_t buf[64];
const uint32_t count = tud_vendor_read(buf, sizeof(buf));
echo_all(buf, count);
}
}
//--------------------------------------------------------------------+

View File

@ -266,9 +266,8 @@ void cdcd_init(void) {
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;
uint8_t *epout_buf = _cdcd_epbuf[i].epout;
uint8_t *epin_buf = _cdcd_epbuf[i].epin;
#endif
tu_edpt_stream_init(&p_cdc->stream.rx, false, false, false, p_cdc->stream.rx_ff_buf, CFG_TUD_CDC_RX_BUFSIZE,
@ -516,11 +515,9 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_
}
// Data sent to host, we continue to fetch from tx fifo to send.
// Note: This will cause incorrect baudrate set in line coding.
// Though maybe the baudrate is not really important !!!
// Note: This will cause incorrect baudrate set in line coding. Though maybe the baudrate is not really important !
if (ep_addr == stream_tx->ep_addr) {
// invoke transmit callback to possibly refill tx fifo
tud_cdc_tx_complete_cb(itf);
tud_cdc_tx_complete_cb(itf); // invoke callback to possibly refill tx fifo
if (0 == tu_edpt_stream_write_xfer(rhport, stream_tx)) {
// If there is no data left, a ZLP should be sent if needed

View File

@ -59,20 +59,30 @@ typedef struct {
static vendord_interface_t _vendord_itf[CFG_TUD_VENDOR];
#if CFG_TUD_EDPT_DEDICATED_HWFIFO == 0 || CFG_TUD_VENDOR_RX_BUFSIZE == 0
typedef struct {
// Skip local EP buffer if dedicated hw FIFO is supported
#if CFG_TUD_EDPT_DEDICATED_HWFIFO == 0 || CFG_TUD_VENDOR_RX_BUFSIZE == 0
TUD_EPBUF_DEF(epout, CFG_TUD_VENDOR_EPSIZE);
#endif
// Skip local EP buffer if dedicated hw FIFO is supported
#if CFG_TUD_EDPT_DEDICATED_HWFIFO == 0
TUD_EPBUF_DEF(epin, CFG_TUD_VENDOR_EPSIZE);
#endif
} vendord_epbuf_t;
CFG_TUD_MEM_SECTION static vendord_epbuf_t _vendord_epbuf[CFG_TUD_VENDOR];
#endif
//--------------------------------------------------------------------+
// Weak stubs: invoked if no strong implementation is available
//--------------------------------------------------------------------+
TU_ATTR_WEAK void tud_vendor_rx_cb(uint8_t idx, const uint8_t *buffer, uint16_t bufsize) {
TU_ATTR_WEAK void tud_vendor_rx_cb(uint8_t idx, const uint8_t *buffer, uint32_t bufsize) {
(void)idx;
(void) buffer;
(void) bufsize;
(void)buffer;
(void)bufsize;
}
TU_ATTR_WEAK void tud_vendor_tx_cb(uint8_t idx, uint32_t sent_bytes) {
@ -153,7 +163,19 @@ void vendord_init(void) {
for(uint8_t i=0; i<CFG_TUD_VENDOR; i++) {
vendord_interface_t* p_itf = &_vendord_itf[i];
vendord_epbuf_t* p_epbuf = &_vendord_epbuf[i];
#if CFG_TUD_EDPT_DEDICATED_HWFIFO
#if CFG_TUD_VENDOR_RX_BUFSIZE == 0 // non-fifo rx still need ep buffer
uint8_t *epout_buf = _vendord_epbuf[i].epout;
#else
uint8_t *epout_buf = NULL;
#endif
uint8_t *epin_buf = NULL;
#else
uint8_t *epout_buf = _vendord_epbuf[i].epout;
uint8_t *epin_buf = _vendord_epbuf[i].epin;
#endif
#if CFG_TUD_VENDOR_RX_BUFSIZE > 0
uint8_t *rx_ff_buf = p_itf->stream.rx_ff_buf;
@ -161,7 +183,7 @@ void vendord_init(void) {
uint8_t *rx_ff_buf = NULL;
#endif
tu_edpt_stream_init(&p_itf->stream.rx, false, false, false, rx_ff_buf, CFG_TUD_VENDOR_RX_BUFSIZE, p_epbuf->epout,
tu_edpt_stream_init(&p_itf->stream.rx, false, false, false, rx_ff_buf, CFG_TUD_VENDOR_RX_BUFSIZE, epout_buf,
CFG_TUD_VENDOR_EPSIZE);
#if CFG_TUD_VENDOR_TX_BUFSIZE > 0
@ -170,7 +192,7 @@ void vendord_init(void) {
uint8_t *tx_ff_buf = NULL;
#endif
tu_edpt_stream_init(&p_itf->stream.tx, false, true, false, tx_ff_buf, CFG_TUD_VENDOR_TX_BUFSIZE, p_epbuf->epin,
tu_edpt_stream_init(&p_itf->stream.tx, false, true, false, tx_ff_buf, CFG_TUD_VENDOR_TX_BUFSIZE, epin_buf,
CFG_TUD_VENDOR_EPSIZE);
}
}
@ -264,16 +286,19 @@ bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint
const uint8_t idx = find_vendor_itf(ep_addr);
TU_VERIFY(idx < CFG_TUD_VENDOR);
vendord_interface_t *p_vendor = &_vendord_itf[idx];
vendord_epbuf_t *p_epbuf = &_vendord_epbuf[idx];
if (ep_addr == p_vendor->stream.rx.ep_addr) {
// Received new data: put into stream's fifo
tu_edpt_stream_read_xfer_complete(&p_vendor->stream.rx, xferred_bytes);
// Invoked callback if any
tud_vendor_rx_cb(idx, p_epbuf->epout, (uint16_t)xferred_bytes);
// invoke callback
#if CFG_TUD_VENDOR_RX_BUFSIZE == 0
tud_vendor_rx_cb(idx, p_vendor->stream.rx.ep_buf, xferred_bytes);
#else
tud_vendor_rx_cb(idx, NULL, 0);
#endif
tu_edpt_stream_read_xfer(rhport, &p_vendor->stream.rx);
tu_edpt_stream_read_xfer(rhport, &p_vendor->stream.rx); // prepare next data
} else if (ep_addr == p_vendor->stream.tx.ep_addr) {
// Send complete
tud_vendor_tx_cb(idx, (uint16_t)xferred_bytes);

View File

@ -121,9 +121,12 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_write_available(void) {
// Application Callback API (weak is optional)
//--------------------------------------------------------------------+
// Invoked when received new data
void tud_vendor_rx_cb(uint8_t idx, const uint8_t *buffer, uint16_t bufsize);
// Invoked when last rx transfer finished
// Invoked when received new data.
// - CFG_TUD_VENDOR_RX_BUFSIZE > 0; buffer and bufsize must not be used (both NULL,0) since data is in RX FIFO
// - CFG_TUD_VENDOR_RX_BUFSIZE = 0: Buffer and bufsize are valid
void tud_vendor_rx_cb(uint8_t idx, const uint8_t *buffer, uint32_t bufsize);
// Invoked when tx transfer is finished
void tud_vendor_tx_cb(uint8_t idx, uint32_t sent_bytes);
//--------------------------------------------------------------------+

View File

@ -323,6 +323,11 @@ typedef struct {
tusb_speed_t speed;
} tusb_rhport_init_t;
typedef struct {
uint16_t len;
uint8_t *buffer;
} tusb_buffer_t;
//--------------------------------------------------------------------+
// USB Descriptors
//--------------------------------------------------------------------+

View File

@ -450,12 +450,19 @@ uint32_t tu_edpt_stream_write(uint8_t hwid, tu_edpt_stream_t *s, const void *buf
TU_VERIFY(bufsize > 0); // TODO support ZLP
if (0 == tu_fifo_depth(&s->ff)) {
// non-fifo mode, ep_buf must be valid
TU_VERIFY(s->ep_buf != NULL, 0);
// non-fifo mode
TU_VERIFY(stream_claim(hwid, s), 0);
const uint32_t xact_len = tu_min32(bufsize, s->ep_bufsize);
memcpy(s->ep_buf, buffer, xact_len);
uint32_t xact_len;
if (s->ep_buf != NULL) {
// using ep buf
xact_len = tu_min32(bufsize, s->ep_bufsize);
memcpy(s->ep_buf, buffer, xact_len);
} else {
// using hwfifo
xact_len = bufsize;
}
TU_ASSERT(stream_xfer(hwid, s, (uint16_t) xact_len), 0);
return xact_len;
} else {
const uint16_t ret = tu_fifo_write_n(&s->ff, buffer, (uint16_t) bufsize);
@ -494,7 +501,8 @@ uint32_t tu_edpt_stream_write_available(uint8_t hwid, tu_edpt_stream_t* s) {
//--------------------------------------------------------------------+
uint32_t tu_edpt_stream_read_xfer(uint8_t hwid, tu_edpt_stream_t* s) {
if (0 == tu_fifo_depth(&s->ff)) {
// non-fifo mode
// non-fifo mode: RX need ep buffer
TU_VERIFY(s->ep_buf != NULL, 0);
TU_VERIFY(stream_claim(hwid, s), 0);
TU_ASSERT(stream_xfer(hwid, s, s->ep_bufsize), 0);
return s->ep_bufsize;
@ -507,11 +515,8 @@ uint32_t tu_edpt_stream_read_xfer(uint8_t hwid, tu_edpt_stream_t* s) {
// and slowly move it to the FIFO when read().
// This pre-check reduces endpoint claiming
TU_VERIFY(available >= mps);
TU_VERIFY(stream_claim(hwid, s), 0);
// get available again since fifo can be changed before endpoint is claimed
available = tu_fifo_remaining(&s->ff);
available = tu_fifo_remaining(&s->ff); // re-get available since fifo can be changed
if (available >= mps) {
// multiple of packet size limit by ep bufsize
@ -532,7 +537,7 @@ uint32_t tu_edpt_stream_read(uint8_t hwid, tu_edpt_stream_t* s, void* buffer, ui
if (tu_fifo_depth(&s->ff) > 0) {
num_read = tu_fifo_read_n(&s->ff, buffer, (uint16_t)bufsize);
} else {
// non-fifo mode
// non-fifo mode not support this
num_read = 0;
}