diff --git a/examples/host/cdc_msc_hid/src/cdc_app.c b/examples/host/cdc_msc_hid/src/cdc_app.c index db652efde..23ea05b2b 100644 --- a/examples/host/cdc_msc_hid/src/cdc_app.c +++ b/examples/host/cdc_msc_hid/src/cdc_app.c @@ -54,8 +54,8 @@ void cdc_app_task(void) uint8_t buf[64+1]; // +1 for extra null character uint32_t const bufsize = sizeof(buf)-1; - uint32_t console_count = get_console_inputs(buf, bufsize); - buf[console_count] = 0; + uint32_t count = get_console_inputs(buf, bufsize); + buf[count] = 0; // loop over all mounted interfaces for(uint8_t idx=0; idx cdc interfaces - if (console_count) + if (count) { - tuh_cdc_write(idx, buf, console_count); + tuh_cdc_write(idx, buf, count); tuh_cdc_write_flush(idx); } - - // cdc interfaces -> console - if ( tuh_cdc_read_available(idx) ) - { - uint8_t buf_cdc[64+1]; - uint32_t cdc_count = tuh_cdc_read(idx, buf_cdc, sizeof(buf_cdc)-1); - buf_cdc[cdc_count] = 0; - - printf((char*) buf_cdc); - } } } } +// Invoked when received new data +void tuh_cdc_rx_cb(uint8_t idx) +{ + uint8_t buf[64+1]; // +1 for extra null character + uint32_t const bufsize = sizeof(buf)-1; + + // forward cdc interfaces -> console + uint32_t count = tuh_cdc_read(idx, buf, bufsize); + buf[count] = 0; + + printf((char*) buf); +} + void tuh_cdc_mount_cb(uint8_t idx) { tuh_cdc_itf_info_t itf_info; diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 326567689..ba2e9e1b7 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -185,6 +185,17 @@ uint32_t tu_edpt_stream_read_available(tu_edpt_stream_t* s) return (uint32_t) tu_fifo_count(&s->ff); } +uint32_t tu_edpt_stream_write_available(tu_edpt_stream_t* s) +{ + return (uint32_t) tu_fifo_remaining(&s->ff); +} + +void tu_edpt_stream_read_clear(uint8_t daddr, tu_edpt_stream_t* s) +{ + tu_fifo_clear(&s->ff); + tu_edpt_stream_read_xfer(daddr, s); +} + typedef struct { uint8_t daddr; uint8_t bInterfaceNumber; @@ -227,6 +238,12 @@ static inline cdch_interface_t* get_itf(uint8_t idx) return (p_cdc->daddr != 0) ? p_cdc : NULL; } +TU_ATTR_ALWAYS_INLINE +static inline uint8_t itf2idx(cdch_interface_t* p_cdc) +{ + return (uint8_t) (p_cdc - cdch_data); +} + static inline cdch_interface_t* get_itf_by_ep_addr(uint8_t daddr, uint8_t ep_addr) { for(uint8_t i=0; idaddr, &p_cdc->stream.tx); } +uint32_t tuh_cdc_write_available(uint8_t idx) +{ + cdch_interface_t* p_cdc = get_itf(idx); + TU_VERIFY(p_cdc); + + return tu_edpt_stream_write_available(&p_cdc->stream.tx); +} + uint32_t tuh_cdc_read (uint8_t idx, void* buffer, uint32_t bufsize) { cdch_interface_t* p_cdc = get_itf(idx); @@ -336,6 +361,14 @@ uint32_t tuh_cdc_read_available(uint8_t idx) return tu_edpt_stream_read_available(&p_cdc->stream.rx); } +void tuh_cdc_read_flush (uint8_t idx) +{ + cdch_interface_t* p_cdc = get_itf(idx); + TU_VERIFY(p_cdc, ); + + tu_edpt_stream_read_clear(p_cdc->daddr, &p_cdc->stream.rx); +} + //--------------------------------------------------------------------+ // Control Endpoint API //--------------------------------------------------------------------+ @@ -463,6 +496,7 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t if (xferred_bytes) tu_edpt_stream_read_xfer_complete(&p_cdc->stream.rx, xferred_bytes); // invoke receive callback + if (tuh_cdc_rx_cb) tuh_cdc_rx_cb(itf2idx(p_cdc)); // prepare for next transfer if needed tu_edpt_stream_read_xfer(daddr, &p_cdc->stream.rx); diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index 54e082e7d..dd8ae80ce 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -97,18 +97,32 @@ TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_connected(uint8_t idx) return tuh_cdc_get_dtr(idx); } +//--------------------------------------------------------------------+ +// Write API +//--------------------------------------------------------------------+ + +// Get the number of bytes available for writing +uint32_t tuh_cdc_write_available(uint8_t idx); + // Write to cdc interface uint32_t tuh_cdc_write(uint8_t idx, void const* buffer, uint32_t bufsize); // Force sending data if possible, return number of forced bytes uint32_t tuh_cdc_write_flush(uint8_t idx); -// Read from cdc interface -uint32_t tuh_cdc_read (uint8_t idx, void* buffer, uint32_t bufsize); +//--------------------------------------------------------------------+ +// Read API +//--------------------------------------------------------------------+ // Get the number of bytes available for reading uint32_t tuh_cdc_read_available(uint8_t idx); +// Read from cdc interface +uint32_t tuh_cdc_read (uint8_t idx, void* buffer, uint32_t bufsize); + +// Clear the received FIFO +void tuh_cdc_read_flush (uint8_t idx); + //--------------------------------------------------------------------+ // Control Endpoint (Request) API //--------------------------------------------------------------------+ @@ -132,47 +146,13 @@ static inline bool tuh_cdc_disconnect(uint8_t idx, tuh_xfer_cb_t complete_cb, ui // Invoked when a device with CDC interface is mounted // idx is index of cdc interface in the internal pool. -TU_ATTR_WEAK void tuh_cdc_mount_cb(uint8_t idx); +TU_ATTR_WEAK extern void tuh_cdc_mount_cb(uint8_t idx); // Invoked when a device with CDC interface is unmounted -TU_ATTR_WEAK void tuh_cdc_umount_cb(uint8_t idx); +TU_ATTR_WEAK extern void tuh_cdc_umount_cb(uint8_t idx); -/** \brief Check if the interface is currently busy or not - * \param[in] dev_addr device address - * \param[in] pipeid value from \ref cdc_pipeid_t to indicate target pipe. - * \retval true if the interface is busy, meaning the stack is still transferring/waiting data from/to device - * \retval false if the interface is not busy, meaning the stack successfully transferred data from/to device - * \note This function is used to check if previous transfer is complete (success or error), so that the next transfer - * can be scheduled. User needs to make sure the corresponding interface is mounted - * (by \ref tuh_cdc_serial_is_mounted) before calling this function. - */ -// bool tuh_cdc_is_busy(uint8_t dev_addr, cdc_pipeid_t pipeid); - -/** \brief Perform USB OUT transfer to device - * \param[in] dev_addr device address - * \param[in] p_data Buffer containing data. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION) - * \param[in] length Number of bytes to be transferred via USB bus - * \retval TUSB_ERROR_NONE on success - * \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device - * \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request) - * \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct - * \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by the - * interface's callback function. \a p_data must be declared with \ref CFG_TUSB_MEM_SECTION. - */ -// bool tuh_cdc_send(uint8_t dev_addr, void const * p_data, uint32_t length, bool is_notify); - -/** \brief Perform USB IN transfer to get data from device - * \param[in] dev_addr device address - * \param[in] p_buffer Buffer containing received data. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION) - * \param[in] length Number of bytes to be transferred via USB bus - * \retval TUSB_ERROR_NONE on success - * \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device - * \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request) - * \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct - * \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by the - * interface's callback function. \a p_data must be declared with \ref CFG_TUSB_MEM_SECTION. - */ -// bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is_notify); +// Invoked when received new data +TU_ATTR_WEAK extern void tuh_cdc_rx_cb(uint8_t idx); //--------------------------------------------------------------------+ // CDC APPLICATION CALLBACKS