summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorZixun LI <[email protected]>2025-12-02 12:00:59 +0100
committerZixun LI <[email protected]>2025-12-02 12:00:59 +0100
commit7a4af1e9b833d334cca8fa98bc200d4738cb6b82 (patch)
treed92ff05ba76c9f752a418089bad64cdc3c42535d /src
parent97c5151b34158f08fbfb51684cbfbc807abd77e5 (diff)
parent7ee288bc223db393d68c7bdb09bf7c05ffd2eb03 (diff)
Merge remote-tracking branch 'tinyusb/master' into hcd_fsdev
Diffstat (limited to 'src')
-rw-r--r--src/class/cdc/cdc_device.c11
-rw-r--r--src/class/vendor/vendor_device.c254
-rw-r--r--src/class/vendor/vendor_device.h132
-rw-r--r--src/common/tusb_fifo.c253
-rw-r--r--src/common/tusb_fifo.h38
-rw-r--r--src/common/tusb_private.h4
-rw-r--r--src/common/tusb_types.h5
-rw-r--r--src/portable/nordic/nrf5x/dcd_nrf5x.c47
-rw-r--r--src/tusb.c33
9 files changed, 416 insertions, 361 deletions
diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c
index 7ef8aa738..d7792afe4 100644
--- a/src/class/cdc/cdc_device.c
+++ b/src/class/cdc/cdc_device.c
@@ -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
diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c
index c7903375d..62e183465 100644
--- a/src/class/vendor/vendor_device.c
+++ b/src/class/vendor/vendor_device.c
@@ -42,43 +42,51 @@ typedef struct {
/*------------- From this point, data is not cleared by bus reset -------------*/
struct {
- tu_edpt_stream_t stream;
- #if CFG_TUD_VENDOR_TX_BUFSIZE > 0
- uint8_t ff_buf[CFG_TUD_VENDOR_TX_BUFSIZE];
- #endif
- } tx;
+ tu_edpt_stream_t tx;
+ tu_edpt_stream_t rx;
- struct {
- tu_edpt_stream_t stream;
- #if CFG_TUD_VENDOR_RX_BUFSIZE > 0
- uint8_t ff_buf[CFG_TUD_VENDOR_RX_BUFSIZE];
- #endif
- } rx;
+ #if CFG_TUD_VENDOR_TX_BUFSIZE > 0
+ uint8_t tx_ff_buf[CFG_TUD_VENDOR_TX_BUFSIZE];
+ #endif
+ #if CFG_TUD_VENDOR_RX_BUFSIZE > 0
+ uint8_t rx_ff_buf[CFG_TUD_VENDOR_RX_BUFSIZE];
+ #endif
+ } stream;
} vendord_interface_t;
-#define ITF_MEM_RESET_SIZE (offsetof(vendord_interface_t, itf_num) + sizeof(((vendord_interface_t *)0)->itf_num))
+#define ITF_MEM_RESET_SIZE (offsetof(vendord_interface_t, itf_num) + sizeof(((vendord_interface_t *)0)->itf_num))
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 itf, uint8_t const* buffer, uint16_t bufsize) {
- (void) itf;
- (void) buffer;
- (void) 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;
}
-TU_ATTR_WEAK void tud_vendor_tx_cb(uint8_t itf, uint32_t sent_bytes) {
- (void) itf;
+TU_ATTR_WEAK void tud_vendor_tx_cb(uint8_t idx, uint32_t sent_bytes) {
+ (void)idx;
(void) sent_bytes;
}
@@ -86,60 +94,79 @@ TU_ATTR_WEAK void tud_vendor_tx_cb(uint8_t itf, uint32_t sent_bytes) {
// Application API
//--------------------------------------------------------------------
-bool tud_vendor_n_mounted(uint8_t itf) {
- TU_VERIFY(itf < CFG_TUD_VENDOR);
- vendord_interface_t* p_itf = &_vendord_itf[itf];
- return p_itf->rx.stream.ep_addr || p_itf->tx.stream.ep_addr;
+bool tud_vendor_n_mounted(uint8_t idx) {
+ TU_VERIFY(idx < CFG_TUD_VENDOR);
+ vendord_interface_t *p_itf = &_vendord_itf[idx];
+ return p_itf->stream.rx.ep_addr || p_itf->stream.tx.ep_addr;
}
//--------------------------------------------------------------------+
// Read API
//--------------------------------------------------------------------+
-uint32_t tud_vendor_n_available(uint8_t itf) {
- TU_VERIFY(itf < CFG_TUD_VENDOR, 0);
- vendord_interface_t* p_itf = &_vendord_itf[itf];
- return tu_edpt_stream_read_available(&p_itf->rx.stream);
+#if CFG_TUD_VENDOR_RX_BUFSIZE > 0
+uint32_t tud_vendor_n_available(uint8_t idx) {
+ TU_VERIFY(idx < CFG_TUD_VENDOR, 0);
+ vendord_interface_t *p_itf = &_vendord_itf[idx];
+ return tu_edpt_stream_read_available(&p_itf->stream.rx);
}
-bool tud_vendor_n_peek(uint8_t itf, uint8_t* u8) {
- TU_VERIFY(itf < CFG_TUD_VENDOR);
- vendord_interface_t* p_itf = &_vendord_itf[itf];
- return tu_edpt_stream_peek(&p_itf->rx.stream, u8);
+bool tud_vendor_n_peek(uint8_t idx, uint8_t *u8) {
+ TU_VERIFY(idx < CFG_TUD_VENDOR);
+ vendord_interface_t *p_itf = &_vendord_itf[idx];
+ return tu_edpt_stream_peek(&p_itf->stream.rx, u8);
}
-uint32_t tud_vendor_n_read (uint8_t itf, void* buffer, uint32_t bufsize) {
- TU_VERIFY(itf < CFG_TUD_VENDOR, 0);
- vendord_interface_t* p_itf = &_vendord_itf[itf];
- return tu_edpt_stream_read(p_itf->rhport, &p_itf->rx.stream, buffer, bufsize);
+uint32_t tud_vendor_n_read(uint8_t idx, void *buffer, uint32_t bufsize) {
+ TU_VERIFY(idx < CFG_TUD_VENDOR, 0);
+ vendord_interface_t *p_itf = &_vendord_itf[idx];
+ return tu_edpt_stream_read(p_itf->rhport, &p_itf->stream.rx, buffer, bufsize);
}
-void tud_vendor_n_read_flush (uint8_t itf) {
- TU_VERIFY(itf < CFG_TUD_VENDOR, );
- vendord_interface_t* p_itf = &_vendord_itf[itf];
- tu_edpt_stream_clear(&p_itf->rx.stream);
- tu_edpt_stream_read_xfer(p_itf->rhport, &p_itf->rx.stream);
+uint32_t tud_vendor_n_read_discard(uint8_t idx, uint32_t count) {
+ TU_VERIFY(idx < CFG_TUD_VENDOR, 0);
+ vendord_interface_t *p_itf = &_vendord_itf[idx];
+ return tu_edpt_stream_discard(&p_itf->stream.rx, count);
}
+void tud_vendor_n_read_flush(uint8_t idx) {
+ TU_VERIFY(idx < CFG_TUD_VENDOR, );
+ vendord_interface_t *p_itf = &_vendord_itf[idx];
+ tu_edpt_stream_clear(&p_itf->stream.rx);
+ tu_edpt_stream_read_xfer(p_itf->rhport, &p_itf->stream.rx);
+}
+#endif
+
+#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];
+ return tu_edpt_stream_read_xfer(p_itf->rhport, &p_itf->stream.rx);
+}
+#endif
+
+
//--------------------------------------------------------------------+
// Write API
//--------------------------------------------------------------------+
-uint32_t tud_vendor_n_write (uint8_t itf, const void* buffer, uint32_t bufsize) {
- TU_VERIFY(itf < CFG_TUD_VENDOR, 0);
- vendord_interface_t* p_itf = &_vendord_itf[itf];
- return tu_edpt_stream_write(p_itf->rhport, &p_itf->tx.stream, buffer, (uint16_t)bufsize);
+uint32_t tud_vendor_n_write(uint8_t idx, const void *buffer, uint32_t bufsize) {
+ TU_VERIFY(idx < CFG_TUD_VENDOR, 0);
+ vendord_interface_t *p_itf = &_vendord_itf[idx];
+ return tu_edpt_stream_write(p_itf->rhport, &p_itf->stream.tx, buffer, (uint16_t)bufsize);
}
-uint32_t tud_vendor_n_write_flush (uint8_t itf) {
- TU_VERIFY(itf < CFG_TUD_VENDOR, 0);
- vendord_interface_t* p_itf = &_vendord_itf[itf];
- return tu_edpt_stream_write_xfer(p_itf->rhport, &p_itf->tx.stream);
+#if CFG_TUD_VENDOR_TX_BUFSIZE > 0
+uint32_t tud_vendor_n_write_flush(uint8_t idx) {
+ TU_VERIFY(idx < CFG_TUD_VENDOR, 0);
+ vendord_interface_t *p_itf = &_vendord_itf[idx];
+ return tu_edpt_stream_write_xfer(p_itf->rhport, &p_itf->stream.tx);
}
-uint32_t tud_vendor_n_write_available (uint8_t itf) {
- TU_VERIFY(itf < CFG_TUD_VENDOR, 0);
- vendord_interface_t* p_itf = &_vendord_itf[itf];
- return tu_edpt_stream_write_available(p_itf->rhport, &p_itf->tx.stream);
+uint32_t tud_vendor_n_write_available(uint8_t idx) {
+ TU_VERIFY(idx < CFG_TUD_VENDOR, 0);
+ vendord_interface_t *p_itf = &_vendord_itf[idx];
+ return tu_edpt_stream_write_available(p_itf->rhport, &p_itf->stream.tx);
}
+#endif
//--------------------------------------------------------------------+
// USBD Driver API
@@ -149,35 +176,45 @@ 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->rx.ff_buf;
+ uint8_t *rx_ff_buf = p_itf->stream.rx_ff_buf;
#else
uint8_t *rx_ff_buf = NULL;
#endif
- tu_edpt_stream_init(&p_itf->rx.stream, false, false, false,
- rx_ff_buf, CFG_TUD_VENDOR_RX_BUFSIZE,
- p_epbuf->epout, CFG_TUD_VENDOR_EPSIZE);
+ 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
- uint8_t *tx_ff_buf = p_itf->tx.ff_buf;
+ uint8_t *tx_ff_buf = p_itf->stream.tx_ff_buf;
#else
- uint8_t* tx_ff_buf = NULL;
+ uint8_t *tx_ff_buf = NULL;
#endif
- tu_edpt_stream_init(&p_itf->tx.stream, false, true, false,
- tx_ff_buf, CFG_TUD_VENDOR_TX_BUFSIZE,
- p_epbuf->epin, CFG_TUD_VENDOR_EPSIZE);
+ 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);
}
}
bool vendord_deinit(void) {
for(uint8_t i=0; i<CFG_TUD_VENDOR; i++) {
vendord_interface_t* p_itf = &_vendord_itf[i];
- tu_edpt_stream_deinit(&p_itf->rx.stream);
- tu_edpt_stream_deinit(&p_itf->tx.stream);
+ tu_edpt_stream_deinit(&p_itf->stream.rx);
+ tu_edpt_stream_deinit(&p_itf->stream.tx);
}
return true;
}
@@ -188,30 +225,42 @@ void vendord_reset(uint8_t rhport) {
for(uint8_t i=0; i<CFG_TUD_VENDOR; i++) {
vendord_interface_t* p_itf = &_vendord_itf[i];
tu_memclr(p_itf, ITF_MEM_RESET_SIZE);
- tu_edpt_stream_clear(&p_itf->rx.stream);
- tu_edpt_stream_close(&p_itf->rx.stream);
- tu_edpt_stream_clear(&p_itf->tx.stream);
- tu_edpt_stream_close(&p_itf->tx.stream);
+ tu_edpt_stream_clear(&p_itf->stream.rx);
+ tu_edpt_stream_close(&p_itf->stream.rx);
+
+ tu_edpt_stream_clear(&p_itf->stream.tx);
+ tu_edpt_stream_close(&p_itf->stream.tx);
}
}
-uint16_t vendord_open(uint8_t rhport, const tusb_desc_interface_t* desc_itf, uint16_t max_len) {
+// Find vendor interface by endpoint address
+static uint8_t find_vendor_itf(uint8_t ep_addr) {
+ for (uint8_t idx = 0; idx < CFG_TUD_VENDOR; idx++) {
+ const vendord_interface_t *p_vendor = &_vendord_itf[idx];
+ if (ep_addr == 0) {
+ // find unused: require both ep == 0
+ if (p_vendor->stream.rx.ep_addr == 0 && p_vendor->stream.tx.ep_addr == 0) {
+ return idx;
+ }
+ } else if (ep_addr == p_vendor->stream.rx.ep_addr || ep_addr == p_vendor->stream.tx.ep_addr) {
+ return idx;
+ } else {
+ // nothing to do
+ }
+ }
+ return 0xff;
+}
+
+uint16_t vendord_open(uint8_t rhport, const tusb_desc_interface_t *desc_itf, uint16_t max_len) {
TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == desc_itf->bInterfaceClass, 0);
const uint8_t* desc_end = (const uint8_t*)desc_itf + max_len;
const uint8_t* p_desc = tu_desc_next(desc_itf);
// Find available interface
- vendord_interface_t* p_vendor = NULL;
- uint8_t itf;
- for(itf=0; itf<CFG_TUD_VENDOR; itf++) {
- if (!tud_vendor_n_mounted(itf)) {
- p_vendor = &_vendord_itf[itf];
- break;
- }
- }
- TU_VERIFY(p_vendor, 0);
-
+ const uint8_t idx = find_vendor_itf(0);
+ TU_ASSERT(idx < CFG_TUD_VENDOR, 0);
+ vendord_interface_t *p_vendor = &_vendord_itf[idx];
p_vendor->rhport = rhport;
p_vendor->itf_num = desc_itf->bInterfaceNumber;
@@ -225,16 +274,18 @@ uint16_t vendord_open(uint8_t rhport, const tusb_desc_interface_t* desc_itf, uin
// open endpoint stream, skip if already opened (multiple IN/OUT endpoints)
if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) {
- tu_edpt_stream_t *stream_tx = &p_vendor->tx.stream;
+ tu_edpt_stream_t *stream_tx = &p_vendor->stream.tx;
if (stream_tx->ep_addr == 0) {
tu_edpt_stream_open(stream_tx, desc_ep);
tu_edpt_stream_write_xfer(rhport, stream_tx); // flush pending data
}
} else {
- tu_edpt_stream_t *stream_rx = &p_vendor->rx.stream;
+ tu_edpt_stream_t *stream_rx = &p_vendor->stream.rx;
if (stream_rx->ep_addr == 0) {
tu_edpt_stream_open(stream_rx, desc_ep);
+ #if CFG_TUD_VENDOR_RX_MANUAL_XFER == 0
TU_ASSERT(tu_edpt_stream_read_xfer(rhport, stream_rx) > 0, 0); // prepare for incoming data
+ #endif
}
}
}
@@ -247,38 +298,35 @@ uint16_t vendord_open(uint8_t rhport, const tusb_desc_interface_t* desc_itf, uin
bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) {
(void) result;
+ const uint8_t idx = find_vendor_itf(ep_addr);
+ TU_VERIFY(idx < CFG_TUD_VENDOR);
+ vendord_interface_t *p_vendor = &_vendord_itf[idx];
- uint8_t itf;
- vendord_interface_t* p_vendor;
-
- for (itf = 0; itf < CFG_TUD_VENDOR; itf++) {
- p_vendor = &_vendord_itf[itf];
- if ((ep_addr == p_vendor->rx.stream.ep_addr) || (ep_addr == p_vendor->tx.stream.ep_addr)) {
- break;
- }
- }
- TU_VERIFY(itf < CFG_TUD_VENDOR);
- vendord_epbuf_t* p_epbuf = &_vendord_epbuf[itf];
-
- if ( ep_addr == p_vendor->rx.stream.ep_addr ) {
+ 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->rx.stream, xferred_bytes);
+ tu_edpt_stream_read_xfer_complete(&p_vendor->stream.rx, xferred_bytes);
- // Invoked callback if any
- tud_vendor_rx_cb(itf, 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->rx.stream);
- } else if ( ep_addr == p_vendor->tx.stream.ep_addr ) {
+ #if CFG_TUD_VENDOR_RX_MANUAL_XFER == 0
+ tu_edpt_stream_read_xfer(rhport, &p_vendor->stream.rx); // prepare next data
+ #endif
+ } else if (ep_addr == p_vendor->stream.tx.ep_addr) {
// Send complete
- tud_vendor_tx_cb(itf, (uint16_t) xferred_bytes);
+ tud_vendor_tx_cb(idx, (uint16_t)xferred_bytes);
- #if CFG_TUD_VENDOR_TX_BUFSIZE > 0
+ #if CFG_TUD_VENDOR_TX_BUFSIZE > 0
// try to send more if possible
- if ( 0 == tu_edpt_stream_write_xfer(rhport, &p_vendor->tx.stream) ) {
+ if (0 == tu_edpt_stream_write_xfer(rhport, &p_vendor->stream.tx)) {
// If there is no data left, a ZLP should be sent if xferred_bytes is multiple of EP Packet size and not zero
- tu_edpt_stream_write_zlp_if_needed(rhport, &p_vendor->tx.stream, xferred_bytes);
+ tu_edpt_stream_write_zlp_if_needed(rhport, &p_vendor->stream.tx, xferred_bytes);
}
- #endif
+ #endif
}
return true;
diff --git a/src/class/vendor/vendor_device.h b/src/class/vendor/vendor_device.h
index 5376f3917..764d99070 100644
--- a/src/class/vendor/vendor_device.h
+++ b/src/class/vendor/vendor_device.h
@@ -27,87 +27,133 @@
#ifndef TUSB_VENDOR_DEVICE_H_
#define TUSB_VENDOR_DEVICE_H_
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include "common/tusb_common.h"
+//--------------------------------------------------------------------+
+// Configuration
+//--------------------------------------------------------------------+
#ifndef CFG_TUD_VENDOR_EPSIZE
-#define CFG_TUD_VENDOR_EPSIZE 64
+ #define CFG_TUD_VENDOR_EPSIZE 64
#endif
// RX FIFO can be disabled by setting this value to 0
#ifndef CFG_TUD_VENDOR_RX_BUFSIZE
-#define CFG_TUD_VENDOR_RX_BUFSIZE 64
+ #define CFG_TUD_VENDOR_RX_BUFSIZE 64
#endif
// TX FIFO can be disabled by setting this value to 0
#ifndef CFG_TUD_VENDOR_TX_BUFSIZE
-#define CFG_TUD_VENDOR_TX_BUFSIZE 64
+ #define CFG_TUD_VENDOR_TX_BUFSIZE 64
#endif
-#ifdef __cplusplus
- extern "C" {
+// Application will manually schedule RX transfer. This can be useful when using with non-fifo (buffered) mode
+// i.e. CFG_TUD_VENDOR_RX_BUFSIZE = 0
+#ifndef CFG_TUD_VENDOR_RX_MANUAL_XFER
+ #define CFG_TUD_VENDOR_RX_MANUAL_XFER 0
#endif
//--------------------------------------------------------------------+
// Application API (Multiple Interfaces) i.e CFG_TUD_VENDOR > 1
//--------------------------------------------------------------------+
-bool tud_vendor_n_mounted (uint8_t itf);
-uint32_t tud_vendor_n_available (uint8_t itf);
-uint32_t tud_vendor_n_read (uint8_t itf, void* buffer, uint32_t bufsize);
-bool tud_vendor_n_peek (uint8_t itf, uint8_t* ui8);
-void tud_vendor_n_read_flush (uint8_t itf);
-uint32_t tud_vendor_n_write (uint8_t itf, void const* buffer, uint32_t bufsize);
-uint32_t tud_vendor_n_write_flush (uint8_t itf);
-uint32_t tud_vendor_n_write_available (uint8_t itf);
+// Return whether the vendor interface is mounted
+bool tud_vendor_n_mounted(uint8_t idx);
+
+#if CFG_TUD_VENDOR_RX_BUFSIZE > 0
+// Return number of available bytes for reading
+uint32_t tud_vendor_n_available(uint8_t idx);
+
+// Peek a byte from RX buffer
+bool tud_vendor_n_peek(uint8_t idx, uint8_t *ui8);
+
+// Read from RX FIFO
+uint32_t tud_vendor_n_read(uint8_t idx, void *buffer, uint32_t bufsize);
-TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_n_write_str (uint8_t itf, char const* str);
+// Discard count bytes in RX FIFO
+uint32_t tud_vendor_n_read_discard(uint8_t idx, uint32_t count);
+
+// Flush (clear) RX FIFO
+void tud_vendor_n_read_flush(uint8_t idx);
+#endif
+
+#if CFG_TUD_VENDOR_RX_MANUAL_XFER
+// Start a new RX transfer to fill the RX FIFO, return false if previous transfer is still ongoing
+bool tud_vendor_n_read_xfer(uint8_t idx);
+#endif
+
+// Write to TX FIFO. This can be buffered and not sent immediately unless buffered bytes >= USB endpoint size
+uint32_t tud_vendor_n_write(uint8_t idx, const void *buffer, uint32_t bufsize);
+
+#if CFG_TUD_VENDOR_TX_BUFSIZE > 0
+// Force sending buffered data, return number of bytes sent
+uint32_t tud_vendor_n_write_flush(uint8_t idx);
+
+// Return number of bytes available for writing in TX FIFO
+uint32_t tud_vendor_n_write_available(uint8_t idx);
+#endif
+
+// Write a null-terminated string to TX FIFO
+TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_n_write_str(uint8_t idx, const char *str) {
+ return tud_vendor_n_write(idx, str, strlen(str));
+}
// backward compatible
-#define tud_vendor_n_flush(itf) tud_vendor_n_write_flush(itf)
+#define tud_vendor_n_flush(idx) tud_vendor_n_write_flush(idx)
//--------------------------------------------------------------------+
// Application API (Single Port) i.e CFG_TUD_VENDOR = 1
//--------------------------------------------------------------------+
-
-TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_n_write_str(uint8_t itf, char const* str) {
- return tud_vendor_n_write(itf, str, strlen(str));
-}
-
TU_ATTR_ALWAYS_INLINE static inline bool tud_vendor_mounted(void) {
- return tud_vendor_n_mounted(0);
+ return tud_vendor_n_mounted(0);
}
+#if CFG_TUD_VENDOR_RX_BUFSIZE > 0
TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_available(void) {
- return tud_vendor_n_available(0);
+ return tud_vendor_n_available(0);
}
-TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_read(void* buffer, uint32_t bufsize) {
- return tud_vendor_n_read(0, buffer, bufsize);
+TU_ATTR_ALWAYS_INLINE static inline bool tud_vendor_peek(uint8_t *ui8) {
+ return tud_vendor_n_peek(0, ui8);
}
-TU_ATTR_ALWAYS_INLINE static inline bool tud_vendor_peek(uint8_t* ui8) {
- return tud_vendor_n_peek(0, ui8);
+TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_read(void *buffer, uint32_t bufsize) {
+ return tud_vendor_n_read(0, buffer, bufsize);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_read_discard(uint32_t count) {
+ return tud_vendor_n_read_discard(0, count);
}
TU_ATTR_ALWAYS_INLINE static inline void tud_vendor_read_flush(void) {
- tud_vendor_n_read_flush(0);
+ tud_vendor_n_read_flush(0);
}
+#endif
-TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_write(void const* buffer, uint32_t bufsize) {
- return tud_vendor_n_write(0, buffer, bufsize);
+#if CFG_TUD_VENDOR_RX_MANUAL_XFER
+TU_ATTR_ALWAYS_INLINE static inline bool tud_vendor_read_xfer(void) {
+ return tud_vendor_n_read_xfer(0);
}
+#endif
-TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_write_str(char const* str) {
- return tud_vendor_n_write_str(0, str);
+TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_write(const void *buffer, uint32_t bufsize) {
+ return tud_vendor_n_write(0, buffer, bufsize);
}
-TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_write_flush(void) {
- return tud_vendor_n_write_flush(0);
+TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_write_str(const char *str) {
+ return tud_vendor_n_write_str(0, str);
}
#if CFG_TUD_VENDOR_TX_BUFSIZE > 0
+TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_write_flush(void) {
+ return tud_vendor_n_write_flush(0);
+}
+
TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_write_available(void) {
- return tud_vendor_n_write_available(0);
+ return tud_vendor_n_write_available(0);
}
#endif
@@ -118,15 +164,13 @@ 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 itf, uint8_t const* buffer, uint16_t bufsize);
-// Invoked when last rx transfer finished
-void tud_vendor_tx_cb(uint8_t itf, uint32_t sent_bytes);
-
-//--------------------------------------------------------------------+
-// Inline Functions
-//--------------------------------------------------------------------+
+// 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);
//--------------------------------------------------------------------+
// Internal Class Driver API
@@ -134,11 +178,11 @@ void tud_vendor_tx_cb(uint8_t itf, uint32_t sent_bytes);
void vendord_init(void);
bool vendord_deinit(void);
void vendord_reset(uint8_t rhport);
-uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
+uint16_t vendord_open(uint8_t rhport, const tusb_desc_interface_t *idx_desc, uint16_t max_len);
bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
#ifdef __cplusplus
- }
+}
#endif
#endif /* TUSB_VENDOR_DEVICE_H_ */
diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c
index 27b97310a..06b0d6a58 100644
--- a/src/common/tusb_fifo.c
+++ b/src/common/tusb_fifo.c
@@ -56,6 +56,9 @@ TU_ATTR_ALWAYS_INLINE static inline void ff_unlock(osal_mutex_t mutex) {
#endif
+//--------------------------------------------------------------------+
+// Setup API
+//--------------------------------------------------------------------+
bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, uint16_t item_size, bool overwritable) {
// Limit index space to 2*depth - this allows for a fast "modulo" calculation
// but limits the maximum depth to 2^16/2 = 2^15 and buffer overflows are detectable
@@ -80,6 +83,36 @@ bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, uint16_t item_si
return true;
}
+// clear fifo by resetting read and write indices
+bool tu_fifo_clear(tu_fifo_t *f) {
+ ff_lock(f->mutex_wr);
+ ff_lock(f->mutex_rd);
+
+ f->rd_idx = 0;
+ f->wr_idx = 0;
+
+ ff_unlock(f->mutex_wr);
+ ff_unlock(f->mutex_rd);
+ return true;
+}
+
+// Change the fifo overwritable mode
+bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) {
+ if (f->overwritable == overwritable) {
+ return true;
+ }
+
+ ff_lock(f->mutex_wr);
+ ff_lock(f->mutex_rd);
+
+ f->overwritable = overwritable;
+
+ ff_unlock(f->mutex_wr);
+ ff_unlock(f->mutex_rd);
+
+ return true;
+}
+
//--------------------------------------------------------------------+
// Pull & Push
// copy data to/from fifo without updating read/write pointers
@@ -295,49 +328,27 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t correct_read_index(tu_fifo_t *f, ui
return rd_idx;
}
-// peek() using local write/read index. Be careful, caller must not lock mutex, since this Will also try to lock mutex
-// in case of overflowed to correct read index
-static bool ff_peek_local(tu_fifo_t *f, void *buf, uint16_t wr_idx, uint16_t rd_idx) {
- const uint16_t ovf_count = tu_ff_overflow_count(f->depth, wr_idx, rd_idx);
- if (ovf_count == 0) {
- return false; // nothing to peek
- }
-
- // Correct read index if overflow
- if (ovf_count > f->depth) {
- ff_lock(f->mutex_rd);
- rd_idx = correct_read_index(f, wr_idx);
- ff_unlock(f->mutex_rd);
- }
-
- const uint16_t rd_ptr = idx2ptr(f->depth, rd_idx);
- memcpy(buf, f->buffer + (rd_ptr * f->item_size), f->item_size);
-
- return true;
-}
-
//--------------------------------------------------------------------+
-// Application API
+// n-API
//--------------------------------------------------------------------+
// Works on local copies of w and r
-// Must be protected by mutexes since in case of an overflow read pointer gets modified
+// Must be protected by read mutex since in case of an overflow read pointer gets modified
uint16_t tu_fifo_peek_n_access_mode(tu_fifo_t *f, void *p_buffer, uint16_t n, uint16_t wr_idx, uint16_t rd_idx,
tu_fifo_access_mode_t access_mode) {
- uint16_t ovf_cnt = tu_ff_overflow_count(f->depth, wr_idx, rd_idx);
-
- if (ovf_cnt == 0) {
+ uint16_t count = tu_ff_overflow_count(f->depth, wr_idx, rd_idx);
+ if (count == 0) {
return 0; // nothing to peek
}
// Check overflow and correct if required
- if (ovf_cnt > f->depth) {
+ if (count > f->depth) {
rd_idx = correct_read_index(f, wr_idx);
- ovf_cnt = f->depth;
+ count = f->depth;
}
- if (ovf_cnt < n) {
- n = ovf_cnt; // limit to available count
+ if (count < n) {
+ n = count; // limit to available count
}
const uint16_t rd_ptr = idx2ptr(f->depth, rd_idx);
@@ -346,6 +357,27 @@ uint16_t tu_fifo_peek_n_access_mode(tu_fifo_t *f, void *p_buffer, uint16_t n, ui
return n;
}
+// Read n items without removing it from the FIFO, correct read pointer if overflowed
+uint16_t tu_fifo_peek_n(tu_fifo_t *f, void *p_buffer, uint16_t n) {
+ ff_lock(f->mutex_rd);
+ const uint16_t ret = tu_fifo_peek_n_access_mode(f, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_INC_ADDR_RW8);
+ ff_unlock(f->mutex_rd);
+ return ret;
+}
+
+// Read n items from fifo with access mode
+uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, tu_fifo_access_mode_t access_mode) {
+ ff_lock(f->mutex_rd);
+
+ // Peek the data: f->rd_idx might get modified in case of an overflow so we can not use a local variable
+ n = tu_fifo_peek_n_access_mode(f, buffer, n, f->wr_idx, f->rd_idx, access_mode);
+ f->rd_idx = advance_index(f->depth, f->rd_idx, n);
+
+ ff_unlock(f->mutex_rd);
+ return n;
+}
+
+// Write n items to fifo with access mode
uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, tu_fifo_access_mode_t access_mode) {
if (n == 0) {
return 0;
@@ -419,40 +451,41 @@ uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n,
return n;
}
-uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, tu_fifo_access_mode_t access_mode) {
+uint16_t tu_fifo_discard_n(tu_fifo_t *f, uint16_t n) {
+ const uint16_t count = tu_min16(n, tu_fifo_count(f)); // limit to available count
ff_lock(f->mutex_rd);
-
- // Peek the data: f->rd_idx might get modified in case of an overflow so we can not use a local variable
- n = tu_fifo_peek_n_access_mode(f, buffer, n, f->wr_idx, f->rd_idx, access_mode);
- f->rd_idx = advance_index(f->depth, f->rd_idx, n);
-
+ f->rd_idx = advance_index(f->depth, f->rd_idx, count);
ff_unlock(f->mutex_rd);
- return n;
-}
-// Only use in case tu_fifo_overflow() returned true!
-void tu_fifo_correct_read_pointer(tu_fifo_t *f) {
- ff_lock(f->mutex_rd);
- correct_read_index(f, f->wr_idx);
- ff_unlock(f->mutex_rd);
+ return count;
}
-/******************************************************************************/
-/*!
- @brief Read one element out of the buffer.
+//--------------------------------------------------------------------+
+// One API
+//--------------------------------------------------------------------+
- This function will return the element located at the array index of the
- read pointer, and then increment the read pointer index.
- This function checks for an overflow and corrects read pointer if required.
+// peek() using local write/read index, correct read index if overflowed
+// Be careful, caller must not lock mutex, since this Will also try to lock mutex
+static bool ff_peek_local(tu_fifo_t *f, void *buf, uint16_t wr_idx, uint16_t rd_idx) {
+ const uint16_t ovf_count = tu_ff_overflow_count(f->depth, wr_idx, rd_idx);
+ if (ovf_count == 0) {
+ return false; // nothing to peek
+ }
- @param[in] f
- Pointer to the FIFO buffer to manipulate
- @param[in] buffer
- Pointer to the place holder for data read from the buffer
+ // Correct read index if overflow
+ if (ovf_count > f->depth) {
+ ff_lock(f->mutex_rd);
+ rd_idx = correct_read_index(f, wr_idx);
+ ff_unlock(f->mutex_rd);
+ }
- @returns TRUE if the queue is not empty
- */
-/******************************************************************************/
+ const uint16_t rd_ptr = idx2ptr(f->depth, rd_idx);
+ memcpy(buf, f->buffer + (rd_ptr * f->item_size), f->item_size);
+
+ return true;
+}
+
+// Read one element out of the buffer, correct read index if overflowed
bool tu_fifo_read(tu_fifo_t *f, void *buffer) {
// Peek the data
// f->rd_idx might get modified in case of an overflow so we can not use a local variable
@@ -466,61 +499,12 @@ bool tu_fifo_read(tu_fifo_t *f, void *buffer) {
return ret;
}
-/******************************************************************************/
-/*!
- @brief Read one item without removing it from the FIFO.
- This function checks for an overflow and corrects read pointer if required.
-
- @param[in] f
- Pointer to the FIFO buffer to manipulate
- @param[in] p_buffer
- Pointer to the place holder for data read from the buffer
-
- @returns TRUE if the queue is not empty
- */
-/******************************************************************************/
+// Read one item without removing it from the FIFO, correct read index if overflowed
bool tu_fifo_peek(tu_fifo_t *f, void *p_buffer) {
return ff_peek_local(f, p_buffer, f->wr_idx, f->rd_idx);
}
-/******************************************************************************/
-/*!
- @brief Read n items without removing it from the FIFO
- This function checks for an overflow and corrects read pointer if required.
-
- @param[in] f
- Pointer to the FIFO buffer to manipulate
- @param[in] p_buffer
- Pointer to the place holder for data read from the buffer
- @param[in] n
- Number of items to peek
-
- @returns Number of bytes written to p_buffer
- */
-/******************************************************************************/
-uint16_t tu_fifo_peek_n(tu_fifo_t *f, void *p_buffer, uint16_t n) {
- ff_lock(f->mutex_rd);
- const uint16_t ret = tu_fifo_peek_n_access_mode(f, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_INC_ADDR_RW8);
- ff_unlock(f->mutex_rd);
- return ret;
-}
-
-/******************************************************************************/
-/*!
- @brief Write one element into the buffer.
-
- This function will write one element into the array index specified by
- the write pointer and increment the write index.
-
- @param[in] f
- Pointer to the FIFO buffer to manipulate
- @param[in] data
- The byte to add to the FIFO
-
- @returns TRUE if the data was written to the FIFO (overwrittable
- FIFO will always return TRUE)
- */
-/******************************************************************************/
+// Write one element into the buffer
bool tu_fifo_write(tu_fifo_t *f, const void *data) {
bool ret;
ff_lock(f->mutex_wr);
@@ -541,51 +525,9 @@ bool tu_fifo_write(tu_fifo_t *f, const void *data) {
return ret;
}
-/******************************************************************************/
-/*!
- @brief Clear the fifo read and write pointers
-
- @param[in] f
- Pointer to the FIFO buffer to manipulate
- */
-/******************************************************************************/
-bool tu_fifo_clear(tu_fifo_t *f) {
- ff_lock(f->mutex_wr);
- ff_lock(f->mutex_rd);
-
- f->rd_idx = 0;
- f->wr_idx = 0;
-
- ff_unlock(f->mutex_wr);
- ff_unlock(f->mutex_rd);
- return true;
-}
-
-/******************************************************************************/
-/*!
- @brief Change the fifo mode to overwritable or not overwritable
-
- @param[in] f
- Pointer to the FIFO buffer to manipulate
- @param[in] overwritable
- Overwritable mode the fifo is set to
- */
-/******************************************************************************/
-bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) {
- if (f->overwritable == overwritable) {
- return true;
- }
-
- ff_lock(f->mutex_wr);
- ff_lock(f->mutex_rd);
-
- f->overwritable = overwritable;
-
- ff_unlock(f->mutex_wr);
- ff_unlock(f->mutex_rd);
-
- return true;
-}
+//--------------------------------------------------------------------+
+// Index API
+//--------------------------------------------------------------------+
/******************************************************************************/
/*!
@@ -607,6 +549,13 @@ void tu_fifo_advance_write_pointer(tu_fifo_t *f, uint16_t n) {
f->wr_idx = advance_index(f->depth, f->wr_idx, n);
}
+// Correct the read index in case tu_fifo_overflow() returned true!
+void tu_fifo_correct_read_pointer(tu_fifo_t *f) {
+ ff_lock(f->mutex_rd);
+ correct_read_index(f, f->wr_idx);
+ ff_unlock(f->mutex_rd);
+}
+
/******************************************************************************/
/*!
@brief Advance read pointer - intended to be used in combination with DMA.
diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h
index 4d8448c44..42f154bca 100644
--- a/src/common/tusb_fifo.h
+++ b/src/common/tusb_fifo.h
@@ -156,9 +156,9 @@ typedef enum {
//--------------------------------------------------------------------+
// Setup API
//--------------------------------------------------------------------+
+bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, uint16_t item_size, bool overwritable);
bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable);
bool tu_fifo_clear(tu_fifo_t *f);
-bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable);
#if OSAL_MUTEX_REQUIRED
TU_ATTR_ALWAYS_INLINE static inline
@@ -171,6 +171,22 @@ void tu_fifo_config_mutex(tu_fifo_t *f, osal_mutex_t wr_mutex, osal_mutex_t rd_m
#endif
//--------------------------------------------------------------------+
+// Index API
+//--------------------------------------------------------------------+
+void tu_fifo_correct_read_pointer(tu_fifo_t *f);
+
+// Pointer modifications intended to be used in combinations with DMAs.
+// USE WITH CARE - NO SAFETY CHECKS CONDUCTED HERE! NOT MUTEX PROTECTED!
+void tu_fifo_advance_write_pointer(tu_fifo_t *f, uint16_t n);
+void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n);
+
+// If you want to read/write from/to the FIFO by use of a DMA, you may need to conduct two copies
+// to handle a possible wrapping part. These functions deliver a pointer to start
+// reading/writing from/to and a valid linear length along which no wrap occurs.
+void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info);
+void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info);
+
+//--------------------------------------------------------------------+
// Peek API
// peek() will correct/re-index read pointer in case of an overflowed fifo to form a full fifo
//--------------------------------------------------------------------+
@@ -189,6 +205,10 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_read_n(tu_fifo_t *f, void *
return tu_fifo_read_n_access_mode(f, buffer, n, TU_FIFO_INC_ADDR_RW8);
}
+// discard first n items from fifo i.e advance read pointer by n with mutex
+// return number of discarded items
+uint16_t tu_fifo_discard_n(tu_fifo_t *f, uint16_t n);
+
//--------------------------------------------------------------------+
// Write API
//--------------------------------------------------------------------+
@@ -199,22 +219,6 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const
}
//--------------------------------------------------------------------+
-// Index API
-//--------------------------------------------------------------------+
-void tu_fifo_correct_read_pointer(tu_fifo_t *f);
-
-// Pointer modifications intended to be used in combinations with DMAs.
-// USE WITH CARE - NO SAFETY CHECKS CONDUCTED HERE! NOT MUTEX PROTECTED!
-void tu_fifo_advance_write_pointer(tu_fifo_t *f, uint16_t n);
-void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n);
-
-// If you want to read/write from/to the FIFO by use of a DMA, you may need to conduct two copies
-// to handle a possible wrapping part. These functions deliver a pointer to start
-// reading/writing from/to and a valid linear length along which no wrap occurs.
-void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info);
-void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info);
-
-//--------------------------------------------------------------------+
// Internal Helper Local
// work on local copies of read/write indices in order to only access them once for re-entrancy
//--------------------------------------------------------------------+
diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h
index 48fd1d6d2..8643bb020 100644
--- a/src/common/tusb_private.h
+++ b/src/common/tusb_private.h
@@ -172,6 +172,10 @@ TU_ATTR_ALWAYS_INLINE static inline bool tu_edpt_stream_peek(tu_edpt_stream_t *s
return tu_fifo_peek(&s->ff, ch);
}
+TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_edpt_stream_discard(tu_edpt_stream_t *s, uint32_t len) {
+ return (uint32_t)tu_fifo_discard_n(&s->ff, (uint16_t)len);
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h
index 73c816e3e..d473e53e6 100644
--- a/src/common/tusb_types.h
+++ b/src/common/tusb_types.h
@@ -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
//--------------------------------------------------------------------+
diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c
index 82b6db5fd..8a41c4790 100644
--- a/src/portable/nordic/nrf5x/dcd_nrf5x.c
+++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c
@@ -59,21 +59,26 @@
/* Try to detect nrfx version if not configured with CFG_TUD_NRF_NRFX_VERSION
* nrfx v1 and v2 are concurrently developed. There is no NRFX_VERSION only MDK VERSION which is as follows:
* - v3.0.0: 8.53.1 (conflict with v2.11.0), v3.1.0: 8.55.0 ...
- * - v2.11.0: 8.53.1, v2.6.0: 8.44.1, v2.5.0: 8.40.2, v2.4.0: 8.37.0, v2.3.0: 8.35.0, v2.2.0: 8.32.1, v2.1.0: 8.30.2, v2.0.0: 8.29.0
+ * - v2.11.0: 8.53.1, v2.6.0: 8.44.1, v2.5.0: 8.40.2, v2.4.0: 8.37.0, v2.3.0: 8.35.0, v2.2.0: 8.32.1, v2.1.0: 8.30.2,
+ * v2.0.0: 8.29.0
* - v1.9.0: 8.40.3, v1.8.6: 8.35.0 (conflict with v2.3.0), v1.8.5: 8.32.3, v1.8.4: 8.32.1 (conflict with v2.2.0),
* v1.8.2: 8.32.1 (conflict with v2.2.0), v1.8.1: 8.27.1
* Therefore the check for v1 would be:
* - MDK < 8.29.0 (v2.0), MDK == 8.32.3, 8.40.3
* - in case of conflict User of those version must upgrade to other 1.x version or set CFG_TUD_NRF_NRFX_VERSION
-*/
+ */
#ifndef CFG_TUD_NRF_NRFX_VERSION
- #define _MDK_VERSION (10000*MDK_MAJOR_VERSION + 100*MDK_MINOR_VERSION + MDK_MICRO_VERSION)
+ #define MDK_VERSION (10000 * MDK_MAJOR_VERSION + 100 * MDK_MINOR_VERSION + MDK_MICRO_VERSION)
- #if _MDK_VERSION < 82900 || _MDK_VERSION == 83203 || _MDK_VERSION == 84003
+ #if MDK_VERSION < 82900 || MDK_VERSION == 83203 || MDK_VERSION == 84003
// nrfx <= 1.8.1, or 1.8.5 or 1.9.0
#define CFG_TUD_NRF_NRFX_VERSION 1
- #else
+ #elif MDK_VERSION < 85301
#define CFG_TUD_NRF_NRFX_VERSION 2
+ #elif MDK_VERSION < 87300
+ #define CFG_TUD_NRF_NRFX_VERSION 3
+ #else
+ #define CFG_TUD_NRF_NRFX_VERSION 4
#endif
#endif
@@ -845,19 +850,19 @@ TU_ATTR_ALWAYS_INLINE static inline bool is_sd_enabled(void) {
#endif
static bool hfclk_running(void) {
-#ifdef SOFTDEVICE_PRESENT
- if ( is_sd_enabled() ) {
+ #ifdef SOFTDEVICE_PRESENT
+ if (is_sd_enabled()) {
uint32_t is_running = 0;
- (void) sd_clock_hfclk_is_running(&is_running);
+ (void)sd_clock_hfclk_is_running(&is_running);
return (is_running ? true : false);
}
-#endif
+ #endif
-#if CFG_TUD_NRF_NRFX_VERSION == 1
+ #if CFG_TUD_NRF_NRFX_VERSION == 1
return nrf_clock_hf_is_running(NRF_CLOCK_HFCLK_HIGH_ACCURACY);
-#else
- return nrf_clock_hf_is_running(NRF_CLOCK, NRF_CLOCK_HFCLK_HIGH_ACCURACY);
-#endif
+ #else
+ return nrf_clock_is_running(NRF_CLOCK, NRF_CLOCK_DOMAIN_HFCLK, NULL);
+ #endif
}
static void hfclk_enable(void) {
@@ -867,22 +872,24 @@ static void hfclk_enable(void) {
#else
// already running, nothing to do
- if (hfclk_running()) return;
+ if (hfclk_running()) {
+ return;
+ }
-#ifdef SOFTDEVICE_PRESENT
- if ( is_sd_enabled() ) {
+ #ifdef SOFTDEVICE_PRESENT
+ if (is_sd_enabled()) {
(void)sd_clock_hfclk_request();
return;
}
-#endif
+ #endif
-#if CFG_TUD_NRF_NRFX_VERSION == 1
+ #if CFG_TUD_NRF_NRFX_VERSION == 1
nrf_clock_event_clear(NRF_CLOCK_EVENT_HFCLKSTARTED);
nrf_clock_task_trigger(NRF_CLOCK_TASK_HFCLKSTART);
-#else
+ #else
nrf_clock_event_clear(NRF_CLOCK, NRF_CLOCK_EVENT_HFCLKSTARTED);
nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_HFCLKSTART);
-#endif
+ #endif
#endif
}
diff --git a/src/tusb.c b/src/tusb.c
index c589e105e..b6cfd1260 100644
--- a/src/tusb.c
+++ b/src/tusb.c
@@ -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
@@ -528,15 +533,7 @@ uint32_t tu_edpt_stream_read_xfer(uint8_t hwid, tu_edpt_stream_t* s) {
}
uint32_t tu_edpt_stream_read(uint8_t hwid, tu_edpt_stream_t* s, void* buffer, uint32_t bufsize) {
- uint32_t num_read;
- if (tu_fifo_depth(&s->ff) > 0) {
- num_read = tu_fifo_read_n(&s->ff, buffer, (uint16_t)bufsize);
- } else {
- // non-fifo mode
- memcpy(buffer, s->ep_buf, bufsize);
- num_read = bufsize;
- }
-
+ const uint32_t num_read = tu_fifo_read_n(&s->ff, buffer, (uint16_t)bufsize);
tu_edpt_stream_read_xfer(hwid, s);
return num_read;
}