diff options
| author | hathach <[email protected]> | 2019-07-24 23:07:30 +0700 |
|---|---|---|
| committer | hathach <[email protected]> | 2019-07-24 23:07:30 +0700 |
| commit | 2a543c0e79b882b054d87f89ee8cf8e83b44e22e (patch) | |
| tree | b3e7e50429b6ed2c1f26b483baf948a4662c64f0 /src/class/vendor | |
| parent | 56b656c768a5e1b775ed41a5f74bbf75901f9d74 (diff) | |
update vendor device similar to cdc read/write
maybe refactor later
Diffstat (limited to 'src/class/vendor')
| -rw-r--r-- | src/class/vendor/vendor_device.c | 123 | ||||
| -rw-r--r-- | src/class/vendor/vendor_device.h | 37 |
2 files changed, 146 insertions, 14 deletions
diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 899d0bc07..2cd815fb4 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -34,9 +34,9 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -typedef struct { +typedef struct +{ uint8_t itf_num; - uint8_t ep_in; uint8_t ep_out; @@ -44,22 +44,103 @@ typedef struct { tu_fifo_t rx_ff; tu_fifo_t tx_ff; + uint8_t rx_ff_buf[CFG_TUD_VENDOR_RX_BUFSIZE]; + uint8_t tx_ff_buf[CFG_TUD_VENDOR_TX_BUFSIZE]; + +#if CFG_FIFO_MUTEX + osal_mutex_def_t rx_ff_mutex; + osal_mutex_def_t tx_ff_mutex; +#endif + // Endpoint Transfer buffer CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_VENDOR_EPSIZE]; CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_VENDOR_EPSIZE]; - } vendord_interface_t; -static vendord_interface_t _vendord_itf[CFG_TUD_VENDOR]; +CFG_TUSB_MEM_SECTION static vendord_interface_t _vendord_itf[CFG_TUD_VENDOR]; #define ITF_MEM_RESET_SIZE offsetof(vendord_interface_t, rx_ff) + + +bool tud_vendor_n_mounted (uint8_t itf) +{ + return _vendord_itf[itf].ep_in && _vendord_itf[itf].ep_out; +} + +uint32_t tud_vendor_n_available (uint8_t itf) +{ + return tu_fifo_count(&_vendord_itf[itf].rx_ff); +} + +//--------------------------------------------------------------------+ +// Read API +//--------------------------------------------------------------------+ +static void _prep_out_transaction (vendord_interface_t* p_itf) +{ + // skip if previous transfer not complete + if ( usbd_edpt_busy(TUD_OPT_RHPORT, p_itf->ep_out) ) return; + + // Prepare for incoming data but only allow what we can store in the ring buffer. + uint16_t max_read = tu_fifo_remaining(&p_itf->rx_ff); + if ( max_read >= CFG_TUD_VENDOR_EPSIZE ) + { + usbd_edpt_xfer(TUD_OPT_RHPORT, p_itf->ep_out, p_itf->epout_buf, CFG_TUD_VENDOR_EPSIZE); + } +} + +uint32_t tud_vendor_n_read (uint8_t itf, void* buffer, uint32_t bufsize) +{ + vendord_interface_t* p_itf = &_vendord_itf[itf]; + uint32_t num_read = tu_fifo_read_n(&p_itf->rx_ff, buffer, bufsize); + _prep_out_transaction(p_itf); + return num_read; +} + +//--------------------------------------------------------------------+ +// Write API +//--------------------------------------------------------------------+ +static bool maybe_transmit(vendord_interface_t* p_itf) +{ + // skip if previous transfer not complete + TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, p_itf->ep_in) ); + + uint16_t count = tu_fifo_read_n(&p_itf->tx_ff, p_itf->epin_buf, CFG_TUD_VENDOR_EPSIZE); + if (count > 0) + { + TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, p_itf->ep_in, p_itf->epin_buf, count) ); + } + return true; +} + +uint32_t tud_vendor_n_write (uint8_t itf, uint8_t const* buffer, uint32_t bufsize) +{ + vendord_interface_t* p_itf = &_vendord_itf[itf]; + uint16_t ret = tu_fifo_write_n(&p_itf->tx_ff, buffer, bufsize); + maybe_transmit(p_itf); + return ret; +} + //--------------------------------------------------------------------+ // USBD Driver API //--------------------------------------------------------------------+ void vendord_init(void) { - tu_varclr(_vendord_itf); + 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]; + + // config fifo + tu_fifo_config(&p_itf->rx_ff, p_itf->rx_ff_buf, CFG_TUD_VENDOR_RX_BUFSIZE, 1, false); + tu_fifo_config(&p_itf->tx_ff, p_itf->tx_ff_buf, CFG_TUD_VENDOR_TX_BUFSIZE, 1, false); + +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&p_itf->rx_ff, osal_mutex_create(&p_itf->rx_ff_mutex)); + tu_fifo_config_mutex(&p_itf->tx_ff, osal_mutex_create(&p_itf->tx_ff_mutex)); +#endif + } } void vendord_reset(uint8_t rhport) @@ -68,7 +149,11 @@ void vendord_reset(uint8_t rhport) for(uint8_t i=0; i<CFG_TUD_VENDOR; i++) { - tu_memclr(&_vendord_itf[i], ITF_MEM_RESET_SIZE); + vendord_interface_t* p_itf = &_vendord_itf[i]; + + tu_memclr(p_itf, ITF_MEM_RESET_SIZE); + tu_fifo_clear(&p_itf->rx_ff); + tu_fifo_clear(&p_itf->tx_ff); } } @@ -98,10 +183,32 @@ bool vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16 return true; } -bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) +bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { + (void) rhport; + (void) result; + + // TODO Support multiple interfaces + uint8_t const itf = 0; + vendord_interface_t* p_itf = &_vendord_itf[itf]; + + if ( ep_addr == p_itf->ep_out ) + { + // Receive new data + tu_fifo_write_n(&p_itf->rx_ff, p_itf->epout_buf, xferred_bytes); + + // Invoked callback if any + if (tud_vendor_rx_cb) tud_vendor_rx_cb(itf); + + _prep_out_transaction(p_itf); + } + else if ( ep_addr == p_itf->ep_in ) + { + // Send complete, try to send more if possible + maybe_transmit(p_itf); + } + return true; } - #endif diff --git a/src/class/vendor/vendor_device.h b/src/class/vendor/vendor_device.h index d2048fb63..0fa1f2d43 100644 --- a/src/class/vendor/vendor_device.h +++ b/src/class/vendor/vendor_device.h @@ -49,16 +49,18 @@ //--------------------------------------------------------------------+ // Application API (Multiple Interfaces) //--------------------------------------------------------------------+ +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); +uint32_t tud_vendor_n_write (uint8_t itf, uint8_t const* buffer, uint32_t bufsize); //--------------------------------------------------------------------+ // Application API (Single Port) //--------------------------------------------------------------------+ - -bool tud_vendor_mounted(void); - -uint32_t tud_vendor_write(void const* buffer, uint32_t bufsize); -uint32_t tud_vendor_read(void* buffer, uint32_t bufsize); - +static inline bool tud_vendor_mounted (void); +static inline uint32_t tud_vendor_available (void); +static inline uint32_t tud_vendor_read (void* buffer, uint32_t bufsize); +static inline uint32_t tud_vendor_write (uint8_t const* buffer, uint32_t bufsize); //--------------------------------------------------------------------+ // Application Callback API (weak is optional) @@ -71,6 +73,29 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // Invoked when received new data TU_ATTR_WEAK void tud_vendor_rx_cb(uint8_t itf); +//--------------------------------------------------------------------+ +// Inline Functions +//--------------------------------------------------------------------+ + +static inline bool tud_vendor_mounted (void) +{ + return tud_vendor_n_mounted(0); +} + +static inline uint32_t tud_vendor_available (void) +{ + return tud_vendor_n_available(0); +} + +static inline uint32_t tud_vendor_read (void* buffer, uint32_t bufsize) +{ + return tud_vendor_n_read(0, buffer, bufsize); +} + +static inline uint32_t tud_vendor_write (uint8_t const* buffer, uint32_t bufsize) +{ + return tud_vendor_n_write(0, buffer, bufsize); +} //--------------------------------------------------------------------+ // Internal Class Driver API |
