summaryrefslogtreecommitdiff
path: root/src/class/vendor
diff options
context:
space:
mode:
authorHiFiPhile <[email protected]>2026-06-22 21:30:58 +0200
committerHiFiPhile <[email protected]>2026-06-22 21:30:58 +0200
commit693cdce08e14833f26f4e8a1f26e4fd546be4c35 (patch)
tree7667d2223dc32d9f21b5b60ab200e64ed46e3e20 /src/class/vendor
parent41e9eaa65a935136085d78ec4b99c81ff991b560 (diff)
parentcd3561bf158afd5a5718904b8139a338d1e3b67c (diff)
Merge remote-tracking branch 'tinyusb/master' into pr-osal-spin-deinit
Signed-off-by: HiFiPhile <[email protected]>
Diffstat (limited to 'src/class/vendor')
-rw-r--r--src/class/vendor/vendor_device.c367
-rw-r--r--src/class/vendor/vendor_device.h167
-rw-r--r--src/class/vendor/vendor_host.h6
3 files changed, 344 insertions, 196 deletions
diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c
index 27724b194..e1017ba48 100644
--- a/src/class/vendor/vendor_device.c
+++ b/src/class/vendor/vendor_device.c
@@ -37,120 +37,160 @@
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
typedef struct {
+ uint8_t rhport;
uint8_t itf_num;
+ #if CFG_TUD_VENDOR_TXRX_BUFFERED
/*------------- 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;
-
- struct {
- tu_edpt_stream_t stream;
- #if CFG_TUD_VENDOR_RX_BUFSIZE > 0
- uint8_t ff_buf[CFG_TUD_VENDOR_RX_BUFSIZE];
- #endif
- } rx;
-
+ tu_edpt_stream_t tx_stream;
+ tu_edpt_stream_t rx_stream;
+ uint8_t tx_ff_buf[CFG_TUD_VENDOR_TX_BUFSIZE];
+ uint8_t rx_ff_buf[CFG_TUD_VENDOR_RX_BUFSIZE];
+ #else
+ uint8_t ep_in;
+ uint8_t ep_out;
+ uint16_t rx_xfer_len;
+ #endif
} vendord_interface_t;
-#define ITF_MEM_RESET_SIZE (offsetof(vendord_interface_t, itf_num) + sizeof(((vendord_interface_t *)0)->itf_num))
+ #if CFG_TUD_VENDOR_TXRX_BUFFERED
+ #define ITF_MEM_RESET_SIZE (offsetof(vendord_interface_t, itf_num) + TU_FIELD_SIZE(vendord_interface_t, itf_num))
+ #else
+ #define ITF_MEM_RESET_SIZE sizeof(vendord_interface_t)
+ #endif
static vendord_interface_t _vendord_itf[CFG_TUD_VENDOR];
+// Skip local EP buffer if dedicated hw FIFO is supported or no fifo mode
+#if CFG_TUD_EDPT_DEDICATED_HWFIFO == 0 || !CFG_TUD_VENDOR_TXRX_BUFFERED
typedef struct {
- TUD_EPBUF_DEF(epout, CFG_TUD_VENDOR_EPSIZE);
- TUD_EPBUF_DEF(epin, CFG_TUD_VENDOR_EPSIZE);
+ TUD_EPBUF_DEF(epout, CFG_TUD_VENDOR_RX_EPSIZE);
+ TUD_EPBUF_DEF(epin, CFG_TUD_VENDOR_TX_EPSIZE);
} 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;
}
-//--------------------------------------------------------------------
-// Application API
-//--------------------------------------------------------------------
+bool tud_vendor_n_mounted(uint8_t idx) {
+ TU_VERIFY(idx < CFG_TUD_VENDOR);
+ vendord_interface_t *p_itf = &_vendord_itf[idx];
-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;
+ #if CFG_TUD_VENDOR_TXRX_BUFFERED
+ return (p_itf->rx_stream.ep_addr != 0) || (p_itf->tx_stream.ep_addr != 0);
+ #else
+ return (p_itf->ep_out != 0) || (p_itf->ep_in != 0);
+ #endif
}
//--------------------------------------------------------------------+
// 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_TXRX_BUFFERED
+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->rx_stream);
}
-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->rx_stream, 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];
- const uint8_t rhport = 0;
+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->rx_stream, buffer, bufsize);
+}
- return tu_edpt_stream_read(rhport, &p_itf->rx.stream, buffer, bufsize);
+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->rx_stream);
+ tu_edpt_stream_read_xfer(&p_itf->rx_stream);
}
+ #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];
-void tud_vendor_n_read_flush (uint8_t itf) {
- TU_VERIFY(itf < CFG_TUD_VENDOR, );
- vendord_interface_t* p_itf = &_vendord_itf[itf];
- const uint8_t rhport = 0;
+ #if CFG_TUD_VENDOR_TXRX_BUFFERED
+ return tu_edpt_stream_read_xfer(&p_itf->rx_stream);
- tu_edpt_stream_clear(&p_itf->rx.stream);
- tu_edpt_stream_read_xfer(rhport, &p_itf->rx.stream);
+ #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, p_itf->rx_xfer_len, false);
+ #endif
}
+ #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];
- const uint8_t rhport = 0;
+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];
+
+ #if CFG_TUD_VENDOR_TXRX_BUFFERED
+ return tu_edpt_stream_write(&p_itf->tx_stream, buffer, (uint16_t)bufsize);
- return tu_edpt_stream_write(rhport, &p_itf->tx.stream, buffer, (uint16_t) bufsize);
+ #else
+ // non-fifo mode: direct transfer
+ TU_VERIFY(usbd_edpt_claim(p_itf->rhport, p_itf->ep_in), 0);
+ const uint32_t xact_len = tu_min32(bufsize, CFG_TUD_VENDOR_TX_EPSIZE);
+ memcpy(_vendord_epbuf[idx].epin, buffer, xact_len);
+ TU_ASSERT(usbd_edpt_xfer(p_itf->rhport, p_itf->ep_in, _vendord_epbuf[idx].epin, (uint16_t)xact_len, false), 0);
+ return xact_len;
+ #endif
}
-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];
- const uint8_t rhport = 0;
+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];
+
+ #if CFG_TUD_VENDOR_TXRX_BUFFERED
+ return tu_edpt_stream_write_available(&p_itf->tx_stream);
- return tu_edpt_stream_write_xfer(rhport, &p_itf->tx.stream);
+ #else
+ // Non-FIFO mode
+ TU_VERIFY(p_itf->ep_in > 0, 0); // must be opened
+ return usbd_edpt_busy(p_itf->rhport, p_itf->ep_in) ? 0 : CFG_TUD_VENDOR_TX_EPSIZE;
+ #endif
}
-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];
- const uint8_t rhport = 0;
+ #if CFG_TUD_VENDOR_TXRX_BUFFERED
+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->tx_stream);
+}
- return tu_edpt_stream_write_available(rhport, &p_itf->tx.stream);
+bool tud_vendor_n_write_clear(uint8_t idx) {
+ TU_VERIFY(idx < CFG_TUD_VENDOR, 0);
+ vendord_interface_t *p_itf = &_vendord_itf[idx];
+ tu_edpt_stream_clear(&p_itf->tx_stream);
+ return true;
}
+#endif
//--------------------------------------------------------------------+
// USBD Driver API
@@ -158,40 +198,35 @@ uint32_t tud_vendor_n_write_available (uint8_t itf) {
void vendord_init(void) {
tu_memclr(_vendord_itf, sizeof(_vendord_itf));
- 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];
-
- uint8_t* rx_ff_buf =
- #if CFG_TUD_VENDOR_RX_BUFSIZE > 0
- p_itf->rx.ff_buf;
- #else
- NULL;
- #endif
+ #if CFG_TUD_VENDOR_TXRX_BUFFERED
+ for (uint8_t i = 0; i < CFG_TUD_VENDOR; i++) {
+ vendord_interface_t *p_itf = &_vendord_itf[i];
- 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);
+ #if CFG_TUD_EDPT_DEDICATED_HWFIFO
+ uint8_t *epout_buf = NULL;
+ uint8_t *epin_buf = NULL;
+ #else
+ uint8_t *epout_buf = _vendord_epbuf[i].epout;
+ uint8_t *epin_buf = _vendord_epbuf[i].epin;
+ #endif
- uint8_t* tx_ff_buf =
- #if CFG_TUD_VENDOR_TX_BUFSIZE > 0
- p_itf->tx.ff_buf;
- #else
- NULL;
- #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);
- 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);
+ 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);
}
+ #endif
}
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);
+ #if CFG_TUD_VENDOR_TXRX_BUFFERED
+ 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);
}
+ #endif
return true;
}
@@ -201,30 +236,58 @@ 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_clear(&p_itf->tx.stream);
- tu_edpt_stream_close(&p_itf->rx.stream);
- tu_edpt_stream_close(&p_itf->tx.stream);
+
+ #if CFG_TUD_VENDOR_TXRX_BUFFERED
+ 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);
+ #endif
+ }
+}
+
+// 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 CFG_TUD_VENDOR_TXRX_BUFFERED
+ if (p_vendor->rx_stream.ep_addr == 0 && p_vendor->tx_stream.ep_addr == 0) {
+ return idx;
+ }
+ #else
+ if (p_vendor->ep_out == 0 && p_vendor->ep_in == 0) {
+ return idx;
+ }
+ #endif
+ } else {
+ #if CFG_TUD_VENDOR_TXRX_BUFFERED
+ if (ep_addr == p_vendor->rx_stream.ep_addr || ep_addr == p_vendor->tx_stream.ep_addr) {
+ return idx;
+ }
+ #else
+ if (ep_addr == p_vendor->ep_out || ep_addr == p_vendor->ep_in) {
+ return idx;
+ }
+ #endif
+ }
}
+ return 0xff;
}
-uint16_t vendord_open(uint8_t rhport, const tusb_desc_interface_t* desc_itf, uint16_t max_len) {
+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;
+
while (tu_desc_in_bounds(p_desc, desc_end)) {
const uint8_t desc_type = tu_desc_type(p_desc);
if (desc_type == TUSB_DESC_INTERFACE || desc_type == TUSB_DESC_INTERFACE_ASSOCIATION) {
@@ -233,61 +296,79 @@ 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));
- // open endpoint stream, skip if already opened
+ uint16_t rx_xfer_len = CFG_TUD_VENDOR_RX_NEED_ZLP ? CFG_TUD_VENDOR_RX_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) {
- if (p_vendor->tx.stream.ep_addr == 0) {
- tu_edpt_stream_open(&p_vendor->tx.stream, desc_ep);
- tud_vendor_n_write_flush(itf);
- }
+ tu_edpt_stream_t *tx_stream = &p_vendor->tx_stream;
+ tu_edpt_stream_open(tx_stream, rhport, desc_ep, CFG_TUD_VENDOR_TX_EPSIZE);
+ tu_edpt_stream_write_xfer(tx_stream); // flush pending data
} else {
- if (p_vendor->rx.stream.ep_addr == 0) {
- tu_edpt_stream_open(&p_vendor->rx.stream, desc_ep);
- TU_ASSERT(tu_edpt_stream_read_xfer(rhport, &p_vendor->rx.stream) > 0, 0); // prepare for incoming data
- }
+ tu_edpt_stream_t *rx_stream = &p_vendor->rx_stream;
+ 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;
+ } else {
+ p_vendor->ep_out = desc_ep->bEndpointAddress;
+ #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, rx_xfer_len, false), 0);
+ #endif
+ }
+ #endif
}
p_desc = tu_desc_next(p_desc);
}
- return (uint16_t) ((uintptr_t) p_desc - (uintptr_t) desc_itf);
+ return (uint16_t)((uintptr_t)p_desc - (uintptr_t)desc_itf);
}
bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) {
- (void) result;
-
- 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 ) {
- // Received new data: put into stream's fifo
- tu_edpt_stream_read_xfer_complete(&p_vendor->rx.stream, xferred_bytes);
-
- // Invoked callback if any
- tud_vendor_rx_cb(itf, p_epbuf->epout, (uint16_t) xferred_bytes);
+ (void)rhport;
+ (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];
- tu_edpt_stream_read_xfer(rhport, &p_vendor->rx.stream);
- } else if ( ep_addr == p_vendor->tx.stream.ep_addr ) {
+#if CFG_TUD_VENDOR_TXRX_BUFFERED
+ if (ep_addr == p_vendor->rx_stream.ep_addr) {
+ // Put received data to FIFO
+ tu_edpt_stream_read_xfer_complete(&p_vendor->rx_stream, xferred_bytes);
+ tud_vendor_rx_cb(idx, NULL, 0);
+ #if CFG_TUD_VENDOR_RX_MANUAL_XFER == 0
+ tu_edpt_stream_read_xfer(&p_vendor->rx_stream); // prepare next data
+ #endif
+ } else if (ep_addr == p_vendor->tx_stream.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
// 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(&p_vendor->tx_stream)) {
// 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(&p_vendor->tx_stream, xferred_bytes);
}
+ }
+ #else
+ if (ep_addr == p_vendor->ep_out) {
+ // 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, p_vendor->rx_xfer_len, false);
#endif
+ } else if (ep_addr == p_vendor->ep_in) {
+ // Send complete
+ tud_vendor_tx_cb(idx, (uint16_t)xferred_bytes);
}
+ #endif
return true;
}
diff --git a/src/class/vendor/vendor_device.h b/src/class/vendor/vendor_device.h
index 5fe4fc9ff..cdca9fd15 100644
--- a/src/class/vendor/vendor_device.h
+++ b/src/class/vendor/vendor_device.h
@@ -24,92 +24,161 @@
* This file is part of the TinyUSB stack.
*/
-#ifndef _TUSB_VENDOR_DEVICE_H_
-#define _TUSB_VENDOR_DEVICE_H_
+#ifndef TUSB_VENDOR_DEVICE_H_
+#define TUSB_VENDOR_DEVICE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
#include "common/tusb_common.h"
-#ifndef CFG_TUD_VENDOR_EPSIZE
-#define CFG_TUD_VENDOR_EPSIZE 64
+//--------------------------------------------------------------------+
+// Configuration
+//--------------------------------------------------------------------+
+#ifndef CFG_TUD_VENDOR_RX_EPSIZE
+ #ifdef CFG_TUD_VENDOR_EPSIZE
+ #define CFG_TUD_VENDOR_RX_EPSIZE CFG_TUD_VENDOR_EPSIZE
+ #else
+ #define CFG_TUD_VENDOR_RX_EPSIZE TUD_EPSIZE_BULK_MAX
+ #endif
+#endif
+
+#ifndef CFG_TUD_VENDOR_TX_EPSIZE
+ #ifdef CFG_TUD_VENDOR_EPSIZE
+ #define CFG_TUD_VENDOR_TX_EPSIZE CFG_TUD_VENDOR_EPSIZE
+ #else
+ #define CFG_TUD_VENDOR_TX_EPSIZE TUD_EPSIZE_BULK_MAX
+ #endif
#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 TUD_EPSIZE_BULK_MAX
#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 TUD_EPSIZE_BULK_MAX
#endif
-#ifdef __cplusplus
- extern "C" {
+// Vendor is buffered (FIFO mode) if both TX and RX buffers are configured
+// If either is 0, vendor operates in non-buffered (direct transfer) mode
+#ifndef CFG_TUD_VENDOR_TXRX_BUFFERED
+ #define CFG_TUD_VENDOR_TXRX_BUFFERED ((CFG_TUD_VENDOR_RX_BUFSIZE > 0) && (CFG_TUD_VENDOR_TX_BUFSIZE > 0))
+#endif
+
+// Application will manually schedule RX transfer. This can be useful when using with non-fifo (buffered) mode
+// i.e. CFG_TUD_VENDOR_TXRX_BUFFERED = 0
+#ifndef CFG_TUD_VENDOR_RX_MANUAL_XFER
+ #define CFG_TUD_VENDOR_RX_MANUAL_XFER 0
+#endif
+
+// Enable multi-packet RX transfer with ZLP termination for better throughput. Requires host support for ZLP.
+#ifndef CFG_TUD_VENDOR_RX_NEED_ZLP
+ #define CFG_TUD_VENDOR_RX_NEED_ZLP 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);
+
+//------------- RX -------------//
+#if CFG_TUD_VENDOR_TXRX_BUFFERED
+// 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);
+
+// 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
+
+//------------- TX -------------//
+// 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);
+
+// Return number of bytes available for writing in TX FIFO (or endpoint if non-buffered)
+uint32_t tud_vendor_n_write_available(uint8_t idx);
-TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_n_write_str (uint8_t itf, char const* str);
+#if CFG_TUD_VENDOR_TXRX_BUFFERED
+// Force sending buffered data, return number of bytes sent
+uint32_t tud_vendor_n_write_flush(uint8_t idx);
+
+// Clear the transmit FIFO
+bool tud_vendor_n_write_clear(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_TXRX_BUFFERED
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 void tud_vendor_read_flush(void) {
- tud_vendor_n_read_flush(0);
+ tud_vendor_n_read_flush(0);
}
-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);
+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(char const* str) {
- return tud_vendor_n_write_str(0, str);
+TU_ATTR_ALWAYS_INLINE static inline bool tud_vendor_write_clear(void) {
+ return tud_vendor_n_write_clear(0);
}
+#endif
-TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_write_flush(void) {
- return tud_vendor_n_write_flush(0);
+#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(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_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_available(void) {
- return tud_vendor_n_write_available(0);
+ return tud_vendor_n_write_available(0);
}
-#endif
// backward compatible
#define tud_vendor_flush() tud_vendor_write_flush()
@@ -118,15 +187,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_TXRX_BUFFERED = 1: buffer and bufsize must not be used (both NULL,0) since data is in RX FIFO
+// - CFG_TUD_VENDOR_TXRX_BUFFERED = 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 +201,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_ */
+#endif /* TUSB_VENDOR_DEVICE_H_ */
diff --git a/src/class/vendor/vendor_host.h b/src/class/vendor/vendor_host.h
index acfebe7a4..00e3c3402 100644
--- a/src/class/vendor/vendor_host.h
+++ b/src/class/vendor/vendor_host.h
@@ -24,8 +24,8 @@
* This file is part of the TinyUSB stack.
*/
-#ifndef _TUSB_VENDOR_HOST_H_
-#define _TUSB_VENDOR_HOST_H_
+#ifndef TUSB_VENDOR_HOST_H_
+#define TUSB_VENDOR_HOST_H_
#include "common/tusb_common.h"
@@ -64,4 +64,4 @@ void cush_close(uint8_t dev_addr);
}
#endif
-#endif /* _TUSB_VENDOR_HOST_H_ */
+#endif /* TUSB_VENDOR_HOST_H_ */