From 6a2cf6728906aa61b44ecfe43b4ceef287b29bf8 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Sun, 4 Dec 2022 13:58:47 +0700 Subject: Fix typos --- src/host/usbh.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/host') diff --git a/src/host/usbh.c b/src/host/usbh.c index d97b160c9..9065e5241 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1275,7 +1275,7 @@ static void process_enumeration(tuh_xfer_t* xfer) // connected directly to roothub hcd_port_reset( _dev0.rhport ); osal_task_delay(RESET_DELAY); // TODO may not work for no-OS on MCU that require reset_end() since - // sof of controller may not running while reseting + // sof of controller may not running while resetting hcd_port_reset_end(_dev0.rhport); // TODO: fall through to SET ADDRESS, refactor later } @@ -1395,7 +1395,7 @@ static bool enum_new_device(hcd_event_t* event) // wait until device is stable TODO non blocking hcd_port_reset(_dev0.rhport); osal_task_delay(RESET_DELAY); // TODO may not work for no-OS on MCU that require reset_end() since - // sof of controller may not running while reseting + // sof of controller may not running while resetting hcd_port_reset_end( _dev0.rhport); // device unplugged while delaying -- cgit v1.3.1 From 88e6da727370114b427287e74c3ade176c483b17 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 15 Dec 2022 18:03:01 +0700 Subject: use OSAL_MUTEX_REQUIRED to replace CFG_FIFO_MUTEX/TUSB_OPT_MUTEX add macro to swallow mutex API in order to simplify code with mutex --- src/class/cdc/cdc_device.c | 8 ++------ src/common/tusb_fifo.h | 19 +++++++++++-------- src/common/tusb_mcu.h | 4 ++++ src/device/usbd.c | 20 +++++++------------- src/host/usbh.c | 41 +++++++++++------------------------------ src/osal/osal.h | 21 ++++++++++++++------- src/osal/osal_none.h | 12 ++++++++++++ src/tusb.c | 16 ++++------------ src/tusb_option.h | 3 --- 9 files changed, 65 insertions(+), 79 deletions(-) (limited to 'src/host') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 7b1e08d5d..0bbbaaa83 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -62,10 +62,8 @@ typedef struct uint8_t rx_ff_buf[CFG_TUD_CDC_RX_BUFSIZE]; uint8_t tx_ff_buf[CFG_TUD_CDC_TX_BUFSIZE]; -#if CFG_FIFO_MUTEX - osal_mutex_def_t rx_ff_mutex; - osal_mutex_def_t tx_ff_mutex; -#endif + OSAL_MUTEX_DEF(rx_ff_mutex); + OSAL_MUTEX_DEF(tx_ff_mutex); // Endpoint Transfer buffer CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_CDC_EP_BUFSIZE]; @@ -248,10 +246,8 @@ void cdcd_init(void) // In this way, the most current data is prioritized. tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, true); -#if CFG_FIFO_MUTEX tu_fifo_config_mutex(&p_cdc->rx_ff, NULL, osal_mutex_create(&p_cdc->rx_ff_mutex)); tu_fifo_config_mutex(&p_cdc->tx_ff, osal_mutex_create(&p_cdc->tx_ff_mutex), NULL); -#endif } } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index e64ab4b6d..e36e3a7f3 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -42,15 +42,13 @@ extern "C" { // within a certain number (see tu_fifo_overflow()). #include "common/tusb_common.h" +#include "osal/osal.h" + +#define tu_fifo_mutex_t osal_mutex_t // mutex is only needed for RTOS // for OS None, we don't get preempted -#define CFG_FIFO_MUTEX (CFG_TUSB_OS != OPT_OS_NONE) - -#if CFG_FIFO_MUTEX -#include "osal/osal.h" -#define tu_fifo_mutex_t osal_mutex_t -#endif +#define CFG_FIFO_MUTEX OSAL_MUTEX_REQUIRED typedef struct { @@ -65,7 +63,7 @@ typedef struct volatile uint16_t wr_idx ; ///< write pointer volatile uint16_t rd_idx ; ///< read pointer -#if CFG_FIFO_MUTEX +#if OSAL_MUTEX_REQUIRED tu_fifo_mutex_t mutex_wr; tu_fifo_mutex_t mutex_rd; #endif @@ -99,13 +97,18 @@ bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable); bool tu_fifo_clear(tu_fifo_t *f); bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable); -#if CFG_FIFO_MUTEX +#if OSAL_MUTEX_REQUIRED TU_ATTR_ALWAYS_INLINE static inline void tu_fifo_config_mutex(tu_fifo_t *f, tu_fifo_mutex_t write_mutex_hdl, tu_fifo_mutex_t read_mutex_hdl) { f->mutex_wr = write_mutex_hdl; f->mutex_rd = read_mutex_hdl; } + +#else + +#define tu_fifo_config_mutex(_f, _wr_mutex, _rd_mutex) + #endif bool tu_fifo_write (tu_fifo_t* f, void const * p_data); diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 86c68baf8..bb4225ad5 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -281,6 +281,10 @@ // Default Values //--------------------------------------------------------------------+ +#ifndef TUP_MCU_MULTIPLE_CORE +#define TUP_MCU_MULTIPLE_CORE 0 +#endif + #ifndef TUP_DCD_ENDPOINT_MAX #warning "TUP_DCD_ENDPOINT_MAX is not defined for this MCU, default to 8" #define TUP_DCD_ENDPOINT_MAX 8 diff --git a/src/device/usbd.c b/src/device/usbd.c index c199e647e..f9a7af21b 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -272,10 +272,12 @@ static uint8_t _usbd_rhport = RHPORT_INVALID; OSAL_QUEUE_DEF(usbd_int_set, _usbd_qdef, CFG_TUD_TASK_QUEUE_SZ, dcd_event_t); static osal_queue_t _usbd_q; -// Mutex for claiming endpoint, only needed when using with preempted RTOS -#if CFG_TUSB_OS != OPT_OS_NONE -static osal_mutex_def_t _ubsd_mutexdef; -static osal_mutex_t _usbd_mutex; +// Mutex for claiming endpoint +#if OSAL_MUTEX_REQUIRED + static osal_mutex_def_t _ubsd_mutexdef; + static osal_mutex_t _usbd_mutex; +#else + #define _usbd_mutex NULL #endif @@ -389,7 +391,7 @@ bool tud_init (uint8_t rhport) tu_varclr(&_usbd_dev); -#if CFG_TUSB_OS != OPT_OS_NONE +#if OSAL_MUTEX_REQUIRED // Init device mutex _usbd_mutex = osal_mutex_create(&_ubsd_mutexdef); TU_ASSERT(_usbd_mutex); @@ -1209,11 +1211,7 @@ bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr) uint8_t const dir = tu_edpt_dir(ep_addr); tu_edpt_state_t* ep_state = &_usbd_dev.ep_status[epnum][dir]; -#if TUSB_OPT_MUTEX return tu_edpt_claim(ep_state, _usbd_mutex); -#else - return tu_edpt_claim(ep_state, NULL); -#endif } bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr) @@ -1224,11 +1222,7 @@ bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr) uint8_t const dir = tu_edpt_dir(ep_addr); tu_edpt_state_t* ep_state = &_usbd_dev.ep_status[epnum][dir]; -#if TUSB_OPT_MUTEX return tu_edpt_release(ep_state, _usbd_mutex); -#else - return tu_edpt_release(ep_state, NULL); -#endif } bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) diff --git a/src/host/usbh.c b/src/host/usbh.c index 9065e5241..ff8fbaef3 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -212,28 +212,12 @@ static usbh_dev0_t _dev0; // TODO: hub can has its own simpler struct to save memory CFG_TUSB_MEM_SECTION usbh_device_t _usbh_devices[TOTAL_DEVICES]; -// Mutex for claiming endpoint, only needed when using with preempted RTOS -#if TUSB_OPT_MUTEX -static osal_mutex_def_t _usbh_mutexdef; -static osal_mutex_t _usbh_mutex; - -TU_ATTR_ALWAYS_INLINE static inline void usbh_lock(void) -{ - osal_mutex_lock(_usbh_mutex, OSAL_TIMEOUT_WAIT_FOREVER); -} - -TU_ATTR_ALWAYS_INLINE static inline void usbh_unlock(void) -{ - osal_mutex_unlock(_usbh_mutex); -} - +// Mutex for claiming endpoint +#if OSAL_MUTEX_REQUIRED + static osal_mutex_def_t _usbh_mutexdef; + static osal_mutex_t _usbh_mutex; #else - -#define _usbh_mutex NULL - -#define usbh_lock() -#define usbh_unlock() - + #define _usbh_mutex NULL #endif // Event queue @@ -277,8 +261,6 @@ static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t // TODO rework time-related function later void osal_task_delay(uint32_t msec) { - (void) msec; - const uint32_t start = hcd_frame_number(_usbh_controller); while ( ( hcd_frame_number(_usbh_controller) - start ) < msec ) {} } @@ -352,8 +334,8 @@ bool tuh_init(uint8_t controller_id) _usbh_q = osal_queue_create( &_usbh_qdef ); TU_ASSERT(_usbh_q != NULL); -#if TUSB_OPT_MUTEX - // Mutex +#if OSAL_MUTEX_REQUIRED + // Init mutex _usbh_mutex = osal_mutex_create(&_usbh_mutexdef); TU_ASSERT(_usbh_mutex); #endif @@ -537,8 +519,7 @@ bool tuh_control_xfer (tuh_xfer_t* xfer) uint8_t const daddr = xfer->daddr; - // TODO probably better to use semaphore as resource management than mutex - usbh_lock(); + (void) osal_mutex_lock(_usbh_mutex, OSAL_TIMEOUT_WAIT_FOREVER); bool const is_idle = (_ctrl_xfer.stage == CONTROL_STAGE_IDLE); if (is_idle) @@ -553,7 +534,7 @@ bool tuh_control_xfer (tuh_xfer_t* xfer) _ctrl_xfer.user_data = xfer->user_data; } - usbh_unlock(); + (void) osal_mutex_unlock(_usbh_mutex); TU_VERIFY(is_idle); const uint8_t rhport = usbh_get_rhport(daddr); @@ -597,9 +578,9 @@ bool tuh_control_xfer (tuh_xfer_t* xfer) TU_ATTR_ALWAYS_INLINE static inline void _set_control_xfer_stage(uint8_t stage) { - usbh_lock(); + osal_mutex_lock(_usbh_mutex, OSAL_TIMEOUT_WAIT_FOREVER); _ctrl_xfer.stage = stage; - usbh_unlock(); + osal_mutex_unlock(_usbh_mutex); } static void _xfer_complete(uint8_t daddr, xfer_result_t result) diff --git a/src/osal/osal.h b/src/osal/osal.h index 9d11866df..9cdab2882 100644 --- a/src/osal/osal.h +++ b/src/osal/osal.h @@ -33,17 +33,24 @@ #include "common/tusb_common.h" -// Return immediately -#define OSAL_TIMEOUT_NOTIMEOUT (0) -// Default timeout -#define OSAL_TIMEOUT_NORMAL (10) -// Wait forever -#define OSAL_TIMEOUT_WAIT_FOREVER (UINT32_MAX) +typedef void (*osal_task_func_t)( void * ); +// Timeout +#define OSAL_TIMEOUT_NOTIMEOUT (0) // Return immediately +#define OSAL_TIMEOUT_NORMAL (10) // Default timeout +#define OSAL_TIMEOUT_WAIT_FOREVER (UINT32_MAX) // Wait forever #define OSAL_TIMEOUT_CONTROL_XFER OSAL_TIMEOUT_WAIT_FOREVER -typedef void (*osal_task_func_t)( void * ); +// Mutex is required when using a preempted RTOS or MCU has multiple cores +#if (CFG_TUSB_OS == OPT_OS_NONE) && !TUP_MCU_MULTIPLE_CORE + #define OSAL_MUTEX_REQUIRED 0 + #define OSAL_MUTEX_DEF(_name) +#else + #define OSAL_MUTEX_REQUIRED 1 + #define OSAL_MUTEX_DEF(_name) osal_mutex_def_t _name +#endif +// OS thin implementation #if CFG_TUSB_OS == OPT_OS_NONE #include "osal_none.h" #elif CFG_TUSB_OS == OPT_OS_FREERTOS diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index 9c80e4548..1ad130557 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -82,6 +82,10 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t s typedef osal_semaphore_def_t osal_mutex_def_t; typedef osal_semaphore_t osal_mutex_t; +#if OSAL_MUTEX_REQUIRED +// Note: multiple cores MCUs usually do provide IPC API for mutex +// or we can use std atomic function + TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) { mdef->count = 1; @@ -98,6 +102,14 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hd return osal_semaphore_post(mutex_hdl, false); } +#else + +#define osal_mutex_create(_mdef) (NULL) +#define osal_mutex_lock(_mutex_hdl, _ms) (true) +#define osal_mutex_unlock(_mutex_hdl) (true) + +#endif + //--------------------------------------------------------------------+ // QUEUE API //--------------------------------------------------------------------+ diff --git a/src/tusb.c b/src/tusb.c index c3787ff8f..f4380f89c 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -74,11 +74,9 @@ bool tu_edpt_claim(tu_edpt_state_t* ep_state, osal_mutex_t mutex) { (void) mutex; -#if TUSB_OPT_MUTEX // pre-check to help reducing mutex lock TU_VERIFY((ep_state->busy == 0) && (ep_state->claimed == 0)); - osal_mutex_lock(mutex, OSAL_TIMEOUT_WAIT_FOREVER); -#endif + (void) osal_mutex_lock(mutex, OSAL_TIMEOUT_WAIT_FOREVER); // can only claim the endpoint if it is not busy and not claimed yet. bool const available = (ep_state->busy == 0) && (ep_state->claimed == 0); @@ -87,9 +85,7 @@ bool tu_edpt_claim(tu_edpt_state_t* ep_state, osal_mutex_t mutex) ep_state->claimed = 1; } -#if TUSB_OPT_MUTEX - osal_mutex_unlock(mutex); -#endif + (void) osal_mutex_unlock(mutex); return available; } @@ -98,9 +94,7 @@ bool tu_edpt_release(tu_edpt_state_t* ep_state, osal_mutex_t mutex) { (void) mutex; -#if TUSB_OPT_MUTEX - osal_mutex_lock(mutex, OSAL_TIMEOUT_WAIT_FOREVER); -#endif + (void) osal_mutex_lock(mutex, OSAL_TIMEOUT_WAIT_FOREVER); // can only release the endpoint if it is claimed and not busy bool const ret = (ep_state->claimed == 1) && (ep_state->busy == 0); @@ -109,9 +103,7 @@ bool tu_edpt_release(tu_edpt_state_t* ep_state, osal_mutex_t mutex) ep_state->claimed = 0; } -#if TUSB_OPT_MUTEX - osal_mutex_unlock(mutex); -#endif + (void) osal_mutex_unlock(mutex); return ret; } diff --git a/src/tusb_option.h b/src/tusb_option.h index f95ae6273..9ca6c794b 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -299,9 +299,6 @@ typedef int make_iso_compilers_happy; #define CFG_TUSB_OS_INC_PATH #endif -// mutex is only needed for RTOS TODO also required with multiple core MCUs -#define TUSB_OPT_MUTEX (CFG_TUSB_OS != OPT_OS_NONE) - //-------------------------------------------------------------------- // Device Options (Default) //-------------------------------------------------------------------- -- cgit v1.3.1 From 1e99480ad28808a29938673d5b05d9461da5d1c1 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 16 Dec 2022 15:19:40 +0700 Subject: fix ci with usbh and unit test --- src/host/usbh.c | 4 ++-- test/unit-test/test/device/msc/test_msc_device.c | 1 + test/unit-test/test/device/usbd/test_usbd.c | 1 + test/unit-test/test/test_fifo.c | 4 +++- 4 files changed, 7 insertions(+), 3 deletions(-) (limited to 'src/host') diff --git a/src/host/usbh.c b/src/host/usbh.c index ff8fbaef3..ca42a523c 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -578,9 +578,9 @@ bool tuh_control_xfer (tuh_xfer_t* xfer) TU_ATTR_ALWAYS_INLINE static inline void _set_control_xfer_stage(uint8_t stage) { - osal_mutex_lock(_usbh_mutex, OSAL_TIMEOUT_WAIT_FOREVER); + (void) osal_mutex_lock(_usbh_mutex, OSAL_TIMEOUT_WAIT_FOREVER); _ctrl_xfer.stage = stage; - osal_mutex_unlock(_usbh_mutex); + (void) osal_mutex_unlock(_usbh_mutex); } static void _xfer_complete(uint8_t daddr, xfer_result_t result) diff --git a/test/unit-test/test/device/msc/test_msc_device.c b/test/unit-test/test/device/msc/test_msc_device.c index 00bb86ccf..63684e76a 100644 --- a/test/unit-test/test/device/msc/test_msc_device.c +++ b/test/unit-test/test/device/msc/test_msc_device.c @@ -28,6 +28,7 @@ #include "unity.h" // Files to test +#include "osal/osal.h" #include "tusb_fifo.h" #include "tusb.h" #include "usbd.h" diff --git a/test/unit-test/test/device/usbd/test_usbd.c b/test/unit-test/test/device/usbd/test_usbd.c index c90383b57..ad95eb47a 100644 --- a/test/unit-test/test/device/usbd/test_usbd.c +++ b/test/unit-test/test/device/usbd/test_usbd.c @@ -25,6 +25,7 @@ #include "unity.h" // Files to test +#include "osal/osal.h" #include "tusb_fifo.h" #include "tusb.h" #include "usbd.h" diff --git a/test/unit-test/test/test_fifo.c b/test/unit-test/test/test_fifo.c index 0a5f4d3b9..1d87081bb 100644 --- a/test/unit-test/test/test_fifo.c +++ b/test/unit-test/test/test_fifo.c @@ -26,6 +26,8 @@ #include #include "unity.h" + +#include "osal/osal.h" #include "tusb_fifo.h" #define FIFO_SIZE 10 @@ -315,4 +317,4 @@ void test_rd_idx_wrap() n = tu_fifo_read_n(&ff10, dst, 4); TEST_ASSERT_EQUAL(n, 2); TEST_ASSERT_EQUAL(ff10.rd_idx, 6); -} \ No newline at end of file +} -- cgit v1.3.1 From f0c51eae44e4cd8f38fdba6469e49b1d98100d7c Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 14 Dec 2022 17:35:01 +0700 Subject: cdc check for bNumEndpoints before checking for endpoint descriptor --- src/class/cdc/cdc_host.c | 64 ++++++++++++++++++++++++++---------------------- src/host/usbh.c | 3 +-- 2 files changed, 36 insertions(+), 31 deletions(-) (limited to 'src/host') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index aa3a7e1e5..83fa1bf5e 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -152,13 +152,43 @@ bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_xf } //--------------------------------------------------------------------+ -// USBH-CLASS DRIVER API +// CLASS-USBH API //--------------------------------------------------------------------+ + void cdch_init(void) { tu_memclr(cdch_data, sizeof(cdch_data)); } +void cdch_close(uint8_t dev_addr) +{ + TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX, ); + + cdch_data_t * p_cdc = get_itf(dev_addr); + + // Invoke application callback + if (tuh_cdc_umount_cb) + { + if (p_cdc->ep_out || p_cdc->ep_in || p_cdc->ep_notif) + { + tuh_cdc_umount_cb(dev_addr); + } + } + + tu_memclr(p_cdc, sizeof(cdch_data_t)); +} + +bool cdch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) +{ + (void) ep_addr; + tuh_cdc_xfer_isr( dev_addr, event, 0, xferred_bytes ); + return true; +} + +//--------------------------------------------------------------------+ +// Enumeration +//--------------------------------------------------------------------+ + bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { (void) rhport; @@ -175,7 +205,7 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it p_cdc->itf_num = itf_desc->bInterfaceNumber; p_cdc->itf_protocol = itf_desc->bInterfaceProtocol; - //------------- Communication Interface -------------// + //------------- Control Interface -------------// uint16_t drv_len = tu_desc_len(itf_desc); uint8_t const * p_desc = tu_desc_next(itf_desc); @@ -192,9 +222,10 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it p_desc = tu_desc_next(p_desc); } - if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) + // Open notification endpoint of control interface if any + if (itf_desc->bNumEndpoints == 1) { - // notification endpoint + TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)); tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; TU_ASSERT( tuh_edpt_open(dev_addr, desc_ep) ); @@ -244,29 +275,4 @@ bool cdch_set_config(uint8_t dev_addr, uint8_t itf_num) return true; } -bool cdch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) -{ - (void) ep_addr; - tuh_cdc_xfer_isr( dev_addr, event, 0, xferred_bytes ); - return true; -} - -void cdch_close(uint8_t dev_addr) -{ - TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX, ); - - cdch_data_t * p_cdc = get_itf(dev_addr); - - // Invoke application callback - if (tuh_cdc_umount_cb) - { - if (p_cdc->ep_out || p_cdc->ep_in || p_cdc->ep_notif) - { - tuh_cdc_umount_cb(dev_addr); - } - } - - tu_memclr(p_cdc, sizeof(cdch_data_t)); -} - #endif diff --git a/src/host/usbh.c b/src/host/usbh.c index ca42a523c..b0cd62bac 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1524,8 +1524,7 @@ static bool _parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configur TU_ASSERT(drv_len >= sizeof(tusb_desc_interface_t)); // Find driver for this interface - uint8_t drv_id; - for (drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) + for (uint8_t drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) { usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id]; -- cgit v1.3.1 From bd1f7f86ce1b6e82c3942d545e984b74b050004e Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 15 Dec 2022 15:27:39 +0700 Subject: add common EPSIZE for bulk/iso in full and highspeed adding cdc host fifo tx/rx --- src/class/cdc/cdc_device.h | 1 - src/class/cdc/cdc_host.c | 71 ++++++++++++++++++++------------------------- src/class/cdc/cdc_host.h | 19 ++++++++++++ src/common/tusb_types.h | 10 ++++++- src/host/usbh_classdriver.h | 4 +++ 5 files changed, 64 insertions(+), 41 deletions(-) (limited to 'src/host') diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index fbc7162a3..f625a7554 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -27,7 +27,6 @@ #ifndef _TUSB_CDC_DEVICE_H_ #define _TUSB_CDC_DEVICE_H_ -#include "common/tusb_common.h" #include "cdc.h" //--------------------------------------------------------------------+ diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 9678b756c..da8ad726b 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -37,7 +37,7 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ typedef struct { - // uint8_t daddr; + uint8_t daddr; uint8_t itf_num; uint8_t itf_protocol; @@ -49,7 +49,6 @@ typedef struct { // Bit 0: DTR (Data Terminal Ready), Bit 1: RTS (Request to Send) // uint8_t line_state; -#if 0 // FIFO tu_fifo_t rx_ff; @@ -64,54 +63,48 @@ typedef struct { #endif // Endpoint Transfer buffer - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUH_CDC_EP_BUFSIZE]; - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUH_CDC_EP_BUFSIZE]; -#endif + CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUH_CDC_RX_EPSIZE]; + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUH_CDC_TX_EPSIZE]; } cdch_interface_t; //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -static cdch_interface_t cdch_data[CFG_TUH_DEVICE_MAX]; + +CFG_TUSB_MEM_SECTION +static cdch_interface_t cdch_data[CFG_TUH_CDC]; static inline cdch_interface_t* get_itf(uint8_t dev_addr) { - return &cdch_data[dev_addr-1]; -} + for(size_t i=0; iep_in && cdc->ep_out; + return NULL; } -bool tuh_cdc_is_busy(uint8_t dev_addr, cdc_pipeid_t pipeid) +static cdch_interface_t* find_new_itf(void) { - if ( !tuh_cdc_mounted(dev_addr) ) return false; - - cdch_interface_t const * p_cdc = get_itf(dev_addr); - - switch (pipeid) + for(size_t i=0; iep_notif ); - - case CDC_PIPE_DATA_IN: - return usbh_edpt_busy(dev_addr, p_cdc->ep_in ); - - case CDC_PIPE_DATA_OUT: - return usbh_edpt_busy(dev_addr, p_cdc->ep_out ); - - default: - return false; + if (cdch_data[i].daddr == 0) return &cdch_data[i]; } + + return NULL; } //--------------------------------------------------------------------+ // APPLICATION API (parameter validation needed) //--------------------------------------------------------------------+ +bool tuh_cdc_mounted(uint8_t dev_addr) +{ + cdch_interface_t* p_cdc = get_itf(dev_addr); + return p_cdc != NULL; +} + uint32_t tuh_cdc_write(uint8_t dev_addr, void const* buffer, uint32_t bufsize) { (void) dev_addr; @@ -121,7 +114,6 @@ uint32_t tuh_cdc_write(uint8_t dev_addr, void const* buffer, uint32_t bufsize) return 0; } - bool tuh_cdc_serial_is_mounted(uint8_t dev_addr) { // TODO consider all AT Command as serial candidate @@ -156,6 +148,7 @@ bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_xfer_cb_t complete_cb) { cdch_interface_t const * p_cdc = get_itf(dev_addr); + TU_VERIFY(p_cdc && p_cdc->acm_capability.support_line_request); tusb_control_request_t const request = { @@ -195,17 +188,13 @@ void cdch_init(void) void cdch_close(uint8_t dev_addr) { - TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX, ); - cdch_interface_t * p_cdc = get_itf(dev_addr); + TU_VERIFY(p_cdc, ); // Invoke application callback if (tuh_cdc_umount_cb) { - if (p_cdc->ep_out || p_cdc->ep_in || p_cdc->ep_notif) - { - tuh_cdc_umount_cb(dev_addr); - } + tuh_cdc_umount_cb(dev_addr); } tu_memclr(p_cdc, sizeof(cdch_interface_t)); @@ -233,8 +222,10 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass && 0xFF != itf_desc->bInterfaceProtocol); - cdch_interface_t * p_cdc = get_itf(dev_addr); + cdch_interface_t * p_cdc = find_new_itf(); + TU_VERIFY(p_cdc); + p_cdc->daddr = dev_addr; p_cdc->itf_num = itf_desc->bInterfaceNumber; p_cdc->itf_protocol = itf_desc->bInterfaceProtocol; @@ -302,9 +293,11 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it bool cdch_set_config(uint8_t dev_addr, uint8_t itf_num) { - (void) dev_addr; (void) itf_num; - if (tuh_cdc_mount_cb) tuh_cdc_mount_cb(dev_addr); + + // notify usbh that driver enumeration is complete + usbh_driver_set_config_complete(dev_addr, itf_num); + return true; } diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index ce1f0f309..b2e75902d 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -37,6 +37,25 @@ // Class Driver Configuration //--------------------------------------------------------------------+ +// RX FIFO size +#ifndef CFG_TUH_CDC_RX_BUFSIZE +#define CFG_TUH_CDC_RX_BUFSIZE USBH_EPSIZE_BULK_MAX +#endif + +// RX Endpoint size +#ifndef CFG_TUH_CDC_RX_EPSIZE +#define CFG_TUH_CDC_RX_EPSIZE USBH_EPSIZE_BULK_MAX +#endif + +// TX FIFO size +#ifndef CFG_TUH_CDC_TX_BUFSIZE +#define CFG_TUH_CDC_TX_BUFSIZE USBH_EPSIZE_BULK_MAX +#endif + +// TX Endpoint size +#ifndef CFG_TUH_CDC_TX_EPSIZE +#define CFG_TUH_CDC_TX_EPSIZE USBH_EPSIZE_BULK_MAX +#endif //--------------------------------------------------------------------+ // Application API diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index 1bfa7c7d1..c4c9d4133 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -69,6 +69,15 @@ typedef enum TUSB_DIR_IN_MASK = 0x80 }tusb_dir_t; +enum +{ + TUSB_EPSIZE_BULK_FS = 64, + TUSB_EPSIZE_BULK_HS= 512, + + TUSB_EPSIZE_ISO_FS_MAX = 1023, + TUSB_EPSIZE_ISO_HS_MAX = 1024, +}; + /// Isochronous End Point Attributes typedef enum { @@ -243,7 +252,6 @@ enum INTERFACE_INVALID_NUMBER = 0xff }; - typedef enum { MS_OS_20_SET_HEADER_DESCRIPTOR = 0x00, diff --git a/src/host/usbh_classdriver.h b/src/host/usbh_classdriver.h index c156afea0..7f72560c3 100644 --- a/src/host/usbh_classdriver.h +++ b/src/host/usbh_classdriver.h @@ -34,6 +34,10 @@ extern "C" { #endif +enum { + USBH_EPSIZE_BULK_MAX = (TUH_OPT_HIGH_SPEED ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS) +}; + //--------------------------------------------------------------------+ // Class Driver API //--------------------------------------------------------------------+ -- cgit v1.3.1 From fc9321ce26ed5662cfa6a48b52507b4a39a8cc08 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 16 Dec 2022 23:54:21 +0700 Subject: correct cdc usbh_driver_set_config_complete() --- src/class/cdc/cdc_host.c | 32 +++++++++++++++++++++----------- src/host/usbh.c | 3 ++- 2 files changed, 23 insertions(+), 12 deletions(-) (limited to 'src/host') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index cb0794fa3..482ccf4be 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -36,13 +36,24 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ +#if 0 +typedef struct { + tu_fifo_t ff; + OSAL_MUTEX_DEF(ff_mutex); +}tu_edpt_stream_t; -//typedef struct { -// tu_fifo_t fifo; -// OSAL_MUTEX_DEF(ff_mutex); -// -// -//}usbh_edpt_stream_t; +uint32_t tud_cdc_read_available (void); +uint32_t tud_cdc_read (void *buffer, uint32_t bufsize); +void tud_cdc_read_flush (void); +bool tud_cdc_peek (uint8_t *ui8); + +uint32_t tud_cdc_write (void const *buffer, uint32_t bufsize); +uint32_t tud_cdc_write_flush (void); +uint32_t tud_cdc_write_available (void); + +//-------------------------------------------------------- +tu_edpt_stream_write() +#endif typedef struct { uint8_t daddr; @@ -65,10 +76,8 @@ typedef struct { uint8_t rx_ff_buf[CFG_TUH_CDC_RX_BUFSIZE]; uint8_t tx_ff_buf[CFG_TUH_CDC_TX_BUFSIZE]; -#if CFG_FIFO_MUTEX - osal_mutex_def_t rx_ff_mutex; - osal_mutex_def_t tx_ff_mutex; -#endif + OSAL_MUTEX_DEF(rx_ff_mutex); + OSAL_MUTEX_DEF(tx_ff_mutex); // Endpoint Transfer buffer CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUH_CDC_RX_EPSIZE]; @@ -311,7 +320,8 @@ bool cdch_set_config(uint8_t dev_addr, uint8_t itf_num) if (tuh_cdc_mount_cb) tuh_cdc_mount_cb(dev_addr); // notify usbh that driver enumeration is complete - usbh_driver_set_config_complete(dev_addr, itf_num); + // itf_num+1 to account for data interface as well + usbh_driver_set_config_complete(dev_addr, itf_num+1); return true; } diff --git a/src/host/usbh.c b/src/host/usbh.c index b0cd62bac..4b278f2da 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1570,7 +1570,8 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) for(itf_num++; itf_num < CFG_TUH_INTERFACE_MAX; itf_num++) { // continue with next valid interface - // TODO skip IAD binding interface such as CDCs + // IAD binding interface such as CDCs should return itf_num + 1 when complete + // with usbh_driver_set_config_complete() uint8_t const drv_id = dev->itf2drv[itf_num]; if (drv_id != DRVID_INVALID) { -- cgit v1.3.1 From d1ea3844f70a5add6e073aa8fa6b562413db4929 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 21 Dec 2022 11:04:57 +0700 Subject: rename TU_LOG_VAR to TU_LOG_PTR, print out setup of failed control transfer when LOG=1 --- src/common/tusb_debug.h | 18 +++++++++--------- src/host/usbh.c | 8 ++++++-- 2 files changed, 15 insertions(+), 11 deletions(-) (limited to 'src/host') diff --git a/src/common/tusb_debug.h b/src/common/tusb_debug.h index ac5bee6ec..65fd1920d 100644 --- a/src/common/tusb_debug.h +++ b/src/common/tusb_debug.h @@ -66,7 +66,7 @@ static inline void tu_print_arr(uint8_t const* buf, uint32_t bufsize) #define TU_LOG(n, ...) TU_XSTRCAT(TU_LOG, n)(__VA_ARGS__) #define TU_LOG_MEM(n, ...) TU_XSTRCAT3(TU_LOG, n, _MEM)(__VA_ARGS__) #define TU_LOG_ARR(n, ...) TU_XSTRCAT3(TU_LOG, n, _ARR)(__VA_ARGS__) -#define TU_LOG_VAR(n, ...) TU_XSTRCAT3(TU_LOG, n, _VAR)(__VA_ARGS__) +#define TU_LOG_PTR(n, ...) TU_XSTRCAT3(TU_LOG, n, _PTR)(__VA_ARGS__) #define TU_LOG_INT(n, ...) TU_XSTRCAT3(TU_LOG, n, _INT)(__VA_ARGS__) #define TU_LOG_HEX(n, ...) TU_XSTRCAT3(TU_LOG, n, _HEX)(__VA_ARGS__) #define TU_LOG_LOCATION() tu_printf("%s: %d:\r\n", __PRETTY_FUNCTION__, __LINE__) @@ -76,7 +76,7 @@ static inline void tu_print_arr(uint8_t const* buf, uint32_t bufsize) #define TU_LOG1 tu_printf #define TU_LOG1_MEM tu_print_mem #define TU_LOG1_ARR(_x, _n) tu_print_arr((uint8_t const*)(_x), _n) -#define TU_LOG1_VAR(_x) tu_print_arr((uint8_t const*)(_x), sizeof(*(_x))) +#define TU_LOG1_PTR(_x) tu_print_arr((uint8_t const*)(_x), sizeof(*(_x))) #define TU_LOG1_INT(_x) tu_printf(#_x " = %ld\r\n", (unsigned long) (_x) ) #define TU_LOG1_HEX(_x) tu_printf(#_x " = %lX\r\n", (unsigned long) (_x) ) @@ -85,7 +85,7 @@ static inline void tu_print_arr(uint8_t const* buf, uint32_t bufsize) #define TU_LOG2 TU_LOG1 #define TU_LOG2_MEM TU_LOG1_MEM #define TU_LOG2_ARR TU_LOG1_ARR - #define TU_LOG2_VAR TU_LOG1_VAR + #define TU_LOG2_PTR TU_LOG1_PTR #define TU_LOG2_INT TU_LOG1_INT #define TU_LOG2_HEX TU_LOG1_HEX #endif @@ -95,7 +95,7 @@ static inline void tu_print_arr(uint8_t const* buf, uint32_t bufsize) #define TU_LOG3 TU_LOG1 #define TU_LOG3_MEM TU_LOG1_MEM #define TU_LOG3_ARR TU_LOG1_ARR - #define TU_LOG3_VAR TU_LOG1_VAR + #define TU_LOG3_PTR TU_LOG1_PTR #define TU_LOG3_INT TU_LOG1_INT #define TU_LOG3_HEX TU_LOG1_HEX #endif @@ -132,7 +132,7 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #ifndef TU_LOG #define TU_LOG(n, ...) #define TU_LOG_MEM(n, ...) - #define TU_LOG_VAR(n, ...) + #define TU_LOG_PTR(n, ...) #define TU_LOG_INT(n, ...) #define TU_LOG_HEX(n, ...) #define TU_LOG_LOCATION() @@ -143,14 +143,14 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #define TU_LOG0(...) #define TU_LOG0_MEM(...) -#define TU_LOG0_VAR(...) +#define TU_LOG0_PTR(...) #define TU_LOG0_INT(...) #define TU_LOG0_HEX(...) #ifndef TU_LOG1 #define TU_LOG1(...) #define TU_LOG1_MEM(...) - #define TU_LOG1_VAR(...) + #define TU_LOG1_PTR(...) #define TU_LOG1_INT(...) #define TU_LOG1_HEX(...) #endif @@ -158,7 +158,7 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #ifndef TU_LOG2 #define TU_LOG2(...) #define TU_LOG2_MEM(...) - #define TU_LOG2_VAR(...) + #define TU_LOG2_PTR(...) #define TU_LOG2_INT(...) #define TU_LOG2_HEX(...) #endif @@ -166,7 +166,7 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #ifndef TU_LOG3 #define TU_LOG3(...) #define TU_LOG3_MEM(...) - #define TU_LOG3_VAR(...) + #define TU_LOG3_PTR(...) #define TU_LOG3_INT(...) #define TU_LOG3_HEX(...) #endif diff --git a/src/host/usbh.c b/src/host/usbh.c index 4b278f2da..59b1c3280 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -540,7 +540,7 @@ bool tuh_control_xfer (tuh_xfer_t* xfer) const uint8_t rhport = usbh_get_rhport(daddr); TU_LOG2("[%u:%u] %s: ", rhport, daddr, xfer->setup->bRequest <= TUSB_REQ_SYNCH_FRAME ? tu_str_std_request[xfer->setup->bRequest] : "Unknown Request"); - TU_LOG2_VAR(xfer->setup); + TU_LOG2_PTR(xfer->setup); TU_LOG2("\r\n"); if (xfer->complete_cb) @@ -618,7 +618,11 @@ static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result if (XFER_RESULT_SUCCESS != result) { - TU_LOG1("[%u:%u] Control %s\r\n", rhport, dev_addr, result == XFER_RESULT_STALLED ? "STALLED" : "FAILED"); + TU_LOG1("[%u:%u] Control %s, xferred_bytes = %lu\r\n", rhport, dev_addr, result == XFER_RESULT_STALLED ? "STALLED" : "FAILED", xferred_bytes); + #if CFG_TUSB_DEBUG == 1 + TU_LOG1_PTR(request); + TU_LOG1("\r\n"); + #endif // terminate transfer if any stage failed _xfer_complete(dev_addr, result); -- cgit v1.3.1 From cb2af4c0bc096e57c3486945eda43dbc26b3829a Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 21 Dec 2022 11:46:58 +0700 Subject: minor debug log --- src/class/cdc/cdc_host.c | 8 +++++ src/class/msc/msc_host.c | 13 +++++--- src/host/usbh.c | 85 ++++++++++++++++++++++++++---------------------- 3 files changed, 63 insertions(+), 43 deletions(-) (limited to 'src/host') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 5aec41cbc..83c623884 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -33,6 +33,12 @@ #include "cdc_host.h" + +// Debug level, TUSB_CFG_DEBUG must be at least this level for debug message +#define CDCH_DEBUG 2 + +#define TU_LOG_CDCH(...) TU_LOG(CDCH_DEBUG, __VA_ARGS__) + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -348,6 +354,8 @@ bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_c cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->acm_capability.support_line_request); + TU_LOG_CDCH("CDC Set Control Line State\r\n"); + tusb_control_request_t const request = { .bmRequestType_bit = diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 32f75a84b..6724e486c 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -33,6 +33,11 @@ #include "msc_host.h" +// Debug level, TUSB_CFG_DEBUG must be at least this level for debug message +#define MSCH_DEBUG 2 + +#define TU_LOG_MSCH(...) TU_LOG(MSCH_DEBUG, __VA_ARGS__) + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -417,7 +422,7 @@ bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) p_msc->configured = true; //------------- Get Max Lun -------------// - TU_LOG2("MSC Get Max Lun\r\n"); + TU_LOG_MSCH("MSC Get Max Lun\r\n"); tusb_control_request_t const request = { .bmRequestType_bit = @@ -456,7 +461,7 @@ static void config_get_maxlun_complete (tuh_xfer_t* xfer) p_msc->max_lun++; // MAX LUN is minus 1 by specs // TODO multiple LUN support - TU_LOG2("SCSI Test Unit Ready\r\n"); + TU_LOG_MSCH("SCSI Test Unit Ready\r\n"); uint8_t const lun = 0; tuh_msc_test_unit_ready(daddr, lun, config_test_unit_ready_complete, 0); } @@ -469,14 +474,14 @@ static bool config_test_unit_ready_complete(uint8_t dev_addr, tuh_msc_complete_d if (csw->status == 0) { // Unit is ready, read its capacity - TU_LOG2("SCSI Read Capacity\r\n"); + TU_LOG_MSCH("SCSI Read Capacity\r\n"); tuh_msc_read_capacity(dev_addr, cbw->lun, (scsi_read_capacity10_resp_t*) ((void*) _msch_buffer), config_read_capacity_complete, 0); }else { // Note: During enumeration, some device fails Test Unit Ready and require a few retries // with Request Sense to start working !! // TODO limit number of retries - TU_LOG2("SCSI Request Sense\r\n"); + TU_LOG_MSCH("SCSI Request Sense\r\n"); TU_ASSERT(tuh_msc_request_sense(dev_addr, cbw->lun, _msch_buffer, config_request_sense_complete, 0)); } diff --git a/src/host/usbh.c b/src/host/usbh.c index 59b1c3280..36fc5fded 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -46,8 +46,10 @@ #define CFG_TUH_INTERFACE_MAX 8 #endif -// Debug level of USBD -#define USBH_DBG_LVL 2 +// Debug level, TUSB_CFG_DEBUG must be at least this level for debug message +#define USBH_DEBUG 2 + +#define TU_LOG_USBH(...) TU_LOG(USBH_DEBUG, __VA_ARGS__) //--------------------------------------------------------------------+ // USBH-HCD common data structure @@ -324,11 +326,11 @@ bool tuh_init(uint8_t controller_id) // skip if already initialized if ( tuh_inited() ) return true; - TU_LOG2("USBH init on controller %u\r\n", controller_id); - TU_LOG2_INT(sizeof(usbh_device_t)); - TU_LOG2_INT(sizeof(hcd_event_t)); - TU_LOG2_INT(sizeof(_ctrl_xfer)); - TU_LOG2_INT(sizeof(tuh_xfer_t)); + TU_LOG_USBH("USBH init on controller %u\r\n", controller_id); + TU_LOG_INT(USBH_DEBUG, sizeof(usbh_device_t)); + TU_LOG_INT(USBH_DEBUG, sizeof(hcd_event_t)); + TU_LOG_INT(USBH_DEBUG, sizeof(_ctrl_xfer)); + TU_LOG_INT(USBH_DEBUG, sizeof(tuh_xfer_t)); // Event queue _usbh_q = osal_queue_create( &_usbh_qdef ); @@ -353,7 +355,7 @@ bool tuh_init(uint8_t controller_id) // Class drivers for (uint8_t drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) { - TU_LOG2("%s init\r\n", usbh_class_drivers[drv_id].name); + TU_LOG_USBH("%s init\r\n", usbh_class_drivers[drv_id].name); usbh_class_drivers[drv_id].init(); } @@ -401,12 +403,12 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) case HCD_EVENT_DEVICE_ATTACH: // TODO due to the shared _usbh_ctrl_buf, we must complete enumerating // one device before enumerating another one. - TU_LOG2("[%u:] USBH DEVICE ATTACH\r\n", event.rhport); + TU_LOG_USBH("[%u:] USBH DEVICE ATTACH\r\n", event.rhport); enum_new_device(&event); break; case HCD_EVENT_DEVICE_REMOVE: - TU_LOG2("[%u:%u:%u] USBH DEVICE REMOVED\r\n", event.rhport, event.connection.hub_addr, event.connection.hub_port); + TU_LOG_USBH("[%u:%u:%u] USBH DEVICE REMOVED\r\n", event.rhport, event.connection.hub_addr, event.connection.hub_port); process_device_unplugged(event.rhport, event.connection.hub_addr, event.connection.hub_port); #if CFG_TUH_HUB @@ -425,7 +427,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const ep_dir = tu_edpt_dir(ep_addr); - TU_LOG2("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); + TU_LOG_USBH("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); if (event.dev_addr == 0) { @@ -449,7 +451,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) uint8_t drv_id = dev->ep2drv[epnum][ep_dir]; if(drv_id < USBH_CLASS_DRIVER_COUNT) { - TU_LOG2("%s xfer callback\r\n", usbh_class_drivers[drv_id].name); + TU_LOG_USBH("%s xfer callback\r\n", usbh_class_drivers[drv_id].name); usbh_class_drivers[drv_id].xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); } else @@ -539,9 +541,11 @@ bool tuh_control_xfer (tuh_xfer_t* xfer) TU_VERIFY(is_idle); const uint8_t rhport = usbh_get_rhport(daddr); - TU_LOG2("[%u:%u] %s: ", rhport, daddr, xfer->setup->bRequest <= TUSB_REQ_SYNCH_FRAME ? tu_str_std_request[xfer->setup->bRequest] : "Unknown Request"); - TU_LOG2_PTR(xfer->setup); - TU_LOG2("\r\n"); + TU_LOG_USBH("[%u:%u] %s: ", rhport, daddr, + (xfer->setup->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && xfer->setup->bRequest <= TUSB_REQ_SYNCH_FRAME) ? + tu_str_std_request[xfer->setup->bRequest] : "Class Request"); + TU_LOG_PTR(USBH_DEBUG, xfer->setup); + TU_LOG_USBH("\r\n"); if (xfer->complete_cb) { @@ -585,7 +589,7 @@ TU_ATTR_ALWAYS_INLINE static inline void _set_control_xfer_stage(uint8_t stage) static void _xfer_complete(uint8_t daddr, xfer_result_t result) { - TU_LOG2("\r\n"); + TU_LOG_USBH("\r\n"); // duplicate xfer since user can execute control transfer within callback tusb_control_request_t const request = _ctrl_xfer.request; @@ -643,8 +647,8 @@ static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result case CONTROL_STAGE_DATA: if (request->wLength) { - TU_LOG2("[%u:%u] Control data:\r\n", rhport, dev_addr); - TU_LOG2_MEM(_ctrl_xfer.buffer, xferred_bytes, 2); + TU_LOG_USBH("[%u:%u] Control data:\r\n", rhport, dev_addr); + TU_LOG_MEM(USBH_DEBUG, _ctrl_xfer.buffer, xferred_bytes, 2); } _ctrl_xfer.actual_len = (uint16_t) xferred_bytes; @@ -760,7 +764,7 @@ bool usbh_edpt_xfer_with_callback(uint8_t dev_addr, uint8_t ep_addr, uint8_t * b uint8_t const dir = tu_edpt_dir(ep_addr); tu_edpt_state_t* ep_state = &dev->ep_status[epnum][dir]; - TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); + TU_LOG_USBH(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); // Attempt to transfer on a busy endpoint, sound like an race condition ! TU_ASSERT(ep_state->busy == 0); @@ -776,7 +780,7 @@ bool usbh_edpt_xfer_with_callback(uint8_t dev_addr, uint8_t ep_addr, uint8_t * b if ( hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes) ) { - TU_LOG2("OK\r\n"); + TU_LOG_USBH("OK\r\n"); return true; }else { @@ -791,7 +795,7 @@ bool usbh_edpt_xfer_with_callback(uint8_t dev_addr, uint8_t ep_addr, uint8_t * b static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) { - TU_LOG2("[%u:%u] Open EP0 with Size = %u\r\n", usbh_get_rhport(dev_addr), dev_addr, max_packet_size); + TU_LOG_USBH("[%u:%u] Open EP0 with Size = %u\r\n", usbh_get_rhport(dev_addr), dev_addr, max_packet_size); tusb_desc_endpoint_t ep0_desc = { @@ -960,7 +964,7 @@ bool tuh_descriptor_get_serial_string(uint8_t daddr, uint16_t language_id, void* bool tuh_descriptor_get_hid_report(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, uint8_t index, void* buffer, uint16_t len, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_LOG2("HID Get Report Descriptor\r\n"); + TU_LOG_USBH("HID Get Report Descriptor\r\n"); tusb_control_request_t const request = { .bmRequestType_bit = @@ -999,7 +1003,7 @@ bool tuh_descriptor_get_hid_report(uint8_t daddr, uint8_t itf_num, uint8_t desc_ bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_LOG2("Set Configuration = %d\r\n", config_num); + TU_LOG_USBH("Set Configuration = %d\r\n", config_num); tusb_control_request_t const request = { @@ -1103,11 +1107,11 @@ static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t h (hub_port == 0 || dev->hub_port == hub_port) && // hub_port = 0 means all devices of downstream hub dev->connected) { - TU_LOG2(" Address = %u\r\n", dev_addr); + TU_LOG_USBH(" Address = %u\r\n", dev_addr); if (is_hub_addr(dev_addr)) { - TU_LOG(USBH_DBG_LVL, "HUB address = %u is unmounted\r\n", dev_addr); + TU_LOG(USBH_DEBUG, "HUB address = %u is unmounted\r\n", dev_addr); // If the device itself is a usb hub, unplug downstream devices. // FIXME un-roll recursive calls to prevent potential stack overflow process_device_unplugged(rhport, dev_addr, 0); @@ -1120,7 +1124,7 @@ static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t h // Close class driver for (uint8_t drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) { - TU_LOG2("%s close\r\n", usbh_class_drivers[drv_id].name); + TU_LOG_USBH("%s close\r\n", usbh_class_drivers[drv_id].name); usbh_class_drivers[drv_id].close(dev_addr); } @@ -1245,7 +1249,7 @@ static void process_enumeration(tuh_xfer_t* xfer) TU_ASSERT( usbh_edpt_control_open(addr0, 8), ); // Get first 8 bytes of device descriptor for Control Endpoint size - TU_LOG2("Get 8 byte of Device Descriptor\r\n"); + TU_LOG_USBH("Get 8 byte of Device Descriptor\r\n"); TU_ASSERT(tuh_descriptor_get_device(addr0, _usbh_ctrl_buf, 8, process_enumeration, ENUM_SET_ADDR), ); } break; @@ -1254,7 +1258,7 @@ static void process_enumeration(tuh_xfer_t* xfer) case ENUM_RESET_2: // TODO not used by now, but may be needed for some devices !? // Reset device again before Set Address - TU_LOG2("Port reset2 \r\n"); + TU_LOG_USBH("Port reset2 \r\n"); if (_dev0.hub_addr == 0) { // connected directly to roothub @@ -1294,7 +1298,7 @@ static void process_enumeration(tuh_xfer_t* xfer) TU_ASSERT( usbh_edpt_control_open(new_addr, new_dev->ep0_size), ); // Get full device descriptor - TU_LOG2("Get Device Descriptor\r\n"); + TU_LOG_USBH("Get Device Descriptor\r\n"); TU_ASSERT(tuh_descriptor_get_device(new_addr, _usbh_ctrl_buf, sizeof(tusb_desc_device_t), process_enumeration, ENUM_GET_9BYTE_CONFIG_DESC), ); } break; @@ -1315,7 +1319,7 @@ static void process_enumeration(tuh_xfer_t* xfer) // Get 9-byte for total length uint8_t const config_idx = CONFIG_NUM - 1; - TU_LOG2("Get Configuration[0] Descriptor (9 bytes)\r\n"); + TU_LOG_USBH("Get Configuration[0] Descriptor (9 bytes)\r\n"); TU_ASSERT( tuh_descriptor_get_configuration(daddr, config_idx, _usbh_ctrl_buf, 9, process_enumeration, ENUM_GET_FULL_CONFIG_DESC), ); } break; @@ -1332,7 +1336,7 @@ static void process_enumeration(tuh_xfer_t* xfer) // Get full configuration descriptor uint8_t const config_idx = CONFIG_NUM - 1; - TU_LOG2("Get Configuration[0] Descriptor\r\n"); + TU_LOG_USBH("Get Configuration[0] Descriptor\r\n"); TU_ASSERT( tuh_descriptor_get_configuration(daddr, config_idx, _usbh_ctrl_buf, total_len, process_enumeration, ENUM_SET_CONFIG), ); } break; @@ -1347,7 +1351,7 @@ static void process_enumeration(tuh_xfer_t* xfer) case ENUM_CONFIG_DRIVER: { - TU_LOG2("Device configured\r\n"); + TU_LOG_USBH("Device configured\r\n"); usbh_device_t* dev = get_device(daddr); TU_ASSERT(dev, ); @@ -1387,7 +1391,7 @@ static bool enum_new_device(hcd_event_t* event) if ( !hcd_port_connect_status(_dev0.rhport) ) return true; _dev0.speed = hcd_port_speed_get(_dev0.rhport ); - TU_LOG2("%s Speed\r\n", tu_str_speed[_dev0.speed]); + TU_LOG_USBH("%s Speed\r\n", tu_str_speed[_dev0.speed]); // fake transfer to kick-off the enumeration process tuh_xfer_t xfer; @@ -1444,7 +1448,7 @@ static bool enum_request_set_addr(void) uint8_t const new_addr = get_new_address(desc_device->bDeviceClass == TUSB_CLASS_HUB); TU_ASSERT(new_addr != 0); - TU_LOG2("Set Address = %d\r\n", new_addr); + TU_LOG_USBH("Set Address = %d\r\n", new_addr); usbh_device_t* new_dev = get_device(new_addr); @@ -1488,9 +1492,12 @@ static bool _parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configur { usbh_device_t* dev = get_device(dev_addr); - uint8_t const* desc_end = ((uint8_t const*) desc_cfg) + tu_le16toh(desc_cfg->wTotalLength); + uint16_t const total_len = tu_le16toh(desc_cfg->wTotalLength); + uint8_t const* desc_end = ((uint8_t const*) desc_cfg) + total_len; uint8_t const* p_desc = tu_desc_next(desc_cfg); + TU_LOG_USBH("Parsing Configuration descriptor (wTotalLength = %u)\r\n", total_len); + // parse each interfaces while( p_desc < desc_end ) { @@ -1535,7 +1542,7 @@ static bool _parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configur if ( driver->open(dev->rhport, dev_addr, desc_itf, drv_len) ) { // open successfully - TU_LOG2(" %s opened\r\n", driver->name); + TU_LOG_USBH(" %s opened\r\n", driver->name); // bind (associated) interfaces to found driver for(uint8_t i=0; i= USBH_CLASS_DRIVER_COUNT ) { - TU_LOG(USBH_DBG_LVL, "Interface %u: class = %u subclass = %u protocol = %u is not supported\r\n", + TU_LOG(USBH_DEBUG, "Interface %u: class = %u subclass = %u protocol = %u is not supported\r\n", desc_itf->bInterfaceNumber, desc_itf->bInterfaceClass, desc_itf->bInterfaceSubClass, desc_itf->bInterfaceProtocol); } } @@ -1580,7 +1587,7 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) if (drv_id != DRVID_INVALID) { usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id]; - TU_LOG2("%s set config: itf = %u\r\n", driver->name, itf_num); + TU_LOG_USBH("%s set config: itf = %u\r\n", driver->name, itf_num); driver->set_config(dev_addr, itf_num); break; } @@ -1593,7 +1600,7 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) if (is_hub_addr(dev_addr)) { - TU_LOG(USBH_DBG_LVL, "HUB address = %u is mounted\r\n", dev_addr); + TU_LOG(USBH_DEBUG, "HUB address = %u is mounted\r\n", dev_addr); }else { // Invoke callback if available -- cgit v1.3.1 From 8323e4b79a2052aee814ca8811e841bceb6a7a7d Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 22 Dec 2022 00:34:35 +0700 Subject: moving edpt_stream API into common tusb.c --- src/class/cdc/cdc_host.c | 179 ++++++++++---------------------------------- src/common/tusb_private.h | 92 ++++++++++++++++++++++- src/host/usbh.c | 1 - src/host/usbh_classdriver.h | 1 + src/tusb.c | 112 +++++++++++++++++++++++++-- 5 files changed, 239 insertions(+), 146 deletions(-) (limited to 'src/host') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 2f3406378..54d81dc0d 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -42,56 +42,23 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -typedef struct { - tu_fifo_t ff; - - // mutex: read if ep rx, write if e tx - OSAL_MUTEX_DEF(ff_mutex); - - // TODO xfer_fifo can skip this buffer - uint8_t* ep_buf; - uint16_t ep_bufsize; - uint8_t ep_addr; -}tu_edpt_stream_t; - -bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool use_wr_mutex, bool overwritable, - void* ff_buf, uint16_t ff_bufsize, - uint8_t* ep_buf, uint16_t ep_bufsize) -{ - osal_mutex_t new_mutex = osal_mutex_create(&s->ff_mutex); - (void) new_mutex; - (void) use_wr_mutex; - - tu_fifo_config(&s->ff, ff_buf, ff_bufsize, 1, overwritable); - tu_fifo_config_mutex(&s->ff, use_wr_mutex ? new_mutex : NULL, use_wr_mutex ? NULL : new_mutex); - - s->ep_buf = ep_buf; - s->ep_bufsize = ep_bufsize; - - return true; -} - -bool tu_edpt_stream_clear(tu_edpt_stream_t* s) -{ - return tu_fifo_clear(&s->ff); -} -bool tu_edpt_stream_write_zlp_if_needed(uint8_t daddr, tu_edpt_stream_t* s, uint32_t last_xferred_bytes) +bool tu_edpt_stream_write_zlp_if_needed(tu_edpt_stream_t* s, uint32_t last_xferred_bytes) { - uint16_t const bulk_packet_size = (tuh_speed_get(daddr) == TUSB_SPEED_HIGH) ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS; + uint16_t const bulk_packet_size = (s->ep_speed == TUSB_SPEED_HIGH) ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS; // ZLP condition: no pending data, last transferred bytes is multiple of packet size TU_VERIFY( !tu_fifo_count(&s->ff) && last_xferred_bytes && (0 == (last_xferred_bytes & (bulk_packet_size-1))) ); - if ( usbh_edpt_claim(daddr, s->ep_addr) ) + if ( usbh_edpt_claim(s->daddr, s->ep_addr) ) { - TU_ASSERT( usbh_edpt_xfer(daddr, s->ep_addr, NULL, 0) ); + TU_ASSERT( usbh_edpt_xfer(s->daddr, s->ep_addr, NULL, 0) ); } return true; } -uint32_t tu_edpt_stream_write_xfer(uint8_t daddr, tu_edpt_stream_t* s) +uint32_t tu_edpt_stream_write_xfer(tu_edpt_stream_t* s) { // skip if no data TU_VERIFY( tu_fifo_count(&s->ff), 0 ); @@ -99,7 +66,7 @@ uint32_t tu_edpt_stream_write_xfer(uint8_t daddr, tu_edpt_stream_t* s) // Claim the endpoint // uint8_t const rhport = 0; // TU_VERIFY( usbd_edpt_claim(rhport, p_cdc->ep_in), 0 ); - TU_VERIFY( usbh_edpt_claim(daddr, s->ep_addr) ); + TU_VERIFY( usbh_edpt_claim(s->daddr, s->ep_addr) ); // Pull data from FIFO -> EP buf uint16_t const count = tu_fifo_read_n(&s->ff, s->ep_buf, s->ep_bufsize); @@ -107,7 +74,7 @@ uint32_t tu_edpt_stream_write_xfer(uint8_t daddr, tu_edpt_stream_t* s) if ( count ) { //TU_ASSERT( usbd_edpt_xfer(rhport, p_cdc->ep_in, p_cdc->epin_buf, count), 0 ); - TU_ASSERT( usbh_edpt_xfer(daddr, s->ep_addr, s->ep_buf, count), 0 ); + TU_ASSERT( usbh_edpt_xfer(s->daddr, s->ep_addr, s->ep_buf, count), 0 ); return count; }else { @@ -115,93 +82,28 @@ uint32_t tu_edpt_stream_write_xfer(uint8_t daddr, tu_edpt_stream_t* s) // Note: data is dropped if terminal is not connected //usbd_edpt_release(rhport, p_cdc->ep_in); - usbh_edpt_release(daddr, s->ep_addr); + usbh_edpt_release(s->daddr, s->ep_addr); return 0; } } -uint32_t tu_edpt_stream_write(uint8_t daddr, tu_edpt_stream_t* s, void const *buffer, uint32_t bufsize) -{ - uint16_t ret = tu_fifo_write_n(&s->ff, buffer, (uint16_t) bufsize); - - // flush if queue more than packet size - uint16_t const bulk_packet_size = (tuh_speed_get(daddr) == TUSB_SPEED_HIGH) ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS; - if ( (tu_fifo_count(&s->ff) >= bulk_packet_size) - /* || ((CFG_TUD_CDC_TX_BUFSIZE < BULK_PACKET_SIZE) && tu_fifo_full(&p_cdc->tx_ff)) */ ) - { - tu_edpt_stream_write_xfer(daddr, s); - } - - return ret; -} - -void tu_edpt_stream_read_xfer_complete(tu_edpt_stream_t* s, uint32_t xferred_bytes) -{ - tu_fifo_write_n(&s->ff, s->ep_buf, (uint16_t) xferred_bytes); -} - -uint32_t tu_edpt_stream_read_xfer(uint8_t daddr, tu_edpt_stream_t* s) +uint32_t tu_edpt_stream_write(tu_edpt_stream_t* s, void const *buffer, uint32_t bufsize) { - uint16_t available = tu_fifo_remaining(&s->ff); + TU_VERIFY(bufsize); // TODO support ZLP - // Prepare for incoming data but only allow what we can store in the ring buffer. - // TODO Actually we can still carry out the transfer, keeping count of received bytes - // and slowly move it to the FIFO when read(). - // This pre-check reduces endpoint claiming - uint16_t const bulk_packet_size = (tuh_speed_get(daddr) == TUSB_SPEED_HIGH) ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS; - TU_VERIFY(available >= bulk_packet_size); - - // claim endpoint - TU_VERIFY(usbh_edpt_claim(daddr, s->ep_addr), 0); - - // fifo can be changed before endpoint is claimed - available = tu_fifo_remaining(&s->ff); - - if ( available >= bulk_packet_size ) - { - // multiple of packet size limit by ep bufsize - uint16_t count = (uint16_t) (available & (bulk_packet_size -1)); - count = tu_min16(count, s->ep_bufsize); + uint16_t ret = tu_fifo_write_n(&s->ff, buffer, (uint16_t) bufsize); - TU_ASSERT( usbh_edpt_xfer(daddr, s->ep_addr, s->ep_buf, count), 0 ); - return count; - }else + // flush if fifo has more than packet size or + // in rare case: fifo depth is configured too small (which never reach packet size) + uint16_t const bulk_packet_size = (s->ep_speed == TUSB_SPEED_HIGH) ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS; + if ( (tu_fifo_count(&s->ff) >= bulk_packet_size) || ( tu_fifo_depth(&s->ff) < bulk_packet_size) ) { - // Release endpoint since we don't make any transfer - usbh_edpt_release(daddr, s->ep_addr); - return 0; + tu_edpt_stream_write_xfer(s); } -} - -uint32_t tu_edpt_stream_read(uint8_t daddr, tu_edpt_stream_t* s, void* buffer, uint32_t bufsize) -{ - uint32_t num_read = tu_fifo_read_n(&s->ff, buffer, (uint16_t) bufsize); - tu_edpt_stream_read_xfer(daddr, s); - return num_read; -} - -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); -} -bool tu_edpt_stream_read_clear(uint8_t daddr, tu_edpt_stream_t* s) -{ - bool ret = tu_fifo_clear(&s->ff); - tu_edpt_stream_read_xfer(daddr, s); return ret; } -bool tu_edpt_stream_write_clear(tu_edpt_stream_t* s) -{ - return tu_fifo_clear(&s->ff); -} - typedef struct { uint8_t daddr; uint8_t bInterfaceNumber; @@ -326,7 +228,7 @@ uint32_t tuh_cdc_write(uint8_t idx, void const* buffer, uint32_t bufsize) cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - return tu_edpt_stream_write(p_cdc->daddr, &p_cdc->stream.tx, buffer, bufsize); + return tu_edpt_stream_write(&p_cdc->stream.tx, buffer, bufsize); } uint32_t tuh_cdc_write_flush(uint8_t idx) @@ -334,7 +236,7 @@ uint32_t tuh_cdc_write_flush(uint8_t idx) cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - return tu_edpt_stream_write_xfer(p_cdc->daddr, &p_cdc->stream.tx); + return tu_edpt_stream_write_xfer(&p_cdc->stream.tx); } bool tuh_cdc_write_clear(uint8_t idx) @@ -342,7 +244,7 @@ bool tuh_cdc_write_clear(uint8_t idx) cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - return tu_edpt_stream_write_clear(&p_cdc->stream.tx); + return tu_edpt_stream_clear(&p_cdc->stream.tx); } uint32_t tuh_cdc_write_available(uint8_t idx) @@ -358,7 +260,7 @@ uint32_t tuh_cdc_read (uint8_t idx, void* buffer, uint32_t bufsize) cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - return tu_edpt_stream_read(p_cdc->daddr, &p_cdc->stream.rx, buffer, bufsize); + return tu_edpt_stream_read(&p_cdc->stream.rx, buffer, bufsize); } uint32_t tuh_cdc_read_available(uint8_t idx) @@ -374,7 +276,9 @@ bool tuh_cdc_read_clear (uint8_t idx) cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - return tu_edpt_stream_read_clear(p_cdc->daddr, &p_cdc->stream.rx); + bool ret = tu_edpt_stream_clear(&p_cdc->stream.rx); + tu_edpt_stream_read_xfer(&p_cdc->stream.rx); + return ret; } //--------------------------------------------------------------------+ @@ -452,13 +356,13 @@ void cdch_init(void) { cdch_interface_t* p_cdc = &cdch_data[i]; - tu_edpt_stream_init(&p_cdc->stream.tx, true, false, - p_cdc->stream.tx_ff_buf, CFG_TUH_CDC_TX_BUFSIZE, - p_cdc->stream.tx_ep_buf, CFG_TUH_CDC_TX_EPSIZE); + tu_edpt_stream_init(&p_cdc->stream.tx, true, true, false, + p_cdc->stream.tx_ff_buf, CFG_TUH_CDC_TX_BUFSIZE, + p_cdc->stream.tx_ep_buf, CFG_TUH_CDC_TX_EPSIZE); - tu_edpt_stream_init(&p_cdc->stream.rx, false, false, - p_cdc->stream.rx_ff_buf, CFG_TUH_CDC_RX_BUFSIZE, - p_cdc->stream.rx_ep_buf, CFG_TUH_CDC_RX_EPSIZE); + tu_edpt_stream_init(&p_cdc->stream.rx, true, false, false, + p_cdc->stream.rx_ff_buf, CFG_TUH_CDC_RX_BUFSIZE, + p_cdc->stream.rx_ep_buf, CFG_TUH_CDC_RX_EPSIZE); } } @@ -475,8 +379,6 @@ void cdch_close(uint8_t daddr) //tu_memclr(p_cdc, sizeof(cdch_interface_t)); p_cdc->daddr = 0; p_cdc->bInterfaceNumber = 0; - tu_edpt_stream_clear(&p_cdc->stream.tx); - tu_edpt_stream_clear(&p_cdc->stream.rx); } } } @@ -495,23 +397,22 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t // invoke tx complete callback to possibly refill tx fifo if (tuh_cdc_tx_complete_cb) tuh_cdc_tx_complete_cb(idx); - if ( 0 == tu_edpt_stream_write_xfer(daddr, &p_cdc->stream.tx) ) + if ( 0 == tu_edpt_stream_write_xfer(&p_cdc->stream.tx) ) { // If there is no data left, a ZLP should be sent if needed // xferred_bytes is multiple of EP Packet size and not zero - tu_edpt_stream_write_zlp_if_needed(daddr, &p_cdc->stream.tx, xferred_bytes); + tu_edpt_stream_write_zlp_if_needed(&p_cdc->stream.tx, xferred_bytes); } } else if ( ep_addr == p_cdc->stream.rx.ep_addr ) { - // skip if ZLP - if (xferred_bytes) tu_edpt_stream_read_xfer_complete(&p_cdc->stream.rx, 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(idx); // prepare for next transfer if needed - tu_edpt_stream_read_xfer(daddr, &p_cdc->stream.rx); + tu_edpt_stream_read_xfer(&p_cdc->stream.rx); }else if ( ep_addr == p_cdc->ep_notif ) { // TODO handle notification endpoint @@ -527,7 +428,7 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t // Enumeration //--------------------------------------------------------------------+ -bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) +bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { (void) rhport; @@ -542,7 +443,7 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it cdch_interface_t * p_cdc = find_new_itf(); TU_VERIFY(p_cdc); - p_cdc->daddr = dev_addr; + p_cdc->daddr = daddr; p_cdc->bInterfaceNumber = itf_desc->bInterfaceNumber; p_cdc->bInterfaceSubClass = itf_desc->bInterfaceSubClass; p_cdc->bInterfaceProtocol = itf_desc->bInterfaceProtocol; @@ -569,7 +470,7 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)); tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT( tuh_edpt_open(dev_addr, desc_ep) ); + TU_ASSERT( tuh_edpt_open(daddr, desc_ep) ); p_cdc->ep_notif = desc_ep->bEndpointAddress; p_desc = tu_desc_next(p_desc); @@ -589,14 +490,14 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_BULK == desc_ep->bmAttributes.xfer); - TU_ASSERT(tuh_edpt_open(dev_addr, desc_ep)); + TU_ASSERT(tuh_edpt_open(daddr, desc_ep)); if ( tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN ) { - p_cdc->stream.rx.ep_addr = desc_ep->bEndpointAddress; + tu_edpt_stream_open(&p_cdc->stream.rx, daddr, desc_ep); }else { - p_cdc->stream.tx.ep_addr = desc_ep->bEndpointAddress; + tu_edpt_stream_open(&p_cdc->stream.tx, daddr, desc_ep); } p_desc = tu_desc_next(p_desc); @@ -616,7 +517,7 @@ static void config_cdc_complete(uint8_t daddr, uint8_t itf_num) // Prepare for incoming data cdch_interface_t* p_cdc = get_itf(idx); - tu_edpt_stream_read_xfer(daddr, &p_cdc->stream.rx); + tu_edpt_stream_read_xfer(&p_cdc->stream.rx); } // notify usbh that driver enumeration is complete diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h index b34506f65..01078eed3 100644 --- a/src/common/tusb_private.h +++ b/src/common/tusb_private.h @@ -28,6 +28,8 @@ #ifndef _TUSB_PRIVATE_H_ #define _TUSB_PRIVATE_H_ +// Internal Helper used by Host and Device Stack + #ifdef __cplusplus extern "C" { #endif @@ -39,8 +41,31 @@ typedef struct TU_ATTR_PACKED volatile uint8_t claimed : 1; }tu_edpt_state_t; +typedef struct { + bool is_host; // host or device most + union { + uint8_t daddr; + uint8_t rhport; + uint8_t hwid; + }; + uint8_t ep_addr; + uint8_t ep_speed; + + uint16_t ep_packetsize; + uint16_t ep_bufsize; + + // TODO xfer_fifo can skip this buffer + uint8_t* ep_buf; + + tu_fifo_t ff; + + // mutex: read if ep rx, write if e tx + OSAL_MUTEX_DEF(ff_mutex); + +}tu_edpt_stream_t; + //--------------------------------------------------------------------+ -// Internal Helper used by Host and Device Stack +// Endpoint //--------------------------------------------------------------------+ // Check if endpoint descriptor is valid per USB specs @@ -58,6 +83,71 @@ bool tu_edpt_claim(tu_edpt_state_t* ep_state, osal_mutex_t mutex); // Release an endpoint with provided mutex bool tu_edpt_release(tu_edpt_state_t* ep_state, osal_mutex_t mutex); +//--------------------------------------------------------------------+ +// Endpoint Stream +//--------------------------------------------------------------------+ + +// Init an stream, should only called once +bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool is_host, bool is_tx, bool overwritable, + void* ff_buf, uint16_t ff_bufsize, uint8_t* ep_buf, uint16_t ep_bufsize); + +// Open an stream for an endpoint +// hwid is either device address (host mode) or rhport (device mode) +TU_ATTR_ALWAYS_INLINE static inline +void tu_edpt_stream_open(tu_edpt_stream_t* s, uint8_t hwid, tusb_desc_endpoint_t const *desc_ep) +{ + tu_fifo_clear(&s->ff); + s->hwid = hwid; + s->ep_addr = desc_ep->bEndpointAddress; + s->ep_packetsize = tu_edpt_packet_size(desc_ep); +} + +// Clear fifo +TU_ATTR_ALWAYS_INLINE static inline +bool tu_edpt_stream_clear(tu_edpt_stream_t* s) +{ + return tu_fifo_clear(&s->ff); +} + +//------------- Write -------------// + +// Write to stream +uint32_t tu_edpt_stream_write(tu_edpt_stream_t* s, void const *buffer, uint32_t bufsize); + +// Start an usb transfer if endpoint is not busy +uint32_t tu_edpt_stream_write_xfer(tu_edpt_stream_t* s); + +// Get the number of bytes available for writing +TU_ATTR_ALWAYS_INLINE static inline +uint32_t tu_edpt_stream_write_available(tu_edpt_stream_t* s) +{ + return (uint32_t) tu_fifo_remaining(&s->ff); +} + + +//------------- Read -------------// + +// Read from stream +uint32_t tu_edpt_stream_read(tu_edpt_stream_t* s, void* buffer, uint32_t bufsize); + +// Start an usb transfer if endpoint is not busy +uint32_t tu_edpt_stream_read_xfer(tu_edpt_stream_t* s); + +// Must be called in the transfer complete callback +TU_ATTR_ALWAYS_INLINE static inline +void tu_edpt_stream_read_xfer_complete(tu_edpt_stream_t* s, uint32_t xferred_bytes) +{ + tu_fifo_write_n(&s->ff, s->ep_buf, (uint16_t) xferred_bytes); +} + +// Get the number of bytes available for reading +TU_ATTR_ALWAYS_INLINE static inline +uint32_t tu_edpt_stream_read_available(tu_edpt_stream_t* s) +{ + return (uint32_t) tu_fifo_count(&s->ff); +} + + #ifdef __cplusplus } #endif diff --git a/src/host/usbh.c b/src/host/usbh.c index 36fc5fded..f0ca7be2e 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -30,7 +30,6 @@ #include "host/hcd.h" #include "tusb.h" -#include "common/tusb_private.h" #include "host/usbh_classdriver.h" #include "hub.h" diff --git a/src/host/usbh_classdriver.h b/src/host/usbh_classdriver.h index 7f72560c3..be9811641 100644 --- a/src/host/usbh_classdriver.h +++ b/src/host/usbh_classdriver.h @@ -29,6 +29,7 @@ #include "osal/osal.h" #include "common/tusb_fifo.h" +#include "common/tusb_private.h" #ifdef __cplusplus extern "C" { diff --git a/src/tusb.c b/src/tusb.c index f4380f89c..05e0d4c1f 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -31,11 +31,18 @@ #include "tusb.h" #include "common/tusb_private.h" -// TODO clean up #if CFG_TUD_ENABLED #include "device/usbd_pvt.h" #endif +#if CFG_TUH_ENABLED +#include "host/usbh_classdriver.h" +#endif + +//--------------------------------------------------------------------+ +// Public API +//--------------------------------------------------------------------+ + bool tusb_init(void) { #if CFG_TUD_ENABLED && defined(TUD_OPT_RHPORT) @@ -67,7 +74,7 @@ bool tusb_inited(void) } //--------------------------------------------------------------------+ -// Internal Helper for both Host and Device stack +// Endpoint Helper for both Host and Device stack //--------------------------------------------------------------------+ bool tu_edpt_claim(tu_edpt_state_t* ep_state, osal_mutex_t mutex) @@ -196,9 +203,104 @@ uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, return len; } -/*------------------------------------------------------------------*/ -/* Debug - *------------------------------------------------------------------*/ +//--------------------------------------------------------------------+ +// Endpoint Stream Helper for both Host and Device stack +//--------------------------------------------------------------------+ + +bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool is_host, bool is_tx, bool overwritable, + void* ff_buf, uint16_t ff_bufsize, uint8_t* ep_buf, uint16_t ep_bufsize) +{ + osal_mutex_t new_mutex = osal_mutex_create(&s->ff_mutex); + (void) new_mutex; + (void) is_tx; + + s->is_host = is_host; + tu_fifo_config(&s->ff, ff_buf, ff_bufsize, 1, overwritable); + tu_fifo_config_mutex(&s->ff, is_tx ? new_mutex : NULL, is_tx ? NULL : new_mutex); + + s->ep_buf = ep_buf; + s->ep_bufsize = ep_bufsize; + + return true; +} + +//------------- Stream Write -------------// + +//------------- Stream Read -------------// + +uint32_t tu_edpt_stream_read_xfer(tu_edpt_stream_t* s) +{ + uint16_t available = tu_fifo_remaining(&s->ff); + + // Prepare for incoming data but only allow what we can store in the ring buffer. + // TODO Actually we can still carry out the transfer, keeping count of received bytes + // and slowly move it to the FIFO when read(). + // This pre-check reduces endpoint claiming + TU_VERIFY(available >= s->ep_packetsize); + + // claim endpoint + if (s->is_host) + { + #if CFG_TUH_ENABLED + TU_VERIFY(usbh_edpt_claim(s->daddr, s->ep_addr), 0); + #endif + }else + { + #if CFG_TUD_ENABLED + TU_VERIFY(usbd_edpt_claim(s->rhport, s->ep_addr), 0); + #endif + } + + // get available again since fifo can be changed before endpoint is claimed + available = tu_fifo_remaining(&s->ff); + + if ( available >= s->ep_packetsize ) + { + // multiple of packet size limit by ep bufsize + uint16_t count = (uint16_t) (available & (s->ep_packetsize -1)); + count = tu_min16(count, s->ep_bufsize); + + if (s->is_host) + { + #if CFG_TUH_ENABLED + TU_ASSERT( usbh_edpt_xfer(s->daddr, s->ep_addr, s->ep_buf, count), 0 ); + #endif + }else + { + #if CFG_TUD_ENABLED + TU_ASSERT( usbd_edpt_xfer(s->rhport, s->ep_addr, s->ep_buf, count), 0 ); + #endif + } + return count; + }else + { + // Release endpoint since we don't make any transfer + if (s->is_host) + { + #if CFG_TUH_ENABLED + usbh_edpt_release(s->daddr, s->ep_addr); + #endif + }else + { + #if CFG_TUD_ENABLED + usbd_edpt_release(s->rhport, s->ep_addr); + #endif + } + + return 0; + } +} + +uint32_t tu_edpt_stream_read(tu_edpt_stream_t* s, void* buffer, uint32_t bufsize) +{ + uint32_t num_read = tu_fifo_read_n(&s->ff, buffer, (uint16_t) bufsize); + tu_edpt_stream_read_xfer(s); + return num_read; +} + +//--------------------------------------------------------------------+ +// Debug +//--------------------------------------------------------------------+ #if CFG_TUSB_DEBUG #include -- cgit v1.3.1 From 14d45b580e0cd82e77e36ecb152f7c001d860ce7 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 22 Dec 2022 19:17:09 +0700 Subject: correct host cdc enum --- src/class/cdc/cdc_host.c | 2 +- src/host/usbh.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src/host') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index fcabb922a..05e0bdfc7 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -522,7 +522,7 @@ static void process_cdc_config(tuh_xfer_t* xfer) #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM { cdc_line_coding_t line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM; - TU_ASSERT( tuh_cdc_set_line_coding(idx, &line_coding, process_cdc_config, 0), ); + TU_ASSERT( tuh_cdc_set_line_coding(idx, &line_coding, process_cdc_config, CONFIG_COMPLETE), ); break; } #endif diff --git a/src/host/usbh.c b/src/host/usbh.c index f0ca7be2e..af1e67d4d 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -330,6 +330,8 @@ bool tuh_init(uint8_t controller_id) TU_LOG_INT(USBH_DEBUG, sizeof(hcd_event_t)); TU_LOG_INT(USBH_DEBUG, sizeof(_ctrl_xfer)); TU_LOG_INT(USBH_DEBUG, sizeof(tuh_xfer_t)); + TU_LOG_INT(USBH_DEBUG, sizeof(tu_fifo_t)); + TU_LOG_INT(USBH_DEBUG, sizeof(tu_edpt_stream_t)); // Event queue _usbh_q = osal_queue_create( &_usbh_qdef ); @@ -1275,7 +1277,7 @@ static void process_enumeration(tuh_xfer_t* xfer) break; } #endif - __attribute__((fallthrough)); + TU_ATTR_FALLTHROUGH; #endif case ENUM_SET_ADDR: -- cgit v1.3.1 From f5cffeedec863c1efd59688fa79a8455046e8377 Mon Sep 17 00:00:00 2001 From: pete-pjb Date: Tue, 3 Jan 2023 10:33:36 +0000 Subject: Fix typo in audio.h. Specifiy _ctrl_xfer struct in CFG_TUSB_MEM_SECTION Add NULL check to loop in list_remove_qhd_by_addr() function in ehci.c --- src/class/audio/audio.h | 2 ++ src/host/usbh.c | 8 ++++---- src/portable/ehci/ehci.c | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) (limited to 'src/host') diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 6f9c1a6b5..ba497906b 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -721,11 +721,13 @@ typedef struct TU_ATTR_PACKED uint8_t bLength ; ///< Size of this descriptor, in bytes: 17. uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL. + uint8_t bTerminalID ; ///< Constant uniquely identifying the Terminal within the audio function. This value is used in all requests to address this terminal. uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_input_type_t for other input types. uint8_t bAssocTerminal ; ///< ID of the Output Terminal to which this Input Terminal is associated. uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Input Terminal is connected. uint8_t bNrChannels ; ///< Number of logical output channels in the Terminal’s output audio channel cluster. uint32_t bmChannelConfig ; ///< Describes the spatial location of the logical channels. See:audio_channel_config_t. + uint8_t iChannelNames ; ///< Index of a string descriptor, describing the name of the first logical channel. uint16_t bmControls ; ///< See: audio_terminal_input_control_pos_t. uint8_t iTerminal ; ///< Index of a string descriptor, describing the Input Terminal. } audio_desc_input_terminal_t; diff --git a/src/host/usbh.c b/src/host/usbh.c index af1e67d4d..5ac9e9cca 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -229,10 +229,10 @@ static osal_queue_t _usbh_q; CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSIZE]; -// Control transfer: since most controller does not support multiple control transfer -// on multiple devices concurrently. And control transfer is not used much except enumeration -// We will only execute control transfer one at a time. -struct +// Control transfers: since most controllers do not support multiple control transfers +// on multiple devices concurrently and control transfers are not used much except for +// enumeration, we will only execute control transfers one at a time. +CFG_TUSB_MEM_SECTION struct { tusb_control_request_t request TU_ATTR_ALIGNED(4); uint8_t* buffer; diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 80f616478..7140897a1 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -188,7 +188,7 @@ tusb_speed_t hcd_port_speed_get(uint8_t rhport) static void list_remove_qhd_by_addr(ehci_link_t* list_head, uint8_t dev_addr) { for(ehci_link_t* prev = list_head; - !prev->terminate && (tu_align32(prev->address) != (uint32_t) list_head); + !prev->terminate && (tu_align32(prev->address) != (uint32_t) list_head) && prev != NULL; prev = list_next(prev) ) { // TODO check type for ISO iTD and siTD -- cgit v1.3.1