From 2a543c0e79b882b054d87f89ee8cf8e83b44e22e Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 24 Jul 2019 23:07:30 +0700 Subject: [PATCH] update vendor device similar to cdc read/write maybe refactor later --- examples/device/webusb/src/tusb_config.h | 2 +- examples/rules.mk | 3 +- src/class/midi/midi_device.c | 13 ++- src/class/vendor/vendor_device.c | 123 +++++++++++++++++++++-- src/class/vendor/vendor_device.h | 37 +++++-- src/device/usbd.c | 2 +- src/device/usbd_pvt.h | 6 +- 7 files changed, 162 insertions(+), 24 deletions(-) diff --git a/examples/device/webusb/src/tusb_config.h b/examples/device/webusb/src/tusb_config.h index 7dd9864df..ffedb997d 100644 --- a/examples/device/webusb/src/tusb_config.h +++ b/examples/device/webusb/src/tusb_config.h @@ -76,7 +76,7 @@ #define CFG_TUD_MSC 0 #define CFG_TUD_HID 0 #define CFG_TUD_MIDI 0 -#define CFG_TUD_VENDOR 0 +#define CFG_TUD_VENDOR 1 // CDC FIFO size of TX and RX #define CFG_TUD_CDC_RX_BUFSIZE 64 diff --git a/examples/rules.mk b/examples/rules.mk index bba0fdb53..4fbce2529 100644 --- a/examples/rules.mk +++ b/examples/rules.mk @@ -7,6 +7,7 @@ LIBS = -lgcc -lc -lm -lnosys # TinyUSB Stack source SRC_C += \ + src/tusb.c \ src/common/tusb_fifo.c \ src/device/usbd.c \ src/device/usbd_control.c \ @@ -14,7 +15,7 @@ SRC_C += \ src/class/cdc/cdc_device.c \ src/class/hid/hid_device.c \ src/class/midi/midi_device.c \ - src/tusb.c \ + src/class/vendor/vendor_device.c \ src/portable/$(VENDOR)/$(CHIP_FAMILY)/dcd_$(CHIP_FAMILY).c # TinyUSB stack include 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 diff --git a/src/device/usbd.c b/src/device/usbd.c index 4ce056e7f..c94d08a67 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -528,7 +528,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; uint16_t itf_len=0; - TU_ASSERT( usbd_class_drivers[drv_id].open( rhport, desc_itf, &itf_len ) ); + TU_ASSERT( usbd_class_drivers[drv_id].open(rhport, desc_itf, &itf_len) ); TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) ); mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, itf_len, drv_id); diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 06f7a3afe..fbf030ce3 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -39,11 +39,13 @@ bool usbd_init (void); // USBD Endpoint API //--------------------------------------------------------------------+ +//bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); + // Submit a usb transfer -bool usbd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); +bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); // Check if endpoint transferring is complete -bool usbd_edpt_busy (uint8_t rhport, uint8_t ep_addr); +bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr); void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr); void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr);