From 2a543c0e79b882b054d87f89ee8cf8e83b44e22e Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 24 Jul 2019 23:07:30 +0700 Subject: update vendor device similar to cdc read/write maybe refactor later --- src/class/midi/midi_device.c | 13 +++-- src/class/vendor/vendor_device.c | 123 ++++++++++++++++++++++++++++++++++++--- src/class/vendor/vendor_device.h | 37 ++++++++++-- 3 files changed, 154 insertions(+), 19 deletions(-) (limited to 'src/class') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index a33ced169..03b0cae57 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -44,6 +44,7 @@ typedef struct uint8_t ep_in; uint8_t ep_out; + /*------------- From this point, data is not cleared by bus reset -------------*/ // FIFO tu_fifo_t rx_ff; tu_fifo_t tx_ff; @@ -77,7 +78,7 @@ CFG_TUSB_MEM_SECTION midid_interface_t _midid_itf[CFG_TUD_MIDI]; bool tud_midi_n_mounted (uint8_t itf) { midid_interface_t* midi = &_midid_itf[itf]; - return midi->itf_num != 0; + return midi->ep_in && midi->ep_out; } //--------------------------------------------------------------------+ @@ -127,7 +128,8 @@ void midi_rx_done_cb(midid_interface_t* midi, uint8_t const* buffer, uint32_t bu static bool maybe_transmit(midid_interface_t* midi, uint8_t itf_index) { - TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, midi->ep_in) ); // skip if previous transfer not complete + // skip if previous transfer not complete + TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, midi->ep_in) ); uint16_t count = tu_fifo_read_n(&midi->tx_ff, midi->epin_buf, CFG_TUD_MIDI_EPSIZE); if (count > 0) @@ -222,6 +224,7 @@ void midid_init(void) // config fifo tu_fifo_config(&midi->rx_ff, midi->rx_ff_buf, CFG_TUD_MIDI_RX_BUFSIZE, 1, true); tu_fifo_config(&midi->tx_ff, midi->tx_ff_buf, CFG_TUD_MIDI_TX_BUFSIZE, 1, true); + #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&midi->rx_ff, osal_mutex_create(&midi->rx_ff_mutex)); tu_fifo_config_mutex(&midi->tx_ff, osal_mutex_create(&midi->tx_ff_mutex)); @@ -314,20 +317,20 @@ bool midid_control_request(uint8_t rhport, tusb_control_request_t const * p_requ return false; } -bool midid_xfer_cb(uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes) +bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { // TODO Support multiple interfaces uint8_t const itf = 0; midid_interface_t* p_midi = &_midid_itf[itf]; // receive new data - if ( edpt_addr == p_midi->ep_out ) + if ( ep_addr == p_midi->ep_out ) { midi_rx_done_cb(p_midi, p_midi->epout_buf, xferred_bytes); // prepare for next TU_ASSERT( usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE), false ); - } else if ( edpt_addr == p_midi->ep_in ) { + } else if ( ep_addr == p_midi->ep_in ) { maybe_transmit(p_midi, itf); } 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; irx_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; irx_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 -- cgit v1.3.1