diff options
Diffstat (limited to 'src/class/vendor')
| -rw-r--r-- | src/class/vendor/vendor_device.c | 367 | ||||
| -rw-r--r-- | src/class/vendor/vendor_device.h | 167 | ||||
| -rw-r--r-- | src/class/vendor/vendor_host.h | 6 |
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_ */ |
