From d069ea1421eace1768157e76c44164262ed9a1e6 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Wed, 25 Aug 2021 10:41:07 +0200 Subject: [PATCH 01/81] vendor: Add tx callback Other drivers already have notification about data sent. It allows batter control in application on vendor protocol level. --- src/class/vendor/vendor_device.c | 1 + src/class/vendor/vendor_device.h | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 8a4ca1d2e..02a4220be 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -247,6 +247,7 @@ bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint } else if ( ep_addr == p_itf->ep_in ) { + if (tud_vendor_tx_cb) tud_vendor_tx_cb(itf, xferred_bytes); // Send complete, try to send more if possible maybe_transmit(p_itf); } diff --git a/src/class/vendor/vendor_device.h b/src/class/vendor/vendor_device.h index d71c2a3e9..75cb77f5b 100644 --- a/src/class/vendor/vendor_device.h +++ b/src/class/vendor/vendor_device.h @@ -71,6 +71,8 @@ static inline uint32_t tud_vendor_write_available (void); // Invoked when received new data TU_ATTR_WEAK void tud_vendor_rx_cb(uint8_t itf); +// Invoked when last rx transfer finished +TU_ATTR_WEAK void tud_vendor_tx_cb(uint8_t itf, uint32_t sent_bytes); //--------------------------------------------------------------------+ // Inline Functions From 4ca22156845162b69410a47a2b43e03ac552b9f3 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Wed, 25 Aug 2021 10:57:35 +0200 Subject: [PATCH 02/81] vendor: Add tx flush functionality So far tud_vendor_n_write() always flushed data. It requires to have whole vendor packed constructed before in one buffer. With this change data do get flushed when endpoint size is filled on write, when there is no enough data to fill endpoint data is not sent and subsequent calls to write functions can add more bytes. Vendor code needs to call tud_vendor_n_flush() when packet is ready to be sent. --- src/class/vendor/vendor_device.c | 16 +++++++++++++--- src/class/vendor/vendor_device.h | 7 +++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 02a4220be..586822f39 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -113,7 +113,7 @@ void tud_vendor_n_read_flush (uint8_t itf) //--------------------------------------------------------------------+ // Write API //--------------------------------------------------------------------+ -static bool maybe_transmit(vendord_interface_t* p_itf) +static uint16_t 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) ); @@ -123,14 +123,24 @@ static bool maybe_transmit(vendord_interface_t* p_itf) { TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, p_itf->ep_in, p_itf->epin_buf, count) ); } - return true; + return count; } uint32_t tud_vendor_n_write (uint8_t itf, void 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); + if (tu_fifo_count(&p_itf->tx_ff) >= CFG_TUD_VENDOR_EPSIZE) { + maybe_transmit(p_itf); + } + return ret; +} + +uint32_t tud_vendor_n_flush (uint8_t itf) +{ + vendord_interface_t* p_itf = &_vendord_itf[itf]; + uint32_t ret = maybe_transmit(p_itf); + return ret; } diff --git a/src/class/vendor/vendor_device.h b/src/class/vendor/vendor_device.h index 75cb77f5b..4a873e5fc 100644 --- a/src/class/vendor/vendor_device.h +++ b/src/class/vendor/vendor_device.h @@ -52,6 +52,7 @@ uint32_t tud_vendor_n_write_available (uint8_t itf); static inline uint32_t tud_vendor_n_write_str (uint8_t itf, char const* str); +uint32_t tud_vendor_n_flush (uint8_t itf); //--------------------------------------------------------------------+ // Application API (Single Port) @@ -64,6 +65,7 @@ static inline void tud_vendor_read_flush (void); static inline uint32_t tud_vendor_write (void const* buffer, uint32_t bufsize); static inline uint32_t tud_vendor_write_str (char const* str); static inline uint32_t tud_vendor_write_available (void); +static inline uint32_t tud_vendor_flush (void); //--------------------------------------------------------------------+ // Application Callback API (weak is optional) @@ -123,6 +125,11 @@ static inline uint32_t tud_vendor_write_available (void) return tud_vendor_n_write_available(0); } +static inline uint32_t tud_vendor_flush (void) +{ + return tud_vendor_n_flush(0); +} + //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ From 1b338b288c3e1b91f8b2b77ef3305142188f922e Mon Sep 17 00:00:00 2001 From: caleb crome Date: Tue, 1 Mar 2022 17:24:28 -0800 Subject: [PATCH 03/81] in TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR, _nitfs should be 3. I believe that there is a mistake in the definition of TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR. The nitfs in the audio descriptor is always 3 regardless of ITF_NUM_TOTAL. --- examples/device/uac2_headset/src/usb_descriptors.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/device/uac2_headset/src/usb_descriptors.h b/examples/device/uac2_headset/src/usb_descriptors.h index d9510ea4f..342b4fac1 100644 --- a/examples/device/uac2_headset/src/usb_descriptors.h +++ b/examples/device/uac2_headset/src/usb_descriptors.h @@ -86,7 +86,7 @@ enum #define TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(_stridx, _epout, _epin) \ /* Standard Interface Association Descriptor (IAD) */\ - TUD_AUDIO_DESC_IAD(/*_firstitfs*/ ITF_NUM_AUDIO_CONTROL, /*_nitfs*/ ITF_NUM_TOTAL, /*_stridx*/ 0x00),\ + TUD_AUDIO_DESC_IAD(/*_firstitfs*/ ITF_NUM_AUDIO_CONTROL, /*_nitfs*/ 3, /*_stridx*/ 0x00),\ /* Standard AC Interface Descriptor(4.7.1) */\ TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ From 2cd73ca60234748a15b74a2c346778fcb4f4ee61 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Thu, 3 Mar 2022 16:53:22 -0800 Subject: [PATCH 04/81] Add host string descriptor functions Plus typo fixes, GCC11 array bounds fix, snprintf for malloc-free debug and pragmas for alignment checks. --- src/common/tusb_common.h | 2 +- src/host/usbh.c | 57 +++++++++++++++++++- src/host/usbh.h | 12 +++++ src/portable/chipidea/ci_hs/hcd_ci_hs.c | 1 + src/portable/ehci/ehci.c | 3 ++ src/portable/ehci/ehci.h | 4 +- src/portable/raspberrypi/rp2040/rp2040_usb.c | 3 ++ 7 files changed, 78 insertions(+), 4 deletions(-) diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 9b9e2b007..80bb40f77 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -349,7 +349,7 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 } // not found return the key value in hex - sprintf(not_found, "0x%08lX", (unsigned long) key); + snprintf(not_found, sizeof(not_found), "0x%08lX", (unsigned long) key); return not_found; } diff --git a/src/host/usbh.c b/src/host/usbh.c index 130aba40e..a3c6c3a04 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -258,6 +258,60 @@ bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t* vid, uint16_t* pid) return true; } +uint8_t tuh_i_manufacturer_get(uint8_t dev_addr) { + TU_VERIFY(tuh_mounted(dev_addr)); + usbh_device_t const* dev = get_device(dev_addr); + + return dev->i_manufacturer; +} + +uint8_t tuh_i_serial_get(uint8_t dev_addr) { + TU_VERIFY(tuh_mounted(dev_addr)); + usbh_device_t const* dev = get_device(dev_addr); + + return dev->i_serial; +} + +uint8_t tuh_i_product_get(uint8_t dev_addr) { + TU_VERIFY(tuh_mounted(dev_addr)); + usbh_device_t const* dev = get_device(dev_addr); + + return dev->i_product; +} + +static tuh_complete_cb_t string_get_cb; + +static bool string_get_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { + if (string_get_cb != NULL) { + TU_LOG2("string get done %d\r\n", result); + string_get_cb(result); + } + string_get_cb = NULL; + return true; +} + +bool tuh_string_get(uint8_t dev_addr, uint8_t string_index, uint16_t* buf, size_t len, tuh_complete_cb_t complete_cb) { + if (string_get_cb != NULL) { + return false; + } + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_IN + }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = TUSB_DESC_STRING << 8 | string_index, + .wIndex = 0, + .wLength = len * sizeof(uint16_t) + }; + string_get_cb = complete_cb; + TU_ASSERT( tuh_control_xfer(dev_addr, &request, buf, string_get_complete) ); + return true; +} + tusb_speed_t tuh_speed_get (uint8_t dev_addr) { return (tusb_speed_t) (dev_addr ? get_device(dev_addr)->speed : _dev0.speed); @@ -561,6 +615,7 @@ void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port tu_memclr(dev->ep_status, sizeof(dev->ep_status)); dev->state = TUSB_DEVICE_STATE_UNPLUG; + dev->configured = false; } } } @@ -609,7 +664,7 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) //--------------------------------------------------------------------+ // Enumeration Process -// is a lengthy process with a seires of control transfer to configure +// is a lengthy process with a series of control transfer to configure // newly attached device. Each step is handled by a function in this // section // TODO due to the shared _usbh_ctrl_buf, we must complete enumerating diff --git a/src/host/usbh.h b/src/host/usbh.h index 8411cad28..98e83fc3c 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -38,6 +38,7 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ +typedef bool (*tuh_complete_cb_t)(xfer_result_t result); typedef bool (*tuh_control_complete_cb_t)(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); //--------------------------------------------------------------------+ @@ -58,6 +59,17 @@ extern void hcd_int_handler(uint8_t rhport); #define tuh_int_handler hcd_int_handler bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t* vid, uint16_t* pid); + +// Gets the string indices for common device descriptor data. +uint8_t tuh_i_manufacturer_get(uint8_t dev_addr); +uint8_t tuh_i_serial_get(uint8_t dev_addr); +uint8_t tuh_i_product_get(uint8_t dev_addr); + +// Reads the string descriptor at the string index into the buffer. This is the +// full response so the first entry is the length and the constant 0x03 for +// string descriptor type. +bool tuh_string_get(uint8_t dev_addr, uint8_t string_index, uint16_t* buf, size_t len, tuh_complete_cb_t complete_cb); + tusb_speed_t tuh_speed_get(uint8_t dev_addr); // Check if device is connected and configured diff --git a/src/portable/chipidea/ci_hs/hcd_ci_hs.c b/src/portable/chipidea/ci_hs/hcd_ci_hs.c index 0754b477e..221721b0f 100644 --- a/src/portable/chipidea/ci_hs/hcd_ci_hs.c +++ b/src/portable/chipidea/ci_hs/hcd_ci_hs.c @@ -35,6 +35,7 @@ // INCLUDE //--------------------------------------------------------------------+ #include "common/tusb_common.h" +#include "host/hcd.h" #include "portable/ehci/ehci_api.h" #include "ci_hs_type.h" diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index e2d51dc4b..6723e99e9 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -189,7 +189,10 @@ static void list_remove_qhd_by_addr(ehci_link_t* list_head, uint8_t dev_addr) prev = list_next(prev) ) { // TODO check type for ISO iTD and siTD + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wcast-align" ehci_qhd_t* qhd = (ehci_qhd_t*) list_next(prev); + #pragma GCC diagnostic pop if ( qhd->dev_addr == dev_addr ) { // TODO deactive all TD, wait for QHD to inactive before removal diff --git a/src/portable/ehci/ehci.h b/src/portable/ehci/ehci.h index c2bee67a5..ff9ae12e7 100644 --- a/src/portable/ehci/ehci.h +++ b/src/portable/ehci/ehci.h @@ -101,8 +101,8 @@ typedef struct // Word 2: qTQ Token volatile uint32_t ping_err : 1 ; ///< For Highspeed: 0 Out, 1 Ping. Full/Slow used as error indicator - volatile uint32_t non_hs_split_state : 1 ; ///< Used by HC to track the state of slipt transaction - volatile uint32_t non_hs_missed_uframe : 1 ; ///< HC misses a complete slip transaction + volatile uint32_t non_hs_split_state : 1 ; ///< Used by HC to track the state of split transaction + volatile uint32_t non_hs_missed_uframe : 1 ; ///< HC misses a complete split transaction volatile uint32_t xact_err : 1 ; ///< Error (Timeout, CRC, Bad PID ... ) volatile uint32_t babble_err : 1 ; ///< Babble detected, also set Halted bit to 1 volatile uint32_t buffer_err : 1 ; ///< Data overrun/underrun error diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 293cefaf6..be02493f0 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -58,8 +58,11 @@ void rp2040_usb_init(void) unreset_block_wait(RESETS_RESET_USBCTRL_BITS); // Clear any previous state just in case +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warray-bounds" memset(usb_hw, 0, sizeof(*usb_hw)); memset(usb_dpram, 0, sizeof(*usb_dpram)); +#pragma GCC diagnostic pop // Mux the controller to the onboard usb phy usb_hw->muxing = USB_USB_MUXING_TO_PHY_BITS | USB_USB_MUXING_SOFTCON_BITS; From eb6b5d1219562e417d879c6d13e0a19eef169ad7 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Thu, 3 Mar 2022 21:57:44 -0800 Subject: [PATCH 05/81] Unused ok --- src/host/usbh.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index a3c6c3a04..a61f40910 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -282,8 +282,9 @@ uint8_t tuh_i_product_get(uint8_t dev_addr) { static tuh_complete_cb_t string_get_cb; static bool string_get_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { + (void) dev_addr; + (void) request; if (string_get_cb != NULL) { - TU_LOG2("string get done %d\r\n", result); string_get_cb(result); } string_get_cb = NULL; From f72da8ee7d7082f9c2f1d796cfb03dcdd1c6d673 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 4 Mar 2022 14:45:26 +0700 Subject: [PATCH 06/81] fix build with esp32s2, also use dwc2 for esp example --- examples/device/hid_composite_freertos/src/CMakeLists.txt | 2 +- src/portable/espressif/esp32sx/dcd_esp32sx.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/device/hid_composite_freertos/src/CMakeLists.txt b/examples/device/hid_composite_freertos/src/CMakeLists.txt index 5d9fc74d3..25da8fcd7 100644 --- a/examples/device/hid_composite_freertos/src/CMakeLists.txt +++ b/examples/device/hid_composite_freertos/src/CMakeLists.txt @@ -31,5 +31,5 @@ target_sources(${COMPONENT_TARGET} PUBLIC "${TOP}/src/class/net/ncm_device.c" "${TOP}/src/class/usbtmc/usbtmc_device.c" "${TOP}/src/class/vendor/vendor_device.c" - "${TOP}/src/portable/espressif/esp32sx/dcd_esp32sx.c" + "${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c" ) diff --git a/src/portable/espressif/esp32sx/dcd_esp32sx.c b/src/portable/espressif/esp32sx/dcd_esp32sx.c index 99cd08e4d..bd8805dd3 100644 --- a/src/portable/espressif/esp32sx/dcd_esp32sx.c +++ b/src/portable/espressif/esp32sx/dcd_esp32sx.c @@ -34,7 +34,6 @@ #include "freertos/xtensa_api.h" #include "esp_intr_alloc.h" #include "esp_log.h" -#include "driver/gpio.h" #include "soc/dport_reg.h" #include "soc/gpio_sig_map.h" #include "soc/usb_periph.h" From 96165a1950140c585db4b739709d079228c3320a Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 4 Mar 2022 17:07:04 +0700 Subject: [PATCH 07/81] rename HCD_MAX_XFER to CFG_TUH_ENDPOINT_MAX minor clean up --- src/host/hcd.h | 26 ++++++++++---------- src/host/hub.c | 2 +- src/portable/ehci/ehci.c | 13 ++++++---- src/portable/nxp/khci/hcd_khci.c | 8 +++--- src/portable/ohci/ohci.c | 4 +-- src/portable/ohci/ohci.h | 4 ++- src/portable/raspberrypi/rp2040/rp2040_usb.c | 1 + 7 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/host/hcd.h b/src/host/hcd.h index 80500f048..d50fc2d60 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -35,6 +35,19 @@ extern "C" { #endif +//--------------------------------------------------------------------+ +// Configuration +//--------------------------------------------------------------------+ + +#ifndef CFG_TUH_ENDPOINT_MAX + #define CFG_TUH_ENDPOINT_MAX (CFG_TUH_DEVICE_MAX*(CFG_TUH_HUB + CFG_TUH_HID*2 + CFG_TUH_MSC*2 + CFG_TUH_CDC*3)) +// #ifdef TUP_HCD_ENDPOINT_MAX +// #define CFG_TUH_ENDPPOINT_MAX TUP_HCD_ENDPOINT_MAX +// #else +// #define +// #endif +#endif + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -81,17 +94,6 @@ typedef struct } hcd_event_t; -#if CFG_TUH_ENABLED -// Max number of endpoints per device -enum { - // TODO better computation - HCD_MAX_ENDPOINT = CFG_TUH_DEVICE_MAX*(CFG_TUH_HUB + CFG_TUH_HID*2 + CFG_TUH_MSC*2 + CFG_TUH_CDC*3), - HCD_MAX_XFER = HCD_MAX_ENDPOINT*2, -}; - -//#define HCD_MAX_ENDPOINT 16 -//#define HCD_MAX_XFER 16 - typedef struct { uint8_t rhport; uint8_t hub_addr; @@ -99,8 +101,6 @@ typedef struct { uint8_t speed; } hcd_devtree_info_t; -#endif - //--------------------------------------------------------------------+ // Controller API //--------------------------------------------------------------------+ diff --git a/src/host/hub.c b/src/host/hub.c index 53eb1d521..1fec8b892 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -54,7 +54,7 @@ static inline hub_interface_t* get_itf(uint8_t dev_addr) return &hub_data[dev_addr-1-CFG_TUH_DEVICE_MAX]; } -#if CFG_TUSB_DEBUG +#if CFG_TUSB_DEBUG >= 2 static char const* const _hub_feature_str[] = { [HUB_FEATURE_PORT_CONNECTION ] = "PORT_CONNECTION", diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 6723e99e9..bc0b7b89a 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -58,6 +58,8 @@ #define FRAMELIST_SIZE (1024 >> FRAMELIST_SIZE_BIT_VALUE) +#define HCD_MAX_XFER CFG_TUH_ENDPOINT_MAX + typedef struct { ehci_link_t period_framelist[FRAMELIST_SIZE]; @@ -73,7 +75,7 @@ typedef struct ehci_qtd_t qtd; }control[CFG_TUH_DEVICE_MAX+CFG_TUH_HUB+1]; - ehci_qhd_t qhd_pool[HCD_MAX_ENDPOINT]; + ehci_qhd_t qhd_pool[CFG_TUH_ENDPOINT_MAX]; ehci_qtd_t qtd_pool[HCD_MAX_XFER] TU_ATTR_ALIGNED(32); ehci_registers_t* regs; @@ -189,6 +191,7 @@ static void list_remove_qhd_by_addr(ehci_link_t* list_head, uint8_t dev_addr) prev = list_next(prev) ) { // TODO check type for ISO iTD and siTD + // TODO Suppress cast-align warning #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-align" ehci_qhd_t* qhd = (ehci_qhd_t*) list_next(prev); @@ -477,7 +480,7 @@ static void async_advance_isr(uint8_t rhport) (void) rhport; ehci_qhd_t* qhd_pool = ehci_data.qhd_pool; - for(uint32_t i = 0; i < HCD_MAX_ENDPOINT; i++) + for(uint32_t i = 0; i < CFG_TUH_ENDPOINT_MAX; i++) { if ( qhd_pool[i].removing ) { @@ -545,7 +548,7 @@ static void period_list_xfer_complete_isr(uint8_t hostid, uint32_t interval_ms) // TODO abstract max loop guard for period while( !next_item.terminate && !(interval_ms > 1 && period_1ms_addr == tu_align32(next_item.address)) && - max_loop < (HCD_MAX_ENDPOINT + EHCI_MAX_ITD + EHCI_MAX_SITD)*CFG_TUH_DEVICE_MAX) + max_loop < (CFG_TUH_ENDPOINT_MAX + EHCI_MAX_ITD + EHCI_MAX_SITD)*CFG_TUH_DEVICE_MAX) { switch ( next_item.type ) { @@ -717,7 +720,7 @@ void hcd_int_handler(uint8_t rhport) //------------- queue head helper -------------// static inline ehci_qhd_t* qhd_find_free (void) { - for (uint32_t i=0; idev_addr == dev_addr) && (p->ep_addr == ep_addr)) return num; @@ -463,7 +463,7 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) const unsigned ie = NVIC_GetEnableIRQ(USB0_IRQn); NVIC_DisableIRQ(USB0_IRQn); pipe_state_t *p = &_hcd.pipe[0]; - pipe_state_t *end = &_hcd.pipe[HCD_MAX_XFER * 2]; + pipe_state_t *end = &_hcd.pipe[CFG_TUH_ENDPOINT_MAX * 2]; for (;p != end; ++p) { if (p->dev_addr == dev_addr) tu_memclr(p, sizeof(*p)); @@ -511,7 +511,7 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const // TU_LOG1("O %u %x\n", dev_addr, ep_addr); /* Find a free pipe */ pipe_state_t *p = &_hcd.pipe[0]; - pipe_state_t *end = &_hcd.pipe[HCD_MAX_XFER * 2]; + pipe_state_t *end = &_hcd.pipe[CFG_TUH_ENDPOINT_MAX * 2]; if (dev_addr || ep_addr) { p += 2; for (; p < end && (p->dev_addr || p->ep_addr); ++p) ; diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c index cb4e6dc4a..c82b9352c 100644 --- a/src/portable/ohci/ohci.c +++ b/src/portable/ohci/ohci.c @@ -313,7 +313,7 @@ static ohci_ed_t * ed_from_addr(uint8_t dev_addr, uint8_t ep_addr) ohci_ed_t* ed_pool = ohci_data.ed_pool; - for(uint32_t i=0; i Date: Fri, 4 Mar 2022 17:16:14 +0700 Subject: [PATCH 08/81] adding new libusb api example --- examples/host/CMakeLists.txt | 1 + examples/host/libusb_api/CMakeLists.txt | 27 ++++++ examples/host/libusb_api/Makefile | 28 +++++++ examples/host/libusb_api/only.txt | 9 ++ examples/host/libusb_api/src/main.c | 98 ++++++++++++++++++++++ examples/host/libusb_api/src/tusb_config.h | 94 +++++++++++++++++++++ 6 files changed, 257 insertions(+) create mode 100644 examples/host/libusb_api/CMakeLists.txt create mode 100644 examples/host/libusb_api/Makefile create mode 100644 examples/host/libusb_api/only.txt create mode 100644 examples/host/libusb_api/src/main.c create mode 100644 examples/host/libusb_api/src/tusb_config.h diff --git a/examples/host/CMakeLists.txt b/examples/host/CMakeLists.txt index 5c63ec0c0..38db6c6cc 100644 --- a/examples/host/CMakeLists.txt +++ b/examples/host/CMakeLists.txt @@ -8,3 +8,4 @@ family_initialize_project(tinyusb_host_examples ${CMAKE_CURRENT_LIST_DIR}) # family_add_subdirectory will filter what to actually add based on selected FAMILY family_add_subdirectory(cdc_msc_hid) family_add_subdirectory(hid_controller) +family_add_subdirectory(libusb_api) diff --git a/examples/host/libusb_api/CMakeLists.txt b/examples/host/libusb_api/CMakeLists.txt new file mode 100644 index 000000000..bff281a8c --- /dev/null +++ b/examples/host/libusb_api/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.5) + +include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) + +# gets PROJECT name for the example +family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR}) + +project(${PROJECT}) + +# Checks this example is valid for the family and initializes the project +family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) + +add_executable(${PROJECT}) + +# Example source +target_sources(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c + ) + +# Example include +target_include_directories(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src + ) + +# Configure compilation flags and libraries for the example... see the corresponding function +# in hw/bsp/FAMILY/family.cmake for details. +family_configure_host_example(${PROJECT}) \ No newline at end of file diff --git a/examples/host/libusb_api/Makefile b/examples/host/libusb_api/Makefile new file mode 100644 index 000000000..c59369ffa --- /dev/null +++ b/examples/host/libusb_api/Makefile @@ -0,0 +1,28 @@ +include ../../../tools/top.mk +include ../../make.mk + +INC += \ + src \ + $(TOP)/hw \ + +# Example source +EXAMPLE_SOURCE += \ + src/main.c + +SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) + +# TODO: suppress warning caused by host stack +CFLAGS += -Wno-error=cast-align -Wno-error=null-dereference + +# TinyUSB Host Stack source +SRC_C += \ + src/class/cdc/cdc_host.c \ + src/class/hid/hid_host.c \ + src/class/msc/msc_host.c \ + src/host/hub.c \ + src/host/usbh.c \ + src/host/usbh_control.c \ + src/portable/ohci/ohci.c \ + src/portable/nxp/lpc17_40/hcd_lpc17_40.c + +include ../../rules.mk diff --git a/examples/host/libusb_api/only.txt b/examples/host/libusb_api/only.txt new file mode 100644 index 000000000..7fe4e3f5c --- /dev/null +++ b/examples/host/libusb_api/only.txt @@ -0,0 +1,9 @@ +mcu:LPC175X_6X +mcu:LPC177X_8X +mcu:LPC18XX +mcu:LPC40XX +mcu:LPC43XX +mcu:MIMXRT10XX +mcu:RP2040 +mcu:MSP432E4 +mcu:RX65X diff --git a/examples/host/libusb_api/src/main.c b/examples/host/libusb_api/src/main.c new file mode 100644 index 000000000..810f8e762 --- /dev/null +++ b/examples/host/libusb_api/src/main.c @@ -0,0 +1,98 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +/* This example current worked and tested with following controller + * - Sony DualShock 4 [CUH-ZCT2x] VID = 0x054c, PID = 0x09cc + */ + + +#include +#include +#include + +#include "bsp/board.h" +#include "tusb.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF PROTYPES +//--------------------------------------------------------------------+ +void led_blinking_task(void); + +extern void cdc_task(void); +extern void hid_app_task(void); + +/*------------- MAIN -------------*/ +int main(void) +{ + board_init(); + + printf("TinyUSB Host HID Controller Example\r\n"); + printf("Note: Events only displayed for explictly supported controllers\r\n"); + + tusb_init(); + + while (1) + { + // tinyusb host task + tuh_task(); + led_blinking_task(); + } + + return 0; +} + +//--------------------------------------------------------------------+ +// TinyUSB Callbacks +//--------------------------------------------------------------------+ + +// Invoked when device is mounted (configured) +void tuh_mount_cb (uint8_t dev_addr) +{ + printf("Device attached, address = %d\r\n", dev_addr); +} + +/// Invoked when device is unmounted (bus reset/unplugged) +void tuh_umount_cb(uint8_t dev_addr) +{ + printf("Device removed, address = %d\r\n", dev_addr); +} + +//--------------------------------------------------------------------+ +// Blinking Task +//--------------------------------------------------------------------+ +void led_blinking_task(void) +{ + const uint32_t interval_ms = 1000; + static uint32_t start_ms = 0; + + static bool led_state = false; + + // Blink every interval ms + if ( board_millis() - start_ms < interval_ms) return; // not enough time + start_ms += interval_ms; + + board_led_write(led_state); + led_state = 1 - led_state; // toggle +} diff --git a/examples/host/libusb_api/src/tusb_config.h b/examples/host/libusb_api/src/tusb_config.h new file mode 100644 index 000000000..234eca402 --- /dev/null +++ b/examples/host/libusb_api/src/tusb_config.h @@ -0,0 +1,94 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#ifndef _TUSB_CONFIG_H_ +#define _TUSB_CONFIG_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +//-------------------------------------------------------------------- +// COMMON CONFIGURATION +//-------------------------------------------------------------------- + +// defined by compiler flags for flexibility +#ifndef CFG_TUSB_MCU + #error CFG_TUSB_MCU must be defined +#endif + +#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX + #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_HOST | OPT_MODE_HIGH_SPEED) +#else + #define CFG_TUSB_RHPORT0_MODE OPT_MODE_HOST +#endif + +#ifndef CFG_TUSB_OS +#define CFG_TUSB_OS OPT_OS_NONE +#endif + +// CFG_TUSB_DEBUG is defined by compiler in DEBUG build +// #define CFG_TUSB_DEBUG 0 + +/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. + * Tinyusb use follows macros to declare transferring memory so that they can be put + * into those specific section. + * e.g + * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) + * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) + */ +#ifndef CFG_TUSB_MEM_SECTION +#define CFG_TUSB_MEM_SECTION +#endif + +#ifndef CFG_TUSB_MEM_ALIGN +#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) +#endif + +//-------------------------------------------------------------------- +// CONFIGURATION +//-------------------------------------------------------------------- + +// Size of buffer to hold descriptors and other data used for enumeration +#define CFG_TUH_ENUMERATION_BUFSIZE 256 + +// only hub class is enabled +#define CFG_TUH_HUB 1 + +// max device support (excluding hub device) +// 1 hub typically has 4 ports +#define CFG_TUH_DEVICE_MAX (CFG_TUH_HUB ? 4 : 1) + +#define CFG_TUH_ENDPOINT_MAX 8 + +//------------- HID -------------// + +#define CFG_TUH_HID_EP_BUFSIZE 64 + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_CONFIG_H_ */ From 3a7d1cfead0d3147425c305d778723a505900d48 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 4 Mar 2022 17:26:21 +0700 Subject: [PATCH 09/81] minor cleanup --- examples/host/libusb_api/src/main.c | 10 +++++++--- src/host/usbh.c | 13 +++++-------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/examples/host/libusb_api/src/main.c b/examples/host/libusb_api/src/main.c index 810f8e762..07dae1dc6 100644 --- a/examples/host/libusb_api/src/main.c +++ b/examples/host/libusb_api/src/main.c @@ -40,9 +40,6 @@ //--------------------------------------------------------------------+ void led_blinking_task(void); -extern void cdc_task(void); -extern void hid_app_task(void); - /*------------- MAIN -------------*/ int main(void) { @@ -67,10 +64,17 @@ int main(void) // TinyUSB Callbacks //--------------------------------------------------------------------+ +void print_device_descriptor(uint8_t dev_addr) +{ + printf("Device Descriptor:\r\n"); + +} + // Invoked when device is mounted (configured) void tuh_mount_cb (uint8_t dev_addr) { printf("Device attached, address = %d\r\n", dev_addr); + print_device_descriptor(dev_addr); } /// Invoked when device is unmounted (bus reset/unplugged) diff --git a/src/host/usbh.c b/src/host/usbh.c index a61f40910..d655ee7ca 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -37,11 +37,6 @@ // USBH Configuration //--------------------------------------------------------------------+ -// TODO remove,update -#ifndef CFG_TUH_EP_MAX -#define CFG_TUH_EP_MAX 9 -#endif - #ifndef CFG_TUH_TASK_QUEUE_SZ #define CFG_TUH_TASK_QUEUE_SZ 16 #endif @@ -72,7 +67,7 @@ typedef struct } usbh_dev0_t; typedef struct { - // port + // port, must be same layout as usbh_dev0_t uint8_t rhport; uint8_t hub_addr; uint8_t hub_port; @@ -102,7 +97,7 @@ typedef struct { volatile uint8_t state; // device state, value from enum tusbh_device_state_t uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) - uint8_t ep2drv[CFG_TUH_EP_MAX][2]; // map endpoint to driver ( 0xff is invalid ) + uint8_t ep2drv[CFG_TUH_ENDPOINT_MAX][2]; // map endpoint to driver ( 0xff is invalid ) struct TU_ATTR_PACKED { @@ -111,7 +106,7 @@ typedef struct { volatile bool claimed : 1; // TODO merge ep2drv here, 4-bit should be sufficient - }ep_status[CFG_TUH_EP_MAX][2]; + }ep_status[CFG_TUH_ENDPOINT_MAX][2]; // Mutex for claiming endpoint, only needed when using with preempted RTOS #if CFG_TUSB_OS != OPT_OS_NONE @@ -344,6 +339,8 @@ bool tuh_init(uint8_t rhport) TU_LOG2("USBH init\r\n"); + TU_LOG2_INT(sizeof(usbh_device_t)); + tu_memclr(_usbh_devices, sizeof(_usbh_devices)); tu_memclr(&_dev0, sizeof(_dev0)); From e08a875d52792c03e1e7cd114f0f3f7013c36210 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 4 Mar 2022 19:26:54 +0700 Subject: [PATCH 10/81] add tuh_descriptor_get() and tuh_descriptor_device_get() --- src/common/tusb_common.h | 1 + src/device/usbd.c | 1 + src/host/usbh.c | 64 ++++++++++++++++++++-------------------- src/host/usbh.h | 39 ++++++++++++++---------- 4 files changed, 58 insertions(+), 47 deletions(-) diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 80bb40f77..26865805e 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -38,6 +38,7 @@ #define TU_MIN(_x, _y) ( ( (_x) < (_y) ) ? (_x) : (_y) ) #define TU_MAX(_x, _y) ( ( (_x) > (_y) ) ? (_x) : (_y) ) +#define TU_U16(_high, _low) ((uint16_t) (((_high) << 8) | (_low))) #define TU_U16_HIGH(_u16) ((uint8_t) (((_u16) >> 8) & 0x00ff)) #define TU_U16_LOW(_u16) ((uint8_t) ((_u16) & 0x00ff)) #define U16_TO_U8S_BE(_u16) TU_U16_HIGH(_u16), TU_U16_LOW(_u16) diff --git a/src/device/usbd.c b/src/device/usbd.c index c20bab76b..7926689b7 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -407,6 +407,7 @@ bool tud_init (uint8_t rhport) if ( tud_inited() ) return true; TU_LOG2("USBD init\r\n"); + TU_LOG2_INT(sizeof(usbd_device_t)); tu_varclr(&_usbd_dev); diff --git a/src/host/usbh.c b/src/host/usbh.c index d655ee7ca..4c3bda4b0 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -96,7 +96,7 @@ typedef struct { //------------- device -------------// volatile uint8_t state; // device state, value from enum tusbh_device_state_t - uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) + uint8_t itf2drv[8]; // map interface number to driver (0xff is invalid) uint8_t ep2drv[CFG_TUH_ENDPOINT_MAX][2]; // map endpoint to driver ( 0xff is invalid ) struct TU_ATTR_PACKED @@ -253,6 +253,34 @@ bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t* vid, uint16_t* pid) return true; } + +bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, + void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) +{ + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_IN + }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = tu_htole16( TU_U16(type, index) ), + .wIndex = 0, + .wLength = len + }; + + TU_ASSERT( tuh_control_xfer(daddr, &request, buffer, complete_cb) ); + + return true; +} + +bool tuh_descriptor_device_get(uint8_t daddr, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) +{ + return tuh_descriptor_get(daddr, TUSB_DESC_DEVICE, 0, buffer, len, complete_cb); +} + uint8_t tuh_i_manufacturer_get(uint8_t dev_addr) { TU_VERIFY(tuh_mounted(dev_addr)); usbh_device_t const* dev = get_device(dev_addr); @@ -338,7 +366,6 @@ bool tuh_init(uint8_t rhport) if (_usbh_initialized) return _usbh_initialized; TU_LOG2("USBH init\r\n"); - TU_LOG2_INT(sizeof(usbh_device_t)); tu_memclr(_usbh_devices, sizeof(_usbh_devices)); @@ -785,23 +812,10 @@ static bool enum_request_addr0_device_desc(void) uint8_t const addr0 = 0; TU_ASSERT( usbh_edpt_control_open(addr0, 8) ); - //------------- Get first 8 bytes of device descriptor to get Control Endpoint Size -------------// + // Get first 8 bytes of device descriptor for Control Endpoint size TU_LOG2("Get 8 byte of Device Descriptor\r\n"); - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_IN - }, - .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = TUSB_DESC_DEVICE << 8, - .wIndex = 0, - .wLength = 8 - }; - TU_ASSERT( tuh_control_xfer(addr0, &request, _usbh_ctrl_buf, enum_get_addr0_device_desc_complete) ); + TU_ASSERT(tuh_descriptor_device_get(addr0, _usbh_ctrl_buf, 8, enum_get_addr0_device_desc_complete)); return true; } @@ -909,22 +923,8 @@ static bool enum_set_address_complete(uint8_t dev_addr, tusb_control_request_t c // Get full device descriptor TU_LOG2("Get Device Descriptor\r\n"); - tusb_control_request_t const new_request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_IN - }, - .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = TUSB_DESC_DEVICE << 8, - .wIndex = 0, - .wLength = sizeof(tusb_desc_device_t) - }; - - TU_ASSERT(tuh_control_xfer(new_addr, &new_request, _usbh_ctrl_buf, enum_get_device_desc_complete)); + TU_ASSERT(tuh_descriptor_device_get(new_addr, _usbh_ctrl_buf, sizeof(tusb_desc_device_t), enum_get_device_desc_complete)); return true; } diff --git a/src/host/usbh.h b/src/host/usbh.h index 98e83fc3c..9af139283 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -39,7 +39,7 @@ //--------------------------------------------------------------------+ typedef bool (*tuh_complete_cb_t)(xfer_result_t result); -typedef bool (*tuh_control_complete_cb_t)(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +typedef bool (*tuh_control_complete_cb_t)(uint8_t daddr, tusb_control_request_t const * request, xfer_result_t result); //--------------------------------------------------------------------+ // APPLICATION API @@ -58,40 +58,49 @@ void tuh_task(void); extern void hcd_int_handler(uint8_t rhport); #define tuh_int_handler hcd_int_handler -bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t* vid, uint16_t* pid); +//------------- descriptors -------------// + +// Get an descriptor +bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, + void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); + +// Get device descriptor +bool tuh_descriptor_device_get(uint8_t daddr, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); + +bool tuh_vid_pid_get(uint8_t daddr, uint16_t* vid, uint16_t* pid); // Gets the string indices for common device descriptor data. -uint8_t tuh_i_manufacturer_get(uint8_t dev_addr); -uint8_t tuh_i_serial_get(uint8_t dev_addr); -uint8_t tuh_i_product_get(uint8_t dev_addr); +uint8_t tuh_i_manufacturer_get(uint8_t daddr); +uint8_t tuh_i_serial_get(uint8_t daddr); +uint8_t tuh_i_product_get(uint8_t daddr); // Reads the string descriptor at the string index into the buffer. This is the // full response so the first entry is the length and the constant 0x03 for // string descriptor type. -bool tuh_string_get(uint8_t dev_addr, uint8_t string_index, uint16_t* buf, size_t len, tuh_complete_cb_t complete_cb); +bool tuh_string_get(uint8_t daddr, uint8_t string_index, uint16_t* buf, size_t len, tuh_complete_cb_t complete_cb); -tusb_speed_t tuh_speed_get(uint8_t dev_addr); +tusb_speed_t tuh_speed_get(uint8_t daddr); // Check if device is connected and configured -bool tuh_mounted(uint8_t dev_addr); +bool tuh_mounted(uint8_t daddr); // Check if device is suspended -static inline bool tuh_suspended(uint8_t dev_addr) +static inline bool tuh_suspended(uint8_t daddr) { // TODO implement suspend & resume on host - (void) dev_addr; + (void) daddr; return false; } // Check if device is ready to communicate with TU_ATTR_ALWAYS_INLINE -static inline bool tuh_ready(uint8_t dev_addr) +static inline bool tuh_ready(uint8_t daddr) { - return tuh_mounted(dev_addr) && !tuh_suspended(dev_addr); + return tuh_mounted(daddr) && !tuh_suspended(daddr); } // Carry out control transfer -bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb); +bool tuh_control_xfer (uint8_t daddr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb); //--------------------------------------------------------------------+ // APPLICATION CALLBACK @@ -99,10 +108,10 @@ bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, //TU_ATTR_WEAK uint8_t tuh_attach_cb (tusb_desc_device_t const *desc_device); // Invoked when device is mounted (configured) -TU_ATTR_WEAK void tuh_mount_cb (uint8_t dev_addr); +TU_ATTR_WEAK void tuh_mount_cb (uint8_t daddr); /// Invoked when device is unmounted (bus reset/unplugged) -TU_ATTR_WEAK void tuh_umount_cb(uint8_t dev_addr); +TU_ATTR_WEAK void tuh_umount_cb(uint8_t daddr); #ifdef __cplusplus } From 032e2c292997f4f8fe58239fcca535bb53ed2348 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 4 Mar 2022 19:28:53 +0700 Subject: [PATCH 11/81] add CFG_TUH_INTERFACE_MAX config --- src/host/usbh.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index 4c3bda4b0..7a994e104 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -41,6 +41,10 @@ #define CFG_TUH_TASK_QUEUE_SZ 16 #endif +#ifndef CFG_TUH_INTERFACE_MAX +#define CFG_TUH_INTERFACE_MAX 8 +#endif + // Debug level of USBD #define USBH_DBG_LVL 2 @@ -96,7 +100,7 @@ typedef struct { //------------- device -------------// volatile uint8_t state; // device state, value from enum tusbh_device_state_t - uint8_t itf2drv[8]; // map interface number to driver (0xff is invalid) + uint8_t itf2drv[CFG_TUH_INTERFACE_MAX]; // map interface number to driver (0xff is invalid) uint8_t ep2drv[CFG_TUH_ENDPOINT_MAX][2]; // map endpoint to driver ( 0xff is invalid ) struct TU_ATTR_PACKED @@ -665,7 +669,7 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) { usbh_device_t* dev = get_device(dev_addr); - for(itf_num++; itf_num < sizeof(dev->itf2drv); 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 @@ -680,7 +684,7 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) } // all interface are configured - if (itf_num == sizeof(dev->itf2drv)) + if (itf_num == CFG_TUH_INTERFACE_MAX) { // Invoke callback if available if (tuh_mount_cb) tuh_mount_cb(dev_addr); From 7480c2e46b10faa0cbdac5c9db803dbb1597cd34 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 4 Mar 2022 21:04:52 +0700 Subject: [PATCH 12/81] correct qhd and qtd count for ehci/ohci --- src/host/hcd.h | 2 +- src/portable/ehci/ehci.c | 7 ++++--- src/portable/ohci/ohci.c | 6 +++--- src/portable/ohci/ohci.h | 5 +++-- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/host/hcd.h b/src/host/hcd.h index d50fc2d60..9819f5f2a 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ #ifndef CFG_TUH_ENDPOINT_MAX - #define CFG_TUH_ENDPOINT_MAX (CFG_TUH_DEVICE_MAX*(CFG_TUH_HUB + CFG_TUH_HID*2 + CFG_TUH_MSC*2 + CFG_TUH_CDC*3)) + #define CFG_TUH_ENDPOINT_MAX (CFG_TUH_HUB + CFG_TUH_HID*2 + CFG_TUH_MSC*2 + CFG_TUH_CDC*3) // #ifdef TUP_HCD_ENDPOINT_MAX // #define CFG_TUH_ENDPPOINT_MAX TUP_HCD_ENDPOINT_MAX // #else diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index bc0b7b89a..2220474d7 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -58,7 +58,8 @@ #define FRAMELIST_SIZE (1024 >> FRAMELIST_SIZE_BIT_VALUE) -#define HCD_MAX_XFER CFG_TUH_ENDPOINT_MAX +#define QHD_MAX (CFG_TUH_DEVICE_MAX*CFG_TUH_ENDPOINT_MAX) +#define QTD_MAX QHD_MAX typedef struct { @@ -76,7 +77,7 @@ typedef struct }control[CFG_TUH_DEVICE_MAX+CFG_TUH_HUB+1]; ehci_qhd_t qhd_pool[CFG_TUH_ENDPOINT_MAX]; - ehci_qtd_t qtd_pool[HCD_MAX_XFER] TU_ATTR_ALIGNED(32); + ehci_qtd_t qtd_pool[QTD_MAX] TU_ATTR_ALIGNED(32); ehci_registers_t* regs; @@ -752,7 +753,7 @@ static inline ehci_qhd_t* qhd_get_from_addr(uint8_t dev_addr, uint8_t ep_addr) //------------- TD helper -------------// static inline ehci_qtd_t* qtd_find_free(void) { - for (uint32_t i=0; i Date: Fri, 4 Mar 2022 21:14:59 +0700 Subject: [PATCH 13/81] add tuh_descriptor_configuration_get() --- src/host/usbh.c | 45 ++++++++++----------------------------------- src/host/usbh.h | 3 +++ 2 files changed, 13 insertions(+), 35 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index 7a994e104..96d2cccd3 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -285,6 +285,11 @@ bool tuh_descriptor_device_get(uint8_t daddr, void* buffer, uint16_t len, tuh_co return tuh_descriptor_get(daddr, TUSB_DESC_DEVICE, 0, buffer, len, complete_cb); } +bool tuh_descriptor_configuration_get(uint8_t daddr, uint8_t index, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) +{ + return tuh_descriptor_get(daddr, TUSB_DESC_CONFIGURATION, index, buffer, len, complete_cb); +} + uint8_t tuh_i_manufacturer_get(uint8_t dev_addr) { TU_VERIFY(tuh_mounted(dev_addr)); usbh_device_t const* dev = get_device(dev_addr); @@ -948,23 +953,9 @@ static bool enum_get_device_desc_complete(uint8_t dev_addr, tusb_control_request // if (tuh_attach_cb) tuh_attach_cb((tusb_desc_device_t*) _usbh_ctrl_buf); - TU_LOG2("Get 9 bytes of Configuration Descriptor\r\n"); - tusb_control_request_t const new_request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_IN - }, - .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = (TUSB_DESC_CONFIGURATION << 8) | (CONFIG_NUM - 1), - .wIndex = 0, - .wLength = 9 - }; - - TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, _usbh_ctrl_buf, enum_get_9byte_config_desc_complete) ); - + // Get 9-byte for total length + TU_LOG2("Get Configuration[0] Descriptor (9 bytes)\r\n"); + TU_ASSERT( tuh_descriptor_configuration_get(dev_addr, 0, _usbh_ctrl_buf, 9, enum_get_9byte_config_desc_complete) ); return true; } @@ -982,24 +973,8 @@ static bool enum_get_9byte_config_desc_complete(uint8_t dev_addr, tusb_control_r TU_ASSERT(total_len <= CFG_TUH_ENUMERATION_BUFSIZE); // Get full configuration descriptor - TU_LOG2("Get Configuration Descriptor\r\n"); - tusb_control_request_t const new_request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_IN - }, - .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = (TUSB_DESC_CONFIGURATION << 8) | (CONFIG_NUM - 1), - .wIndex = 0, - .wLength = total_len - - }; - - TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, _usbh_ctrl_buf, enum_get_config_desc_complete) ); - + TU_LOG2("Get Configuration[0] Descriptor\r\n"); + TU_ASSERT( tuh_descriptor_configuration_get(dev_addr, 0, _usbh_ctrl_buf, total_len, enum_get_config_desc_complete) ); return true; } diff --git a/src/host/usbh.h b/src/host/usbh.h index 9af139283..6926fce8a 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -67,6 +67,9 @@ bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, // Get device descriptor bool tuh_descriptor_device_get(uint8_t daddr, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); +// Get configuration descriptor +bool tuh_descriptor_configuration_get(uint8_t daddr, uint8_t index, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); + bool tuh_vid_pid_get(uint8_t daddr, uint16_t* vid, uint16_t* pid); // Gets the string indices for common device descriptor data. From 15ced09bb2c19663670e2f3a268155b5ecc6e72d Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 4 Mar 2022 21:41:27 +0700 Subject: [PATCH 14/81] add tuh_configuration_set() --- src/host/usbh.c | 116 +++++++++++++++++++++++------------------------- src/host/usbh.h | 52 +++++++++++++--------- 2 files changed, 86 insertions(+), 82 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index 96d2cccd3..ec607a1b6 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -257,9 +257,26 @@ bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t* vid, uint16_t* pid) return true; } +tusb_speed_t tuh_speed_get (uint8_t dev_addr) +{ + return (tusb_speed_t) (dev_addr ? get_device(dev_addr)->speed : _dev0.speed); +} -bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, - void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) +#if CFG_TUSB_OS == OPT_OS_NONE +void osal_task_delay(uint32_t msec) +{ + (void) msec; + + const uint32_t start = hcd_frame_number(TUH_OPT_RHPORT); + while ( ( hcd_frame_number(TUH_OPT_RHPORT) - start ) < msec ) {} +} +#endif + +//--------------------------------------------------------------------+ +// Descriptors +//--------------------------------------------------------------------+ + +bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) { tusb_control_request_t const request = { @@ -272,7 +289,7 @@ bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, .bRequest = TUSB_REQ_GET_DESCRIPTOR, .wValue = tu_htole16( TU_U16(type, index) ), .wIndex = 0, - .wLength = len + .wLength = tu_htole16(len) }; TU_ASSERT( tuh_control_xfer(daddr, &request, buffer, complete_cb) ); @@ -290,6 +307,27 @@ bool tuh_descriptor_configuration_get(uint8_t daddr, uint8_t index, void* buffer return tuh_descriptor_get(daddr, TUSB_DESC_CONFIGURATION, index, buffer, len, complete_cb); } +bool tuh_descriptor_string_get(uint8_t daddr, uint16_t language_id, uint8_t index, + void* buf, uint16_t len, tuh_control_complete_cb_t complete_cb) +{ + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_IN + }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = tu_htole16( TU_U16(TUSB_DESC_STRING, index) ), + .wIndex = tu_htole16(language_id), + .wLength = tu_htole16(len) + }; + + TU_ASSERT( tuh_control_xfer(daddr, &request, buf, complete_cb) ); + return true; +} + uint8_t tuh_i_manufacturer_get(uint8_t dev_addr) { TU_VERIFY(tuh_mounted(dev_addr)); usbh_device_t const* dev = get_device(dev_addr); @@ -311,55 +349,27 @@ uint8_t tuh_i_product_get(uint8_t dev_addr) { return dev->i_product; } -static tuh_complete_cb_t string_get_cb; - -static bool string_get_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { - (void) dev_addr; - (void) request; - if (string_get_cb != NULL) { - string_get_cb(result); - } - string_get_cb = NULL; - return true; -} - -bool tuh_string_get(uint8_t dev_addr, uint8_t string_index, uint16_t* buf, size_t len, tuh_complete_cb_t complete_cb) { - if (string_get_cb != NULL) { - return false; - } +bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, tuh_control_complete_cb_t complete_cb) +{ + TU_LOG2("Set Configuration = %d\r\n", config_num); tusb_control_request_t const request = { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_IN + .direction = TUSB_DIR_OUT }, - .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = TUSB_DESC_STRING << 8 | string_index, + .bRequest = TUSB_REQ_SET_CONFIGURATION, + .wValue = tu_htole16(config_num), .wIndex = 0, - .wLength = len * sizeof(uint16_t) + .wLength = 0 }; - string_get_cb = complete_cb; - TU_ASSERT( tuh_control_xfer(dev_addr, &request, buf, string_get_complete) ); + + TU_ASSERT( tuh_control_xfer(daddr, &request, NULL, complete_cb) ); return true; } -tusb_speed_t tuh_speed_get (uint8_t dev_addr) -{ - return (tusb_speed_t) (dev_addr ? get_device(dev_addr)->speed : _dev0.speed); -} - -#if CFG_TUSB_OS == OPT_OS_NONE -void osal_task_delay(uint32_t msec) -{ - (void) msec; - - const uint32_t start = hcd_frame_number(TUH_OPT_RHPORT); - while ( ( hcd_frame_number(TUH_OPT_RHPORT) - start ) < msec ) {} -} -#endif - //--------------------------------------------------------------------+ // CLASS-USBD API (don't require to verify parameters) //--------------------------------------------------------------------+ @@ -903,7 +913,7 @@ static bool enum_request_set_addr(void) .direction = TUSB_DIR_OUT }, .bRequest = TUSB_REQ_SET_ADDRESS, - .wValue = new_addr, + .wValue = tu_htole16(new_addr), .wIndex = 0, .wLength = 0 }; @@ -954,8 +964,9 @@ static bool enum_get_device_desc_complete(uint8_t dev_addr, tusb_control_request // if (tuh_attach_cb) tuh_attach_cb((tusb_desc_device_t*) _usbh_ctrl_buf); // 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_ASSERT( tuh_descriptor_configuration_get(dev_addr, 0, _usbh_ctrl_buf, 9, enum_get_9byte_config_desc_complete) ); + TU_ASSERT( tuh_descriptor_configuration_get(dev_addr, config_idx, _usbh_ctrl_buf, 9, enum_get_9byte_config_desc_complete) ); return true; } @@ -973,8 +984,9 @@ static bool enum_get_9byte_config_desc_complete(uint8_t dev_addr, tusb_control_r TU_ASSERT(total_len <= CFG_TUH_ENUMERATION_BUFSIZE); // Get full configuration descriptor + uint8_t const config_idx = CONFIG_NUM - 1; TU_LOG2("Get Configuration[0] Descriptor\r\n"); - TU_ASSERT( tuh_descriptor_configuration_get(dev_addr, 0, _usbh_ctrl_buf, total_len, enum_get_config_desc_complete) ); + TU_ASSERT( tuh_descriptor_configuration_get(dev_addr, config_idx, _usbh_ctrl_buf, total_len, enum_get_config_desc_complete) ); return true; } @@ -987,23 +999,7 @@ static bool enum_get_config_desc_complete(uint8_t dev_addr, tusb_control_request // Driver open aren't allowed to make any usb transfer yet TU_ASSERT( parse_configuration_descriptor(dev_addr, (tusb_desc_configuration_t*) _usbh_ctrl_buf) ); - TU_LOG2("Set Configuration = %d\r\n", CONFIG_NUM); - tusb_control_request_t const new_request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_OUT - }, - .bRequest = TUSB_REQ_SET_CONFIGURATION, - .wValue = CONFIG_NUM, - .wIndex = 0, - .wLength = 0 - }; - - TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, NULL, enum_set_config_complete) ); - + TU_ASSERT( tuh_configuration_set(dev_addr, CONFIG_NUM, enum_set_config_complete) ); return true; } diff --git a/src/host/usbh.h b/src/host/usbh.h index 6926fce8a..a10d6df0e 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -58,36 +58,15 @@ void tuh_task(void); extern void hcd_int_handler(uint8_t rhport); #define tuh_int_handler hcd_int_handler -//------------- descriptors -------------// - -// Get an descriptor -bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, - void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); - -// Get device descriptor -bool tuh_descriptor_device_get(uint8_t daddr, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); - -// Get configuration descriptor -bool tuh_descriptor_configuration_get(uint8_t daddr, uint8_t index, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); - bool tuh_vid_pid_get(uint8_t daddr, uint16_t* vid, uint16_t* pid); -// Gets the string indices for common device descriptor data. -uint8_t tuh_i_manufacturer_get(uint8_t daddr); -uint8_t tuh_i_serial_get(uint8_t daddr); -uint8_t tuh_i_product_get(uint8_t daddr); - -// Reads the string descriptor at the string index into the buffer. This is the -// full response so the first entry is the length and the constant 0x03 for -// string descriptor type. -bool tuh_string_get(uint8_t daddr, uint8_t string_index, uint16_t* buf, size_t len, tuh_complete_cb_t complete_cb); - tusb_speed_t tuh_speed_get(uint8_t daddr); // Check if device is connected and configured bool tuh_mounted(uint8_t daddr); // Check if device is suspended +TU_ATTR_ALWAYS_INLINE static inline bool tuh_suspended(uint8_t daddr) { // TODO implement suspend & resume on host @@ -105,6 +84,35 @@ static inline bool tuh_ready(uint8_t daddr) // Carry out control transfer bool tuh_control_xfer (uint8_t daddr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb); +// Set Configuration +// config_num = 0 will un-configure device. Note: config_num = config_descriptor_index + 1 +bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, tuh_control_complete_cb_t complete_cb); + +//------------- descriptors -------------// + +// Get an descriptor +bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, + void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); + +// Get device descriptor +bool tuh_descriptor_device_get(uint8_t daddr, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); + +// Get configuration descriptor +bool tuh_descriptor_configuration_get(uint8_t daddr, uint8_t index, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); + +// Get string descriptor +// Reads the string descriptor at the string index into the buffer. This is the +// full response so the first entry is the length and the constant 0x03 for +// string descriptor type. +bool tuh_descriptor_string_get(uint8_t daddr, uint16_t language_id, uint8_t index, + void* buf, uint16_t len, tuh_control_complete_cb_t complete_cb); + + +// Gets the string indices for common device descriptor data. +uint8_t tuh_i_manufacturer_get(uint8_t daddr); +uint8_t tuh_i_serial_get(uint8_t daddr); +uint8_t tuh_i_product_get(uint8_t daddr); + //--------------------------------------------------------------------+ // APPLICATION CALLBACK //--------------------------------------------------------------------+ From 271f905521edfdcfc5649bbe6906f3d3c6d4b10f Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 4 Mar 2022 22:23:56 +0700 Subject: [PATCH 15/81] add tuh_descriptor_string_manufacturer/produce/serial_get --- src/host/usbh.c | 47 +++++++++++++++++++++++++---------------------- src/host/usbh.h | 16 ++++++++-------- 2 files changed, 33 insertions(+), 30 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index ec607a1b6..241231c1e 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -86,10 +86,11 @@ typedef struct { }; //------------- device descriptor -------------// + uint8_t ep0_size; + uint16_t vid; uint16_t pid; - uint8_t ep0_size; uint8_t i_manufacturer; uint8_t i_product; uint8_t i_serial; @@ -248,7 +249,6 @@ bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t* vid, uint16_t* pid) *vid = *pid = 0; TU_VERIFY(tuh_mounted(dev_addr)); - usbh_device_t const* dev = get_device(dev_addr); *vid = dev->vid; @@ -308,7 +308,7 @@ bool tuh_descriptor_configuration_get(uint8_t daddr, uint8_t index, void* buffer } bool tuh_descriptor_string_get(uint8_t daddr, uint16_t language_id, uint8_t index, - void* buf, uint16_t len, tuh_control_complete_cb_t complete_cb) + void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) { tusb_control_request_t const request = { @@ -324,29 +324,32 @@ bool tuh_descriptor_string_get(uint8_t daddr, uint16_t language_id, uint8_t inde .wLength = tu_htole16(len) }; - TU_ASSERT( tuh_control_xfer(daddr, &request, buf, complete_cb) ); + TU_ASSERT( tuh_control_xfer(daddr, &request, buffer, complete_cb) ); return true; } -uint8_t tuh_i_manufacturer_get(uint8_t dev_addr) { - TU_VERIFY(tuh_mounted(dev_addr)); - usbh_device_t const* dev = get_device(dev_addr); - - return dev->i_manufacturer; +// Get manufacturer string descriptor +bool tuh_descriptor_string_manufacturer_get(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) +{ + TU_VERIFY(tuh_mounted(daddr)); + usbh_device_t const* dev = get_device(daddr); + return tuh_descriptor_string_get(daddr, language_id, dev->i_manufacturer, buffer, len, complete_cb); } -uint8_t tuh_i_serial_get(uint8_t dev_addr) { - TU_VERIFY(tuh_mounted(dev_addr)); - usbh_device_t const* dev = get_device(dev_addr); - - return dev->i_serial; +// Get product string descriptor +bool tuh_descriptor_string_product_get(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) +{ + TU_VERIFY(tuh_mounted(daddr)); + usbh_device_t const* dev = get_device(daddr); + return tuh_descriptor_string_get(daddr, language_id, dev->i_product, buffer, len, complete_cb); } -uint8_t tuh_i_product_get(uint8_t dev_addr) { - TU_VERIFY(tuh_mounted(dev_addr)); - usbh_device_t const* dev = get_device(dev_addr); - - return dev->i_product; +// Get serial string descriptor +bool tuh_descriptor_string_serial_get(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) +{ + TU_VERIFY(tuh_mounted(daddr)); + usbh_device_t const* dev = get_device(daddr); + return tuh_descriptor_string_get(daddr, language_id, dev->i_serial, buffer, len, complete_cb); } bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, tuh_control_complete_cb_t complete_cb) @@ -957,9 +960,9 @@ static bool enum_get_device_desc_complete(uint8_t dev_addr, tusb_control_request dev->vid = desc_device->idVendor; dev->pid = desc_device->idProduct; - dev->i_manufacturer = desc_device->iManufacturer; - dev->i_product = desc_device->iProduct; - dev->i_serial = desc_device->iSerialNumber; +// dev->i_manufacturer = desc_device->iManufacturer; +// dev->i_product = desc_device->iProduct; +// dev->i_serial = desc_device->iSerialNumber; // if (tuh_attach_cb) tuh_attach_cb((tusb_desc_device_t*) _usbh_ctrl_buf); diff --git a/src/host/usbh.h b/src/host/usbh.h index a10d6df0e..1aef603a0 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -101,17 +101,17 @@ bool tuh_descriptor_device_get(uint8_t daddr, void* buffer, uint16_t len, tuh_co bool tuh_descriptor_configuration_get(uint8_t daddr, uint8_t index, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); // Get string descriptor -// Reads the string descriptor at the string index into the buffer. This is the -// full response so the first entry is the length and the constant 0x03 for -// string descriptor type. bool tuh_descriptor_string_get(uint8_t daddr, uint16_t language_id, uint8_t index, - void* buf, uint16_t len, tuh_control_complete_cb_t complete_cb); + void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); +// Get manufacturer string descriptor +bool tuh_descriptor_string_manufacturer_get(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); -// Gets the string indices for common device descriptor data. -uint8_t tuh_i_manufacturer_get(uint8_t daddr); -uint8_t tuh_i_serial_get(uint8_t daddr); -uint8_t tuh_i_product_get(uint8_t daddr); +// Get product string descriptor +bool tuh_descriptor_string_product_get(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); + +// Get serial string descriptor +bool tuh_descriptor_string_serial_get(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); //--------------------------------------------------------------------+ // APPLICATION CALLBACK From b9a6cd8b6163e79d42ba3b56515579f6c1d5f3b2 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 4 Mar 2022 22:25:50 +0700 Subject: [PATCH 16/81] rename example --- examples/host/CMakeLists.txt | 1 - examples/host/{libusb_api => bare_api}/CMakeLists.txt | 0 examples/host/{libusb_api => bare_api}/Makefile | 0 examples/host/{libusb_api => bare_api}/only.txt | 0 examples/host/{libusb_api => bare_api}/src/main.c | 0 examples/host/{libusb_api => bare_api}/src/tusb_config.h | 0 6 files changed, 1 deletion(-) rename examples/host/{libusb_api => bare_api}/CMakeLists.txt (100%) rename examples/host/{libusb_api => bare_api}/Makefile (100%) rename examples/host/{libusb_api => bare_api}/only.txt (100%) rename examples/host/{libusb_api => bare_api}/src/main.c (100%) rename examples/host/{libusb_api => bare_api}/src/tusb_config.h (100%) diff --git a/examples/host/CMakeLists.txt b/examples/host/CMakeLists.txt index 38db6c6cc..5c63ec0c0 100644 --- a/examples/host/CMakeLists.txt +++ b/examples/host/CMakeLists.txt @@ -8,4 +8,3 @@ family_initialize_project(tinyusb_host_examples ${CMAKE_CURRENT_LIST_DIR}) # family_add_subdirectory will filter what to actually add based on selected FAMILY family_add_subdirectory(cdc_msc_hid) family_add_subdirectory(hid_controller) -family_add_subdirectory(libusb_api) diff --git a/examples/host/libusb_api/CMakeLists.txt b/examples/host/bare_api/CMakeLists.txt similarity index 100% rename from examples/host/libusb_api/CMakeLists.txt rename to examples/host/bare_api/CMakeLists.txt diff --git a/examples/host/libusb_api/Makefile b/examples/host/bare_api/Makefile similarity index 100% rename from examples/host/libusb_api/Makefile rename to examples/host/bare_api/Makefile diff --git a/examples/host/libusb_api/only.txt b/examples/host/bare_api/only.txt similarity index 100% rename from examples/host/libusb_api/only.txt rename to examples/host/bare_api/only.txt diff --git a/examples/host/libusb_api/src/main.c b/examples/host/bare_api/src/main.c similarity index 100% rename from examples/host/libusb_api/src/main.c rename to examples/host/bare_api/src/main.c diff --git a/examples/host/libusb_api/src/tusb_config.h b/examples/host/bare_api/src/tusb_config.h similarity index 100% rename from examples/host/libusb_api/src/tusb_config.h rename to examples/host/bare_api/src/tusb_config.h From 56c2d4b666856dedd9ced301d8a273c55ee2afd6 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 4 Mar 2022 22:31:48 +0700 Subject: [PATCH 17/81] fix naming, and build --- examples/host/bare_api/src/main.c | 2 +- src/host/usbh.h | 1 - src/portable/ehci/ehci.c | 10 +++++----- src/portable/ohci/ohci.h | 2 +- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/examples/host/bare_api/src/main.c b/examples/host/bare_api/src/main.c index 07dae1dc6..b6b1527c0 100644 --- a/examples/host/bare_api/src/main.c +++ b/examples/host/bare_api/src/main.c @@ -66,8 +66,8 @@ int main(void) void print_device_descriptor(uint8_t dev_addr) { + (void) dev_addr; printf("Device Descriptor:\r\n"); - } // Invoked when device is mounted (configured) diff --git a/src/host/usbh.h b/src/host/usbh.h index 1aef603a0..9465d1d1b 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -38,7 +38,6 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -typedef bool (*tuh_complete_cb_t)(xfer_result_t result); typedef bool (*tuh_control_complete_cb_t)(uint8_t daddr, tusb_control_request_t const * request, xfer_result_t result); //--------------------------------------------------------------------+ diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 2220474d7..8d420f26a 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -76,7 +76,7 @@ typedef struct ehci_qtd_t qtd; }control[CFG_TUH_DEVICE_MAX+CFG_TUH_HUB+1]; - ehci_qhd_t qhd_pool[CFG_TUH_ENDPOINT_MAX]; + ehci_qhd_t qhd_pool[QHD_MAX]; ehci_qtd_t qtd_pool[QTD_MAX] TU_ATTR_ALIGNED(32); ehci_registers_t* regs; @@ -481,7 +481,7 @@ static void async_advance_isr(uint8_t rhport) (void) rhport; ehci_qhd_t* qhd_pool = ehci_data.qhd_pool; - for(uint32_t i = 0; i < CFG_TUH_ENDPOINT_MAX; i++) + for(uint32_t i = 0; i < QHD_MAX; i++) { if ( qhd_pool[i].removing ) { @@ -549,7 +549,7 @@ static void period_list_xfer_complete_isr(uint8_t hostid, uint32_t interval_ms) // TODO abstract max loop guard for period while( !next_item.terminate && !(interval_ms > 1 && period_1ms_addr == tu_align32(next_item.address)) && - max_loop < (CFG_TUH_ENDPOINT_MAX + EHCI_MAX_ITD + EHCI_MAX_SITD)*CFG_TUH_DEVICE_MAX) + max_loop < (QHD_MAX + EHCI_MAX_ITD + EHCI_MAX_SITD)*CFG_TUH_DEVICE_MAX) { switch ( next_item.type ) { @@ -721,7 +721,7 @@ void hcd_int_handler(uint8_t rhport) //------------- queue head helper -------------// static inline ehci_qhd_t* qhd_find_free (void) { - for (uint32_t i=0; i Date: Fri, 4 Mar 2022 15:35:32 +0000 Subject: [PATCH 18/81] documentatio: fix bad supported dev table format --- docs/reference/supported.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/supported.rst b/docs/reference/supported.rst index 7c5402d93..7ce982713 100644 --- a/docs/reference/supported.rst +++ b/docs/reference/supported.rst @@ -42,7 +42,7 @@ Supported MCUs +--------------+---------+-------------+--------+------+-----------+-------------------+--------------+ | NXP | iMXRT | RT10xx | ✔ | ✔ | ✔ | ci_hs | | | +---------+-------------+--------+------+-----------+-------------------+--------------+ -| | Kinetis | KL25 | ✔ | ⚠ | ✖ | | | +| | Kinetis | KL25 | ✔ | ⚠ | ✖ | | | | | +-------------+--------+------+-----------+-------------------+--------------+ | | | K32L2 | ✔ | | ✖ | | | | +---------+-------------+--------+------+-----------+-------------------+--------------+ From f291243121ef35e88c16c47a259213d455c4a401 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Fri, 4 Mar 2022 11:38:02 -0800 Subject: [PATCH 19/81] Fix string descriptor fetch --- src/host/usbh.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index 241231c1e..192979ce6 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -333,6 +333,9 @@ bool tuh_descriptor_string_manufacturer_get(uint8_t daddr, uint16_t language_id, { TU_VERIFY(tuh_mounted(daddr)); usbh_device_t const* dev = get_device(daddr); + if (dev->i_manufacturer == 0) { + return false; + } return tuh_descriptor_string_get(daddr, language_id, dev->i_manufacturer, buffer, len, complete_cb); } @@ -341,6 +344,9 @@ bool tuh_descriptor_string_product_get(uint8_t daddr, uint16_t language_id, void { TU_VERIFY(tuh_mounted(daddr)); usbh_device_t const* dev = get_device(daddr); + if (dev->i_product == 0) { + return false; + } return tuh_descriptor_string_get(daddr, language_id, dev->i_product, buffer, len, complete_cb); } @@ -349,6 +355,9 @@ bool tuh_descriptor_string_serial_get(uint8_t daddr, uint16_t language_id, void* { TU_VERIFY(tuh_mounted(daddr)); usbh_device_t const* dev = get_device(daddr); + if (dev->i_serial == 0) { + return false; + } return tuh_descriptor_string_get(daddr, language_id, dev->i_serial, buffer, len, complete_cb); } @@ -960,9 +969,9 @@ static bool enum_get_device_desc_complete(uint8_t dev_addr, tusb_control_request dev->vid = desc_device->idVendor; dev->pid = desc_device->idProduct; -// dev->i_manufacturer = desc_device->iManufacturer; -// dev->i_product = desc_device->iProduct; -// dev->i_serial = desc_device->iSerialNumber; + dev->i_manufacturer = desc_device->iManufacturer; + dev->i_product = desc_device->iProduct; + dev->i_serial = desc_device->iSerialNumber; // if (tuh_attach_cb) tuh_attach_cb((tusb_desc_device_t*) _usbh_ctrl_buf); From 2bef4410f9ca71e60ce4072cca02ca6b544c0caa Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Sat, 5 Mar 2022 17:07:04 +0100 Subject: [PATCH 20/81] Add stm32wb cmsis and hal driver submodules from ST --- .gitmodules | 6 ++++++ hw/mcu/st/cmsis_device_wb | 1 + hw/mcu/st/stm32wbxx_hal_driver | 1 + 3 files changed, 8 insertions(+) create mode 160000 hw/mcu/st/cmsis_device_wb create mode 160000 hw/mcu/st/stm32wbxx_hal_driver diff --git a/.gitmodules b/.gitmodules index fb551060a..21bbf08c0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -97,6 +97,12 @@ [submodule "hw/mcu/st/stm32l5xx_hal_driver"] path = hw/mcu/st/stm32l5xx_hal_driver url = https://github.com/STMicroelectronics/stm32l5xx_hal_driver.git +[submodule "hw/mcu/st/cmsis_device_wb"] + path = hw/mcu/st/cmsis_device_wb + url = https://github.com/STMicroelectronics/cmsis_device_wb.git +[submodule "hw/mcu/st/stm32wbxx_hal_driver"] + path = hw/mcu/st/stm32wbxx_hal_driver + url = https://github.com/STMicroelectronics/stm32wbxx_hal_driver.git [submodule "lib/sct_neopixel"] path = lib/sct_neopixel url = https://github.com/gsteiert/sct_neopixel diff --git a/hw/mcu/st/cmsis_device_wb b/hw/mcu/st/cmsis_device_wb new file mode 160000 index 000000000..9c5d1920d --- /dev/null +++ b/hw/mcu/st/cmsis_device_wb @@ -0,0 +1 @@ +Subproject commit 9c5d1920dd9fabbe2548e10561d63db829bb744f diff --git a/hw/mcu/st/stm32wbxx_hal_driver b/hw/mcu/st/stm32wbxx_hal_driver new file mode 160000 index 000000000..2c5f06638 --- /dev/null +++ b/hw/mcu/st/stm32wbxx_hal_driver @@ -0,0 +1 @@ +Subproject commit 2c5f06638be516c1b772f768456ba637f077bac8 From 65bf5ddb1bfe87719fc612d1eae44087b87e682a Mon Sep 17 00:00:00 2001 From: QianHao <929254256@qq.com> Date: Mon, 7 Mar 2022 08:04:49 +0000 Subject: [PATCH 21/81] Modify the wrong macro definition code --- src/portable/synopsys/dwc2/dwc2_type.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/portable/synopsys/dwc2/dwc2_type.h b/src/portable/synopsys/dwc2/dwc2_type.h index dbef20314..7fa2028eb 100644 --- a/src/portable/synopsys/dwc2/dwc2_type.h +++ b/src/portable/synopsys/dwc2/dwc2_type.h @@ -986,16 +986,16 @@ TU_VERIFY_STATIC(offsetof(dwc2_regs_t, fifo ) == 0x1000, "incorrect size"); /******************** Bit definition for OTG register ********************/ #define GNPTXFSIZ_NPTXFSA_Pos (0U) -#define GNPTXFSIZ_NPTXFSA_Msk (0xFFFFUL << NPTXFSA_Pos) // 0x0000FFFF */ +#define GNPTXFSIZ_NPTXFSA_Msk (0xFFFFUL << GNPTXFSIZ_NPTXFSA_Pos) // 0x0000FFFF */ #define GNPTXFSIZ_NPTXFSA GNPTXFSIZ_NPTXFSA_Msk // Nonperiodic transmit RAM start address */ #define GNPTXFSIZ_NPTXFD_Pos (16U) -#define GNPTXFSIZ_NPTXFD_Msk (0xFFFFUL << NPTXFD_Pos) // 0xFFFF0000 */ +#define GNPTXFSIZ_NPTXFD_Msk (0xFFFFUL << GNPTXFSIZ_NPTXFD_Pos) // 0xFFFF0000 */ #define GNPTXFSIZ_NPTXFD GNPTXFSIZ_NPTXFD_Msk // Nonperiodic TxFIFO depth */ #define DIEPTXF0_TX0FSA_Pos (0U) -#define DIEPTXF0_TX0FSA_Msk (0xFFFFUL << TX0FSA_Pos) // 0x0000FFFF */ +#define DIEPTXF0_TX0FSA_Msk (0xFFFFUL << DIEPTXF0_TX0FSA_Pos) // 0x0000FFFF */ #define DIEPTXF0_TX0FSA DIEPTXF0_TX0FSA_Msk // Endpoint 0 transmit RAM start address */ #define DIEPTXF0_TX0FD_Pos (16U) -#define DIEPTXF0_TX0FD_Msk (0xFFFFUL << TX0FD_Pos) // 0xFFFF0000 */ +#define DIEPTXF0_TX0FD_Msk (0xFFFFUL << DIEPTXF0_TX0FD_Pos) // 0xFFFF0000 */ #define DIEPTXF0_TX0FD DIEPTXF0_TX0FD_Msk // Endpoint 0 TxFIFO depth */ /******************** Bit definition for DVBUSPULSE register ********************/ From a18ac842298d3742dc7044bd0db5c2351a4219a8 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Sat, 5 Mar 2022 17:09:04 +0100 Subject: [PATCH 22/81] Add support for STM32WB mcu --- src/common/tusb_mcu.h | 3 +++ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 10 +++++++++- src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h | 7 +++++++ src/tusb_option.h | 1 + 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 465e33ec7..8eb4ad475 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -184,6 +184,9 @@ #define TUP_DCD_ENDPOINT_MAX 8 #endif +#elif TU_CHECK_MCU(OPT_MCU_STM32WB) +#define TUP_DCD_ENDPOINT_MAX 8 + //------------- Sony -------------// #elif TU_CHECK_MCU(OPT_MCU_CXD56) #define TUP_DCD_ENDPOINT_MAX 7 diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index f201a02cf..4fd189188 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -110,7 +110,7 @@ #endif #if CFG_TUD_ENABLED && \ - ( TU_CHECK_MCU(OPT_MCU_STM32F0, OPT_MCU_STM32F3, OPT_MCU_STM32L0, OPT_MCU_STM32L1, OPT_MCU_STM32G4) || \ + ( TU_CHECK_MCU(OPT_MCU_STM32F0, OPT_MCU_STM32F3, OPT_MCU_STM32L0, OPT_MCU_STM32L1, OPT_MCU_STM32G4, OPT_MCU_STM32WB) || \ (TU_CHECK_MCU(OPT_MCU_STM32F1) && defined(STM32F1_FSDEV)) \ ) @@ -328,6 +328,10 @@ void dcd_int_enable (uint8_t rhport) NVIC_EnableIRQ(USB_LP_IRQn); NVIC_EnableIRQ(USBWakeUp_IRQn); +#elif CFG_TUSB_MCU == OPT_MCU_STM32WB + NVIC_EnableIRQ(USB_HP_IRQn); + NVIC_EnableIRQ(USB_LP_IRQn); + #else #error Unknown arch in USB driver #endif @@ -370,6 +374,10 @@ void dcd_int_disable(uint8_t rhport) NVIC_DisableIRQ(USB_LP_IRQn); NVIC_DisableIRQ(USBWakeUp_IRQn); +#elif CFG_TUSB_MCU == OPT_MCU_STM32WB + NVIC_DisableIRQ(USB_HP_IRQn); + NVIC_DisableIRQ(USB_LP_IRQn); + #else #error Unknown arch in USB driver #endif diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h index 596f7be6c..bffae4500 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h @@ -91,6 +91,13 @@ #include "stm32g4xx.h" #define PMA_LENGTH (1024u) +#elif CFG_TUSB_MCU == OPT_MCU_STM32WB + #include "stm32wbxx.h" + #define PMA_LENGTH (1024u) + /* ST provided header has incorrect value */ + #undef USB_PMAADDR + #define USB_PMAADDR USB1_PMAADDR + #else #error You are using an untested or unimplemented STM32 variant. Please update the driver. // This includes L1x0, L1x1, L1x2, L4x2 and L4x3, G1x1, G1x3, and G1x4 diff --git a/src/tusb_option.h b/src/tusb_option.h index 25e536787..3f404872a 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -80,6 +80,7 @@ #define OPT_MCU_STM32L4 309 ///< ST L4 #define OPT_MCU_STM32G0 310 ///< ST G0 #define OPT_MCU_STM32G4 311 ///< ST G4 +#define OPT_MCU_STM32WB 312 ///< ST WB // Sony #define OPT_MCU_CXD56 400 ///< SONY CXD56 From 76c8d4d95b78ae479ce21e8780c50c733ac18829 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Sat, 5 Mar 2022 17:12:01 +0100 Subject: [PATCH 23/81] Add support for nucleo-wb55rg --- hw/bsp/stm32wb/boards/stm32wb55nucleo/board.h | 122 ++++++ .../stm32wb/boards/stm32wb55nucleo/board.mk | 9 + .../stm32wb55nucleo/stm32wb55xx_flash_cm4.ld | 171 +++++++++ hw/bsp/stm32wb/family.c | 190 ++++++++++ hw/bsp/stm32wb/family.mk | 44 +++ hw/bsp/stm32wb/stm32wbxx_hal_conf.h | 349 ++++++++++++++++++ 6 files changed, 885 insertions(+) create mode 100644 hw/bsp/stm32wb/boards/stm32wb55nucleo/board.h create mode 100644 hw/bsp/stm32wb/boards/stm32wb55nucleo/board.mk create mode 100644 hw/bsp/stm32wb/boards/stm32wb55nucleo/stm32wb55xx_flash_cm4.ld create mode 100644 hw/bsp/stm32wb/family.c create mode 100644 hw/bsp/stm32wb/family.mk create mode 100644 hw/bsp/stm32wb/stm32wbxx_hal_conf.h diff --git a/hw/bsp/stm32wb/boards/stm32wb55nucleo/board.h b/hw/bsp/stm32wb/boards/stm32wb55nucleo/board.h new file mode 100644 index 000000000..f42c7d6dd --- /dev/null +++ b/hw/bsp/stm32wb/boards/stm32wb55nucleo/board.h @@ -0,0 +1,122 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2022, Jerzy Kasenberg + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// LED +#define LED_PORT GPIOB +#define LED_PIN GPIO_PIN_5 +#define LED_STATE_ON 1 + +// Button +#define BUTTON_PORT GPIOC +#define BUTTON_PIN GPIO_PIN_4 +#define BUTTON_STATE_ACTIVE 0 + +// UART Enable for STLink VCOM +#define UART_DEV USART1 +#define UART_CLK_EN __HAL_RCC_USART1_CLK_ENABLE +#define UART_GPIO_PORT GPIOB +#define UART_GPIO_AF GPIO_AF7_USART1 +#define UART_TX_PIN GPIO_PIN_6 +#define UART_RX_PIN GPIO_PIN_7 + + +//--------------------------------------------------------------------+ +// RCC Clock +//--------------------------------------------------------------------+ +static inline void board_clock_init(void) +{ + RCC_OscInitTypeDef RCC_OscInitStruct = {0}; + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; + + // Initializes the CPU, AHB and APB busses clocks + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48 | RCC_OSCILLATORTYPE_HSE; + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV4; + RCC_OscInitStruct.PLL.PLLN = 24; + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4; + RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV4; + RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV3; + HAL_RCC_OscConfig(&RCC_OscInitStruct); + + // Initializes the CPU, AHB and APB busses clocks + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; + HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3); + + PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB; + PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_HSI48; + HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) ; + +#if 0 // TODO need to check if USB clock is enabled + /* Enable HSI48 */ + memset(&RCC_OscInitStruct, 0, sizeof(RCC_OscInitStruct)); + + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48; + RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; + HAL_RCC_OscConfig(&RCC_OscInitStruct); + + /*Enable CRS Clock*/ + RCC_CRSInitTypeDef RCC_CRSInitStruct= {0}; + __HAL_RCC_CRS_CLK_ENABLE(); + + /* Default Synchro Signal division factor (not divided) */ + RCC_CRSInitStruct.Prescaler = RCC_CRS_SYNC_DIV1; + + /* Set the SYNCSRC[1:0] bits according to CRS_Source value */ + RCC_CRSInitStruct.Source = RCC_CRS_SYNC_SOURCE_USB; + + /* HSI48 is synchronized with USB SOF at 1KHz rate */ + RCC_CRSInitStruct.ReloadValue = __HAL_RCC_CRS_RELOADVALUE_CALCULATE(48000000, 1000); + RCC_CRSInitStruct.ErrorLimitValue = RCC_CRS_ERRORLIMIT_DEFAULT; + + /* Set the TRIM[5:0] to the default value */ + RCC_CRSInitStruct.HSI48CalibrationValue = RCC_CRS_HSI48CALIBRATION_DEFAULT; + + /* Start automatic synchronization */ + HAL_RCCEx_CRSConfig(&RCC_CRSInitStruct); +#endif +} + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/stm32wb/boards/stm32wb55nucleo/board.mk b/hw/bsp/stm32wb/boards/stm32wb55nucleo/board.mk new file mode 100644 index 000000000..d6adc6b63 --- /dev/null +++ b/hw/bsp/stm32wb/boards/stm32wb55nucleo/board.mk @@ -0,0 +1,9 @@ +CFLAGS += \ + -DSTM32WB55xx + +LD_FILE = $(BOARD_PATH)/stm32wb55xx_flash_cm4.ld + +SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32wb55xx_cm4.s + +# For flash-jlink target +JLINK_DEVICE = STM32WB55RG diff --git a/hw/bsp/stm32wb/boards/stm32wb55nucleo/stm32wb55xx_flash_cm4.ld b/hw/bsp/stm32wb/boards/stm32wb55nucleo/stm32wb55xx_flash_cm4.ld new file mode 100644 index 000000000..660f30161 --- /dev/null +++ b/hw/bsp/stm32wb/boards/stm32wb55nucleo/stm32wb55xx_flash_cm4.ld @@ -0,0 +1,171 @@ +/** +***************************************************************************** +** +** File : stm32wb55xx_flash_cm4.ld +** +** Abstract : System Workbench Minimal System calls file +** +** For more information about which c-functions +** need which of these lowlevel functions +** please consult the Newlib libc-manual +** +** Environment : System Workbench for MCU +** +** Distribution: The file is distributed “as is,” without any warranty +** of any kind. +** +***************************************************************************** +** @attention +** +** Copyright (c) 2019 STMicroelectronics. +** All rights reserved. +** +** This software is licensed under terms that can be found in the LICENSE file +** in the root directory of this software component. +** If no LICENSE file comes with this software, it is provided AS-IS. +** +***************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +_estack = 0x20030000; /* end of RAM */ +/* Generate a link error if heap and stack don't fit into RAM */ +_Min_Heap_Size = 0x400; /* required amount of heap */ +_Min_Stack_Size = 0x1000; /* required amount of stack */ + +/* Specify the memory areas */ +MEMORY +{ +FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K +RAM1 (xrw) : ORIGIN = 0x20000008, LENGTH = 0x2FFF8 +RAM_SHARED (xrw) : ORIGIN = 0x20030000, LENGTH = 10K +} + +/* Define output sections */ +SECTIONS +{ + /* The startup code goes first into FLASH */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data goes into FLASH */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + + /* used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + } >RAM1 AT> FLASH + + + /* Uninitialized data section */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss section */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM1 + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >RAM1 + + + + /* Remove information from the standard libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } + MAPPING_TABLE (NOLOAD) : { *(MAPPING_TABLE) } >RAM_SHARED + MB_MEM1 (NOLOAD) : { *(MB_MEM1) } >RAM_SHARED + MB_MEM2 (NOLOAD) : { _sMB_MEM2 = . ; *(MB_MEM2) ; _eMB_MEM2 = . ; } >RAM_SHARED +} + + diff --git a/hw/bsp/stm32wb/family.c b/hw/bsp/stm32wb/family.c new file mode 100644 index 000000000..1ed38308b --- /dev/null +++ b/hw/bsp/stm32wb/family.c @@ -0,0 +1,190 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2022 Jerzy Kasenberg + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "stm32wbxx_hal.h" +#include "bsp/board.h" +#include "board.h" + +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_HP_IRQHandler(void) +{ + tud_int_handler(0); +} + +void USB_LP_IRQHandler(void) +{ + tud_int_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ +UART_HandleTypeDef UartHandle; + +void board_init(void) +{ + board_clock_init(); + + // Enable All GPIOs clocks + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOD_CLK_ENABLE(); + __HAL_RCC_GPIOE_CLK_ENABLE(); + + UART_CLK_EN(); + +#if CFG_TUSB_OS == OPT_OS_NONE + // 1ms tick timer + SysTick_Config(SystemCoreClock / 1000); +#elif CFG_TUSB_OS == OPT_OS_FREERTOS + // Explicitly disable systick to prevent its ISR runs before scheduler start + SysTick->CTRL &= ~1U; + + // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) + NVIC_SetPriority(OTG_FS_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); +#endif + + GPIO_InitTypeDef GPIO_InitStruct; + + // LED + GPIO_InitStruct.Pin = LED_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct); + +#if 0 + // MCO configuration for System clock value verification PA8 will have SYSCLK / 2 + GPIO_InitStruct.Pin = 8; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF0_MCO; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_SYSCLK, RCC_MCODIV_2); +#endif + + board_led_write(false); + + // Button + GPIO_InitStruct.Pin = BUTTON_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = BUTTON_STATE_ACTIVE ? GPIO_PULLDOWN : GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(BUTTON_PORT, &GPIO_InitStruct); + +#ifdef UART_DEV + // UART + GPIO_InitStruct.Pin = UART_TX_PIN | UART_RX_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Alternate = UART_GPIO_AF; + HAL_GPIO_Init(UART_GPIO_PORT, &GPIO_InitStruct); + + UartHandle = (UART_HandleTypeDef){ + .Instance = UART_DEV, + .Init.BaudRate = CFG_BOARD_UART_BAUDRATE, + .Init.WordLength = UART_WORDLENGTH_8B, + .Init.StopBits = UART_STOPBITS_1, + .Init.Parity = UART_PARITY_NONE, + .Init.HwFlowCtl = UART_HWCONTROL_NONE, + .Init.Mode = UART_MODE_TX_RX, + .Init.OverSampling = UART_OVERSAMPLING_16 + }; + HAL_UART_Init(&UartHandle); +#endif + + // USB Pins TODO double check USB clock and pin setup + // Configure USB DM and DP pins. This is optional, and maintained only for user guidance. + GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12); + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + HAL_PWREx_EnableVddUSB(); + __HAL_RCC_USB_CLK_ENABLE(); +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) +{ + HAL_GPIO_WritePin(LED_PORT, LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON)); +} + +uint32_t board_button_read(void) +{ + return BUTTON_STATE_ACTIVE == HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN); +} + +int board_uart_read(uint8_t* buf, int len) +{ + (void) buf; (void) len; + return 0; +} + +int board_uart_write(void const * buf, int len) +{ +#ifdef UART_DEV + HAL_UART_Transmit(&UartHandle, (uint8_t*)(uintptr_t) buf, len, 0xffff); + return len; +#else + (void) buf; (void) len; (void) UartHandle; + return 0; +#endif +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; +void SysTick_Handler (void) +{ + system_ticks++; +} + +uint32_t board_millis(void) +{ + return system_ticks; +} +#endif + +void HardFault_Handler (void) +{ + asm("bkpt"); +} + +// Required by __libc_init_array in startup code if we are compiling using +// -nostdlib/-nostartfiles. +void _init(void) +{ + +} diff --git a/hw/bsp/stm32wb/family.mk b/hw/bsp/stm32wb/family.mk new file mode 100644 index 000000000..f85c5badd --- /dev/null +++ b/hw/bsp/stm32wb/family.mk @@ -0,0 +1,44 @@ +UF2_FAMILY_ID = 0x70d16653 +ST_FAMILY = wb +DEPS_SUBMODULES += lib/CMSIS_5 hw/mcu/st/cmsis_device_$(ST_FAMILY) hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver + +ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) +ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver + +include $(TOP)/$(BOARD_PATH)/board.mk + +CFLAGS += \ + -flto \ + -mthumb \ + -mabi=aapcs \ + -mcpu=cortex-m4 \ + -mfloat-abi=hard \ + -mfpu=fpv4-sp-d16 \ + -nostdlib -nostartfiles \ + -DCFG_TUSB_MCU=OPT_MCU_STM32WB + +# suppress warning caused by vendor mcu driver +CFLAGS += -Wno-error=cast-align -Wno-unused-parameter + +SRC_C += \ + src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_pwr_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_uart.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c + +INC += \ + $(TOP)/$(BOARD_PATH) \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ + $(TOP)/$(ST_CMSIS)/Include \ + $(TOP)/$(ST_HAL_DRIVER)/Inc + +# For freeRTOS port source +FREERTOS_PORT = ARM_CM4F + +# flash target using on-board stlink +flash: flash-stlink diff --git a/hw/bsp/stm32wb/stm32wbxx_hal_conf.h b/hw/bsp/stm32wb/stm32wbxx_hal_conf.h new file mode 100644 index 000000000..754c94ed9 --- /dev/null +++ b/hw/bsp/stm32wb/stm32wbxx_hal_conf.h @@ -0,0 +1,349 @@ +/** + ****************************************************************************** + * @file stm32wbxx_hal_conf.h + * @author MCD Application Team + * @brief HAL configuration file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32WBxx_HAL_CONF_H +#define __STM32WBxx_HAL_CONF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ +#define HAL_MODULE_ENABLED +/*#define HAL_ADC_MODULE_ENABLED */ +/*#define HAL_COMP_MODULE_ENABLED */ +/*#define HAL_CRC_MODULE_ENABLED */ +/*#define HAL_HSEM_MODULE_ENABLED */ +/*#define HAL_IPCC_MODULE_ENABLED */ +/*#define HAL_IRDA_MODULE_ENABLED */ +/*#define HAL_LCD_MODULE_ENABLED */ +/*#define HAL_LPTIM_MODULE_ENABLED */ +/*#define HAL_PCD_MODULE_ENABLED */ +/*#define HAL_PKA_MODULE_ENABLED */ +/*#define HAL_QSPI_MODULE_ENABLED */ +#define HAL_RTC_MODULE_ENABLED +/*#define HAL_SAI_MODULE_ENABLED */ +/*#define HAL_SMBUS_MODULE_ENABLED */ +/*#define HAL_SMARTCARD_MODULE_ENABLED */ +/*#define HAL_TSC_MODULE_ENABLED */ +#define HAL_UART_MODULE_ENABLED +/*#define HAL_USART_MODULE_ENABLED */ +/*#define HAL_WWDG_MODULE_ENABLED */ +#define HAL_CORTEX_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_IWDG_MODULE_ENABLED +#define HAL_TIM_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +#define HAL_RNG_MODULE_ENABLED +/*#define HAL_CRYP_MODULE_ENABLED */ + +#define USE_HAL_ADC_REGISTER_CALLBACKS 0u +#define USE_HAL_COMP_REGISTER_CALLBACKS 0u +#define USE_HAL_CRYP_REGISTER_CALLBACKS 0u +#define USE_HAL_I2C_REGISTER_CALLBACKS 0u +#define USE_HAL_IRDA_REGISTER_CALLBACKS 0u +#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0u +#define USE_HAL_PCD_REGISTER_CALLBACKS 0u +#define USE_HAL_PKA_REGISTER_CALLBACKS 0u +#define USE_HAL_QSPI_REGISTER_CALLBACKS 0u +#define USE_HAL_RNG_REGISTER_CALLBACKS 0u +#define USE_HAL_RTC_REGISTER_CALLBACKS 0u +#define USE_HAL_SAI_REGISTER_CALLBACKS 0u +#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0u +#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0u +#define USE_HAL_SPI_REGISTER_CALLBACKS 0u +#define USE_HAL_TIM_REGISTER_CALLBACKS 0u +#define USE_HAL_TSC_REGISTER_CALLBACKS 0u +#define USE_HAL_UART_REGISTER_CALLBACKS 0u +#define USE_HAL_USART_REGISTER_CALLBACKS 0u +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0u + +/* ########################## Oscillator Values adaptation ####################*/ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) +#define HSE_VALUE 32000000U /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) + #define HSE_STARTUP_TIMEOUT ((uint32_t)100) /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal Multiple Speed oscillator (MSI) default value. + * This value is the default MSI range value after Reset. + */ +#if !defined (MSI_VALUE) + #define MSI_VALUE ((uint32_t)4000000) /*!< Value of the Internal oscillator in Hz*/ +#endif /* MSI_VALUE */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) +#define HSI_VALUE 16000000U /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI1) value. + */ +#if !defined (LSI1_VALUE) + #define LSI1_VALUE ((uint32_t)32000) /*!< LSI1 Typical Value in Hz*/ +#endif /* LSI1_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz + The real value may vary depending on the variations + in voltage and temperature.*/ +/** + * @brief Internal Low Speed oscillator (LSI2) value. + */ +#if !defined (LSI2_VALUE) + #define LSI2_VALUE ((uint32_t)32000) /*!< LSI2 Typical Value in Hz*/ +#endif /* LSI2_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz + The real value may vary depending on the variations + in voltage and temperature.*/ + +/** + * @brief External Low Speed oscillator (LSE) value. + * This value is used by the UART, RTC HAL module to compute the system frequency + */ +#if !defined (LSE_VALUE) +#define LSE_VALUE 32768U /*!< Value of the External oscillator in Hz*/ +#endif /* LSE_VALUE */ + +/** + * @brief Internal Multiple Speed oscillator (HSI48) default value. + * This value is the default HSI48 range value after Reset. + */ +#if !defined (HSI48_VALUE) + #define HSI48_VALUE ((uint32_t)48000000) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI48_VALUE */ + +#if !defined (LSE_STARTUP_TIMEOUT) +#define LSE_STARTUP_TIMEOUT 5000U /*!< Time out for LSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief External clock source for SAI1 peripheral + * This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source + * frequency. + */ +#if !defined (EXTERNAL_SAI1_CLOCK_VALUE) + #define EXTERNAL_SAI1_CLOCK_VALUE ((uint32_t)2097000) /*!< Value of the SAI1 External clock source in Hz*/ +#endif /* EXTERNAL_SAI1_CLOCK_VALUE */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ + +#define VDD_VALUE 3300U /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY 0U /*!< tick interrupt priority */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 1 +#define INSTRUCTION_CACHE_ENABLE 1 +#define DATA_CACHE_ENABLE 1 + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1U */ + +/* ################## SPI peripheral configuration ########################## */ + +/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver + * Activated: CRC code is present inside driver + * Deactivated: CRC code cleaned from driver + */ + +#define USE_SPI_CRC 0U + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ +#ifdef HAL_DMA_MODULE_ENABLED + #include "stm32wbxx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED + #include "stm32wbxx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_COMP_MODULE_ENABLED + #include "stm32wbxx_hal_comp.h" +#endif /* HAL_COMP_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED + #include "stm32wbxx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED + #include "stm32wbxx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED + #include "stm32wbxx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED + #include "stm32wbxx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED + #include "stm32wbxx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_HSEM_MODULE_ENABLED + #include "stm32wbxx_hal_hsem.h" +#endif /* HAL_HSEM_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED + #include "stm32wbxx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_IPCC_MODULE_ENABLED + #include "stm32wbxx_hal_ipcc.h" +#endif /* HAL_IPCC_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED + #include "stm32wbxx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED + #include "stm32wbxx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_LCD_MODULE_ENABLED + #include "stm32wbxx_hal_lcd.h" +#endif /* HAL_LCD_MODULE_ENABLED */ + +#ifdef HAL_LPTIM_MODULE_ENABLED + #include "stm32wbxx_hal_lptim.h" +#endif /* HAL_LPTIM_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED + #include "stm32wbxx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_PKA_MODULE_ENABLED + #include "stm32wbxx_hal_pka.h" +#endif /* HAL_PKA_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED + #include "stm32wbxx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_QSPI_MODULE_ENABLED + #define USE_HAL_QSPI_REGISTER_CALLBACKS 0U + #include "stm32wbxx_hal_qspi.h" +#endif /* HAL_QSPI_MODULE_ENABLED */ + +#ifdef HAL_RCC_MODULE_ENABLED + #include "stm32wbxx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED + #include "stm32wbxx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED + #include "stm32wbxx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SAI_MODULE_ENABLED + #include "stm32wbxx_hal_sai.h" +#endif /* HAL_SAI_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED + #include "stm32wbxx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_SMBUS_MODULE_ENABLED + #include "stm32wbxx_hal_smbus.h" +#endif /* HAL_SMBUS_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED + #include "stm32wbxx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED + #include "stm32wbxx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_TSC_MODULE_ENABLED + #include "stm32wbxx_hal_tsc.h" +#endif /* HAL_TSC_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED + #include "stm32wbxx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED + #include "stm32wbxx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED + #include "stm32wbxx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ +#define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ +void assert_failed(uint8_t* file, uint32_t line); +#else + #define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32WBxx_HAL_CONF_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ From 61615203fde586211854e531a5c6a88da5c8ea4a Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 7 Mar 2022 15:33:27 +0100 Subject: [PATCH 24/81] Add missing releases to Mynewt repository.yml This make it possible to setup Mynewt project with latest releases. --- repository.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/repository.yml b/repository.yml index 21d092373..aaec10eb7 100644 --- a/repository.yml +++ b/repository.yml @@ -9,7 +9,9 @@ repo.versions: "0.10.0": "0.10.0" "0.10.1": "0.10.1" "0.11.0": "0.11.0" + "0.12.0": "0.12.0" + "0.13.0": "0.13.0" "0-dev": "0.0.0" # master - "0-latest": "0.11.0" # latest stable release + "0-latest": "0.13.0" # latest stable release From 6b2ea2bd1dbf05ae9fb04546b532df293521ccfb Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 8 Mar 2022 13:52:20 +0700 Subject: [PATCH 25/81] fix issue 1359 --- src/tusb_option.h | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/tusb_option.h b/src/tusb_option.h index 25e536787..b613eec44 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -207,18 +207,23 @@ //------------- Roothub as Device -------------// #if (CFG_TUSB_RHPORT0_MODE) & OPT_MODE_DEVICE - #define TUD_RHPORT_MODE (CFG_TUSB_RHPORT0_MODE) - #define TUD_OPT_RHPORT 0 + #define TUD_RHPORT_MODE (CFG_TUSB_RHPORT0_MODE) + #define TUD_OPT_RHPORT 0 #elif (CFG_TUSB_RHPORT1_MODE) & OPT_MODE_DEVICE - #define TUD_RHPORT_MODE (CFG_TUSB_RHPORT1_MODE) - #define TUD_OPT_RHPORT 1 + #define TUD_RHPORT_MODE (CFG_TUSB_RHPORT1_MODE) + #define TUD_OPT_RHPORT 1 #else - #define TUD_RHPORT_MODE OPT_MODE_NONE - #define TUD_OPT_RHPORT -1 + #define TUD_RHPORT_MODE OPT_MODE_NONE + #define TUD_OPT_RHPORT -1 #endif -#define CFG_TUD_ENABLED ( TUD_RHPORT_MODE & OPT_MODE_DEVICE ) -#define TUD_OPT_HIGH_SPEED ( (TUD_RHPORT_MODE & OPT_MODE_SPEED_MASK) ? (TUD_RHPORT_MODE & OPT_MODE_HIGH_SPEED) : (TUP_RHPORT_HIGHSPEED & (1 << TUD_OPT_RHPORT)) ) +#define CFG_TUD_ENABLED (TUD_RHPORT_MODE & OPT_MODE_DEVICE) + +#if CFG_TUD_ENABLED + #define TUD_OPT_HIGH_SPEED ((TUD_RHPORT_MODE & OPT_MODE_SPEED_MASK) ? (TUD_RHPORT_MODE & OPT_MODE_HIGH_SPEED) : (TUP_RHPORT_HIGHSPEED & (1 << TUD_OPT_RHPORT))) +#else + #define TUD_OPT_HIGH_SPEED 0 +#endif //------------- Roothub as Host -------------// From db9d97c9473f29ad59a87d641e6d41a27a00f332 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 9 Mar 2022 11:03:29 +0700 Subject: [PATCH 26/81] add tuh_descriptor_hid_report_get() --- examples/host/bare_api/src/main.c | 48 ++++++++++++++++++++++++++----- src/class/hid/hid_host.c | 17 +---------- src/host/usbh.c | 22 ++++++++++++++ src/host/usbh.h | 3 ++ 4 files changed, 67 insertions(+), 23 deletions(-) diff --git a/examples/host/bare_api/src/main.c b/examples/host/bare_api/src/main.c index b6b1527c0..2fe5999bc 100644 --- a/examples/host/bare_api/src/main.c +++ b/examples/host/bare_api/src/main.c @@ -64,23 +64,57 @@ int main(void) // TinyUSB Callbacks //--------------------------------------------------------------------+ -void print_device_descriptor(uint8_t dev_addr) +uint8_t usb_buf[256] TU_ATTR_ALIGNED(4); + +tusb_desc_device_t desc_device; + +bool print_device_descriptor(uint8_t daddr, tusb_control_request_t const * request, xfer_result_t result) { - (void) dev_addr; + (void) request; + + if ( XFER_RESULT_SUCCESS != result ) + { + printf("Failed to get device descriptor\r\n"); + return false; + } + + printf("Rhport %u Device %u: ID %04x:%04x\r\n", 0, daddr, desc_device.idVendor, desc_device.idProduct); printf("Device Descriptor:\r\n"); + printf(" bLength %u\r\n", desc_device.bLength); + printf(" bDescriptorType %u\r\n", desc_device.bDescriptorType); + printf(" bcdUSB %04x\r\n", desc_device.bcdUSB); + + printf(" bDeviceClass %u\r\n", desc_device.bDeviceClass); + printf(" bDeviceSubClass %u\r\n", desc_device.bDeviceSubClass); + printf(" bDeviceProtocol %u\r\n", desc_device.bDeviceProtocol); + printf(" bMaxPacketSize0 %u\r\n", desc_device.bMaxPacketSize0); + + printf(" idVendor 0x%04x\r\n", desc_device.idVendor); + printf(" idProduct 0x%04x\r\n", desc_device.idProduct); + printf(" bcdDevice %04x\r\n", desc_device.bcdDevice); + + printf(" iManufacturer %u\r\n", desc_device.iManufacturer); + printf(" iProduct %u\r\n", desc_device.iProduct); + printf(" iSerialNumber %u\r\n", desc_device.iSerialNumber); + + printf(" bNumConfigurations %u\r\n", desc_device.bNumConfigurations); + + return true; } // Invoked when device is mounted (configured) -void tuh_mount_cb (uint8_t dev_addr) +void tuh_mount_cb (uint8_t daddr) { - printf("Device attached, address = %d\r\n", dev_addr); - print_device_descriptor(dev_addr); + printf("Device attached, address = %d\r\n", daddr); + + // get device descriptor + tuh_descriptor_device_get(daddr, &desc_device, 18, print_device_descriptor); } /// Invoked when device is unmounted (bus reset/unplugged) -void tuh_umount_cb(uint8_t dev_addr) +void tuh_umount_cb(uint8_t daddr) { - printf("Device removed, address = %d\r\n", dev_addr); + printf("Device removed, address = %d\r\n", daddr); } //--------------------------------------------------------------------+ diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 9190642c6..32bb775b0 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -409,22 +409,7 @@ static bool config_get_report_desc(uint8_t dev_addr, tusb_control_request_t cons config_driver_mount_complete(dev_addr, instance, NULL, 0); }else { - TU_LOG2("HID Get Report Descriptor\r\n"); - tusb_control_request_t const new_request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_IN - }, - .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = tu_u16(hid_itf->report_desc_type, 0), - .wIndex = itf_num, - .wLength = hid_itf->report_desc_len - }; - - TU_ASSERT(tuh_control_xfer(dev_addr, &new_request, usbh_get_enum_buf(), config_get_report_desc_complete)); + TU_ASSERT(tuh_descriptor_hid_report_get(dev_addr, itf_num, hid_itf->report_desc_type, usbh_get_enum_buf(), hid_itf->report_desc_len, config_get_report_desc_complete)); } return true; diff --git a/src/host/usbh.c b/src/host/usbh.c index 192979ce6..b047179c5 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -299,6 +299,7 @@ bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, void* buffer bool tuh_descriptor_device_get(uint8_t daddr, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) { + len = tu_min16(len, sizeof(tusb_desc_device_t)); return tuh_descriptor_get(daddr, TUSB_DESC_DEVICE, 0, buffer, len, complete_cb); } @@ -361,6 +362,27 @@ bool tuh_descriptor_string_serial_get(uint8_t daddr, uint16_t language_id, void* return tuh_descriptor_string_get(daddr, language_id, dev->i_serial, buffer, len, complete_cb); } +// Get HID report descriptor +bool tuh_descriptor_hid_report_get(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) +{ + TU_LOG2("HID Get Report Descriptor\r\n"); + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_IN + }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = tu_htole16(TU_U16(desc_type, 0)), + .wIndex = itf_num, + .wLength = len + }; + + return tuh_control_xfer(daddr, &request, buffer, complete_cb); +} + bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, tuh_control_complete_cb_t complete_cb) { TU_LOG2("Set Configuration = %d\r\n", config_num); diff --git a/src/host/usbh.h b/src/host/usbh.h index 9465d1d1b..6fea2fac5 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -112,6 +112,9 @@ bool tuh_descriptor_string_product_get(uint8_t daddr, uint16_t language_id, void // Get serial string descriptor bool tuh_descriptor_string_serial_get(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); +// Get HID report descriptor +bool tuh_descriptor_hid_report_get(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); + //--------------------------------------------------------------------+ // APPLICATION CALLBACK //--------------------------------------------------------------------+ From f920e1c17102cac04b20ad3908efff24d96d8e7c Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 9 Mar 2022 11:21:13 +0700 Subject: [PATCH 27/81] rename host descriptor function --- examples/host/bare_api/src/main.c | 2 +- src/class/hid/hid_host.c | 2 +- src/host/usbh.c | 28 ++++++++++++++-------------- src/host/usbh.h | 14 +++++++------- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/examples/host/bare_api/src/main.c b/examples/host/bare_api/src/main.c index 2fe5999bc..5f8f886c8 100644 --- a/examples/host/bare_api/src/main.c +++ b/examples/host/bare_api/src/main.c @@ -108,7 +108,7 @@ void tuh_mount_cb (uint8_t daddr) printf("Device attached, address = %d\r\n", daddr); // get device descriptor - tuh_descriptor_device_get(daddr, &desc_device, 18, print_device_descriptor); + tuh_descriptor_get_device(daddr, &desc_device, 18, print_device_descriptor); } /// Invoked when device is unmounted (bus reset/unplugged) diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 32bb775b0..323debe69 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -409,7 +409,7 @@ static bool config_get_report_desc(uint8_t dev_addr, tusb_control_request_t cons config_driver_mount_complete(dev_addr, instance, NULL, 0); }else { - TU_ASSERT(tuh_descriptor_hid_report_get(dev_addr, itf_num, hid_itf->report_desc_type, usbh_get_enum_buf(), hid_itf->report_desc_len, config_get_report_desc_complete)); + TU_ASSERT(tuh_descriptor_get_hid_report(dev_addr, itf_num, hid_itf->report_desc_type, usbh_get_enum_buf(), hid_itf->report_desc_len, config_get_report_desc_complete)); } return true; diff --git a/src/host/usbh.c b/src/host/usbh.c index b047179c5..74c763552 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -297,18 +297,18 @@ bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, void* buffer return true; } -bool tuh_descriptor_device_get(uint8_t daddr, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) +bool tuh_descriptor_get_device(uint8_t daddr, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) { len = tu_min16(len, sizeof(tusb_desc_device_t)); return tuh_descriptor_get(daddr, TUSB_DESC_DEVICE, 0, buffer, len, complete_cb); } -bool tuh_descriptor_configuration_get(uint8_t daddr, uint8_t index, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) +bool tuh_descriptor_get_configuration(uint8_t daddr, uint8_t index, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) { return tuh_descriptor_get(daddr, TUSB_DESC_CONFIGURATION, index, buffer, len, complete_cb); } -bool tuh_descriptor_string_get(uint8_t daddr, uint16_t language_id, uint8_t index, +bool tuh_descriptor_get_string(uint8_t daddr, uint16_t language_id, uint8_t index, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) { tusb_control_request_t const request = @@ -330,40 +330,40 @@ bool tuh_descriptor_string_get(uint8_t daddr, uint16_t language_id, uint8_t inde } // Get manufacturer string descriptor -bool tuh_descriptor_string_manufacturer_get(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) +bool tuh_descriptor_get_manufacturer_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) { TU_VERIFY(tuh_mounted(daddr)); usbh_device_t const* dev = get_device(daddr); if (dev->i_manufacturer == 0) { return false; } - return tuh_descriptor_string_get(daddr, language_id, dev->i_manufacturer, buffer, len, complete_cb); + return tuh_descriptor_get_string(daddr, language_id, dev->i_manufacturer, buffer, len, complete_cb); } // Get product string descriptor -bool tuh_descriptor_string_product_get(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) +bool tuh_descriptor_get_product_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) { TU_VERIFY(tuh_mounted(daddr)); usbh_device_t const* dev = get_device(daddr); if (dev->i_product == 0) { return false; } - return tuh_descriptor_string_get(daddr, language_id, dev->i_product, buffer, len, complete_cb); + return tuh_descriptor_get_string(daddr, language_id, dev->i_product, buffer, len, complete_cb); } // Get serial string descriptor -bool tuh_descriptor_string_serial_get(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) +bool tuh_descriptor_get_serial_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) { TU_VERIFY(tuh_mounted(daddr)); usbh_device_t const* dev = get_device(daddr); if (dev->i_serial == 0) { return false; } - return tuh_descriptor_string_get(daddr, language_id, dev->i_serial, buffer, len, complete_cb); + return tuh_descriptor_get_string(daddr, language_id, dev->i_serial, buffer, len, complete_cb); } // Get HID report descriptor -bool tuh_descriptor_hid_report_get(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) +bool tuh_descriptor_get_hid_report(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) { TU_LOG2("HID Get Report Descriptor\r\n"); tusb_control_request_t const request = @@ -868,7 +868,7 @@ static bool enum_request_addr0_device_desc(void) // Get first 8 bytes of device descriptor for Control Endpoint size TU_LOG2("Get 8 byte of Device Descriptor\r\n"); - TU_ASSERT(tuh_descriptor_device_get(addr0, _usbh_ctrl_buf, 8, enum_get_addr0_device_desc_complete)); + TU_ASSERT(tuh_descriptor_get_device(addr0, _usbh_ctrl_buf, 8, enum_get_addr0_device_desc_complete)); return true; } @@ -977,7 +977,7 @@ static bool enum_set_address_complete(uint8_t dev_addr, tusb_control_request_t c // Get full device descriptor TU_LOG2("Get Device Descriptor\r\n"); - TU_ASSERT(tuh_descriptor_device_get(new_addr, _usbh_ctrl_buf, sizeof(tusb_desc_device_t), enum_get_device_desc_complete)); + TU_ASSERT(tuh_descriptor_get_device(new_addr, _usbh_ctrl_buf, sizeof(tusb_desc_device_t), enum_get_device_desc_complete)); return true; } @@ -1000,7 +1000,7 @@ static bool enum_get_device_desc_complete(uint8_t dev_addr, tusb_control_request // 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_ASSERT( tuh_descriptor_configuration_get(dev_addr, config_idx, _usbh_ctrl_buf, 9, enum_get_9byte_config_desc_complete) ); + TU_ASSERT( tuh_descriptor_get_configuration(dev_addr, config_idx, _usbh_ctrl_buf, 9, enum_get_9byte_config_desc_complete) ); return true; } @@ -1020,7 +1020,7 @@ static bool enum_get_9byte_config_desc_complete(uint8_t dev_addr, tusb_control_r // Get full configuration descriptor uint8_t const config_idx = CONFIG_NUM - 1; TU_LOG2("Get Configuration[0] Descriptor\r\n"); - TU_ASSERT( tuh_descriptor_configuration_get(dev_addr, config_idx, _usbh_ctrl_buf, total_len, enum_get_config_desc_complete) ); + TU_ASSERT( tuh_descriptor_get_configuration(dev_addr, config_idx, _usbh_ctrl_buf, total_len, enum_get_config_desc_complete) ); return true; } diff --git a/src/host/usbh.h b/src/host/usbh.h index 6fea2fac5..31d63d6a7 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -94,26 +94,26 @@ bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); // Get device descriptor -bool tuh_descriptor_device_get(uint8_t daddr, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); +bool tuh_descriptor_get_device(uint8_t daddr, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); // Get configuration descriptor -bool tuh_descriptor_configuration_get(uint8_t daddr, uint8_t index, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); +bool tuh_descriptor_get_configuration(uint8_t daddr, uint8_t index, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); // Get string descriptor -bool tuh_descriptor_string_get(uint8_t daddr, uint16_t language_id, uint8_t index, +bool tuh_descriptor_get_string(uint8_t daddr, uint16_t language_id, uint8_t index, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); // Get manufacturer string descriptor -bool tuh_descriptor_string_manufacturer_get(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); +bool tuh_descriptor_get_manufacturer_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); // Get product string descriptor -bool tuh_descriptor_string_product_get(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); +bool tuh_descriptor_get_product_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); // Get serial string descriptor -bool tuh_descriptor_string_serial_get(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); +bool tuh_descriptor_get_serial_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); // Get HID report descriptor -bool tuh_descriptor_hid_report_get(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); +bool tuh_descriptor_get_hid_report(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); //--------------------------------------------------------------------+ // APPLICATION CALLBACK From 2f593e767c28ac5b789a5def2221620c1a2e58b8 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 9 Mar 2022 12:26:56 +0700 Subject: [PATCH 28/81] update use of mutex for host --- src/device/usbd.c | 2 +- src/host/usbh.c | 96 +++++++++++++++++++++++++++-------------------- src/tusb_option.h | 3 ++ 3 files changed, 59 insertions(+), 42 deletions(-) diff --git a/src/device/usbd.c b/src/device/usbd.c index 7926689b7..b14b5e0fc 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -273,7 +273,7 @@ enum { RHPORT_INVALID = 0xFFu }; static uint8_t _usbd_rhport = RHPORT_INVALID; // Event queue -// OPT_MODE_DEVICE is used by OS NONE for mutex (disable usb isr) +// usbd_int_set() is used as mutex in OS NONE config OSAL_QUEUE_DEF(usbd_int_set, _usbd_qdef, CFG_TUD_TASK_QUEUE_SZ, dcd_event_t); static osal_queue_t _usbd_q; diff --git a/src/host/usbh.c b/src/host/usbh.c index 74c763552..59fcb4da3 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -112,13 +112,6 @@ typedef struct { // TODO merge ep2drv here, 4-bit should be sufficient }ep_status[CFG_TUH_ENDPOINT_MAX][2]; - - // Mutex for claiming endpoint, only needed when using with preempted RTOS -#if CFG_TUSB_OS != OPT_OS_NONE - osal_mutex_def_t mutexdef; - osal_mutex_t mutex; -#endif - } usbh_device_t; @@ -204,6 +197,9 @@ enum { CONFIG_NUM = 1 }; // default to use configuration 1 // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ +// sum of end device + hub +#define TOTAL_DEVICES (CFG_TUH_DEVICE_MAX + CFG_TUH_HUB) + static bool _usbh_initialized = false; // Device with address = 0 for enumeration @@ -211,14 +207,43 @@ static usbh_dev0_t _dev0; // all devices excluding zero-address // hub address start from CFG_TUH_DEVICE_MAX+1 -CFG_TUSB_MEM_SECTION usbh_device_t _usbh_devices[CFG_TUH_DEVICE_MAX + CFG_TUH_HUB]; +// 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[TOTAL_DEVICES]; +static osal_mutex_t _usbh_mutex[TOTAL_DEVICES]; + +static inline void lock_device(uint8_t daddr) +{ + // addr0 is always available + if (daddr) return; + osal_mutex_lock(&_usbh_mutex[daddr-1], OSAL_TIMEOUT_WAIT_FOREVER); +} + +static inline void unlock_device(uint8_t daddr) +{ + // addr0 is always available + if (daddr) return; + osal_mutex_unlock(&_usbh_mutex[daddr-1]); +} + +#else + +#define lock_device(_addr) +#define unlock_device(_addr) + +#endif // Event queue -// role device/host is used by OS NONE for mutex (disable usb isr) +// usbh_int_set is used as mutex in OS NONE config OSAL_QUEUE_DEF(usbh_int_set, _usbh_qdef, CFG_TUH_TASK_QUEUE_SZ, hcd_event_t); static osal_queue_t _usbh_q; -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSIZE]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN +static uint8_t _usbh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSIZE]; //------------- Helper Function -------------// @@ -408,6 +433,13 @@ bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, tuh_control_comple // CLASS-USBD API (don't require to verify parameters) //--------------------------------------------------------------------+ +static void clear_device(usbh_device_t* dev) +{ + tu_memclr(dev, sizeof(usbh_device_t)); + memset(dev->itf2drv, DRVID_INVALID, sizeof(dev->itf2drv)); // invalid mapping + memset(dev->ep2drv , DRVID_INVALID, sizeof(dev->ep2drv )); // invalid mapping +} + bool tuh_inited(void) { return _usbh_initialized; @@ -421,25 +453,22 @@ bool tuh_init(uint8_t rhport) TU_LOG2("USBH init\r\n"); TU_LOG2_INT(sizeof(usbh_device_t)); - tu_memclr(_usbh_devices, sizeof(_usbh_devices)); - tu_memclr(&_dev0, sizeof(_dev0)); - //------------- Enumeration & Reporter Task init -------------// _usbh_q = osal_queue_create( &_usbh_qdef ); TU_ASSERT(_usbh_q != NULL); //------------- Semaphore, Mutex for Control Pipe -------------// - for(uint8_t i=0; imutex = osal_mutex_create(&dev->mutexdef); - TU_ASSERT(dev->mutex); +#if TUSB_OPT_MUTEX + _usbh_mutex[i] = osal_mutex_create(&_usbh_mutexdef[i]); + TU_ASSERT(_usbh_mutex[i]); #endif - - memset(dev->itf2drv, DRVID_INVALID, sizeof(dev->itf2drv)); // invalid mapping - memset(dev->ep2drv , DRVID_INVALID, sizeof(dev->ep2drv )); // invalid mapping } // Class drivers init @@ -686,14 +715,7 @@ void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port } hcd_device_close(rhport, dev_addr); - - // release all endpoints associated with the device - memset(dev->itf2drv, DRVID_INVALID, sizeof(dev->itf2drv)); // invalid mapping - memset(dev->ep2drv , DRVID_INVALID, sizeof(dev->ep2drv )); // invalid mapping - tu_memclr(dev->ep_status, sizeof(dev->ep_status)); - - dev->state = TUSB_DEVICE_STATE_UNPLUG; - dev->configured = false; + clear_device(dev); } } } @@ -1161,11 +1183,9 @@ bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) usbh_device_t* dev = get_device(dev_addr); -#if CFG_TUSB_OS != OPT_OS_NONE // pre-check to help reducing mutex lock TU_VERIFY((dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0)); - osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER); -#endif + lock_device(dev_addr); // can only claim the endpoint if it is not busy and not claimed yet. bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0); @@ -1174,9 +1194,7 @@ bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) dev->ep_status[epnum][dir].claimed = 1; } -#if CFG_TUSB_OS != OPT_OS_NONE - osal_mutex_unlock(dev->mutex); -#endif + unlock_device(dev_addr); return ret; } @@ -1189,9 +1207,7 @@ bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) usbh_device_t* dev = get_device(dev_addr); -#if CFG_TUSB_OS != OPT_OS_NONE - osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER); -#endif + lock_device(dev_addr); // can only release the endpoint if it is claimed and not busy bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 1); @@ -1200,9 +1216,7 @@ bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) dev->ep_status[epnum][dir].claimed = 0; } -#if CFG_TUSB_OS != OPT_OS_NONE - osal_mutex_unlock(dev->mutex); -#endif + unlock_device(dev_addr); return ret; } diff --git a/src/tusb_option.h b/src/tusb_option.h index afd69c38b..e5351b1c4 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -285,6 +285,9 @@ #define CFG_TUSB_OS_INC_PATH #endif +// mutex is only needed for RTOS +#define TUSB_OPT_MUTEX (CFG_TUSB_OS != OPT_OS_NONE) + //-------------------------------------------------------------------- // DEVICE OPTIONS //-------------------------------------------------------------------- From 708f05668d681439e521379e281d087d1910a0f3 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 9 Mar 2022 16:42:51 +0700 Subject: [PATCH 29/81] add tusb_debug.h remove tusb_error.h move debug utils to new header --- src/class/cdc/cdc_host.c | 4 +- src/class/cdc/cdc_rndis_host.h | 2 +- src/class/vendor/vendor_host.h | 12 +-- src/common/tusb_common.h | 134 +------------------------ src/common/tusb_debug.h | 174 +++++++++++++++++++++++++++++++++ src/common/tusb_error.h | 77 --------------- src/common/tusb_verify.h | 28 ------ src/device/usbd.c | 21 +--- src/host/usbh.c | 13 ++- src/host/usbh_control.c | 7 +- src/tusb.c | 22 ++++- 11 files changed, 220 insertions(+), 274 deletions(-) create mode 100644 src/common/tusb_debug.h delete mode 100644 src/common/tusb_error.h diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index c18234db4..2787cd201 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -100,7 +100,7 @@ bool tuh_cdc_send(uint8_t dev_addr, void const * p_data, uint32_t length, bool i { (void) is_notify; TU_VERIFY( tuh_cdc_mounted(dev_addr) ); - TU_VERIFY( p_data != NULL && length, TUSB_ERROR_INVALID_PARA); + TU_VERIFY( p_data != NULL && length); uint8_t const ep_out = cdch_data[dev_addr-1].ep_out; if ( usbh_edpt_busy(dev_addr, ep_out) ) return false; @@ -112,7 +112,7 @@ bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is { (void) is_notify; TU_VERIFY( tuh_cdc_mounted(dev_addr) ); - TU_VERIFY( p_buffer != NULL && length, TUSB_ERROR_INVALID_PARA); + TU_VERIFY( p_buffer != NULL && length ); uint8_t const ep_in = cdch_data[dev_addr-1].ep_in; if ( usbh_edpt_busy(dev_addr, ep_in) ) return false; diff --git a/src/class/cdc/cdc_rndis_host.h b/src/class/cdc/cdc_rndis_host.h index 170cb3b0e..447cc4e97 100644 --- a/src/class/cdc/cdc_rndis_host.h +++ b/src/class/cdc/cdc_rndis_host.h @@ -50,7 +50,7 @@ typedef struct { }rndish_data_t; void rndish_init(void); -tusb_error_t rndish_open_subtask(uint8_t dev_addr, cdch_data_t *p_cdc); +bool rndish_open_subtask(uint8_t dev_addr, cdch_data_t *p_cdc); void rndish_xfer_isr(cdch_data_t *p_cdc, pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes); void rndish_close(uint8_t dev_addr); diff --git a/src/class/vendor/vendor_host.h b/src/class/vendor/vendor_host.h index 07fa56c61..65223fbca 100644 --- a/src/class/vendor/vendor_host.h +++ b/src/class/vendor/vendor_host.h @@ -49,16 +49,16 @@ static inline bool tusbh_custom_is_mounted(uint8_t dev_addr, uint16_t vendor_id, return false; } -tusb_error_t tusbh_custom_read(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void * p_buffer, uint16_t length); -tusb_error_t tusbh_custom_write(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void const * p_data, uint16_t length); +bool tusbh_custom_read(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void * p_buffer, uint16_t length); +bool tusbh_custom_write(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void const * p_data, uint16_t length); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void cush_init(void); -tusb_error_t cush_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length); -void cush_isr(pipe_handle_t pipe_hdl, xfer_result_t event); -void cush_close(uint8_t dev_addr); +void cush_init(void); +bool cush_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length); +void cush_isr(pipe_handle_t pipe_hdl, xfer_result_t event); +void cush_close(uint8_t dev_addr); #ifdef __cplusplus } diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 26865805e..34f3bb8f7 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -71,8 +71,8 @@ #include "tusb_compiler.h" #include "tusb_verify.h" #include "tusb_types.h" +#include "tusb_debug.h" -#include "tusb_error.h" // TODO remove #include "tusb_timeout.h" // TODO remove //--------------------------------------------------------------------+ @@ -268,138 +268,6 @@ TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16 (void* mem, ui + TU_BIN8(dlsb)) #endif -//--------------------------------------------------------------------+ -// Debug Function -//--------------------------------------------------------------------+ - -// CFG_TUSB_DEBUG for debugging -// 0 : no debug -// 1 : print error -// 2 : print warning -// 3 : print info -#if CFG_TUSB_DEBUG - -void tu_print_mem(void const *buf, uint32_t count, uint8_t indent); - -#ifdef CFG_TUSB_DEBUG_PRINTF - extern int CFG_TUSB_DEBUG_PRINTF(const char *format, ...); - #define tu_printf CFG_TUSB_DEBUG_PRINTF -#else - #define tu_printf printf -#endif - -static inline -void tu_print_var(uint8_t const* buf, uint32_t bufsize) -{ - for(uint32_t i=0; i= 2 - #define TU_LOG2 TU_LOG1 - #define TU_LOG2_MEM TU_LOG1_MEM - #define TU_LOG2_VAR TU_LOG1_VAR - #define TU_LOG2_INT TU_LOG1_INT - #define TU_LOG2_HEX TU_LOG1_HEX -#endif - -// Log Level 3: Info -#if CFG_TUSB_DEBUG >= 3 - #define TU_LOG3 TU_LOG1 - #define TU_LOG3_MEM TU_LOG1_MEM - #define TU_LOG3_VAR TU_LOG1_VAR - #define TU_LOG3_INT TU_LOG1_INT - #define TU_LOG3_HEX TU_LOG1_HEX -#endif - -typedef struct -{ - uint32_t key; - const char* data; -} tu_lookup_entry_t; - -typedef struct -{ - uint16_t count; - tu_lookup_entry_t const* items; -} tu_lookup_table_t; - -static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint32_t key) -{ - static char not_found[11]; - - for(uint16_t i=0; icount; i++) - { - if (p_table->items[i].key == key) return p_table->items[i].data; - } - - // not found return the key value in hex - snprintf(not_found, sizeof(not_found), "0x%08lX", (unsigned long) key); - - return not_found; -} - -#endif // CFG_TUSB_DEBUG - -#ifndef TU_LOG -#define TU_LOG(n, ...) -#define TU_LOG_MEM(n, ...) -#define TU_LOG_VAR(n, ...) -#define TU_LOG_INT(n, ...) -#define TU_LOG_HEX(n, ...) -#define TU_LOG_LOCATION() -#define TU_LOG_FAILED() -#endif - -// TODO replace all TU_LOGn with TU_LOG(n) - -#define TU_LOG0(...) -#define TU_LOG0_MEM(...) -#define TU_LOG0_VAR(...) -#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_INT(...) - #define TU_LOG1_HEX(...) -#endif - -#ifndef TU_LOG2 - #define TU_LOG2(...) - #define TU_LOG2_MEM(...) - #define TU_LOG2_VAR(...) - #define TU_LOG2_INT(...) - #define TU_LOG2_HEX(...) -#endif - -#ifndef TU_LOG3 - #define TU_LOG3(...) - #define TU_LOG3_MEM(...) - #define TU_LOG3_VAR(...) - #define TU_LOG3_INT(...) - #define TU_LOG3_HEX(...) -#endif - #ifdef __cplusplus } #endif diff --git a/src/common/tusb_debug.h b/src/common/tusb_debug.h new file mode 100644 index 000000000..647e8a8db --- /dev/null +++ b/src/common/tusb_debug.h @@ -0,0 +1,174 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2022, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_DEBUG_H_ +#define _TUSB_DEBUG_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Debug +//--------------------------------------------------------------------+ + +// CFG_TUSB_DEBUG for debugging +// 0 : no debug +// 1 : print error +// 2 : print warning +// 3 : print info +#if CFG_TUSB_DEBUG + +// Enum to String for debugging purposes +#if CFG_TUSB_DEBUG >= 2 +extern char const* const tu_str_speed[]; +extern char const* const tu_str_std_request[]; +#endif + +void tu_print_mem(void const *buf, uint32_t count, uint8_t indent); + +#ifdef CFG_TUSB_DEBUG_PRINTF + extern int CFG_TUSB_DEBUG_PRINTF(const char *format, ...); + #define tu_printf CFG_TUSB_DEBUG_PRINTF +#else + #define tu_printf printf +#endif + +static inline void tu_print_var(uint8_t const* buf, uint32_t bufsize) +{ + for(uint32_t i=0; i= 2 + #define TU_LOG2 TU_LOG1 + #define TU_LOG2_MEM TU_LOG1_MEM + #define TU_LOG2_VAR TU_LOG1_VAR + #define TU_LOG2_INT TU_LOG1_INT + #define TU_LOG2_HEX TU_LOG1_HEX +#endif + +// Log Level 3: Info +#if CFG_TUSB_DEBUG >= 3 + #define TU_LOG3 TU_LOG1 + #define TU_LOG3_MEM TU_LOG1_MEM + #define TU_LOG3_VAR TU_LOG1_VAR + #define TU_LOG3_INT TU_LOG1_INT + #define TU_LOG3_HEX TU_LOG1_HEX +#endif + +typedef struct +{ + uint32_t key; + const char* data; +} tu_lookup_entry_t; + +typedef struct +{ + uint16_t count; + tu_lookup_entry_t const* items; +} tu_lookup_table_t; + +static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint32_t key) +{ + static char not_found[11]; + + for(uint16_t i=0; icount; i++) + { + if (p_table->items[i].key == key) return p_table->items[i].data; + } + + // not found return the key value in hex + snprintf(not_found, sizeof(not_found), "0x%08lX", (unsigned long) key); + + return not_found; +} + +#endif // CFG_TUSB_DEBUG + +#ifndef TU_LOG + #define TU_LOG(n, ...) + #define TU_LOG_MEM(n, ...) + #define TU_LOG_VAR(n, ...) + #define TU_LOG_INT(n, ...) + #define TU_LOG_HEX(n, ...) + #define TU_LOG_LOCATION() + #define TU_LOG_FAILED() +#endif + +// TODO replace all TU_LOGn with TU_LOG(n) + +#define TU_LOG0(...) +#define TU_LOG0_MEM(...) +#define TU_LOG0_VAR(...) +#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_INT(...) + #define TU_LOG1_HEX(...) +#endif + +#ifndef TU_LOG2 + #define TU_LOG2(...) + #define TU_LOG2_MEM(...) + #define TU_LOG2_VAR(...) + #define TU_LOG2_INT(...) + #define TU_LOG2_HEX(...) +#endif + +#ifndef TU_LOG3 + #define TU_LOG3(...) + #define TU_LOG3_MEM(...) + #define TU_LOG3_VAR(...) + #define TU_LOG3_INT(...) + #define TU_LOG3_HEX(...) +#endif + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_DEBUG_H_ */ diff --git a/src/common/tusb_error.h b/src/common/tusb_error.h deleted file mode 100644 index 42541acd6..000000000 --- a/src/common/tusb_error.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup Group_Common - * \defgroup Group_Error Error Codes - * @{ */ - -#ifndef _TUSB_ERRORS_H_ -#define _TUSB_ERRORS_H_ - -#include "tusb_option.h" - -#ifdef __cplusplus - extern "C" { -#endif - -#define ERROR_ENUM(x) x, -#define ERROR_STRING(x) #x, - -#define ERROR_TABLE(ENTRY) \ - ENTRY(TUSB_ERROR_NONE )\ - ENTRY(TUSB_ERROR_INVALID_PARA )\ - ENTRY(TUSB_ERROR_DEVICE_NOT_READY )\ - ENTRY(TUSB_ERROR_INTERFACE_IS_BUSY )\ - ENTRY(TUSB_ERROR_HCD_OPEN_PIPE_FAILED )\ - ENTRY(TUSB_ERROR_OSAL_TIMEOUT )\ - ENTRY(TUSB_ERROR_CDCH_DEVICE_NOT_MOUNTED )\ - ENTRY(TUSB_ERROR_MSCH_DEVICE_NOT_MOUNTED )\ - ENTRY(TUSB_ERROR_NOT_SUPPORTED )\ - ENTRY(TUSB_ERROR_NOT_ENOUGH_MEMORY )\ - ENTRY(TUSB_ERROR_FAILED )\ - -/// \brief Error Code returned -/// TODO obsolete and to be remove -typedef enum -{ - ERROR_TABLE(ERROR_ENUM) - TUSB_ERROR_COUNT -}tusb_error_t; - -#if CFG_TUSB_DEBUG -/// Enum to String for debugging purposes. Only available if \ref CFG_TUSB_DEBUG > 0 -extern char const* const tusb_strerr[TUSB_ERROR_COUNT]; -extern char const* const tusb_speed_str[]; - -#endif - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_ERRORS_H_ */ - -/** @} */ diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index 8fef11dc7..f4a08ce2f 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -74,10 +74,8 @@ #if CFG_TUSB_DEBUG #include - #define _MESS_ERR(_err) tu_printf("%s %d: failed, error = %s\r\n", __func__, __LINE__, tusb_strerr[_err]) #define _MESS_FAILED() tu_printf("%s %d: ASSERT FAILED\r\n", __func__, __LINE__) #else - #define _MESS_ERR(_err) do {} while (0) #define _MESS_FAILED() do {} while (0) #endif @@ -144,32 +142,6 @@ #define TU_ASSERT(...) GET_3RD_ARG(__VA_ARGS__, ASSERT_2ARGS, ASSERT_1ARGS,UNUSED)(__VA_ARGS__) #endif -// TODO remove TU_ASSERT_ERR() later - -/*------------- Generator for TU_VERIFY_ERR and TU_VERIFY_ERR_HDLR -------------*/ -#define TU_VERIFY_ERR_DEF2(_error, _handler) do \ -{ \ - uint32_t _err = (uint32_t)(_error); \ - if ( 0 != _err ) { _MESS_ERR(_err); _handler; return _err; } \ -} while(0) - -#define TU_VERIFY_ERR_DEF3(_error, _handler, _ret) do \ -{ \ - uint32_t _err = (uint32_t)(_error); \ - if ( 0 != _err ) { _MESS_ERR(_err); _handler; return _ret; } \ -} while(0) - -/*------------------------------------------------------------------*/ -/* ASSERT Error - * basically TU_VERIFY Error with TU_BREAKPOINT() as handler - *------------------------------------------------------------------*/ -#define ASSERT_ERR_1ARGS(_error) TU_VERIFY_ERR_DEF2(_error, TU_BREAKPOINT()) -#define ASSERT_ERR_2ARGS(_error, _ret) TU_VERIFY_ERR_DEF3(_error, TU_BREAKPOINT(), _ret) - -#ifndef TU_ASSERT_ERR -#define TU_ASSERT_ERR(...) GET_3RD_ARG(__VA_ARGS__, ASSERT_ERR_2ARGS, ASSERT_ERR_1ARGS,UNUSED)(__VA_ARGS__) -#endif - /*------------------------------------------------------------------*/ /* ASSERT HDLR *------------------------------------------------------------------*/ diff --git a/src/device/usbd.c b/src/device/usbd.c index b14b5e0fc..fc66f83c6 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -315,23 +315,6 @@ static char const* const _usbd_event_str[DCD_EVENT_COUNT] = "Func Call" }; -static char const* const _tusb_std_request_str[] = -{ - "Get Status" , - "Clear Feature" , - "Reserved" , - "Set Feature" , - "Reserved" , - "Set Address" , - "Get Descriptor" , - "Set Descriptor" , - "Get Configuration" , - "Set Configuration" , - "Get Interface" , - "Set Interface" , - "Synch Frame" -}; - // for usbd_control to print the name of control complete driver void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback) { @@ -508,7 +491,7 @@ void tud_task (void) switch ( event.event_id ) { case DCD_EVENT_BUS_RESET: - TU_LOG2(": %s Speed\r\n", tusb_speed_str[event.bus_reset.speed]); + TU_LOG2(": %s Speed\r\n", tu_str_speed[event.bus_reset.speed]); usbd_reset(event.rhport); _usbd_dev.speed = event.bus_reset.speed; break; @@ -650,7 +633,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const #if CFG_TUSB_DEBUG >= 2 if (TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type && p_request->bRequest <= TUSB_REQ_SYNCH_FRAME) { - TU_LOG2(" %s", _tusb_std_request_str[p_request->bRequest]); + TU_LOG2(" %s", tu_str_std_request[p_request->bRequest]); if (TUSB_REQ_GET_DESCRIPTOR != p_request->bRequest) TU_LOG2("\r\n"); } #endif diff --git a/src/host/usbh.c b/src/host/usbh.c index 59fcb4da3..5d167408a 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -259,6 +259,7 @@ static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t h static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size); // from usbh_control.c +extern bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb); extern bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); //--------------------------------------------------------------------+ @@ -297,6 +298,16 @@ void osal_task_delay(uint32_t msec) } #endif + +bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb) +{ + TU_LOG2("[%u:%u] %s: ", usbh_get_rhport(dev_addr), dev_addr, request->bRequest <= TUSB_REQ_SYNCH_FRAME ? tu_str_std_request[request->bRequest] : "Unknown Request"); + TU_LOG2_VAR(request); + TU_LOG2("\r\n"); + + return usbh_control_xfer(dev_addr, request, buffer, complete_cb); +} + //--------------------------------------------------------------------+ // Descriptors //--------------------------------------------------------------------+ @@ -864,7 +875,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", tusb_speed_str[_dev0.speed]); + TU_LOG2("%s Speed\r\n", tu_str_speed[_dev0.speed]); enum_request_addr0_device_desc(); } diff --git a/src/host/usbh_control.c b/src/host/usbh_control.c index d034eec7f..5f4fcf52f 100644 --- a/src/host/usbh_control.c +++ b/src/host/usbh_control.c @@ -33,6 +33,7 @@ enum { + STAGE_IDLE, STAGE_SETUP, STAGE_DATA, STAGE_ACK @@ -56,7 +57,7 @@ static usbh_control_xfer_t _ctrl_xfer; // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ -bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb) +bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb) { // TODO need to claim the endpoint first const uint8_t rhport = usbh_get_rhport(dev_addr); @@ -66,10 +67,6 @@ bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, _ctrl_xfer.stage = STAGE_SETUP; _ctrl_xfer.complete_cb = complete_cb; - TU_LOG2("Control Setup (addr = %u): ", dev_addr); - TU_LOG2_VAR(request); - TU_LOG2("\r\n"); - // Send setup packet TU_ASSERT( hcd_setup_send(rhport, dev_addr, (uint8_t const*) &_ctrl_xfer.request) ); diff --git a/src/tusb.c b/src/tusb.c index a30221059..c6c04262c 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -161,9 +161,27 @@ uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, #if CFG_TUSB_DEBUG #include -char const* const tusb_strerr[TUSB_ERROR_COUNT] = { ERROR_TABLE(ERROR_STRING) }; +#if CFG_TUSB_DEBUG >= 2 -char const* const tusb_speed_str[] = { "Full", "Low", "High" }; +char const* const tu_str_speed[] = { "Full", "Low", "High" }; +char const* const tu_str_std_request[] = +{ + "Get Status" , + "Clear Feature" , + "Reserved" , + "Set Feature" , + "Reserved" , + "Set Address" , + "Get Descriptor" , + "Set Descriptor" , + "Get Configuration" , + "Set Configuration" , + "Get Interface" , + "Set Interface" , + "Synch Frame" +}; + +#endif static void dump_str_line(uint8_t const* buf, uint16_t count) { From a5fb20533cc1c9e0ed155083c1bbcb3e7be75e67 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 9 Mar 2022 17:17:27 +0700 Subject: [PATCH 30/81] adding tusb_private.h to implement common edpt claim --- src/common/tusb_common.h | 13 --------- src/common/tusb_private.h | 61 +++++++++++++++++++++++++++++++++++++++ src/device/usbd.c | 4 +++ src/host/usbh.c | 41 +++++++++----------------- src/tusb.c | 25 ++++++++++++++++ src/tusb.h | 4 --- 6 files changed, 104 insertions(+), 44 deletions(-) create mode 100644 src/common/tusb_private.h diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 34f3bb8f7..58591f0be 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -75,19 +75,6 @@ #include "tusb_timeout.h" // TODO remove -//--------------------------------------------------------------------+ -// Internal Helper used by Host and Device Stack -//--------------------------------------------------------------------+ - -// Check if endpoint descriptor is valid per USB specs -bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed); - -// Bind all endpoint of a interface descriptor to class driver -void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* p_desc, uint16_t desc_len, uint8_t driver_id); - -// Calculate total length of n interfaces (depending on IAD) -uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len); - //--------------------------------------------------------------------+ // Internal Inline Functions //--------------------------------------------------------------------+ diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h new file mode 100644 index 000000000..5315c352f --- /dev/null +++ b/src/common/tusb_private.h @@ -0,0 +1,61 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2022, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + + +#ifndef _TUSB_PRIVATE_H_ +#define _TUSB_PRIVATE_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +typedef struct TU_ATTR_PACKED +{ + volatile uint8_t busy : 1; + volatile uint8_t stalled : 1; + volatile uint8_t claimed : 1; +}tu_edpt_state_t; + +//--------------------------------------------------------------------+ +// Internal Helper used by Host and Device Stack +//--------------------------------------------------------------------+ + +// Check if endpoint descriptor is valid per USB specs +bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed); + +// Bind all endpoint of a interface descriptor to class driver +void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* p_desc, uint16_t desc_len, uint8_t driver_id); + +// Calculate total length of n interfaces (depending on IAD) +uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len); + +bool tu_edpt_claim(tu_edpt_state_t* ep_state, osal_mutex_t mutex); + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_PRIVATE_H_ */ diff --git a/src/device/usbd.c b/src/device/usbd.c index fc66f83c6..4b37e8bd9 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -29,6 +29,8 @@ #if CFG_TUD_ENABLED #include "tusb.h" +#include "common/tusb_private.h" + #include "device/usbd.h" #include "device/usbd_pvt.h" #include "device/dcd.h" @@ -70,6 +72,8 @@ typedef struct uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) uint8_t ep2drv[CFG_TUD_ENDPPOINT_MAX][2]; // map endpoint to driver ( 0xff is invalid ) + // TODO 4-bit should be sufficient for ep2drv if we want to save half its bytes + struct TU_ATTR_PACKED { volatile bool busy : 1; diff --git a/src/host/usbh.c b/src/host/usbh.c index 5d167408a..319031f5b 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -29,6 +29,8 @@ #if CFG_TUH_ENABLED #include "tusb.h" +#include "common/tusb_private.h" + #include "host/usbh.h" #include "host/usbh_classdriver.h" #include "hub.h" @@ -104,14 +106,7 @@ typedef struct { uint8_t itf2drv[CFG_TUH_INTERFACE_MAX]; // map interface number to driver (0xff is invalid) uint8_t ep2drv[CFG_TUH_ENDPOINT_MAX][2]; // map endpoint to driver ( 0xff is invalid ) - struct TU_ATTR_PACKED - { - volatile bool busy : 1; - volatile bool stalled : 1; - volatile bool claimed : 1; - - // TODO merge ep2drv here, 4-bit should be sufficient - }ep_status[CFG_TUH_ENDPOINT_MAX][2]; + tu_edpt_state_t ep_status[CFG_TUH_ENDPOINT_MAX][2]; } usbh_device_t; @@ -1189,25 +1184,19 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura // TODO has some duplication code with device, refactor later bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) { - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + // addr0 is always available + if (dev_addr == 0) return true; - usbh_device_t* dev = get_device(dev_addr); + usbh_device_t* dev = get_device(dev_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + tu_edpt_state_t* ep_state = &dev->ep_status[epnum][dir]; - // pre-check to help reducing mutex lock - TU_VERIFY((dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0)); - lock_device(dev_addr); - - // can only claim the endpoint if it is not busy and not claimed yet. - bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0); - if (ret) - { - dev->ep_status[epnum][dir].claimed = 1; - } - - unlock_device(dev_addr); - - return ret; +#if TUSB_OPT_MUTEX + return tu_edpt_claim(ep_state, &_usbh_mutex[dev_addr-1]); +#else + return tu_edpt_claim(ep_state, NULL); +#endif } // TODO has some duplication code with device, refactor later @@ -1299,6 +1288,4 @@ bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) return dev->ep_status[epnum][dir].busy; } - - #endif diff --git a/src/tusb.c b/src/tusb.c index c6c04262c..6ed2a3c05 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -29,6 +29,7 @@ #if CFG_TUH_ENABLED || CFG_TUD_ENABLED #include "tusb.h" +#include "common/tusb_private.h" // TODO clean up #if CFG_TUD_ENABLED @@ -67,6 +68,30 @@ bool tusb_inited(void) // Internal Helper for both Host and Device stack //--------------------------------------------------------------------+ +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 + + // 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); + if (available) + { + ep_state->claimed = 1; + } + +#if TUSB_OPT_MUTEX + osal_mutex_unlock(mutex); +#endif + + return available; +} + bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed) { uint16_t const max_packet_size = tu_edpt_packet_size(desc_ep); diff --git a/src/tusb.h b/src/tusb.h index 549f00b43..222855fcb 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -117,8 +117,6 @@ //--------------------------------------------------------------------+ // APPLICATION API //--------------------------------------------------------------------+ -/** \ingroup group_application_api - * @{ */ // Initialize device/host stack // Note: when using with RTOS, this should be called after scheduler/kernel is started. @@ -131,8 +129,6 @@ bool tusb_inited(void); // TODO // bool tusb_teardown(void); -/** @} */ - #ifdef __cplusplus } #endif From 110879074f3785c07bf3f125e26a2bbaa51897e4 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 9 Mar 2022 17:26:55 +0700 Subject: [PATCH 31/81] implement tu_edpt_release() --- src/common/tusb_private.h | 4 ++++ src/host/usbh.c | 26 +++++++++++--------------- src/tusb.c | 22 ++++++++++++++++++++++ 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h index 5315c352f..b34506f65 100644 --- a/src/common/tusb_private.h +++ b/src/common/tusb_private.h @@ -52,8 +52,12 @@ void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* p_des // Calculate total length of n interfaces (depending on IAD) uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len); +// Claim an endpoint with provided mutex 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); + #ifdef __cplusplus } #endif diff --git a/src/host/usbh.c b/src/host/usbh.c index 319031f5b..8206c06a4 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1202,23 +1202,19 @@ bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) // TODO has some duplication code with device, refactor later bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) { - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + // addr0 is always available + if (dev_addr == 0) return true; - usbh_device_t* dev = get_device(dev_addr); + usbh_device_t* dev = get_device(dev_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + tu_edpt_state_t* ep_state = &dev->ep_status[epnum][dir]; - lock_device(dev_addr); - - // can only release the endpoint if it is claimed and not busy - bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 1); - if (ret) - { - dev->ep_status[epnum][dir].claimed = 0; - } - - unlock_device(dev_addr); - - return ret; +#if TUSB_OPT_MUTEX + return tu_edpt_release(ep_state, &_usbh_mutex[dev_addr-1]); +#else + return tu_edpt_release(ep_state, NULL); +#endif } // TODO has some duplication code with device, refactor later diff --git a/src/tusb.c b/src/tusb.c index 6ed2a3c05..c86bdd891 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -92,6 +92,28 @@ bool tu_edpt_claim(tu_edpt_state_t* ep_state, osal_mutex_t mutex) return available; } +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 + + // can only release the endpoint if it is claimed and not busy + bool const ret = (ep_state->claimed == 1) && (ep_state->busy == 0); + if (ret) + { + ep_state->claimed = 0; + } + +#if TUSB_OPT_MUTEX + osal_mutex_unlock(mutex); +#endif + + return ret; +} + bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed) { uint16_t const max_packet_size = tu_edpt_packet_size(desc_ep); From d56cde33ef66985b5d3cb087f87cf8bc1a2b111d Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 9 Mar 2022 17:34:12 +0700 Subject: [PATCH 32/81] refactor usbd to also use common endpoint claim/release --- src/device/usbd.c | 65 +++++++++++++---------------------------------- src/host/usbh.c | 7 ++--- 2 files changed, 21 insertions(+), 51 deletions(-) diff --git a/src/device/usbd.c b/src/device/usbd.c index 4b37e8bd9..7ab2660f4 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -69,19 +69,10 @@ typedef struct volatile uint8_t cfg_num; // current active configuration (0x00 is not configured) uint8_t speed; - uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) - uint8_t ep2drv[CFG_TUD_ENDPPOINT_MAX][2]; // map endpoint to driver ( 0xff is invalid ) + uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) + uint8_t ep2drv[CFG_TUD_ENDPPOINT_MAX][2]; // map endpoint to driver ( 0xff is invalid ), can use only 4-bit each - // TODO 4-bit should be sufficient for ep2drv if we want to save half its bytes - - struct TU_ATTR_PACKED - { - volatile bool busy : 1; - volatile bool stalled : 1; - volatile bool claimed : 1; - - // TODO merge ep2drv here, 4-bit should be sufficient - }ep_status[CFG_TUD_ENDPPOINT_MAX][2]; + tu_edpt_state_t ep_status[CFG_TUD_ENDPPOINT_MAX][2]; }usbd_device_t; @@ -1229,52 +1220,30 @@ bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr) // TODO add this check later, also make sure we don't starve an out endpoint while suspending // TU_VERIFY(tud_ready()); - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + tu_edpt_state_t* ep_state = &_usbd_dev.ep_status[epnum][dir]; -#if CFG_TUSB_OS != OPT_OS_NONE - // pre-check to help reducing mutex lock - TU_VERIFY((_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 0)); - osal_mutex_lock(_usbd_mutex, OSAL_TIMEOUT_WAIT_FOREVER); +#if TUSB_OPT_MUTEX + return tu_edpt_claim(ep_state, _usbd_mutex); +#else + return tu_edpt_claim(ep_state, NULL); #endif - - // can only claim the endpoint if it is not busy and not claimed yet. - bool const ret = (_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 0); - if (ret) - { - _usbd_dev.ep_status[epnum][dir].claimed = 1; - } - -#if CFG_TUSB_OS != OPT_OS_NONE - osal_mutex_unlock(_usbd_mutex); -#endif - - return ret; } bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr) { (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + tu_edpt_state_t* ep_state = &_usbd_dev.ep_status[epnum][dir]; -#if CFG_TUSB_OS != OPT_OS_NONE - osal_mutex_lock(_usbd_mutex, OSAL_TIMEOUT_WAIT_FOREVER); +#if TUSB_OPT_MUTEX + return tu_edpt_release(ep_state, _usbd_mutex); +#else + return tu_edpt_release(ep_state, NULL); #endif - - // can only release the endpoint if it is claimed and not busy - bool const ret = (_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 1); - if (ret) - { - _usbd_dev.ep_status[epnum][dir].claimed = 0; - } - -#if CFG_TUSB_OS != OPT_OS_NONE - osal_mutex_unlock(_usbd_mutex); -#endif - - return ret; } 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 8206c06a4..69ec081fd 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -104,9 +104,10 @@ typedef struct { volatile uint8_t state; // device state, value from enum tusbh_device_state_t uint8_t itf2drv[CFG_TUH_INTERFACE_MAX]; // map interface number to driver (0xff is invalid) - uint8_t ep2drv[CFG_TUH_ENDPOINT_MAX][2]; // map endpoint to driver ( 0xff is invalid ) + uint8_t ep2drv[CFG_TUH_ENDPOINT_MAX][2]; // map endpoint to driver ( 0xff is invalid ), can use only 4-bit each tu_edpt_state_t ep_status[CFG_TUH_ENDPOINT_MAX][2]; + } usbh_device_t; @@ -1193,7 +1194,7 @@ bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) tu_edpt_state_t* ep_state = &dev->ep_status[epnum][dir]; #if TUSB_OPT_MUTEX - return tu_edpt_claim(ep_state, &_usbh_mutex[dev_addr-1]); + return tu_edpt_claim(ep_state, _usbh_mutex[dev_addr-1]); #else return tu_edpt_claim(ep_state, NULL); #endif @@ -1211,7 +1212,7 @@ bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) tu_edpt_state_t* ep_state = &dev->ep_status[epnum][dir]; #if TUSB_OPT_MUTEX - return tu_edpt_release(ep_state, &_usbh_mutex[dev_addr-1]); + return tu_edpt_release(ep_state, _usbh_mutex[dev_addr-1]); #else return tu_edpt_release(ep_state, NULL); #endif From 0e5e644d27a722f7a95fcd5f049770094fb02cd6 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 9 Mar 2022 17:51:35 +0700 Subject: [PATCH 33/81] minor clean up --- src/host/usbh.c | 2 +- src/host/usbh_control.c | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index 69ec081fd..808ef1299 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -561,7 +561,7 @@ void tuh_task(void) else { usbh_device_t* dev = get_device(event.dev_addr); - dev->ep_status[epnum][ep_dir].busy = false; + dev->ep_status[epnum][ep_dir].busy = 0; dev->ep_status[epnum][ep_dir].claimed = 0; if ( 0 == epnum ) diff --git a/src/host/usbh_control.c b/src/host/usbh_control.c index 5f4fcf52f..f311cc257 100644 --- a/src/host/usbh_control.c +++ b/src/host/usbh_control.c @@ -50,9 +50,6 @@ typedef struct static usbh_control_xfer_t _ctrl_xfer; -//CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN -//static uint8_t _tuh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSIZE]; - //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ @@ -76,6 +73,7 @@ bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, static void _xfer_complete(uint8_t dev_addr, xfer_result_t result) { TU_LOG2("\r\n"); + _ctrl_xfer.stage = STAGE_IDLE; if (_ctrl_xfer.complete_cb) _ctrl_xfer.complete_cb(dev_addr, &_ctrl_xfer.request, result); } @@ -90,7 +88,7 @@ bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t resu if (XFER_RESULT_SUCCESS != result) { - TU_LOG2("Control failed: result = %d\r\n", result); + TU_LOG2("[%u:%u] Control %s\r\n", rhport, dev_addr, result == XFER_RESULT_STALLED ? "STALLED" : "FAILED"); // terminate transfer if any stage failed _xfer_complete(dev_addr, result); @@ -113,7 +111,7 @@ bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t resu if (request->wLength) { - TU_LOG2("Control data (addr = %u):\r\n", dev_addr); + TU_LOG2("[%u:%u] Control data:\r\n", rhport, dev_addr); TU_LOG2_MEM(_ctrl_xfer.buffer, request->wLength, 2); } From 97636eff8e855c1f901477ca7914c0eca5024432 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 10 Mar 2022 00:36:49 +0700 Subject: [PATCH 34/81] more clean up --- src/host/usbh.c | 251 ++++++++++++++++++++++-------------------------- 1 file changed, 115 insertions(+), 136 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index 808ef1299..aec97cf2a 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -65,10 +65,10 @@ typedef struct struct TU_ATTR_PACKED { - volatile uint8_t connected : 1; - volatile uint8_t addressed : 1; - volatile uint8_t configured : 1; - volatile uint8_t suspended : 1; + volatile uint8_t connected : 1; + volatile uint8_t addressed : 1; + volatile uint8_t configured : 1; + volatile uint8_t suspended : 1; }; } usbh_dev0_t; @@ -81,10 +81,10 @@ typedef struct { struct TU_ATTR_PACKED { - volatile uint8_t connected : 1; - volatile uint8_t addressed : 1; - volatile uint8_t configured : 1; - volatile uint8_t suspended : 1; + volatile uint8_t connected : 1; + volatile uint8_t addressed : 1; + volatile uint8_t configured : 1; + volatile uint8_t suspended : 1; }; //------------- device descriptor -------------// @@ -208,29 +208,8 @@ 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[TOTAL_DEVICES]; static osal_mutex_t _usbh_mutex[TOTAL_DEVICES]; - -static inline void lock_device(uint8_t daddr) -{ - // addr0 is always available - if (daddr) return; - osal_mutex_lock(&_usbh_mutex[daddr-1], OSAL_TIMEOUT_WAIT_FOREVER); -} - -static inline void unlock_device(uint8_t daddr) -{ - // addr0 is always available - if (daddr) return; - osal_mutex_unlock(&_usbh_mutex[daddr-1]); -} - -#else - -#define lock_device(_addr) -#define unlock_device(_addr) - #endif // Event queue @@ -769,6 +748,113 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) } } +//--------------------------------------------------------------------+ +// Endpoint API +//--------------------------------------------------------------------+ + +// TODO has some duplication code with device, refactor later +bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) +{ + // addr0 is always available + if (dev_addr == 0) return true; + + usbh_device_t* dev = get_device(dev_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + tu_edpt_state_t* ep_state = &dev->ep_status[epnum][dir]; + +#if TUSB_OPT_MUTEX + return tu_edpt_claim(ep_state, _usbh_mutex[dev_addr-1]); +#else + return tu_edpt_claim(ep_state, NULL); +#endif +} + +// TODO has some duplication code with device, refactor later +bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) +{ + // addr0 is always available + if (dev_addr == 0) return true; + + usbh_device_t* dev = get_device(dev_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + tu_edpt_state_t* ep_state = &dev->ep_status[epnum][dir]; + +#if TUSB_OPT_MUTEX + return tu_edpt_release(ep_state, _usbh_mutex[dev_addr-1]); +#else + return tu_edpt_release(ep_state, NULL); +#endif +} + +// TODO has some duplication code with device, refactor later +bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + usbh_device_t* dev = get_device(dev_addr); + + TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); + + // Attempt to transfer on a busy endpoint, sound like an race condition ! + TU_ASSERT(dev->ep_status[epnum][dir].busy == 0); + + // Set busy first since the actual transfer can be complete before hcd_edpt_xfer() + // could return and USBH task can preempt and clear the busy + dev->ep_status[epnum][dir].busy = true; + + if ( hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes) ) + { + TU_LOG2("OK\r\n"); + return true; + }else + { + // HCD error, mark endpoint as ready to allow next transfer + dev->ep_status[epnum][dir].busy = false; + dev->ep_status[epnum][dir].claimed = 0; + TU_LOG2("failed\r\n"); + TU_BREAKPOINT(); + return false; + } +} + +static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) +{ + TU_LOG2("Open EP0 with Size = %u (addr = %u)\r\n", max_packet_size, dev_addr); + + tusb_desc_endpoint_t ep0_desc = + { + .bLength = sizeof(tusb_desc_endpoint_t), + .bDescriptorType = TUSB_DESC_ENDPOINT, + .bEndpointAddress = 0, + .bmAttributes = { .xfer = TUSB_XFER_CONTROL }, + .wMaxPacketSize = max_packet_size, + .bInterval = 0 + }; + + return hcd_edpt_open(usbh_get_rhport(dev_addr), dev_addr, &ep0_desc); +} + +bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep) +{ + usbh_device_t* dev = get_device(dev_addr); + TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) dev->speed)); + + return hcd_edpt_open(rhport, dev_addr, desc_ep); +} + +bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + usbh_device_t* dev = get_device(dev_addr); + + return dev->ep_status[epnum][dir].busy; +} + //--------------------------------------------------------------------+ // Enumeration Process // is a lengthy process with a series of control transfer to configure @@ -1178,111 +1264,4 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura return true; } -//--------------------------------------------------------------------+ -// Endpoint API -//--------------------------------------------------------------------+ - -// TODO has some duplication code with device, refactor later -bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) -{ - // addr0 is always available - if (dev_addr == 0) return true; - - usbh_device_t* dev = get_device(dev_addr); - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - tu_edpt_state_t* ep_state = &dev->ep_status[epnum][dir]; - -#if TUSB_OPT_MUTEX - return tu_edpt_claim(ep_state, _usbh_mutex[dev_addr-1]); -#else - return tu_edpt_claim(ep_state, NULL); -#endif -} - -// TODO has some duplication code with device, refactor later -bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) -{ - // addr0 is always available - if (dev_addr == 0) return true; - - usbh_device_t* dev = get_device(dev_addr); - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - tu_edpt_state_t* ep_state = &dev->ep_status[epnum][dir]; - -#if TUSB_OPT_MUTEX - return tu_edpt_release(ep_state, _usbh_mutex[dev_addr-1]); -#else - return tu_edpt_release(ep_state, NULL); -#endif -} - -// TODO has some duplication code with device, refactor later -bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - usbh_device_t* dev = get_device(dev_addr); - - TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); - - // Attempt to transfer on a busy endpoint, sound like an race condition ! - TU_ASSERT(dev->ep_status[epnum][dir].busy == 0); - - // Set busy first since the actual transfer can be complete before hcd_edpt_xfer() - // could return and USBH task can preempt and clear the busy - dev->ep_status[epnum][dir].busy = true; - - if ( hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes) ) - { - TU_LOG2("OK\r\n"); - return true; - }else - { - // HCD error, mark endpoint as ready to allow next transfer - dev->ep_status[epnum][dir].busy = false; - dev->ep_status[epnum][dir].claimed = 0; - TU_LOG2("failed\r\n"); - TU_BREAKPOINT(); - return false; - } -} - -static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) -{ - TU_LOG2("Open EP0 with Size = %u (addr = %u)\r\n", max_packet_size, dev_addr); - - tusb_desc_endpoint_t ep0_desc = - { - .bLength = sizeof(tusb_desc_endpoint_t), - .bDescriptorType = TUSB_DESC_ENDPOINT, - .bEndpointAddress = 0, - .bmAttributes = { .xfer = TUSB_XFER_CONTROL }, - .wMaxPacketSize = max_packet_size, - .bInterval = 0 - }; - - return hcd_edpt_open(usbh_get_rhport(dev_addr), dev_addr, &ep0_desc); -} - -bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep) -{ - usbh_device_t* dev = get_device(dev_addr); - TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) dev->speed)); - - return hcd_edpt_open(rhport, dev_addr, desc_ep); -} - -bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - usbh_device_t* dev = get_device(dev_addr); - - return dev->ep_status[epnum][dir].busy; -} - #endif From 22f682c37879a38aa662c2205d411b2246d0639c Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Wed, 9 Mar 2022 15:22:31 -0800 Subject: [PATCH 35/81] Add host example that prints out info of connected devices --- examples/host/device_info/CMakeLists.txt | 27 +++ examples/host/device_info/Makefile | 28 ++++ examples/host/device_info/only.txt | 9 + examples/host/device_info/src/main.c | 175 ++++++++++++++++++++ examples/host/device_info/src/tusb_config.h | 96 +++++++++++ 5 files changed, 335 insertions(+) create mode 100644 examples/host/device_info/CMakeLists.txt create mode 100644 examples/host/device_info/Makefile create mode 100644 examples/host/device_info/only.txt create mode 100644 examples/host/device_info/src/main.c create mode 100644 examples/host/device_info/src/tusb_config.h diff --git a/examples/host/device_info/CMakeLists.txt b/examples/host/device_info/CMakeLists.txt new file mode 100644 index 000000000..bff281a8c --- /dev/null +++ b/examples/host/device_info/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.5) + +include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) + +# gets PROJECT name for the example +family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR}) + +project(${PROJECT}) + +# Checks this example is valid for the family and initializes the project +family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) + +add_executable(${PROJECT}) + +# Example source +target_sources(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c + ) + +# Example include +target_include_directories(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src + ) + +# Configure compilation flags and libraries for the example... see the corresponding function +# in hw/bsp/FAMILY/family.cmake for details. +family_configure_host_example(${PROJECT}) \ No newline at end of file diff --git a/examples/host/device_info/Makefile b/examples/host/device_info/Makefile new file mode 100644 index 000000000..c59369ffa --- /dev/null +++ b/examples/host/device_info/Makefile @@ -0,0 +1,28 @@ +include ../../../tools/top.mk +include ../../make.mk + +INC += \ + src \ + $(TOP)/hw \ + +# Example source +EXAMPLE_SOURCE += \ + src/main.c + +SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) + +# TODO: suppress warning caused by host stack +CFLAGS += -Wno-error=cast-align -Wno-error=null-dereference + +# TinyUSB Host Stack source +SRC_C += \ + src/class/cdc/cdc_host.c \ + src/class/hid/hid_host.c \ + src/class/msc/msc_host.c \ + src/host/hub.c \ + src/host/usbh.c \ + src/host/usbh_control.c \ + src/portable/ohci/ohci.c \ + src/portable/nxp/lpc17_40/hcd_lpc17_40.c + +include ../../rules.mk diff --git a/examples/host/device_info/only.txt b/examples/host/device_info/only.txt new file mode 100644 index 000000000..7fe4e3f5c --- /dev/null +++ b/examples/host/device_info/only.txt @@ -0,0 +1,9 @@ +mcu:LPC175X_6X +mcu:LPC177X_8X +mcu:LPC18XX +mcu:LPC40XX +mcu:LPC43XX +mcu:MIMXRT10XX +mcu:RP2040 +mcu:MSP432E4 +mcu:RX65X diff --git a/examples/host/device_info/src/main.c b/examples/host/device_info/src/main.c new file mode 100644 index 000000000..45b616af0 --- /dev/null +++ b/examples/host/device_info/src/main.c @@ -0,0 +1,175 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2022 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +/* This example prints out info about the enumerated devices. */ + + +#include +#include +#include + +#include "bsp/board.h" +#include "tusb.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF PROTYPES +//--------------------------------------------------------------------+ +void led_blinking_task(void); + +static xfer_result_t _get_string_result; + +static bool _transfer_done_cb(uint8_t daddr, tusb_control_request_t const *request, xfer_result_t result) { + (void)daddr; + (void)request; + _get_string_result = result; + return true; +} + +static void _convert_utf16le_to_utf8(const uint16_t *utf16, size_t utf16_len, uint8_t *utf8, size_t utf8_len) { + // TODO: Check for runover. + (void)utf8_len; + // Get the UTF-16 length out of the data itself. + + for (size_t i = 0; i < utf16_len; i++) { + uint16_t chr = utf16[i]; + if (chr < 0x80) { + *utf8++ = chr & 0xff; + } else if (chr < 0x800) { + *utf8++ = (uint8_t)(0xC0 | (chr >> 6 & 0x1F)); + *utf8++ = (uint8_t)(0x80 | (chr >> 0 & 0x3F)); + } else { + // TODO: Verify surrogate. + *utf8++ = (uint8_t)(0xE0 | (chr >> 12 & 0x0F)); + *utf8++ = (uint8_t)(0x80 | (chr >> 6 & 0x3F)); + *utf8++ = (uint8_t)(0x80 | (chr >> 0 & 0x3F)); + } + // TODO: Handle UTF-16 code points that take two entries. + } +} + +// Count how many bytes a utf-16-le encoded string will take in utf-8. +static int _count_utf8_bytes(const uint16_t *buf, size_t len) { + size_t total_bytes = 0; + for (size_t i = 0; i < len; i++) { + uint16_t chr = buf[i]; + if (chr < 0x80) { + total_bytes += 1; + } else if (chr < 0x800) { + total_bytes += 2; + } else { + total_bytes += 3; + } + // TODO: Handle UTF-16 code points that take two entries. + } + return total_bytes; +} + +static void _wait_and_convert(uint16_t *temp_buf, size_t buf_len) { + while (_get_string_result == 0xff) { + tuh_task(); + } + size_t utf16_len = ((temp_buf[0] & 0xff) - 2) / sizeof(uint16_t); + size_t utf8_len = _count_utf8_bytes(temp_buf + 1, utf16_len); + _convert_utf16le_to_utf8(temp_buf + 1, utf16_len, (uint8_t *) temp_buf, sizeof(uint16_t) * buf_len); + ((uint8_t*) temp_buf)[utf8_len] = '\0'; +} + +/*------------- MAIN -------------*/ +int main(void) +{ + board_init(); + + printf("TinyUSB Host Device Info Example\r\n"); + + tusb_init(); + + uint32_t interval_ms = 5000; + uint32_t start_time = 0; + + while (1) + { + // tinyusb host task + tuh_task(); + led_blinking_task(); + + if (board_millis() - start_time < interval_ms) { + continue; + } + start_time = board_millis(); + // Brute force check every device address to see if it is active. + for (int i = 1; i < CFG_TUH_DEVICE_MAX + CFG_TUH_HUB + 1; i++) { + if (!tuh_ready(i)) { + continue; + } + uint16_t vid; + uint16_t pid; + tuh_vid_pid_get(i, &vid, &pid); + printf("%d vid %04x pid %04x\r\n", i, vid, pid); + + _get_string_result = 0xff; + uint16_t temp_buf[127]; + if (tuh_descriptor_string_serial_get(i, 0, temp_buf, TU_ARRAY_SIZE(temp_buf), _transfer_done_cb)) { + _wait_and_convert(temp_buf, TU_ARRAY_SIZE(temp_buf)); + printf("Serial: %s\r\n", (const char*) temp_buf); + } + + _get_string_result = 0xff; + temp_buf[0] = 0; + if (tuh_descriptor_string_product_get(i, 0, temp_buf, TU_ARRAY_SIZE(temp_buf), _transfer_done_cb)) { + _wait_and_convert(temp_buf, TU_ARRAY_SIZE(temp_buf)); + printf("Product: %s\r\n", (const char*) temp_buf); + } + + _get_string_result = 0xff; + temp_buf[0] = 0; + if (tuh_descriptor_string_manufacturer_get(i, 0, temp_buf, TU_ARRAY_SIZE(temp_buf), _transfer_done_cb)) { + _wait_and_convert(temp_buf, TU_ARRAY_SIZE(temp_buf)); + printf("Manufacturer: %s\r\n", (const char*) temp_buf); + } + } + printf("\n"); + } + + return 0; +} + + +//--------------------------------------------------------------------+ +// Blinking Task +//--------------------------------------------------------------------+ +void led_blinking_task(void) +{ + const uint32_t interval_ms = 1000; + static uint32_t start_ms = 0; + + static bool led_state = false; + + // Blink every interval ms + if ( board_millis() - start_ms < interval_ms) return; // not enough time + start_ms += interval_ms; + + board_led_write(led_state); + led_state = 1 - led_state; // toggle +} diff --git a/examples/host/device_info/src/tusb_config.h b/examples/host/device_info/src/tusb_config.h new file mode 100644 index 000000000..6b413e46f --- /dev/null +++ b/examples/host/device_info/src/tusb_config.h @@ -0,0 +1,96 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#ifndef _TUSB_CONFIG_H_ +#define _TUSB_CONFIG_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +//-------------------------------------------------------------------- +// COMMON CONFIGURATION +//-------------------------------------------------------------------- + +// defined by compiler flags for flexibility +#ifndef CFG_TUSB_MCU + #error CFG_TUSB_MCU must be defined +#endif + +#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX + #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_HOST | OPT_MODE_HIGH_SPEED) +#else + #define CFG_TUSB_RHPORT0_MODE OPT_MODE_HOST +#endif + +#ifndef CFG_TUSB_OS +#define CFG_TUSB_OS OPT_OS_NONE +#endif + +// CFG_TUSB_DEBUG is defined by compiler in DEBUG build +// #define CFG_TUSB_DEBUG 0 + +/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. + * Tinyusb use follows macros to declare transferring memory so that they can be put + * into those specific section. + * e.g + * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) + * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) + */ +#ifndef CFG_TUSB_MEM_SECTION +#define CFG_TUSB_MEM_SECTION +#endif + +#ifndef CFG_TUSB_MEM_ALIGN +#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) +#endif + +//-------------------------------------------------------------------- +// CONFIGURATION +//-------------------------------------------------------------------- + +// Size of buffer to hold descriptors and other data used for enumeration +#define CFG_TUH_ENUMERATION_BUFSIZE 256 + +// only hub class is enabled +#define CFG_TUH_HUB 1 + +// max device support (excluding hub device) +// 1 hub typically has 4 ports +#define CFG_TUH_DEVICE_MAX (CFG_TUH_HUB ? 4 : 1) + +#define CFG_TUH_ENDPOINT_MAX 8 + +#define CFG_TUH_TASK_QUEUE_SZ 64 + +//------------- HID -------------// + +#define CFG_TUH_HID_EP_BUFSIZE 64 + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_CONFIG_H_ */ From b05401a5ab788a9b1a56bdb79b74e49b6909339f Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 10 Mar 2022 11:59:51 +0700 Subject: [PATCH 36/81] merge control stage host and device value --- src/common/tusb_types.h | 1 + src/host/usbh_control.c | 22 +++++++--------------- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index 5b26f5aec..f998eabfb 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -265,6 +265,7 @@ typedef enum enum { + CONTROL_STAGE_IDLE, CONTROL_STAGE_SETUP, CONTROL_STAGE_DATA, CONTROL_STAGE_ACK diff --git a/src/host/usbh_control.c b/src/host/usbh_control.c index f311cc257..741b0723a 100644 --- a/src/host/usbh_control.c +++ b/src/host/usbh_control.c @@ -31,14 +31,6 @@ #include "tusb.h" #include "usbh_classdriver.h" -enum -{ - STAGE_IDLE, - STAGE_SETUP, - STAGE_DATA, - STAGE_ACK -}; - typedef struct { tusb_control_request_t request TU_ATTR_ALIGNED(4); @@ -61,7 +53,7 @@ bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, _ctrl_xfer.request = (*request); _ctrl_xfer.buffer = buffer; - _ctrl_xfer.stage = STAGE_SETUP; + _ctrl_xfer.stage = CONTROL_STAGE_SETUP; _ctrl_xfer.complete_cb = complete_cb; // Send setup packet @@ -73,7 +65,7 @@ bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, static void _xfer_complete(uint8_t dev_addr, xfer_result_t result) { TU_LOG2("\r\n"); - _ctrl_xfer.stage = STAGE_IDLE; + _ctrl_xfer.stage = CONTROL_STAGE_IDLE; if (_ctrl_xfer.complete_cb) _ctrl_xfer.complete_cb(dev_addr, &_ctrl_xfer.request, result); } @@ -96,8 +88,8 @@ bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t resu { switch(_ctrl_xfer.stage) { - case STAGE_SETUP: - _ctrl_xfer.stage = STAGE_DATA; + case CONTROL_STAGE_SETUP: + _ctrl_xfer.stage = CONTROL_STAGE_DATA; if (request->wLength) { // DATA stage: initial data toggle is always 1 @@ -106,8 +98,8 @@ bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t resu } __attribute__((fallthrough)); - case STAGE_DATA: - _ctrl_xfer.stage = STAGE_ACK; + case CONTROL_STAGE_DATA: + _ctrl_xfer.stage = CONTROL_STAGE_ACK; if (request->wLength) { @@ -119,7 +111,7 @@ bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t resu hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, 1-request->bmRequestType_bit.direction), NULL, 0); break; - case STAGE_ACK: + case CONTROL_STAGE_ACK: _xfer_complete(dev_addr, result); break; From 5e9f522b9ad1c9c9b905101c364d0728d4895d5b Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 10 Mar 2022 12:56:15 +0700 Subject: [PATCH 37/81] refactor host control xfer --- src/host/usbh.c | 30 +++++++++++++++++++++--------- src/host/usbh_control.c | 16 ++++++---------- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index aec97cf2a..9a2bc86a8 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -55,6 +55,7 @@ //--------------------------------------------------------------------+ // device0 struct must be strictly a subset of normal device struct +// TODO refactor later typedef struct { // port @@ -70,6 +71,8 @@ typedef struct volatile uint8_t configured : 1; volatile uint8_t suspended : 1; }; + + uint8_t control_stage; // state of control transfer } usbh_dev0_t; typedef struct { @@ -87,12 +90,13 @@ typedef struct { volatile uint8_t suspended : 1; }; - //------------- device descriptor -------------// - uint8_t ep0_size; + uint8_t control_stage; // state of control transfer + //------------- device descriptor -------------// uint16_t vid; uint16_t pid; + uint8_t ep0_size; uint8_t i_manufacturer; uint8_t i_product; uint8_t i_serial; @@ -234,8 +238,8 @@ static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t h static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size); // from usbh_control.c -extern bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb); -extern bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +extern bool usbh_control_xfer (uint8_t daddr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb); +extern uint8_t usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, uint8_t* stage, xfer_result_t result, uint32_t xferred_bytes); //--------------------------------------------------------------------+ // PUBLIC API (Parameter Verification is required) @@ -274,13 +278,21 @@ void osal_task_delay(uint32_t msec) #endif -bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb) +bool tuh_control_xfer (uint8_t daddr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb) { - TU_LOG2("[%u:%u] %s: ", usbh_get_rhport(dev_addr), dev_addr, request->bRequest <= TUSB_REQ_SYNCH_FRAME ? tu_str_std_request[request->bRequest] : "Unknown Request"); + TU_LOG2("[%u:%u] %s: ", usbh_get_rhport(daddr), daddr, request->bRequest <= TUSB_REQ_SYNCH_FRAME ? tu_str_std_request[request->bRequest] : "Unknown Request"); TU_LOG2_VAR(request); TU_LOG2("\r\n"); - return usbh_control_xfer(dev_addr, request, buffer, complete_cb); + if (daddr) + { + get_device(daddr)->control_stage = CONTROL_STAGE_SETUP; + }else + { + _dev0.control_stage = CONTROL_STAGE_SETUP; + } + + return usbh_control_xfer(daddr, request, buffer, complete_cb); } //--------------------------------------------------------------------+ @@ -535,7 +547,7 @@ void tuh_task(void) { // device 0 only has control endpoint TU_ASSERT(epnum == 0, ); - usbh_control_xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + usbh_control_xfer_cb(event.dev_addr, ep_addr, &_dev0.control_stage, event.xfer_complete.result, event.xfer_complete.len); } else { @@ -545,7 +557,7 @@ void tuh_task(void) if ( 0 == epnum ) { - usbh_control_xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + usbh_control_xfer_cb(event.dev_addr, ep_addr, &dev->control_stage, event.xfer_complete.result, event.xfer_complete.len); }else { uint8_t drv_id = dev->ep2drv[epnum][ep_dir]; diff --git a/src/host/usbh_control.c b/src/host/usbh_control.c index 741b0723a..88287a47b 100644 --- a/src/host/usbh_control.c +++ b/src/host/usbh_control.c @@ -34,8 +34,6 @@ typedef struct { tusb_control_request_t request TU_ATTR_ALIGNED(4); - - uint8_t stage; uint8_t* buffer; tuh_control_complete_cb_t complete_cb; } usbh_control_xfer_t; @@ -53,7 +51,6 @@ bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, _ctrl_xfer.request = (*request); _ctrl_xfer.buffer = buffer; - _ctrl_xfer.stage = CONTROL_STAGE_SETUP; _ctrl_xfer.complete_cb = complete_cb; // Send setup packet @@ -65,17 +62,15 @@ bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, static void _xfer_complete(uint8_t dev_addr, xfer_result_t result) { TU_LOG2("\r\n"); - _ctrl_xfer.stage = CONTROL_STAGE_IDLE; if (_ctrl_xfer.complete_cb) _ctrl_xfer.complete_cb(dev_addr, &_ctrl_xfer.request, result); } -bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, uint8_t* stage, xfer_result_t result, uint32_t xferred_bytes) { (void) ep_addr; (void) xferred_bytes; const uint8_t rhport = usbh_get_rhport(dev_addr); - tusb_control_request_t const * request = &_ctrl_xfer.request; if (XFER_RESULT_SUCCESS != result) @@ -83,13 +78,14 @@ bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t resu TU_LOG2("[%u:%u] Control %s\r\n", rhport, dev_addr, result == XFER_RESULT_STALLED ? "STALLED" : "FAILED"); // terminate transfer if any stage failed + *stage = CONTROL_STAGE_IDLE; _xfer_complete(dev_addr, result); }else { - switch(_ctrl_xfer.stage) + switch(*stage) { case CONTROL_STAGE_SETUP: - _ctrl_xfer.stage = CONTROL_STAGE_DATA; + *stage = CONTROL_STAGE_DATA; if (request->wLength) { // DATA stage: initial data toggle is always 1 @@ -99,8 +95,7 @@ bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t resu __attribute__((fallthrough)); case CONTROL_STAGE_DATA: - _ctrl_xfer.stage = CONTROL_STAGE_ACK; - + *stage = CONTROL_STAGE_ACK; if (request->wLength) { TU_LOG2("[%u:%u] Control data:\r\n", rhport, dev_addr); @@ -112,6 +107,7 @@ bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t resu break; case CONTROL_STAGE_ACK: + *stage = CONTROL_STAGE_IDLE; _xfer_complete(dev_addr, result); break; From b9ca301527040458bd369cf967732a76d5139222 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 10 Mar 2022 13:19:15 +0700 Subject: [PATCH 38/81] remove obsolete device state --- src/common/tusb_types.h | 8 -------- src/host/hcd.h | 3 ++- src/host/usbh.c | 36 ++++++++++++++++-------------------- 3 files changed, 18 insertions(+), 29 deletions(-) diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index f998eabfb..da164145b 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -223,14 +223,6 @@ enum { #define TUSB_DESC_CONFIG_POWER_MA(x) ((x)/2) -/// Device State TODO remove -typedef enum -{ - TUSB_DEVICE_STATE_UNPLUG = 0 , - TUSB_DEVICE_STATE_CONFIGURED , - TUSB_DEVICE_STATE_SUSPENDED , -}tusb_device_state_t; - typedef enum { XFER_RESULT_SUCCESS, diff --git a/src/host/hcd.h b/src/host/hcd.h index 9819f5f2a..c40bea64c 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -94,7 +94,8 @@ typedef struct } hcd_event_t; -typedef struct { +typedef struct +{ uint8_t rhport; uint8_t hub_addr; uint8_t hub_port; diff --git a/src/host/usbh.c b/src/host/usbh.c index 9a2bc86a8..07baeee96 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -82,6 +82,7 @@ typedef struct { uint8_t hub_port; uint8_t speed; + // Device State struct TU_ATTR_PACKED { volatile uint8_t connected : 1; @@ -92,7 +93,7 @@ typedef struct { uint8_t control_stage; // state of control transfer - //------------- device descriptor -------------// + // Device Descriptor uint16_t vid; uint16_t pid; @@ -101,12 +102,10 @@ typedef struct { uint8_t i_product; uint8_t i_serial; - //------------- configuration descriptor -------------// + // Configuration Descriptor // uint8_t interface_count; // bNumInterfaces alias - //------------- device -------------// - volatile uint8_t state; // device state, value from enum tusbh_device_state_t - + // Endpoint & Interface uint8_t itf2drv[CFG_TUH_INTERFACE_MAX]; // map interface number to driver (0xff is invalid) uint8_t ep2drv[CFG_TUH_ENDPOINT_MAX][2]; // map endpoint to driver ( 0xff is invalid ), can use only 4-bit each @@ -685,9 +684,8 @@ void hcd_event_device_remove(uint8_t hostid, bool in_isr) } -// a device unplugged on hostid, hub_addr, hub_port -// return true if found and unmounted device, false if cannot find -void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) +// a device unplugged from rhport:hub_addr:hub_port +static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) { //------------- find the all devices (star-network) under port that is unplugged -------------// // TODO mark as disconnected in ISR, also handle dev0 @@ -700,7 +698,7 @@ void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port if (dev->rhport == rhport && (hub_addr == 0 || dev->hub_addr == hub_addr) && // hub_addr == 0 & hub_port == 0 means roothub (hub_port == 0 || dev->hub_port == hub_port) && - dev->state != TUSB_DEVICE_STATE_UNPLUG) + dev->connected) { // Invoke callback before close driver if (tuh_umount_cb) tuh_umount_cb(dev_addr); @@ -729,7 +727,7 @@ static uint8_t get_new_address(bool is_hub) for (uint8_t i=0; i < count; i++) { uint8_t const addr = start + i; - if (get_device(addr)->state == TUSB_DEVICE_STATE_UNPLUG) return addr; + if (!get_device(addr)->connected) return addr; } return ADDR_INVALID; } @@ -951,17 +949,17 @@ static bool enum_hub_get_status0_complete(uint8_t dev_addr, tusb_control_request return true; } -#endif +#endif // hub static bool enum_new_device(hcd_event_t* event) { - _dev0.rhport = event->rhport; // TODO refractor integrate to device_pool + _dev0.rhport = event->rhport; _dev0.hub_addr = event->connection.hub_addr; _dev0.hub_port = event->connection.hub_port; - //------------- connected/disconnected directly with roothub -------------// if (_dev0.hub_addr == 0) { + // connected/disconnected directly with roothub // wait until device is stable TODO non blocking osal_task_delay(RESET_DELAY); @@ -974,14 +972,14 @@ static bool enum_new_device(hcd_event_t* event) enum_request_addr0_device_desc(); } #if CFG_TUH_HUB - //------------- connected/disconnected via hub -------------// else { + // connected/disconnected via external hub // wait until device is stable osal_task_delay(RESET_DELAY); TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, enum_hub_get_status0_complete) ); } -#endif // CFG_TUH_HUB +#endif // hub return true; } @@ -994,7 +992,6 @@ static bool enum_request_addr0_device_desc(void) // Get first 8 bytes of device descriptor for Control Endpoint size TU_LOG2("Get 8 byte of Device Descriptor\r\n"); - TU_ASSERT(tuh_descriptor_get_device(addr0, _usbh_ctrl_buf, 8, enum_get_addr0_device_desc_complete)); return true; } @@ -1024,7 +1021,7 @@ static bool enum_get_addr0_device_desc_complete(uint8_t dev_addr, tusb_control_r if (_dev0.hub_addr == 0) { // connected directly to roothub - hcd_port_reset( _dev0.rhport ); // reset port after 8 byte descriptor + hcd_port_reset( _dev0.rhport ); osal_task_delay(RESET_DELAY); enum_request_set_addr(); @@ -1040,14 +1037,13 @@ static bool enum_get_addr0_device_desc_complete(uint8_t dev_addr, tusb_control_r TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, enum_hub_get_status1_complete) ); } -#endif +#endif // hub return true; } static bool enum_request_set_addr(void) { - uint8_t const addr0 = 0; tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf; // Get new address @@ -1079,6 +1075,7 @@ static bool enum_request_set_addr(void) .wLength = 0 }; + uint8_t const addr0 = 0; TU_ASSERT( tuh_control_xfer(addr0, &new_request, NULL, enum_set_address_complete) ); return true; @@ -1172,7 +1169,6 @@ static bool enum_set_config_complete(uint8_t dev_addr, tusb_control_request_t co TU_LOG2("Device configured\r\n"); usbh_device_t* dev = get_device(dev_addr); dev->configured = 1; - dev->state = TUSB_DEVICE_STATE_CONFIGURED; // Start the Set Configuration process for interfaces (itf = DRVID_INVALID) // Since driver can perform control transfer within its set_config, this is done asynchronously. From 171d021ab56960f8d7e222faa263168ead0f9d6a Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 10 Mar 2022 22:22:05 +0700 Subject: [PATCH 39/81] refactor and integrate usbh control xfer back to usbh.c fix enumeration with hub when reset port before set address --- src/device/usbd_pvt.h | 2 +- src/host/usbh.c | 447 +++++++++++++++++++++++------------- src/host/usbh_classdriver.h | 1 + src/host/usbh_control.c | 82 ++----- src/osal/osal_none.h | 2 +- 5 files changed, 317 insertions(+), 217 deletions(-) diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index dae95cebb..29753451e 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -80,7 +80,7 @@ bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 // If caller does not make any transfer, it must release endpoint for others. bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr); -// Release an endpoint without submitting a transfer +// Release claimed endpoint without submitting a transfer bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr); // Check if endpoint is busy transferring diff --git a/src/host/usbh.c b/src/host/usbh.c index 07baeee96..3d9db70fa 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -72,7 +72,6 @@ typedef struct volatile uint8_t suspended : 1; }; - uint8_t control_stage; // state of control transfer } usbh_dev0_t; typedef struct { @@ -91,13 +90,12 @@ typedef struct { volatile uint8_t suspended : 1; }; - uint8_t control_stage; // state of control transfer - // Device Descriptor + uint8_t ep0_size; + uint16_t vid; uint16_t pid; - uint8_t ep0_size; uint8_t i_manufacturer; uint8_t i_product; uint8_t i_serial; @@ -113,6 +111,14 @@ typedef struct { } usbh_device_t; +typedef struct +{ + tusb_control_request_t request TU_ATTR_ALIGNED(4); + uint8_t* buffer; + tuh_control_complete_cb_t complete_cb; + + uint8_t daddr; +} usbh_control_xfer_t; //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF @@ -211,8 +217,24 @@ 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[TOTAL_DEVICES]; -static osal_mutex_t _usbh_mutex[TOTAL_DEVICES]; +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); +} + +#else + +#define usbh_lock() +#define usbh_unlock() + #endif // Event queue @@ -223,6 +245,15 @@ 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 +{ + usbh_control_xfer_t xfer; + uint8_t stage; +}_ctrl_xfer; + //------------- Helper Function -------------// TU_ATTR_ALWAYS_INLINE @@ -235,10 +266,7 @@ static inline usbh_device_t* get_device(uint8_t dev_addr) static bool enum_new_device(hcd_event_t* event); static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port); static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size); - -// from usbh_control.c -extern bool usbh_control_xfer (uint8_t daddr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb); -extern uint8_t usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, uint8_t* stage, xfer_result_t result, uint32_t xferred_bytes); +static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); //--------------------------------------------------------------------+ // PUBLIC API (Parameter Verification is required) @@ -276,24 +304,6 @@ void osal_task_delay(uint32_t msec) } #endif - -bool tuh_control_xfer (uint8_t daddr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb) -{ - TU_LOG2("[%u:%u] %s: ", usbh_get_rhport(daddr), daddr, request->bRequest <= TUSB_REQ_SYNCH_FRAME ? tu_str_std_request[request->bRequest] : "Unknown Request"); - TU_LOG2_VAR(request); - TU_LOG2("\r\n"); - - if (daddr) - { - get_device(daddr)->control_stage = CONTROL_STAGE_SETUP; - }else - { - _dev0.control_stage = CONTROL_STAGE_SETUP; - } - - return usbh_control_xfer(daddr, request, buffer, complete_cb); -} - //--------------------------------------------------------------------+ // Descriptors //--------------------------------------------------------------------+ @@ -449,26 +459,30 @@ bool tuh_init(uint8_t rhport) TU_LOG2("USBH init\r\n"); TU_LOG2_INT(sizeof(usbh_device_t)); + TU_LOG2_INT(sizeof(hcd_event_t)); + TU_LOG2_INT(sizeof(usbh_control_xfer_t)); - //------------- Enumeration & Reporter Task init -------------// + // Event queue _usbh_q = osal_queue_create( &_usbh_qdef ); TU_ASSERT(_usbh_q != NULL); - //------------- Semaphore, Mutex for Control Pipe -------------// +#if TUSB_OPT_MUTEX + // Mutex + _usbh_mutex = osal_mutex_create(&_usbh_mutexdef); + TU_ASSERT(_usbh_mutex); +#endif + + // Device tu_memclr(&_dev0, sizeof(_dev0)); tu_memclr(_usbh_devices, sizeof(_usbh_devices)); + tu_memclr(&_ctrl_xfer, sizeof(_ctrl_xfer)); for(uint8_t i=0; icontrol_stage, event.xfer_complete.result, event.xfer_complete.len); + usbh_control_xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); }else { uint8_t drv_id = dev->ep2drv[epnum][ep_dir]; @@ -683,81 +697,6 @@ void hcd_event_device_remove(uint8_t hostid, bool in_isr) hcd_event_handler(&event, in_isr); } - -// a device unplugged from rhport:hub_addr:hub_port -static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) -{ - //------------- find the all devices (star-network) under port that is unplugged -------------// - // TODO mark as disconnected in ISR, also handle dev0 - for ( uint8_t dev_id = 0; dev_id < TU_ARRAY_SIZE(_usbh_devices); dev_id++ ) - { - usbh_device_t* dev = &_usbh_devices[dev_id]; - uint8_t const dev_addr = dev_id+1; - - // TODO Hub multiple level - if (dev->rhport == rhport && - (hub_addr == 0 || dev->hub_addr == hub_addr) && // hub_addr == 0 & hub_port == 0 means roothub - (hub_port == 0 || dev->hub_port == hub_port) && - dev->connected) - { - // Invoke callback before close driver - if (tuh_umount_cb) tuh_umount_cb(dev_addr); - - // 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); - usbh_class_drivers[drv_id].close(dev_addr); - } - - hcd_device_close(rhport, dev_addr); - clear_device(dev); - } - } -} - -//--------------------------------------------------------------------+ -// INTERNAL HELPER -//--------------------------------------------------------------------+ -static uint8_t get_new_address(bool is_hub) -{ - uint8_t const start = (is_hub ? CFG_TUH_DEVICE_MAX : 0) + 1; - uint8_t const count = (is_hub ? CFG_TUH_HUB : CFG_TUH_DEVICE_MAX); - - for (uint8_t i=0; i < count; i++) - { - uint8_t const addr = start + i; - if (!get_device(addr)->connected) return addr; - } - return ADDR_INVALID; -} - -void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) -{ - usbh_device_t* dev = get_device(dev_addr); - - for(itf_num++; itf_num < CFG_TUH_INTERFACE_MAX; itf_num++) - { - // continue with next valid interface - // TODO skip IAD binding interface such as CDCs - uint8_t const drv_id = dev->itf2drv[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); - driver->set_config(dev_addr, itf_num); - break; - } - } - - // all interface are configured - if (itf_num == CFG_TUH_INTERFACE_MAX) - { - // Invoke callback if available - if (tuh_mount_cb) tuh_mount_cb(dev_addr); - } -} - //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ @@ -774,7 +713,7 @@ bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) tu_edpt_state_t* ep_state = &dev->ep_status[epnum][dir]; #if TUSB_OPT_MUTEX - return tu_edpt_claim(ep_state, _usbh_mutex[dev_addr-1]); + return tu_edpt_claim(ep_state, _usbh_mutex); #else return tu_edpt_claim(ep_state, NULL); #endif @@ -792,7 +731,7 @@ bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) tu_edpt_state_t* ep_state = &dev->ep_status[epnum][dir]; #if TUSB_OPT_MUTEX - return tu_edpt_release(ep_state, _usbh_mutex[dev_addr-1]); + return tu_edpt_release(ep_state, _usbh_mutex); #else return tu_edpt_release(ep_state, NULL); #endif @@ -865,6 +804,183 @@ bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) return dev->ep_status[epnum][dir].busy; } +//--------------------------------------------------------------------+ +// Control transfer +//--------------------------------------------------------------------+ + +bool tuh_control_xfer (uint8_t daddr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb) +{ + // pre-check to help reducing mutex lock + TU_VERIFY(_ctrl_xfer.stage == CONTROL_STAGE_IDLE); + + usbh_lock(); + + bool const is_idle = (_ctrl_xfer.stage == CONTROL_STAGE_IDLE); + if (is_idle) _ctrl_xfer.stage = CONTROL_STAGE_SETUP; + + usbh_unlock(); + + TU_VERIFY(is_idle); + + const uint8_t rhport = usbh_get_rhport(daddr); + + TU_LOG2("[%u:%u] %s: ", rhport, daddr, request->bRequest <= TUSB_REQ_SYNCH_FRAME ? tu_str_std_request[request->bRequest] : "Unknown Request"); + TU_LOG2_VAR(request); + TU_LOG2("\r\n"); + + _ctrl_xfer.xfer.request = (*request); + _ctrl_xfer.xfer.buffer = buffer; + _ctrl_xfer.xfer.complete_cb = complete_cb; + _ctrl_xfer.xfer.daddr = daddr; + + return hcd_setup_send(rhport, daddr, (uint8_t const*) &_ctrl_xfer.xfer.request); +} + +TU_ATTR_ALWAYS_INLINE static inline void set_control_xfer_stage(uint8_t stage) +{ + usbh_lock(); + _ctrl_xfer.stage = stage; + usbh_unlock(); +} + +static void _xfer_complete(uint8_t dev_addr, xfer_result_t result) +{ + TU_LOG2("\r\n"); + + usbh_lock(); + _ctrl_xfer.stage = CONTROL_STAGE_IDLE; + usbh_unlock(); + + if (_ctrl_xfer.xfer.complete_cb) _ctrl_xfer.xfer.complete_cb(dev_addr, &_ctrl_xfer.xfer.request, result); +} + +static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void) ep_addr; + (void) xferred_bytes; + + const uint8_t rhport = usbh_get_rhport(dev_addr); + tusb_control_request_t const * request = &_ctrl_xfer.xfer.request; + + if (XFER_RESULT_SUCCESS != result) + { + TU_LOG2("[%u:%u] Control %s\r\n", rhport, dev_addr, result == XFER_RESULT_STALLED ? "STALLED" : "FAILED"); + + // terminate transfer if any stage failed + _xfer_complete(dev_addr, result); + }else + { + switch(_ctrl_xfer.stage) + { + case CONTROL_STAGE_SETUP: + if (request->wLength) + { + // DATA stage: initial data toggle is always 1 + set_control_xfer_stage(CONTROL_STAGE_DATA); + return hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.xfer.buffer, request->wLength); + } + __attribute__((fallthrough)); + + case CONTROL_STAGE_DATA: + if (request->wLength) + { + TU_LOG2("[%u:%u] Control data:\r\n", rhport, dev_addr); + TU_LOG2_MEM(_ctrl_xfer.xfer.buffer, request->wLength, 2); + } + + // ACK stage: toggle is always 1 + set_control_xfer_stage(CONTROL_STAGE_ACK); + hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, 1-request->bmRequestType_bit.direction), NULL, 0); + break; + + case CONTROL_STAGE_ACK: + _xfer_complete(dev_addr, result); + break; + + default: return false; + } + } + + return true; +} + +// a device unplugged from rhport:hub_addr:hub_port +static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) +{ + //------------- find the all devices (star-network) under port that is unplugged -------------// + // TODO mark as disconnected in ISR, also handle dev0 + for ( uint8_t dev_id = 0; dev_id < TU_ARRAY_SIZE(_usbh_devices); dev_id++ ) + { + usbh_device_t* dev = &_usbh_devices[dev_id]; + uint8_t const dev_addr = dev_id+1; + + // TODO Hub multiple level + if (dev->rhport == rhport && + (hub_addr == 0 || dev->hub_addr == hub_addr) && // hub_addr == 0 & hub_port == 0 means roothub + (hub_port == 0 || dev->hub_port == hub_port) && + dev->connected) + { + // Invoke callback before close driver + if (tuh_umount_cb) tuh_umount_cb(dev_addr); + + // 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); + usbh_class_drivers[drv_id].close(dev_addr); + } + + hcd_device_close(rhport, dev_addr); + clear_device(dev); + // abort on-going control xfer if any + if (_ctrl_xfer.xfer.daddr == dev_addr) set_control_xfer_stage(CONTROL_STAGE_IDLE); + } + } +} + +//--------------------------------------------------------------------+ +// INTERNAL HELPER +//--------------------------------------------------------------------+ + +static uint8_t get_new_address(bool is_hub) +{ + uint8_t const start = (is_hub ? CFG_TUH_DEVICE_MAX : 0) + 1; + uint8_t const count = (is_hub ? CFG_TUH_HUB : CFG_TUH_DEVICE_MAX); + + for (uint8_t i=0; i < count; i++) + { + uint8_t const addr = start + i; + if (!get_device(addr)->connected) return addr; + } + return ADDR_INVALID; +} + +void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) +{ + usbh_device_t* dev = get_device(dev_addr); + + for(itf_num++; itf_num < CFG_TUH_INTERFACE_MAX; itf_num++) + { + // continue with next valid interface + // TODO skip IAD binding interface such as CDCs + uint8_t const drv_id = dev->itf2drv[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); + driver->set_config(dev_addr, itf_num); + break; + } + } + + // all interface are configured + if (itf_num == CFG_TUH_INTERFACE_MAX) + { + // Invoke callback if available + if (tuh_mount_cb) tuh_mount_cb(dev_addr); + } +} + //--------------------------------------------------------------------+ // Enumeration Process // is a lengthy process with a series of control transfer to configure @@ -886,43 +1002,16 @@ static bool enum_set_config_complete (uint8_t dev_addr, tusb_control_ static bool parse_configuration_descriptor (uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg); #if CFG_TUH_HUB -static bool enum_hub_clear_reset0_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - (void) dev_addr; (void) request; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - enum_request_addr0_device_desc(); - return true; -} -static bool enum_hub_clear_reset1_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - (void) dev_addr; (void) request; - TU_ASSERT(XFER_RESULT_SUCCESS == result); +// Enum sequence: +// New device (reset on the way) -> Get Status 0 -> Clear Reset 0 -> Get 8byte Device Descriptor +// -> Port Reset 1 -> reset delay -> Get Status 1 -> Clear Reset 1 -> queue hub interrupt endpoint - enum_request_set_addr(); - - // done with hub, waiting for next data on status pipe - (void) hub_status_pipe_queue( _dev0.hub_addr ); - - return true; -} - -static bool enum_hub_get_status1_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - (void) dev_addr; (void) request; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - hub_port_status_response_t port_status; - memcpy(&port_status, _usbh_ctrl_buf, sizeof(hub_port_status_response_t)); - - // Acknowledge Port Reset Change if Reset Successful - if (port_status.change.reset) - { - TU_ASSERT( hub_port_clear_feature(_dev0.hub_addr, _dev0.hub_port, HUB_FEATURE_PORT_RESET_CHANGE, enum_hub_clear_reset1_complete) ); - } - - return true; -} +static bool enum_hub_get_status0_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool enum_hub_clear_reset0_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool enum_hub_set_reset1_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool enum_hub_get_status1_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool enum_hub_clear_reset1_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool enum_hub_get_status0_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { @@ -949,6 +1038,57 @@ static bool enum_hub_get_status0_complete(uint8_t dev_addr, tusb_control_request return true; } + +static bool enum_hub_clear_reset0_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + (void) dev_addr; (void) request; + TU_ASSERT(XFER_RESULT_SUCCESS == result); + enum_request_addr0_device_desc(); + return true; +} + +static bool enum_hub_set_reset1_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + (void) dev_addr; (void) request; + TU_ASSERT(XFER_RESULT_SUCCESS == result); + + osal_task_delay(RESET_DELAY); + + TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, enum_hub_get_status1_complete) ); + + return true; +} + +static bool enum_hub_get_status1_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + (void) dev_addr; (void) request; + TU_ASSERT(XFER_RESULT_SUCCESS == result); + + hub_port_status_response_t port_status; + memcpy(&port_status, _usbh_ctrl_buf, sizeof(hub_port_status_response_t)); + + // Acknowledge Port Reset Change if Reset Successful + if (port_status.change.reset) + { + TU_ASSERT( hub_port_clear_feature(_dev0.hub_addr, _dev0.hub_port, HUB_FEATURE_PORT_RESET_CHANGE, enum_hub_clear_reset1_complete) ); + } + + return true; +} + +static bool enum_hub_clear_reset1_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + (void) dev_addr; (void) request; + TU_ASSERT(XFER_RESULT_SUCCESS == result); + + enum_request_set_addr(); + + // done with hub, waiting for next data on status pipe + (void) hub_status_pipe_queue( _dev0.hub_addr ); + + return true; +} + #endif // hub static bool enum_new_device(hcd_event_t* event) @@ -1030,12 +1170,7 @@ static bool enum_get_addr0_device_desc_complete(uint8_t dev_addr, tusb_control_r else { // after RESET_DELAY the hub_port_reset() already complete - TU_ASSERT( hub_port_reset(_dev0.hub_addr, _dev0.hub_port, NULL) ); - osal_task_delay(RESET_DELAY); - - tuh_task(); // FIXME temporarily to clean up port_reset control transfer - - TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, enum_hub_get_status1_complete) ); + TU_ASSERT( hub_port_reset(_dev0.hub_addr, _dev0.hub_port, enum_hub_set_reset1_complete) ); } #endif // hub diff --git a/src/host/usbh_classdriver.h b/src/host/usbh_classdriver.h index 2f9957cc6..0435eae70 100644 --- a/src/host/usbh_classdriver.h +++ b/src/host/usbh_classdriver.h @@ -73,6 +73,7 @@ bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_ // If caller does not make any transfer, it must release endpoint for others. bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr); +// Release claimed endpoint without submitting a transfer bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr); // Check if endpoint transferring is complete diff --git a/src/host/usbh_control.c b/src/host/usbh_control.c index 88287a47b..38f03a8d2 100644 --- a/src/host/usbh_control.c +++ b/src/host/usbh_control.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if CFG_TUH_ENABLED +#if CFG_TUH_ENABLED && 0 #include "tusb.h" #include "usbh_classdriver.h" @@ -36,86 +36,50 @@ typedef struct tusb_control_request_t request TU_ATTR_ALIGNED(4); uint8_t* buffer; tuh_control_complete_cb_t complete_cb; + + uint8_t daddr; } usbh_control_xfer_t; -static usbh_control_xfer_t _ctrl_xfer; +static usbh_control_xfer_t _xfer; +static uint8_t _stage = CONTROL_STAGE_IDLE; //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ +uint8_t usbh_control_xfer_stage(void) +{ + return _stage; +} + bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb) { // TODO need to claim the endpoint first const uint8_t rhport = usbh_get_rhport(dev_addr); - _ctrl_xfer.request = (*request); - _ctrl_xfer.buffer = buffer; - _ctrl_xfer.complete_cb = complete_cb; + _ctrl_xfer.xfer.daddr = dev_addr; + _ctrl_xfer.xfer.request = (*request); + _ctrl_xfer.xfer.buffer = buffer; + _ctrl_xfer.xfer.complete_cb = complete_cb; + + _stage = CONTROL_STAGE_SETUP; // Send setup packet - TU_ASSERT( hcd_setup_send(rhport, dev_addr, (uint8_t const*) &_ctrl_xfer.request) ); + TU_ASSERT( hcd_setup_send(rhport, dev_addr, (uint8_t const*) &_ctrl_xfer.xfer.request) ); return true; } +void usbh_control_xfer_abort(uint8_t dev_addr) +{ + if (_ctrl_xfer.xfer.daddr == dev_addr) _stage = CONTROL_STAGE_IDLE; +} + static void _xfer_complete(uint8_t dev_addr, xfer_result_t result) { TU_LOG2("\r\n"); - if (_ctrl_xfer.complete_cb) _ctrl_xfer.complete_cb(dev_addr, &_ctrl_xfer.request, result); + if (_ctrl_xfer.xfer.complete_cb) _ctrl_xfer.xfer.complete_cb(dev_addr, &_ctrl_xfer.xfer.request, result); } -bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, uint8_t* stage, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) ep_addr; - (void) xferred_bytes; - - const uint8_t rhport = usbh_get_rhport(dev_addr); - tusb_control_request_t const * request = &_ctrl_xfer.request; - - if (XFER_RESULT_SUCCESS != result) - { - TU_LOG2("[%u:%u] Control %s\r\n", rhport, dev_addr, result == XFER_RESULT_STALLED ? "STALLED" : "FAILED"); - - // terminate transfer if any stage failed - *stage = CONTROL_STAGE_IDLE; - _xfer_complete(dev_addr, result); - }else - { - switch(*stage) - { - case CONTROL_STAGE_SETUP: - *stage = CONTROL_STAGE_DATA; - if (request->wLength) - { - // DATA stage: initial data toggle is always 1 - hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.buffer, request->wLength); - return true; - } - __attribute__((fallthrough)); - - case CONTROL_STAGE_DATA: - *stage = CONTROL_STAGE_ACK; - if (request->wLength) - { - TU_LOG2("[%u:%u] Control data:\r\n", rhport, dev_addr); - TU_LOG2_MEM(_ctrl_xfer.buffer, request->wLength, 2); - } - - // ACK stage: toggle is always 1 - hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, 1-request->bmRequestType_bit.direction), NULL, 0); - break; - - case CONTROL_STAGE_ACK: - *stage = CONTROL_STAGE_IDLE; - _xfer_complete(dev_addr, result); - break; - - default: return false; - } - } - - return true; -} #endif diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index e1dd95c34..4217f0422 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -111,7 +111,7 @@ typedef struct typedef osal_queue_def_t* osal_queue_t; -// role device/host is used by OS NONE for mutex (disable usb isr) only +// _int_set is used as mutex in OS NONE (disable/enable USB ISR) #define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \ uint8_t _name##_buf[_depth*sizeof(_type)]; \ osal_queue_def_t _name = { \ From 66c933fb61ee01ba640f39a9328b4892d16bb225 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 10 Mar 2022 23:16:59 +0700 Subject: [PATCH 40/81] fix enumeration issue when plugging hub with multiple devices attached --- src/host/hub.c | 4 +- src/host/hub.h | 2 +- src/host/usbh.c | 121 ++++++++++++++++++++++++++---------------------- src/host/usbh.h | 3 +- 4 files changed, 70 insertions(+), 60 deletions(-) diff --git a/src/host/hub.c b/src/host/hub.c index 1fec8b892..4c375c290 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -189,7 +189,7 @@ void hub_close(uint8_t dev_addr) if (p_hub->ep_in) tu_memclr(p_hub, sizeof( hub_interface_t)); } -bool hub_status_pipe_queue(uint8_t dev_addr) +bool hub_edpt_status_xfer(uint8_t dev_addr) { hub_interface_t* hub_itf = get_itf(dev_addr); return usbh_edpt_xfer(dev_addr, hub_itf->ep_in, &hub_itf->status_change, 1); @@ -324,7 +324,7 @@ static bool connection_get_status_complete (uint8_t dev_addr, tusb_control_reque // prepare for next hub status // TODO continue with status_change, or maybe we can do it again with status - hub_status_pipe_queue(dev_addr); + hub_edpt_status_xfer(dev_addr); } return true; diff --git a/src/host/hub.h b/src/host/hub.h index c4d544193..6d81f6773 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -176,7 +176,7 @@ bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, t bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, tuh_control_complete_cb_t complete_cb); bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_control_complete_cb_t complete_cb); -bool hub_status_pipe_queue(uint8_t dev_addr); +bool hub_edpt_status_xfer(uint8_t dev_addr); //--------------------------------------------------------------------+ // Internal Class Driver API diff --git a/src/host/usbh.c b/src/host/usbh.c index 3d9db70fa..01675cddd 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -543,7 +543,7 @@ void tuh_task(void) if ( event.connection.hub_addr != 0) { // done with hub, waiting for next data on status pipe - (void) hub_status_pipe_queue( event.connection.hub_addr ); + (void) hub_edpt_status_xfer( event.connection.hub_addr ); } #endif break; @@ -904,6 +904,10 @@ static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result return true; } +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + // a device unplugged from rhport:hub_addr:hub_port static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) { @@ -938,49 +942,6 @@ static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t h } } -//--------------------------------------------------------------------+ -// INTERNAL HELPER -//--------------------------------------------------------------------+ - -static uint8_t get_new_address(bool is_hub) -{ - uint8_t const start = (is_hub ? CFG_TUH_DEVICE_MAX : 0) + 1; - uint8_t const count = (is_hub ? CFG_TUH_HUB : CFG_TUH_DEVICE_MAX); - - for (uint8_t i=0; i < count; i++) - { - uint8_t const addr = start + i; - if (!get_device(addr)->connected) return addr; - } - return ADDR_INVALID; -} - -void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) -{ - usbh_device_t* dev = get_device(dev_addr); - - for(itf_num++; itf_num < CFG_TUH_INTERFACE_MAX; itf_num++) - { - // continue with next valid interface - // TODO skip IAD binding interface such as CDCs - uint8_t const drv_id = dev->itf2drv[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); - driver->set_config(dev_addr, itf_num); - break; - } - } - - // all interface are configured - if (itf_num == CFG_TUH_INTERFACE_MAX) - { - // Invoke callback if available - if (tuh_mount_cb) tuh_mount_cb(dev_addr); - } -} - //--------------------------------------------------------------------+ // Enumeration Process // is a lengthy process with a series of control transfer to configure @@ -991,9 +952,9 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) //--------------------------------------------------------------------+ static bool enum_request_addr0_device_desc(void); -static bool enum_request_set_addr(void); - static bool enum_get_addr0_device_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); + +static bool enum_request_set_addr(void); static bool enum_set_address_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool enum_get_device_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool enum_get_9byte_config_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); @@ -1001,6 +962,9 @@ static bool enum_get_config_desc_complete (uint8_t dev_addr, tusb_control_ static bool enum_set_config_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool parse_configuration_descriptor (uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg); +static uint8_t get_new_address(bool is_hub); +static void enum_full_complete(void); + #if CFG_TUH_HUB // Enum sequence: @@ -1015,7 +979,7 @@ static bool enum_hub_clear_reset1_complete(uint8_t dev_addr, tusb_control_reques static bool enum_hub_get_status0_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { - (void) dev_addr; (void) request; + (void) request; TU_ASSERT(XFER_RESULT_SUCCESS == result); hub_port_status_response_t port_status; @@ -1024,7 +988,8 @@ static bool enum_hub_get_status0_complete(uint8_t dev_addr, tusb_control_request if ( !port_status.status.connection ) { // device unplugged while delaying, nothing else to do, queue hub status - return hub_status_pipe_queue(dev_addr); + enum_full_complete(); + return false; } _dev0.speed = (port_status.status.high_speed) ? TUSB_SPEED_HIGH : @@ -1083,9 +1048,6 @@ static bool enum_hub_clear_reset1_complete(uint8_t dev_addr, tusb_control_reques enum_request_set_addr(); - // done with hub, waiting for next data on status pipe - (void) hub_status_pipe_queue( _dev0.hub_addr ); - return true; } @@ -1144,11 +1106,8 @@ static bool enum_get_addr0_device_desc_complete(uint8_t dev_addr, tusb_control_r if (XFER_RESULT_SUCCESS != result) { -#if CFG_TUH_HUB - // TODO remove, waiting for next data on status pipe - if (_dev0.hub_addr != 0) hub_status_pipe_queue(_dev0.hub_addr); -#endif - + // stop enumeration, maybe we could retry this + enum_full_complete(); return false; } @@ -1407,4 +1366,54 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura return true; } +void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) +{ + usbh_device_t* dev = get_device(dev_addr); + + for(itf_num++; itf_num < CFG_TUH_INTERFACE_MAX; itf_num++) + { + // continue with next valid interface + // TODO skip IAD binding interface such as CDCs + uint8_t const drv_id = dev->itf2drv[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); + driver->set_config(dev_addr, itf_num); + break; + } + } + + // all interface are configured + if (itf_num == CFG_TUH_INTERFACE_MAX) + { + enum_full_complete(); + + // Invoke callback if available + if (tuh_mount_cb) tuh_mount_cb(dev_addr); + } +} + +static void enum_full_complete(void) +{ +#if CFG_TUH_HUB + // get next hub status + if (_dev0.hub_addr) hub_edpt_status_xfer(_dev0.hub_addr); +#endif + +} + +static uint8_t get_new_address(bool is_hub) +{ + uint8_t const start = (is_hub ? CFG_TUH_DEVICE_MAX : 0) + 1; + uint8_t const count = (is_hub ? CFG_TUH_HUB : CFG_TUH_DEVICE_MAX); + + for (uint8_t i=0; i < count; i++) + { + uint8_t const addr = start + i; + if (!get_device(addr)->connected) return addr; + } + return ADDR_INVALID; +} + #endif diff --git a/src/host/usbh.h b/src/host/usbh.h index 31d63d6a7..eec2ed702 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -80,7 +80,8 @@ static inline bool tuh_ready(uint8_t daddr) return tuh_mounted(daddr) && !tuh_suspended(daddr); } -// Carry out control transfer +// Carry out a control transfer +// true on success, false if there is on-going control trasnfer bool tuh_control_xfer (uint8_t daddr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb); // Set Configuration From 951ece17e1e26c297f3c05807271ab1ba56a2ada Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 10 Mar 2022 23:20:12 +0700 Subject: [PATCH 41/81] fix build warning --- src/host/usbh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index 01675cddd..11bf2f997 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -979,7 +979,7 @@ static bool enum_hub_clear_reset1_complete(uint8_t dev_addr, tusb_control_reques static bool enum_hub_get_status0_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { - (void) request; + (void) dev_addr; (void) request; TU_ASSERT(XFER_RESULT_SUCCESS == result); hub_port_status_response_t port_status; From 37960990a5fb0a42a5faa19230f0051efaa4e6c0 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Thu, 10 Mar 2022 11:01:44 -0800 Subject: [PATCH 42/81] Print speed. Don't crash if string get fails --- examples/host/device_info/src/main.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/examples/host/device_info/src/main.c b/examples/host/device_info/src/main.c index 45b616af0..e6149db89 100644 --- a/examples/host/device_info/src/main.c +++ b/examples/host/device_info/src/main.c @@ -90,6 +90,10 @@ static void _wait_and_convert(uint16_t *temp_buf, size_t buf_len) { while (_get_string_result == 0xff) { tuh_task(); } + if (_get_string_result != XFER_RESULT_SUCCESS) { + temp_buf[0] = 0; + return; + } size_t utf16_len = ((temp_buf[0] & 0xff) - 2) / sizeof(uint16_t); size_t utf8_len = _count_utf8_bytes(temp_buf + 1, utf16_len); _convert_utf16le_to_utf8(temp_buf + 1, utf16_len, (uint8_t *) temp_buf, sizeof(uint16_t) * buf_len); @@ -128,6 +132,21 @@ int main(void) tuh_vid_pid_get(i, &vid, &pid); printf("%d vid %04x pid %04x\r\n", i, vid, pid); + tusb_speed_t speed = tuh_speed_get(i); + switch (speed) { + case TUSB_SPEED_FULL: + printf("Full speed\r\n"); + break; + case TUSB_SPEED_LOW: + printf("Low speed\r\n"); + break; + case TUSB_SPEED_HIGH: + printf("High speed\r\n"); + break; + default: + break; + } + _get_string_result = 0xff; uint16_t temp_buf[127]; if (tuh_descriptor_string_serial_get(i, 0, temp_buf, TU_ARRAY_SIZE(temp_buf), _transfer_done_cb)) { From a715077b1079993f4cd01bbf54b8166a6612b29b Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 11 Mar 2022 09:57:35 +0700 Subject: [PATCH 43/81] remove usbh_control.c --- examples/host/bare_api/Makefile | 1 - examples/host/cdc_msc_hid/Makefile | 1 - examples/host/hid_controller/Makefile | 1 - examples/host/hid_to_cdc/Makefile | 3 +- hw/bsp/rp2040/family.cmake | 1 - src/host/usbh_control.c | 85 --------------------------- 6 files changed, 1 insertion(+), 91 deletions(-) delete mode 100644 src/host/usbh_control.c diff --git a/examples/host/bare_api/Makefile b/examples/host/bare_api/Makefile index c59369ffa..13e14df53 100644 --- a/examples/host/bare_api/Makefile +++ b/examples/host/bare_api/Makefile @@ -21,7 +21,6 @@ SRC_C += \ src/class/msc/msc_host.c \ src/host/hub.c \ src/host/usbh.c \ - src/host/usbh_control.c \ src/portable/ohci/ohci.c \ src/portable/nxp/lpc17_40/hcd_lpc17_40.c diff --git a/examples/host/cdc_msc_hid/Makefile b/examples/host/cdc_msc_hid/Makefile index ce0dd1a40..272acbac8 100644 --- a/examples/host/cdc_msc_hid/Makefile +++ b/examples/host/cdc_msc_hid/Makefile @@ -19,7 +19,6 @@ SRC_C += \ src/class/msc/msc_host.c \ src/host/hub.c \ src/host/usbh.c \ - src/host/usbh_control.c \ src/portable/ohci/ohci.c \ src/portable/nxp/lpc17_40/hcd_lpc17_40.c diff --git a/examples/host/hid_controller/Makefile b/examples/host/hid_controller/Makefile index c58df562b..06dc56914 100644 --- a/examples/host/hid_controller/Makefile +++ b/examples/host/hid_controller/Makefile @@ -22,7 +22,6 @@ SRC_C += \ src/class/msc/msc_host.c \ src/host/hub.c \ src/host/usbh.c \ - src/host/usbh_control.c \ src/portable/ohci/ohci.c \ src/portable/nxp/lpc17_40/hcd_lpc17_40.c diff --git a/examples/host/hid_to_cdc/Makefile b/examples/host/hid_to_cdc/Makefile index b62a383eb..3fe9b0888 100644 --- a/examples/host/hid_to_cdc/Makefile +++ b/examples/host/hid_to_cdc/Makefile @@ -14,7 +14,6 @@ CFLAGS += -Wno-error=cast-align -Wno-error=null-dereference SRC_C += \ src/class/hid/hid_host.c \ src/host/hub.c \ - src/host/usbh.c \ - src/host/usbh_control.c + src/host/usbh.c include ../../rules.mk diff --git a/hw/bsp/rp2040/family.cmake b/hw/bsp/rp2040/family.cmake index 1aa180ef8..e832c0756 100644 --- a/hw/bsp/rp2040/family.cmake +++ b/hw/bsp/rp2040/family.cmake @@ -83,7 +83,6 @@ if (NOT TARGET _rp2040_family_inclusion_marker) ${TOP}/src/portable/raspberrypi/rp2040/hcd_rp2040.c ${TOP}/src/portable/raspberrypi/rp2040/rp2040_usb.c ${TOP}/src/host/usbh.c - ${TOP}/src/host/usbh_control.c ${TOP}/src/host/hub.c ${TOP}/src/class/cdc/cdc_host.c ${TOP}/src/class/hid/hid_host.c diff --git a/src/host/usbh_control.c b/src/host/usbh_control.c deleted file mode 100644 index 38f03a8d2..000000000 --- a/src/host/usbh_control.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if CFG_TUH_ENABLED && 0 - -#include "tusb.h" -#include "usbh_classdriver.h" - -typedef struct -{ - tusb_control_request_t request TU_ATTR_ALIGNED(4); - uint8_t* buffer; - tuh_control_complete_cb_t complete_cb; - - uint8_t daddr; -} usbh_control_xfer_t; - -static usbh_control_xfer_t _xfer; -static uint8_t _stage = CONTROL_STAGE_IDLE; - -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM DECLARATION -//--------------------------------------------------------------------+ - -uint8_t usbh_control_xfer_stage(void) -{ - return _stage; -} - -bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb) -{ - // TODO need to claim the endpoint first - const uint8_t rhport = usbh_get_rhport(dev_addr); - - _ctrl_xfer.xfer.daddr = dev_addr; - _ctrl_xfer.xfer.request = (*request); - _ctrl_xfer.xfer.buffer = buffer; - _ctrl_xfer.xfer.complete_cb = complete_cb; - - _stage = CONTROL_STAGE_SETUP; - - // Send setup packet - TU_ASSERT( hcd_setup_send(rhport, dev_addr, (uint8_t const*) &_ctrl_xfer.xfer.request) ); - - return true; -} - -void usbh_control_xfer_abort(uint8_t dev_addr) -{ - if (_ctrl_xfer.xfer.daddr == dev_addr) _stage = CONTROL_STAGE_IDLE; -} - -static void _xfer_complete(uint8_t dev_addr, xfer_result_t result) -{ - TU_LOG2("\r\n"); - if (_ctrl_xfer.xfer.complete_cb) _ctrl_xfer.xfer.complete_cb(dev_addr, &_ctrl_xfer.xfer.request, result); -} - - -#endif From 6b5490ced687ba44ede9a0dd1dd62b4b67eedf59 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 11 Mar 2022 13:12:36 +0700 Subject: [PATCH 44/81] merge device_info into bare_api example --- examples/host/bare_api/src/main.c | 123 +++++++++++-- examples/host/device_info/CMakeLists.txt | 27 --- examples/host/device_info/Makefile | 28 --- examples/host/device_info/only.txt | 9 - examples/host/device_info/src/main.c | 194 -------------------- examples/host/device_info/src/tusb_config.h | 96 ---------- src/host/usbh.c | 4 +- 7 files changed, 107 insertions(+), 374 deletions(-) delete mode 100644 examples/host/device_info/CMakeLists.txt delete mode 100644 examples/host/device_info/Makefile delete mode 100644 examples/host/device_info/only.txt delete mode 100644 examples/host/device_info/src/main.c delete mode 100644 examples/host/device_info/src/tusb_config.h diff --git a/examples/host/bare_api/src/main.c b/examples/host/bare_api/src/main.c index 5f8f886c8..73e97c390 100644 --- a/examples/host/bare_api/src/main.c +++ b/examples/host/bare_api/src/main.c @@ -46,8 +46,6 @@ int main(void) board_init(); printf("TinyUSB Host HID Controller Example\r\n"); - printf("Note: Events only displayed for explictly supported controllers\r\n"); - tusb_init(); while (1) @@ -64,10 +62,74 @@ int main(void) // TinyUSB Callbacks //--------------------------------------------------------------------+ -uint8_t usb_buf[256] TU_ATTR_ALIGNED(4); +// English +#define LANGUAGE_ID 0x0409 +//uint8_t usb_buf[256] TU_ATTR_ALIGNED(4); tusb_desc_device_t desc_device; +static volatile xfer_result_t _get_string_result; + +static bool _transfer_done_cb(uint8_t daddr, tusb_control_request_t const *request, xfer_result_t result) { + (void)daddr; + (void)request; + _get_string_result = result; + return true; +} + +static void _convert_utf16le_to_utf8(const uint16_t *utf16, size_t utf16_len, uint8_t *utf8, size_t utf8_len) { + // TODO: Check for runover. + (void)utf8_len; + // Get the UTF-16 length out of the data itself. + + for (size_t i = 0; i < utf16_len; i++) { + uint16_t chr = utf16[i]; + if (chr < 0x80) { + *utf8++ = chr & 0xff; + } else if (chr < 0x800) { + *utf8++ = (uint8_t)(0xC0 | (chr >> 6 & 0x1F)); + *utf8++ = (uint8_t)(0x80 | (chr >> 0 & 0x3F)); + } else { + // TODO: Verify surrogate. + *utf8++ = (uint8_t)(0xE0 | (chr >> 12 & 0x0F)); + *utf8++ = (uint8_t)(0x80 | (chr >> 6 & 0x3F)); + *utf8++ = (uint8_t)(0x80 | (chr >> 0 & 0x3F)); + } + // TODO: Handle UTF-16 code points that take two entries. + } +} + +// Count how many bytes a utf-16-le encoded string will take in utf-8. +static int _count_utf8_bytes(const uint16_t *buf, size_t len) { + size_t total_bytes = 0; + for (size_t i = 0; i < len; i++) { + uint16_t chr = buf[i]; + if (chr < 0x80) { + total_bytes += 1; + } else if (chr < 0x800) { + total_bytes += 2; + } else { + total_bytes += 3; + } + // TODO: Handle UTF-16 code points that take two entries. + } + return total_bytes; +} + +static void _wait_and_convert(uint16_t *temp_buf, size_t buf_len) { + while (_get_string_result == 0xff) { + tuh_task(); + } + if (_get_string_result != XFER_RESULT_SUCCESS) { + temp_buf[0] = 0; + return; + } + size_t utf16_len = ((temp_buf[0] & 0xff) - 2) / sizeof(uint16_t); + size_t utf8_len = _count_utf8_bytes(temp_buf + 1, utf16_len); + _convert_utf16le_to_utf8(temp_buf + 1, utf16_len, (uint8_t *) temp_buf, sizeof(uint16_t) * buf_len); + ((uint8_t*) temp_buf)[utf8_len] = '\0'; +} + bool print_device_descriptor(uint8_t daddr, tusb_control_request_t const * request, xfer_result_t result) { (void) request; @@ -78,26 +140,49 @@ bool print_device_descriptor(uint8_t daddr, tusb_control_request_t const * reque return false; } - printf("Rhport %u Device %u: ID %04x:%04x\r\n", 0, daddr, desc_device.idVendor, desc_device.idProduct); + printf("Device %u: ID %04x:%04x\r\n", daddr, desc_device.idVendor, desc_device.idProduct); printf("Device Descriptor:\r\n"); - printf(" bLength %u\r\n", desc_device.bLength); - printf(" bDescriptorType %u\r\n", desc_device.bDescriptorType); - printf(" bcdUSB %04x\r\n", desc_device.bcdUSB); + printf(" bLength %u\r\n" , desc_device.bLength); + printf(" bDescriptorType %u\r\n" , desc_device.bDescriptorType); + printf(" bcdUSB %04x\r\n" , desc_device.bcdUSB); + printf(" bDeviceClass %u\r\n" , desc_device.bDeviceClass); + printf(" bDeviceSubClass %u\r\n" , desc_device.bDeviceSubClass); + printf(" bDeviceProtocol %u\r\n" , desc_device.bDeviceProtocol); + printf(" bMaxPacketSize0 %u\r\n" , desc_device.bMaxPacketSize0); + printf(" idVendor 0x%04x\r\n" , desc_device.idVendor); + printf(" idProduct 0x%04x\r\n" , desc_device.idProduct); + printf(" bcdDevice %04x\r\n" , desc_device.bcdDevice); - printf(" bDeviceClass %u\r\n", desc_device.bDeviceClass); - printf(" bDeviceSubClass %u\r\n", desc_device.bDeviceSubClass); - printf(" bDeviceProtocol %u\r\n", desc_device.bDeviceProtocol); - printf(" bMaxPacketSize0 %u\r\n", desc_device.bMaxPacketSize0); + _get_string_result = 0xff; + uint16_t temp_buf[128]; - printf(" idVendor 0x%04x\r\n", desc_device.idVendor); - printf(" idProduct 0x%04x\r\n", desc_device.idProduct); - printf(" bcdDevice %04x\r\n", desc_device.bcdDevice); + printf(" iManufacturer %u " , desc_device.iManufacturer); + temp_buf[0] = 0; + if (tuh_descriptor_get_manufacturer_string(daddr, LANGUAGE_ID, temp_buf, TU_ARRAY_SIZE(temp_buf), _transfer_done_cb)) { + _wait_and_convert(temp_buf, TU_ARRAY_SIZE(temp_buf)); + printf((const char*) temp_buf); + } + printf("\r\n"); - printf(" iManufacturer %u\r\n", desc_device.iManufacturer); - printf(" iProduct %u\r\n", desc_device.iProduct); - printf(" iSerialNumber %u\r\n", desc_device.iSerialNumber); + printf(" iProduct %u " , desc_device.iProduct); + _get_string_result = 0xff; + temp_buf[0] = 0; + if (tuh_descriptor_get_product_string(daddr, LANGUAGE_ID, temp_buf, TU_ARRAY_SIZE(temp_buf), _transfer_done_cb)) { + _wait_and_convert(temp_buf, TU_ARRAY_SIZE(temp_buf)); + printf((const char*) temp_buf); + } + printf("\r\n"); - printf(" bNumConfigurations %u\r\n", desc_device.bNumConfigurations); + printf(" iSerialNumber %u " , desc_device.iSerialNumber); + _get_string_result = 0xff; + temp_buf[0] = 0; + if (tuh_descriptor_get_serial_string(daddr, LANGUAGE_ID, temp_buf, TU_ARRAY_SIZE(temp_buf), _transfer_done_cb)) { + _wait_and_convert(temp_buf, TU_ARRAY_SIZE(temp_buf)); + printf((const char*) temp_buf); + } + printf("\r\n"); + + printf(" bNumConfigurations %u\r\n" , desc_device.bNumConfigurations); return true; } @@ -107,7 +192,7 @@ void tuh_mount_cb (uint8_t daddr) { printf("Device attached, address = %d\r\n", daddr); - // get device descriptor + // Get Device Descriptor tuh_descriptor_get_device(daddr, &desc_device, 18, print_device_descriptor); } diff --git a/examples/host/device_info/CMakeLists.txt b/examples/host/device_info/CMakeLists.txt deleted file mode 100644 index bff281a8c..000000000 --- a/examples/host/device_info/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -cmake_minimum_required(VERSION 3.5) - -include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) - -# gets PROJECT name for the example -family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR}) - -project(${PROJECT}) - -# Checks this example is valid for the family and initializes the project -family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) - -add_executable(${PROJECT}) - -# Example source -target_sources(${PROJECT} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c - ) - -# Example include -target_include_directories(${PROJECT} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src - ) - -# Configure compilation flags and libraries for the example... see the corresponding function -# in hw/bsp/FAMILY/family.cmake for details. -family_configure_host_example(${PROJECT}) \ No newline at end of file diff --git a/examples/host/device_info/Makefile b/examples/host/device_info/Makefile deleted file mode 100644 index c59369ffa..000000000 --- a/examples/host/device_info/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -include ../../../tools/top.mk -include ../../make.mk - -INC += \ - src \ - $(TOP)/hw \ - -# Example source -EXAMPLE_SOURCE += \ - src/main.c - -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) - -# TODO: suppress warning caused by host stack -CFLAGS += -Wno-error=cast-align -Wno-error=null-dereference - -# TinyUSB Host Stack source -SRC_C += \ - src/class/cdc/cdc_host.c \ - src/class/hid/hid_host.c \ - src/class/msc/msc_host.c \ - src/host/hub.c \ - src/host/usbh.c \ - src/host/usbh_control.c \ - src/portable/ohci/ohci.c \ - src/portable/nxp/lpc17_40/hcd_lpc17_40.c - -include ../../rules.mk diff --git a/examples/host/device_info/only.txt b/examples/host/device_info/only.txt deleted file mode 100644 index 7fe4e3f5c..000000000 --- a/examples/host/device_info/only.txt +++ /dev/null @@ -1,9 +0,0 @@ -mcu:LPC175X_6X -mcu:LPC177X_8X -mcu:LPC18XX -mcu:LPC40XX -mcu:LPC43XX -mcu:MIMXRT10XX -mcu:RP2040 -mcu:MSP432E4 -mcu:RX65X diff --git a/examples/host/device_info/src/main.c b/examples/host/device_info/src/main.c deleted file mode 100644 index e6149db89..000000000 --- a/examples/host/device_info/src/main.c +++ /dev/null @@ -1,194 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2022 Scott Shawcroft for Adafruit Industries - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - */ - -/* This example prints out info about the enumerated devices. */ - - -#include -#include -#include - -#include "bsp/board.h" -#include "tusb.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF PROTYPES -//--------------------------------------------------------------------+ -void led_blinking_task(void); - -static xfer_result_t _get_string_result; - -static bool _transfer_done_cb(uint8_t daddr, tusb_control_request_t const *request, xfer_result_t result) { - (void)daddr; - (void)request; - _get_string_result = result; - return true; -} - -static void _convert_utf16le_to_utf8(const uint16_t *utf16, size_t utf16_len, uint8_t *utf8, size_t utf8_len) { - // TODO: Check for runover. - (void)utf8_len; - // Get the UTF-16 length out of the data itself. - - for (size_t i = 0; i < utf16_len; i++) { - uint16_t chr = utf16[i]; - if (chr < 0x80) { - *utf8++ = chr & 0xff; - } else if (chr < 0x800) { - *utf8++ = (uint8_t)(0xC0 | (chr >> 6 & 0x1F)); - *utf8++ = (uint8_t)(0x80 | (chr >> 0 & 0x3F)); - } else { - // TODO: Verify surrogate. - *utf8++ = (uint8_t)(0xE0 | (chr >> 12 & 0x0F)); - *utf8++ = (uint8_t)(0x80 | (chr >> 6 & 0x3F)); - *utf8++ = (uint8_t)(0x80 | (chr >> 0 & 0x3F)); - } - // TODO: Handle UTF-16 code points that take two entries. - } -} - -// Count how many bytes a utf-16-le encoded string will take in utf-8. -static int _count_utf8_bytes(const uint16_t *buf, size_t len) { - size_t total_bytes = 0; - for (size_t i = 0; i < len; i++) { - uint16_t chr = buf[i]; - if (chr < 0x80) { - total_bytes += 1; - } else if (chr < 0x800) { - total_bytes += 2; - } else { - total_bytes += 3; - } - // TODO: Handle UTF-16 code points that take two entries. - } - return total_bytes; -} - -static void _wait_and_convert(uint16_t *temp_buf, size_t buf_len) { - while (_get_string_result == 0xff) { - tuh_task(); - } - if (_get_string_result != XFER_RESULT_SUCCESS) { - temp_buf[0] = 0; - return; - } - size_t utf16_len = ((temp_buf[0] & 0xff) - 2) / sizeof(uint16_t); - size_t utf8_len = _count_utf8_bytes(temp_buf + 1, utf16_len); - _convert_utf16le_to_utf8(temp_buf + 1, utf16_len, (uint8_t *) temp_buf, sizeof(uint16_t) * buf_len); - ((uint8_t*) temp_buf)[utf8_len] = '\0'; -} - -/*------------- MAIN -------------*/ -int main(void) -{ - board_init(); - - printf("TinyUSB Host Device Info Example\r\n"); - - tusb_init(); - - uint32_t interval_ms = 5000; - uint32_t start_time = 0; - - while (1) - { - // tinyusb host task - tuh_task(); - led_blinking_task(); - - if (board_millis() - start_time < interval_ms) { - continue; - } - start_time = board_millis(); - // Brute force check every device address to see if it is active. - for (int i = 1; i < CFG_TUH_DEVICE_MAX + CFG_TUH_HUB + 1; i++) { - if (!tuh_ready(i)) { - continue; - } - uint16_t vid; - uint16_t pid; - tuh_vid_pid_get(i, &vid, &pid); - printf("%d vid %04x pid %04x\r\n", i, vid, pid); - - tusb_speed_t speed = tuh_speed_get(i); - switch (speed) { - case TUSB_SPEED_FULL: - printf("Full speed\r\n"); - break; - case TUSB_SPEED_LOW: - printf("Low speed\r\n"); - break; - case TUSB_SPEED_HIGH: - printf("High speed\r\n"); - break; - default: - break; - } - - _get_string_result = 0xff; - uint16_t temp_buf[127]; - if (tuh_descriptor_string_serial_get(i, 0, temp_buf, TU_ARRAY_SIZE(temp_buf), _transfer_done_cb)) { - _wait_and_convert(temp_buf, TU_ARRAY_SIZE(temp_buf)); - printf("Serial: %s\r\n", (const char*) temp_buf); - } - - _get_string_result = 0xff; - temp_buf[0] = 0; - if (tuh_descriptor_string_product_get(i, 0, temp_buf, TU_ARRAY_SIZE(temp_buf), _transfer_done_cb)) { - _wait_and_convert(temp_buf, TU_ARRAY_SIZE(temp_buf)); - printf("Product: %s\r\n", (const char*) temp_buf); - } - - _get_string_result = 0xff; - temp_buf[0] = 0; - if (tuh_descriptor_string_manufacturer_get(i, 0, temp_buf, TU_ARRAY_SIZE(temp_buf), _transfer_done_cb)) { - _wait_and_convert(temp_buf, TU_ARRAY_SIZE(temp_buf)); - printf("Manufacturer: %s\r\n", (const char*) temp_buf); - } - } - printf("\n"); - } - - return 0; -} - - -//--------------------------------------------------------------------+ -// Blinking Task -//--------------------------------------------------------------------+ -void led_blinking_task(void) -{ - const uint32_t interval_ms = 1000; - static uint32_t start_ms = 0; - - static bool led_state = false; - - // Blink every interval ms - if ( board_millis() - start_ms < interval_ms) return; // not enough time - start_ms += interval_ms; - - board_led_write(led_state); - led_state = 1 - led_state; // toggle -} diff --git a/examples/host/device_info/src/tusb_config.h b/examples/host/device_info/src/tusb_config.h deleted file mode 100644 index 6b413e46f..000000000 --- a/examples/host/device_info/src/tusb_config.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - */ - -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -//-------------------------------------------------------------------- -// COMMON CONFIGURATION -//-------------------------------------------------------------------- - -// defined by compiler flags for flexibility -#ifndef CFG_TUSB_MCU - #error CFG_TUSB_MCU must be defined -#endif - -#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX - #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_HOST | OPT_MODE_HIGH_SPEED) -#else - #define CFG_TUSB_RHPORT0_MODE OPT_MODE_HOST -#endif - -#ifndef CFG_TUSB_OS -#define CFG_TUSB_OS OPT_OS_NONE -#endif - -// CFG_TUSB_DEBUG is defined by compiler in DEBUG build -// #define CFG_TUSB_DEBUG 0 - -/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. - * Tinyusb use follows macros to declare transferring memory so that they can be put - * into those specific section. - * e.g - * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) - * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) - */ -#ifndef CFG_TUSB_MEM_SECTION -#define CFG_TUSB_MEM_SECTION -#endif - -#ifndef CFG_TUSB_MEM_ALIGN -#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) -#endif - -//-------------------------------------------------------------------- -// CONFIGURATION -//-------------------------------------------------------------------- - -// Size of buffer to hold descriptors and other data used for enumeration -#define CFG_TUH_ENUMERATION_BUFSIZE 256 - -// only hub class is enabled -#define CFG_TUH_HUB 1 - -// max device support (excluding hub device) -// 1 hub typically has 4 ports -#define CFG_TUH_DEVICE_MAX (CFG_TUH_HUB ? 4 : 1) - -#define CFG_TUH_ENDPOINT_MAX 8 - -#define CFG_TUH_TASK_QUEUE_SZ 64 - -//------------- HID -------------// - -#define CFG_TUH_HID_EP_BUFSIZE 64 - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_CONFIG_H_ */ diff --git a/src/host/usbh.c b/src/host/usbh.c index 11bf2f997..617aff79a 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -535,7 +535,7 @@ void tuh_task(void) break; case HCD_EVENT_DEVICE_REMOVE: - TU_LOG2("USBH DEVICE REMOVED\r\n"); + TU_LOG2("[%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 @@ -924,6 +924,8 @@ static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t h (hub_port == 0 || dev->hub_port == hub_port) && dev->connected) { + TU_LOG2(" Address = %u\r\n", dev_addr); + // Invoke callback before close driver if (tuh_umount_cb) tuh_umount_cb(dev_addr); From bcdeb386cc4d3afb3d7213c961e4611e511c4e97 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 11 Mar 2022 21:57:55 +0700 Subject: [PATCH 45/81] rework usbh control xfer - change API of tuh_control_xfer and its callback - rename tuh_control_complete_cb_t to tuh_control_xfer_cb_t - add user argument to control callback - migrate usbh and hub --- examples/host/bare_api/src/main.c | 16 +- src/class/cdc/cdc_host.c | 2 +- src/class/cdc/cdc_host.h | 6 +- src/host/hub.c | 148 +++++++++------ src/host/hub.h | 8 +- src/host/usbh.c | 292 +++++++++++++++++------------- src/host/usbh.h | 70 ++++--- 7 files changed, 315 insertions(+), 227 deletions(-) diff --git a/examples/host/bare_api/src/main.c b/examples/host/bare_api/src/main.c index 73e97c390..6888d13a2 100644 --- a/examples/host/bare_api/src/main.c +++ b/examples/host/bare_api/src/main.c @@ -70,9 +70,9 @@ tusb_desc_device_t desc_device; static volatile xfer_result_t _get_string_result; -static bool _transfer_done_cb(uint8_t daddr, tusb_control_request_t const *request, xfer_result_t result) { +static bool _transfer_done_cb(uint8_t daddr, tuh_control_xfer_t const *xfer, xfer_result_t result) { (void)daddr; - (void)request; + (void)xfer; _get_string_result = result; return true; } @@ -130,9 +130,9 @@ static void _wait_and_convert(uint16_t *temp_buf, size_t buf_len) { ((uint8_t*) temp_buf)[utf8_len] = '\0'; } -bool print_device_descriptor(uint8_t daddr, tusb_control_request_t const * request, xfer_result_t result) +bool print_device_descriptor(uint8_t daddr, tuh_control_xfer_t const * xfer, xfer_result_t result) { - (void) request; + (void) xfer; if ( XFER_RESULT_SUCCESS != result ) { @@ -158,7 +158,7 @@ bool print_device_descriptor(uint8_t daddr, tusb_control_request_t const * reque printf(" iManufacturer %u " , desc_device.iManufacturer); temp_buf[0] = 0; - if (tuh_descriptor_get_manufacturer_string(daddr, LANGUAGE_ID, temp_buf, TU_ARRAY_SIZE(temp_buf), _transfer_done_cb)) { + if (tuh_descriptor_get_manufacturer_string(daddr, LANGUAGE_ID, temp_buf, TU_ARRAY_SIZE(temp_buf), _transfer_done_cb, 0)) { _wait_and_convert(temp_buf, TU_ARRAY_SIZE(temp_buf)); printf((const char*) temp_buf); } @@ -167,7 +167,7 @@ bool print_device_descriptor(uint8_t daddr, tusb_control_request_t const * reque printf(" iProduct %u " , desc_device.iProduct); _get_string_result = 0xff; temp_buf[0] = 0; - if (tuh_descriptor_get_product_string(daddr, LANGUAGE_ID, temp_buf, TU_ARRAY_SIZE(temp_buf), _transfer_done_cb)) { + if (tuh_descriptor_get_product_string(daddr, LANGUAGE_ID, temp_buf, TU_ARRAY_SIZE(temp_buf), _transfer_done_cb, 0)) { _wait_and_convert(temp_buf, TU_ARRAY_SIZE(temp_buf)); printf((const char*) temp_buf); } @@ -176,7 +176,7 @@ bool print_device_descriptor(uint8_t daddr, tusb_control_request_t const * reque printf(" iSerialNumber %u " , desc_device.iSerialNumber); _get_string_result = 0xff; temp_buf[0] = 0; - if (tuh_descriptor_get_serial_string(daddr, LANGUAGE_ID, temp_buf, TU_ARRAY_SIZE(temp_buf), _transfer_done_cb)) { + if (tuh_descriptor_get_serial_string(daddr, LANGUAGE_ID, temp_buf, TU_ARRAY_SIZE(temp_buf), _transfer_done_cb, 0)) { _wait_and_convert(temp_buf, TU_ARRAY_SIZE(temp_buf)); printf((const char*) temp_buf); } @@ -193,7 +193,7 @@ void tuh_mount_cb (uint8_t daddr) printf("Device attached, address = %d\r\n", daddr); // Get Device Descriptor - tuh_descriptor_get_device(daddr, &desc_device, 18, print_device_descriptor); + tuh_descriptor_get_device(daddr, &desc_device, 18, print_device_descriptor, 0); } /// Invoked when device is unmounted (bus reset/unplugged) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 2787cd201..6a29f3f43 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -120,7 +120,7 @@ bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is return usbh_edpt_xfer(dev_addr, ep_in, p_buffer, length); } -bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_control_complete_cb_t complete_cb) +bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_control_xfer_cb_t complete_cb) { cdch_data_t const * p_cdc = get_itf(dev_addr); tusb_control_request_t const request = diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index 0d435138b..67162a0ca 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -42,14 +42,14 @@ * \defgroup CDC_Serial_Host Host * @{ */ -bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_control_complete_cb_t complete_cb); +bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_control_xfer_cb_t complete_cb); -static inline bool tuh_cdc_connect(uint8_t dev_addr, tuh_control_complete_cb_t complete_cb) +static inline bool tuh_cdc_connect(uint8_t dev_addr, tuh_control_xfer_cb_t complete_cb) { return tuh_cdc_set_control_line_state(dev_addr, true, true, complete_cb); } -static inline bool tuh_cdc_disconnect(uint8_t dev_addr, tuh_control_complete_cb_t complete_cb) +static inline bool tuh_cdc_disconnect(uint8_t dev_addr, tuh_control_xfer_cb_t complete_cb) { return tuh_cdc_set_control_line_state(dev_addr, false, false, complete_cb); } diff --git a/src/host/hub.c b/src/host/hub.c index 4c375c290..a0cf7b7e5 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -77,71 +77,92 @@ static char const* const _hub_feature_str[] = //--------------------------------------------------------------------+ // HUB //--------------------------------------------------------------------+ -bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_complete_cb_t complete_cb) +bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_xfer_cb_t complete_cb) { - tusb_control_request_t const request = + tuh_control_xfer_t const xfer = { - .bmRequestType_bit = + .request = { - .recipient = TUSB_REQ_RCPT_OTHER, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_OTHER, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HUB_REQUEST_CLEAR_FEATURE, + .wValue = feature, + .wIndex = hub_port, + .wLength = 0 }, - .bRequest = HUB_REQUEST_CLEAR_FEATURE, - .wValue = feature, - .wIndex = hub_port, - .wLength = 0 + + .buffer = NULL, + .complete_cb = complete_cb, + .user_arg = 0 }; TU_LOG2("HUB Clear Feature: %s, addr = %u port = %u\r\n", _hub_feature_str[feature], hub_addr, hub_port); - TU_ASSERT( tuh_control_xfer(hub_addr, &request, NULL, complete_cb) ); + TU_ASSERT( tuh_control_xfer(hub_addr, &xfer) ); return true; } -bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_complete_cb_t complete_cb) +bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_xfer_cb_t complete_cb) { - tusb_control_request_t const request = + tuh_control_xfer_t const xfer = { - .bmRequestType_bit = + .request = { - .recipient = TUSB_REQ_RCPT_OTHER, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_OTHER, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HUB_REQUEST_SET_FEATURE, + .wValue = feature, + .wIndex = hub_port, + .wLength = 0 }, - .bRequest = HUB_REQUEST_SET_FEATURE, - .wValue = feature, - .wIndex = hub_port, - .wLength = 0 + + .buffer = NULL, + .complete_cb = complete_cb, + .user_arg = 0 }; TU_LOG2("HUB Set Feature: %s, addr = %u port = %u\r\n", _hub_feature_str[feature], hub_addr, hub_port); - TU_ASSERT( tuh_control_xfer(hub_addr, &request, NULL, complete_cb) ); + TU_ASSERT( tuh_control_xfer(hub_addr, &xfer) ); return true; } -bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, tuh_control_complete_cb_t complete_cb) +bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, tuh_control_xfer_cb_t complete_cb) { return hub_port_set_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET, complete_cb); } -bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_control_complete_cb_t complete_cb) +bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_control_xfer_cb_t complete_cb) { - tusb_control_request_t const request = + tuh_control_xfer_t const xfer = { - .bmRequestType_bit = + .request = { - .recipient = TUSB_REQ_RCPT_OTHER, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_IN + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_OTHER, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_IN + }, + .bRequest = HUB_REQUEST_GET_STATUS, + .wValue = 0, + .wIndex = hub_port, + .wLength = 4 }, - .bRequest = HUB_REQUEST_GET_STATUS, - .wValue = 0, - .wIndex = hub_port, - .wLength = 4 + + .buffer = resp, + .complete_cb = complete_cb, + .user_arg = 0 }; TU_LOG2("HUB Get Port Status: addr = %u port = %u\r\n", hub_addr, hub_port); - TU_ASSERT( tuh_control_xfer( hub_addr, &request, resp, complete_cb) ); + TU_ASSERT( tuh_control_xfer( hub_addr, &xfer) ); return true; } @@ -200,8 +221,8 @@ bool hub_edpt_status_xfer(uint8_t dev_addr) // Set Configure //--------------------------------------------------------------------+ -static bool config_set_port_power (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool config_port_power_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool config_set_port_power (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); +static bool config_port_power_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) { @@ -209,28 +230,35 @@ bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) TU_ASSERT(itf_num == p_hub->itf_num); // Get Hub Descriptor - tusb_control_request_t const request = + tuh_control_xfer_t const xfer = { - .bmRequestType_bit = + .request = { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_IN + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_IN + }, + .bRequest = HUB_REQUEST_GET_DESCRIPTOR, + .wValue = 0, + .wIndex = 0, + .wLength = sizeof(descriptor_hub_desc_t) }, - .bRequest = HUB_REQUEST_GET_DESCRIPTOR, - .wValue = 0, - .wIndex = 0, - .wLength = sizeof(descriptor_hub_desc_t) + + .buffer = _hub_buffer, + .complete_cb = config_set_port_power, + .user_arg = 0 }; - TU_ASSERT( tuh_control_xfer(dev_addr, &request, _hub_buffer, config_set_port_power) ); + TU_ASSERT( tuh_control_xfer(dev_addr, &xfer) ); return true; } -static bool config_set_port_power (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool config_set_port_power (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) { - (void) request; + (void) xfer; TU_ASSERT(XFER_RESULT_SUCCESS == result); hub_interface_t* p_hub = get_itf(dev_addr); @@ -246,12 +274,12 @@ static bool config_set_port_power (uint8_t dev_addr, tusb_control_request_t cons return hub_port_set_feature(dev_addr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete); } -static bool config_port_power_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool config_port_power_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) { TU_ASSERT(XFER_RESULT_SUCCESS == result); hub_interface_t* p_hub = get_itf(dev_addr); - if (request->wIndex == p_hub->port_count) + if (xfer->request.wIndex == p_hub->port_count) { // All ports are power -> queue notification status endpoint and // complete the SET CONFIGURATION @@ -261,7 +289,7 @@ static bool config_port_power_complete (uint8_t dev_addr, tusb_control_request_t }else { // power next port - uint8_t const hub_port = (uint8_t) (request->wIndex + 1); + uint8_t const hub_port = (uint8_t) (xfer->request.wIndex + 1); return hub_port_set_feature(dev_addr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete); } @@ -272,9 +300,9 @@ static bool config_port_power_complete (uint8_t dev_addr, tusb_control_request_t // Connection Changes //--------------------------------------------------------------------+ -static bool connection_get_status_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool connection_clear_conn_change_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool connection_port_reset_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool connection_get_status_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); +static bool connection_clear_conn_change_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); +static bool connection_port_reset_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); // callback as response of interrupt endpoint polling bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) @@ -302,12 +330,12 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32 return true; } -static bool connection_get_status_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool connection_get_status_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) { TU_ASSERT(result == XFER_RESULT_SUCCESS); hub_interface_t* p_hub = get_itf(dev_addr); - uint8_t const port_num = (uint8_t) request->wIndex; + uint8_t const port_num = (uint8_t) xfer->request.wIndex; // Connection change if (p_hub->port_status.change.connection) @@ -330,12 +358,12 @@ static bool connection_get_status_complete (uint8_t dev_addr, tusb_control_reque return true; } -static bool connection_clear_conn_change_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool connection_clear_conn_change_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) { TU_ASSERT(result == XFER_RESULT_SUCCESS); hub_interface_t* p_hub = get_itf(dev_addr); - uint8_t const port_num = (uint8_t) request->wIndex; + uint8_t const port_num = (uint8_t) xfer->request.wIndex; if ( p_hub->port_status.status.connection ) { @@ -361,12 +389,12 @@ static bool connection_clear_conn_change_complete (uint8_t dev_addr, tusb_contro return true; } -static bool connection_port_reset_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool connection_port_reset_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) { TU_ASSERT(result == XFER_RESULT_SUCCESS); // hub_interface_t* p_hub = get_itf(dev_addr); - uint8_t const port_num = (uint8_t) request->wIndex; + uint8_t const port_num = (uint8_t) xfer->request.wIndex; // submit attach event hcd_event_t event = diff --git a/src/host/hub.h b/src/host/hub.h index 6d81f6773..a5d8704d3 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -171,11 +171,11 @@ typedef struct { TU_VERIFY_STATIC( sizeof(hub_port_status_response_t) == 4, "size is not correct"); -bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_complete_cb_t complete_cb); -bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_complete_cb_t complete_cb); +bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_xfer_cb_t complete_cb); +bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_xfer_cb_t complete_cb); -bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, tuh_control_complete_cb_t complete_cb); -bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_control_complete_cb_t complete_cb); +bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, tuh_control_xfer_cb_t complete_cb); +bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_control_xfer_cb_t complete_cb); bool hub_edpt_status_xfer(uint8_t dev_addr); //--------------------------------------------------------------------+ diff --git a/src/host/usbh.c b/src/host/usbh.c index 617aff79a..a8692c8e5 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -111,15 +111,6 @@ typedef struct { } usbh_device_t; -typedef struct -{ - tusb_control_request_t request TU_ATTR_ALIGNED(4); - uint8_t* buffer; - tuh_control_complete_cb_t complete_cb; - - uint8_t daddr; -} usbh_control_xfer_t; - //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -250,7 +241,8 @@ static uint8_t _usbh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSIZE]; // We will only execute control transfer one at a time. struct { - usbh_control_xfer_t xfer; + tuh_control_xfer_t xfer; + uint8_t daddr; // device address that is transferring uint8_t stage; }_ctrl_xfer; @@ -308,132 +300,165 @@ void osal_task_delay(uint32_t msec) // Descriptors //--------------------------------------------------------------------+ -bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) +bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len, + tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) { - tusb_control_request_t const request = + tuh_control_xfer_t const xfer = { - .bmRequestType_bit = + .request = { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_IN + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_IN + }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = tu_htole16( TU_U16(type, index) ), + .wIndex = 0, + .wLength = tu_htole16(len) }, - .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = tu_htole16( TU_U16(type, index) ), - .wIndex = 0, - .wLength = tu_htole16(len) + + .buffer = buffer, + .complete_cb = complete_cb, + .user_arg = user_arg }; - TU_ASSERT( tuh_control_xfer(daddr, &request, buffer, complete_cb) ); - - return true; + return tuh_control_xfer(daddr, &xfer); } -bool tuh_descriptor_get_device(uint8_t daddr, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) +bool tuh_descriptor_get_device(uint8_t daddr, void* buffer, uint16_t len, + tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) { len = tu_min16(len, sizeof(tusb_desc_device_t)); - return tuh_descriptor_get(daddr, TUSB_DESC_DEVICE, 0, buffer, len, complete_cb); + return tuh_descriptor_get(daddr, TUSB_DESC_DEVICE, 0, buffer, len, complete_cb, user_arg); } -bool tuh_descriptor_get_configuration(uint8_t daddr, uint8_t index, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) +bool tuh_descriptor_get_configuration(uint8_t daddr, uint8_t index, void* buffer, uint16_t len, + tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) { - return tuh_descriptor_get(daddr, TUSB_DESC_CONFIGURATION, index, buffer, len, complete_cb); + return tuh_descriptor_get(daddr, TUSB_DESC_CONFIGURATION, index, buffer, len, complete_cb, user_arg); } -bool tuh_descriptor_get_string(uint8_t daddr, uint16_t language_id, uint8_t index, - void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) +bool tuh_descriptor_get_string(uint8_t daddr, uint16_t language_id, uint8_t index, void* buffer, uint16_t len, + tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) { - tusb_control_request_t const request = + tuh_control_xfer_t const xfer = { - .bmRequestType_bit = + .request = { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_IN + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_IN + }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = tu_htole16( TU_U16(TUSB_DESC_STRING, index) ), + .wIndex = tu_htole16(language_id), + .wLength = tu_htole16(len) }, - .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = tu_htole16( TU_U16(TUSB_DESC_STRING, index) ), - .wIndex = tu_htole16(language_id), - .wLength = tu_htole16(len) + + .buffer = buffer, + .complete_cb = complete_cb, + .user_arg = user_arg }; - TU_ASSERT( tuh_control_xfer(daddr, &request, buffer, complete_cb) ); - return true; + return tuh_control_xfer(daddr, &xfer); } // Get manufacturer string descriptor -bool tuh_descriptor_get_manufacturer_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) +bool tuh_descriptor_get_manufacturer_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, + tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) { TU_VERIFY(tuh_mounted(daddr)); usbh_device_t const* dev = get_device(daddr); if (dev->i_manufacturer == 0) { return false; } - return tuh_descriptor_get_string(daddr, language_id, dev->i_manufacturer, buffer, len, complete_cb); + return tuh_descriptor_get_string(daddr, language_id, dev->i_manufacturer, buffer, len, complete_cb, user_arg); } // Get product string descriptor -bool tuh_descriptor_get_product_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) +bool tuh_descriptor_get_product_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, + tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) { TU_VERIFY(tuh_mounted(daddr)); usbh_device_t const* dev = get_device(daddr); if (dev->i_product == 0) { return false; } - return tuh_descriptor_get_string(daddr, language_id, dev->i_product, buffer, len, complete_cb); + return tuh_descriptor_get_string(daddr, language_id, dev->i_product, buffer, len, complete_cb, user_arg); } // Get serial string descriptor -bool tuh_descriptor_get_serial_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) +bool tuh_descriptor_get_serial_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, + tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) { TU_VERIFY(tuh_mounted(daddr)); usbh_device_t const* dev = get_device(daddr); if (dev->i_serial == 0) { return false; } - return tuh_descriptor_get_string(daddr, language_id, dev->i_serial, buffer, len, complete_cb); + return tuh_descriptor_get_string(daddr, language_id, dev->i_serial, buffer, len, complete_cb, user_arg); } // Get HID report descriptor -bool tuh_descriptor_get_hid_report(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) +bool tuh_descriptor_get_hid_report(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, void* buffer, uint16_t len, + tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) { TU_LOG2("HID Get Report Descriptor\r\n"); - tusb_control_request_t const request = + tuh_control_xfer_t const xfer = { - .bmRequestType_bit = + .request = { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_IN + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_IN + }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = tu_htole16(TU_U16(desc_type, 0)), + .wIndex = itf_num, + .wLength = len }, - .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = tu_htole16(TU_U16(desc_type, 0)), - .wIndex = itf_num, - .wLength = len + + .buffer = buffer, + .complete_cb = complete_cb, + .user_arg = user_arg }; - return tuh_control_xfer(daddr, &request, buffer, complete_cb); + return tuh_control_xfer(daddr, &xfer); } -bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, tuh_control_complete_cb_t complete_cb) +bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, + tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) { TU_LOG2("Set Configuration = %d\r\n", config_num); - tusb_control_request_t const request = + + tuh_control_xfer_t const xfer = { - .bmRequestType_bit = + .request = { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_OUT + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_OUT + }, + .bRequest = TUSB_REQ_SET_CONFIGURATION, + .wValue = tu_htole16(config_num), + .wIndex = 0, + .wLength = 0 }, - .bRequest = TUSB_REQ_SET_CONFIGURATION, - .wValue = tu_htole16(config_num), - .wIndex = 0, - .wLength = 0 + + .buffer = NULL, + .complete_cb = complete_cb, + .user_arg = user_arg }; - TU_ASSERT( tuh_control_xfer(daddr, &request, NULL, complete_cb) ); - return true; + return tuh_control_xfer(daddr, &xfer); } //--------------------------------------------------------------------+ @@ -460,7 +485,7 @@ bool tuh_init(uint8_t rhport) TU_LOG2("USBH init\r\n"); TU_LOG2_INT(sizeof(usbh_device_t)); TU_LOG2_INT(sizeof(hcd_event_t)); - TU_LOG2_INT(sizeof(usbh_control_xfer_t)); + TU_LOG2_INT(sizeof(tuh_control_xfer_t)); // Event queue _usbh_q = osal_queue_create( &_usbh_qdef ); @@ -808,7 +833,7 @@ bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) // Control transfer //--------------------------------------------------------------------+ -bool tuh_control_xfer (uint8_t daddr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb) +bool tuh_control_xfer (uint8_t daddr, tuh_control_xfer_t const* xfer) { // pre-check to help reducing mutex lock TU_VERIFY(_ctrl_xfer.stage == CONTROL_STAGE_IDLE); @@ -824,16 +849,13 @@ bool tuh_control_xfer (uint8_t daddr, tusb_control_request_t const* request, voi const uint8_t rhport = usbh_get_rhport(daddr); - TU_LOG2("[%u:%u] %s: ", rhport, daddr, request->bRequest <= TUSB_REQ_SYNCH_FRAME ? tu_str_std_request[request->bRequest] : "Unknown Request"); - TU_LOG2_VAR(request); + TU_LOG2("[%u:%u] %s: ", rhport, daddr, xfer->request.bRequest <= TUSB_REQ_SYNCH_FRAME ? tu_str_std_request[xfer->request.bRequest] : "Unknown Request"); + TU_LOG2_VAR(&xfer->request); TU_LOG2("\r\n"); - _ctrl_xfer.xfer.request = (*request); - _ctrl_xfer.xfer.buffer = buffer; - _ctrl_xfer.xfer.complete_cb = complete_cb; - _ctrl_xfer.xfer.daddr = daddr; - - return hcd_setup_send(rhport, daddr, (uint8_t const*) &_ctrl_xfer.xfer.request); + _ctrl_xfer.daddr = daddr; + _ctrl_xfer.xfer = (*xfer); + return hcd_setup_send(rhport, daddr, (uint8_t*) &_ctrl_xfer.xfer.request); } TU_ATTR_ALWAYS_INLINE static inline void set_control_xfer_stage(uint8_t stage) @@ -851,7 +873,12 @@ static void _xfer_complete(uint8_t dev_addr, xfer_result_t result) _ctrl_xfer.stage = CONTROL_STAGE_IDLE; usbh_unlock(); - if (_ctrl_xfer.xfer.complete_cb) _ctrl_xfer.xfer.complete_cb(dev_addr, &_ctrl_xfer.xfer.request, result); + if (_ctrl_xfer.xfer.complete_cb) + { + // duplicate xfer since user can execute control transfer within callback + tuh_control_xfer_t const xfer_temp = _ctrl_xfer.xfer; + _ctrl_xfer.xfer.complete_cb(dev_addr, &xfer_temp, result); + } } static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) @@ -939,7 +966,7 @@ static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t h hcd_device_close(rhport, dev_addr); clear_device(dev); // abort on-going control xfer if any - if (_ctrl_xfer.xfer.daddr == dev_addr) set_control_xfer_stage(CONTROL_STAGE_IDLE); + if (_ctrl_xfer.daddr == dev_addr) set_control_xfer_stage(CONTROL_STAGE_IDLE); } } } @@ -954,14 +981,14 @@ static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t h //--------------------------------------------------------------------+ static bool enum_request_addr0_device_desc(void); -static bool enum_get_addr0_device_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool enum_get_addr0_device_desc_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); static bool enum_request_set_addr(void); -static bool enum_set_address_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool enum_get_device_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool enum_get_9byte_config_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool enum_get_config_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool enum_set_config_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool enum_set_address_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); +static bool enum_get_device_desc_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); +static bool enum_get_9byte_config_desc_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); +static bool enum_get_config_desc_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); +static bool enum_set_config_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); static bool parse_configuration_descriptor (uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg); static uint8_t get_new_address(bool is_hub); @@ -973,15 +1000,15 @@ static void enum_full_complete(void); // New device (reset on the way) -> Get Status 0 -> Clear Reset 0 -> Get 8byte Device Descriptor // -> Port Reset 1 -> reset delay -> Get Status 1 -> Clear Reset 1 -> queue hub interrupt endpoint -static bool enum_hub_get_status0_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool enum_hub_clear_reset0_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool enum_hub_set_reset1_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool enum_hub_get_status1_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool enum_hub_clear_reset1_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool enum_hub_get_status0_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); +static bool enum_hub_clear_reset0_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); +static bool enum_hub_set_reset1_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); +static bool enum_hub_get_status1_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); +static bool enum_hub_clear_reset1_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); -static bool enum_hub_get_status0_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool enum_hub_get_status0_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) { - (void) dev_addr; (void) request; + (void) dev_addr; (void) xfer; TU_ASSERT(XFER_RESULT_SUCCESS == result); hub_port_status_response_t port_status; @@ -1006,17 +1033,17 @@ static bool enum_hub_get_status0_complete(uint8_t dev_addr, tusb_control_request return true; } -static bool enum_hub_clear_reset0_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool enum_hub_clear_reset0_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) { - (void) dev_addr; (void) request; + (void) dev_addr; (void) xfer; TU_ASSERT(XFER_RESULT_SUCCESS == result); enum_request_addr0_device_desc(); return true; } -static bool enum_hub_set_reset1_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool enum_hub_set_reset1_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) { - (void) dev_addr; (void) request; + (void) dev_addr; (void) xfer; TU_ASSERT(XFER_RESULT_SUCCESS == result); osal_task_delay(RESET_DELAY); @@ -1026,9 +1053,9 @@ static bool enum_hub_set_reset1_complete(uint8_t dev_addr, tusb_control_request_ return true; } -static bool enum_hub_get_status1_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool enum_hub_get_status1_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) { - (void) dev_addr; (void) request; + (void) dev_addr; (void) xfer; TU_ASSERT(XFER_RESULT_SUCCESS == result); hub_port_status_response_t port_status; @@ -1043,9 +1070,9 @@ static bool enum_hub_get_status1_complete(uint8_t dev_addr, tusb_control_request return true; } -static bool enum_hub_clear_reset1_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool enum_hub_clear_reset1_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) { - (void) dev_addr; (void) request; + (void) dev_addr; (void) xfer; TU_ASSERT(XFER_RESULT_SUCCESS == result); enum_request_set_addr(); @@ -1096,14 +1123,14 @@ static bool enum_request_addr0_device_desc(void) // Get first 8 bytes of device descriptor for Control Endpoint size TU_LOG2("Get 8 byte of Device Descriptor\r\n"); - TU_ASSERT(tuh_descriptor_get_device(addr0, _usbh_ctrl_buf, 8, enum_get_addr0_device_desc_complete)); + TU_ASSERT(tuh_descriptor_get_device(addr0, _usbh_ctrl_buf, 8, enum_get_addr0_device_desc_complete, 0)); return true; } // After Get Device Descriptor of Address 0 -static bool enum_get_addr0_device_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool enum_get_addr0_device_desc_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) { - (void) request; + (void) xfer; TU_ASSERT(0 == dev_addr); if (XFER_RESULT_SUCCESS != result) @@ -1157,33 +1184,40 @@ static bool enum_request_set_addr(void) new_dev->connected = 1; new_dev->ep0_size = desc_device->bMaxPacketSize0; - tusb_control_request_t const new_request = + tuh_control_xfer_t const xfer = { - .bmRequestType_bit = + .request = { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_OUT + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_OUT + }, + .bRequest = TUSB_REQ_SET_ADDRESS, + .wValue = tu_htole16(new_addr), + .wIndex = 0, + .wLength = 0 }, - .bRequest = TUSB_REQ_SET_ADDRESS, - .wValue = tu_htole16(new_addr), - .wIndex = 0, - .wLength = 0 + + .buffer = NULL, + .complete_cb = enum_set_address_complete, + .user_arg = 0 }; uint8_t const addr0 = 0; - TU_ASSERT( tuh_control_xfer(addr0, &new_request, NULL, enum_set_address_complete) ); + TU_ASSERT( tuh_control_xfer(addr0, &xfer) ); return true; } // After SET_ADDRESS is complete -static bool enum_set_address_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool enum_set_address_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) { TU_ASSERT(0 == dev_addr); TU_ASSERT(XFER_RESULT_SUCCESS == result); - uint8_t const new_addr = (uint8_t const) request->wValue; + uint8_t const new_addr = (uint8_t const) xfer->request.wValue; usbh_device_t* new_dev = get_device(new_addr); new_dev->addressed = 1; @@ -1197,13 +1231,13 @@ static bool enum_set_address_complete(uint8_t dev_addr, tusb_control_request_t c // Get full device descriptor TU_LOG2("Get Device Descriptor\r\n"); - TU_ASSERT(tuh_descriptor_get_device(new_addr, _usbh_ctrl_buf, sizeof(tusb_desc_device_t), enum_get_device_desc_complete)); + TU_ASSERT(tuh_descriptor_get_device(new_addr, _usbh_ctrl_buf, sizeof(tusb_desc_device_t), enum_get_device_desc_complete, 0)); return true; } -static bool enum_get_device_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool enum_get_device_desc_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) { - (void) request; + (void) xfer; TU_ASSERT(XFER_RESULT_SUCCESS == result); tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf; @@ -1220,13 +1254,13 @@ static bool enum_get_device_desc_complete(uint8_t dev_addr, tusb_control_request // 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_ASSERT( tuh_descriptor_get_configuration(dev_addr, config_idx, _usbh_ctrl_buf, 9, enum_get_9byte_config_desc_complete) ); + TU_ASSERT( tuh_descriptor_get_configuration(dev_addr, config_idx, _usbh_ctrl_buf, 9, enum_get_9byte_config_desc_complete, 0) ); return true; } -static bool enum_get_9byte_config_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool enum_get_9byte_config_desc_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) { - (void) request; + (void) xfer; TU_ASSERT(XFER_RESULT_SUCCESS == result); // TODO not enough buffer to hold configuration descriptor @@ -1240,26 +1274,26 @@ static bool enum_get_9byte_config_desc_complete(uint8_t dev_addr, tusb_control_r // Get full configuration descriptor uint8_t const config_idx = CONFIG_NUM - 1; TU_LOG2("Get Configuration[0] Descriptor\r\n"); - TU_ASSERT( tuh_descriptor_get_configuration(dev_addr, config_idx, _usbh_ctrl_buf, total_len, enum_get_config_desc_complete) ); + TU_ASSERT( tuh_descriptor_get_configuration(dev_addr, config_idx, _usbh_ctrl_buf, total_len, enum_get_config_desc_complete, 0) ); return true; } -static bool enum_get_config_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool enum_get_config_desc_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) { - (void) request; + (void) xfer; TU_ASSERT(XFER_RESULT_SUCCESS == result); // Parse configuration & set up drivers // Driver open aren't allowed to make any usb transfer yet TU_ASSERT( parse_configuration_descriptor(dev_addr, (tusb_desc_configuration_t*) _usbh_ctrl_buf) ); - TU_ASSERT( tuh_configuration_set(dev_addr, CONFIG_NUM, enum_set_config_complete) ); + TU_ASSERT( tuh_configuration_set(dev_addr, CONFIG_NUM, enum_set_config_complete, 0) ); return true; } -static bool enum_set_config_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool enum_set_config_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) { - (void) request; + (void) xfer; TU_ASSERT(XFER_RESULT_SUCCESS == result); TU_LOG2("Device configured\r\n"); diff --git a/src/host/usbh.h b/src/host/usbh.h index eec2ed702..d836d9593 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -38,7 +38,19 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -typedef bool (*tuh_control_complete_cb_t)(uint8_t daddr, tusb_control_request_t const * request, xfer_result_t result); +// forward declaration +struct tuh_control_xfer_s; +typedef struct tuh_control_xfer_s tuh_control_xfer_t; + +typedef bool (*tuh_control_xfer_cb_t)(uint8_t daddr, tuh_control_xfer_t const * xfer, xfer_result_t result); + +struct tuh_control_xfer_s +{ + tusb_control_request_t request TU_ATTR_ALIGNED(4); + uint8_t* buffer; + tuh_control_xfer_cb_t complete_cb; + uintptr_t user_arg; +}; //--------------------------------------------------------------------+ // APPLICATION API @@ -81,40 +93,54 @@ static inline bool tuh_ready(uint8_t daddr) } // Carry out a control transfer -// true on success, false if there is on-going control trasnfer -bool tuh_control_xfer (uint8_t daddr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb); +// true on success, false if there is on-going control transfer +// Note: function is blocking if complete callback is NULL +bool tuh_control_xfer (uint8_t daddr, tuh_control_xfer_t const* xfer); + +// Carry out a control transfer +// true on success, false if there is on-going control transfer +// Note: function is blocking if complete callback is NULL +//bool tuh_control_xfer (uint8_t daddr, tusb_control_request_t const* request, void* buffer, +// tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); // Set Configuration // config_num = 0 will un-configure device. Note: config_num = config_descriptor_index + 1 -bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, tuh_control_complete_cb_t complete_cb); +bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, + tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); //------------- descriptors -------------// // Get an descriptor -bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, - void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); +bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len, + tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); // Get device descriptor -bool tuh_descriptor_get_device(uint8_t daddr, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); +bool tuh_descriptor_get_device(uint8_t daddr, void* buffer, uint16_t len, + tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); // Get configuration descriptor -bool tuh_descriptor_get_configuration(uint8_t daddr, uint8_t index, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); - -// Get string descriptor -bool tuh_descriptor_get_string(uint8_t daddr, uint16_t language_id, uint8_t index, - void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); - -// Get manufacturer string descriptor -bool tuh_descriptor_get_manufacturer_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); - -// Get product string descriptor -bool tuh_descriptor_get_product_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); - -// Get serial string descriptor -bool tuh_descriptor_get_serial_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); +bool tuh_descriptor_get_configuration(uint8_t daddr, uint8_t index, void* buffer, uint16_t len, + tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); // Get HID report descriptor -bool tuh_descriptor_get_hid_report(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); +bool tuh_descriptor_get_hid_report(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, void* buffer, uint16_t len, + tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); + +// Get string descriptor +bool tuh_descriptor_get_string(uint8_t daddr, uint16_t language_id, uint8_t index, void* buffer, uint16_t len, + tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); + +// Get manufacturer string descriptor +bool tuh_descriptor_get_manufacturer_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, + tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); + +// Get product string descriptor +bool tuh_descriptor_get_product_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, + tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); + +// Get serial string descriptor +bool tuh_descriptor_get_serial_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, + tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); //--------------------------------------------------------------------+ // APPLICATION CALLBACK From ec28593ce56a9a1726cfe8a43f6a8c421fd3916b Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 11 Mar 2022 22:13:57 +0700 Subject: [PATCH 46/81] update hid,msc to new usbh control API --- examples/host/cdc_msc_hid/src/main.c | 27 +++-- src/class/cdc/cdc_host.c | 29 ++++-- src/class/hid/hid_host.c | 148 ++++++++++++++++----------- src/class/msc/msc_host.c | 33 +++--- 4 files changed, 139 insertions(+), 98 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index a14be05ea..0fc7ef146 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -71,20 +71,6 @@ int main(void) #if CFG_TUH_CDC CFG_TUSB_MEM_SECTION static char serial_in_buffer[64] = { 0 }; -void tuh_mount_cb(uint8_t dev_addr) -{ - // application set-up - printf("A device with address %d is mounted\r\n", dev_addr); - - tuh_cdc_receive(dev_addr, serial_in_buffer, sizeof(serial_in_buffer), true); // schedule first transfer -} - -void tuh_umount_cb(uint8_t dev_addr) -{ - // application tear-down - printf("A device with address %d is unmounted \r\n", dev_addr); -} - // invoked ISR context void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_id, uint32_t xferred_bytes) { @@ -109,6 +95,19 @@ void cdc_task(void) // TinyUSB Callbacks //--------------------------------------------------------------------+ +void tuh_mount_cb(uint8_t dev_addr) +{ + // application set-up + printf("A device with address %d is mounted\r\n", dev_addr); +} + +void tuh_umount_cb(uint8_t dev_addr) +{ + // application tear-down + printf("A device with address %d is unmounted \r\n", dev_addr); +} + + //--------------------------------------------------------------------+ // Blinking Task //--------------------------------------------------------------------+ diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 6a29f3f43..8ca3dfbcb 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -123,22 +123,29 @@ 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_control_xfer_cb_t complete_cb) { cdch_data_t const * p_cdc = get_itf(dev_addr); - tusb_control_request_t const request = + + tuh_control_xfer_t const xfer = { - .bmRequestType_bit = + .request = { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE, + .wValue = (rts ? 2 : 0) | (dtr ? 1 : 0), + .wIndex = p_cdc->itf_num, + .wLength = 0 }, - .bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE, - .wValue = (rts ? 2 : 0) | (dtr ? 1 : 0), - .wIndex = p_cdc->itf_num, - .wLength = 0 + + .buffer = NULL, + .complete_cb = complete_cb, + .user_arg = 0 }; - TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, complete_cb) ); - return true; + return tuh_control_xfer(dev_addr, &xfer); } //--------------------------------------------------------------------+ diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 323debe69..4de3551c2 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -103,13 +103,13 @@ uint8_t tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance) return hid_itf->protocol_mode; } -static bool set_protocol_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool set_protocol_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) { - uint8_t const itf_num = (uint8_t) request->wIndex; + uint8_t const itf_num = (uint8_t) xfer->request.wIndex; uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - if (XFER_RESULT_SUCCESS == result) hid_itf->protocol_mode = (uint8_t) request->wValue; + if (XFER_RESULT_SUCCESS == result) hid_itf->protocol_mode = (uint8_t) xfer->request.wValue; if (tuh_hid_set_protocol_complete_cb) { @@ -126,37 +126,44 @@ bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) TU_LOG2("HID Set Protocol = %d\r\n", protocol); - tusb_control_request_t const request = + tuh_control_xfer_t const xfer = { - .bmRequestType_bit = + .request = { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HID_REQ_CONTROL_SET_PROTOCOL, + .wValue = protocol, + .wIndex = hid_itf->itf_num, + .wLength = 0 }, - .bRequest = HID_REQ_CONTROL_SET_PROTOCOL, - .wValue = protocol, - .wIndex = hid_itf->itf_num, - .wLength = 0 + + .buffer = NULL, + .complete_cb = set_protocol_complete, + .user_arg = 0 }; - TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, set_protocol_complete) ); + TU_ASSERT( tuh_control_xfer(dev_addr, &xfer) ); return true; } -static bool set_report_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool set_report_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) { TU_LOG2("HID Set Report complete\r\n"); if (tuh_hid_set_report_complete_cb) { - uint8_t const itf_num = (uint8_t) request->wIndex; + uint8_t const itf_num = (uint8_t) xfer->request.wIndex; uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); - uint8_t const report_type = tu_u16_high(request->wValue); - uint8_t const report_id = tu_u16_low(request->wValue); + uint8_t const report_type = tu_u16_high(xfer->request.wValue); + uint8_t const report_id = tu_u16_low(xfer->request.wValue); - tuh_hid_set_report_complete_cb(dev_addr, instance, report_id, report_type, (result == XFER_RESULT_SUCCESS) ? request->wLength : 0); + tuh_hid_set_report_complete_cb(dev_addr, instance, report_id, report_type, (result == XFER_RESULT_SUCCESS) ? xfer->request.wLength : 0); } return true; @@ -167,21 +174,28 @@ bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, u hidh_interface_t* hid_itf = get_instance(dev_addr, instance); TU_LOG2("HID Set Report: id = %u, type = %u, len = %u\r\n", report_id, report_type, len); - tusb_control_request_t const request = + tuh_control_xfer_t const xfer = { - .bmRequestType_bit = + .request = { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HID_REQ_CONTROL_SET_REPORT, + .wValue = tu_u16(report_type, report_id), + .wIndex = hid_itf->itf_num, + .wLength = len }, - .bRequest = HID_REQ_CONTROL_SET_REPORT, - .wValue = tu_u16(report_type, report_id), - .wIndex = hid_itf->itf_num, - .wLength = len + + .buffer = report, + .complete_cb = set_report_complete, + .user_arg = 0 }; - TU_ASSERT( tuh_control_xfer(dev_addr, &request, report, set_report_complete) ); + TU_ASSERT( tuh_control_xfer(dev_addr, &xfer) ); return true; } @@ -256,9 +270,9 @@ void hidh_close(uint8_t dev_addr) // Enumeration //--------------------------------------------------------------------+ -static bool config_set_protocol (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool config_get_report_desc (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool config_get_report_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool config_set_protocol (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); +static bool config_get_report_desc (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); +static bool config_get_report_desc_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len); @@ -337,65 +351,79 @@ bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) // SET IDLE request, device can stall if not support this request TU_LOG2("HID Set Idle \r\n"); - tusb_control_request_t const request = + tuh_control_xfer_t const xfer = { - .bmRequestType_bit = + .request = { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HID_REQ_CONTROL_SET_IDLE, + .wValue = idle_rate, + .wIndex = itf_num, + .wLength = 0 }, - .bRequest = HID_REQ_CONTROL_SET_IDLE, - .wValue = idle_rate, - .wIndex = itf_num, - .wLength = 0 + + .buffer = NULL, + .complete_cb = (hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE) ? config_set_protocol : config_get_report_desc, + .user_arg = 0 }; - TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, (hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE) ? config_set_protocol : config_get_report_desc) ); + TU_ASSERT( tuh_control_xfer(dev_addr, &xfer) ); return true; } // Force device to work in BOOT protocol -static bool config_set_protocol(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool config_set_protocol(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) { // Stall is a valid response for SET_IDLE, therefore we could ignore its result (void) result; - uint8_t const itf_num = (uint8_t) request->wIndex; + uint8_t const itf_num = (uint8_t) xfer->request.wIndex; uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); hidh_interface_t* hid_itf = get_instance(dev_addr, instance); TU_LOG2("HID Set Protocol to Boot Mode\r\n"); hid_itf->protocol_mode = HID_PROTOCOL_BOOT; - tusb_control_request_t const new_request = + tuh_control_xfer_t const new_xfer = { - .bmRequestType_bit = + .request = { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HID_REQ_CONTROL_SET_PROTOCOL, + .wValue = HID_PROTOCOL_BOOT, + .wIndex = hid_itf->itf_num, + .wLength = 0 }, - .bRequest = HID_REQ_CONTROL_SET_PROTOCOL, - .wValue = HID_PROTOCOL_BOOT, - .wIndex = hid_itf->itf_num, - .wLength = 0 + + .buffer = NULL, + .complete_cb = config_get_report_desc, + .user_arg = 0 }; - TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, NULL, config_get_report_desc) ); + TU_ASSERT( tuh_control_xfer(dev_addr, &new_xfer) ); return true; } -static bool config_get_report_desc(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool config_get_report_desc(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) { // We can be here after SET_IDLE or SET_PROTOCOL (boot device) // Trigger assert if result is not successful with set protocol - if ( request->bRequest != HID_REQ_CONTROL_SET_IDLE ) + if ( xfer->request.bRequest != HID_REQ_CONTROL_SET_IDLE ) { TU_ASSERT(result == XFER_RESULT_SUCCESS); } - uint8_t const itf_num = (uint8_t) request->wIndex; + uint8_t const itf_num = (uint8_t) xfer->request.wIndex; uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); hidh_interface_t* hid_itf = get_instance(dev_addr, instance); @@ -409,21 +437,21 @@ static bool config_get_report_desc(uint8_t dev_addr, tusb_control_request_t cons config_driver_mount_complete(dev_addr, instance, NULL, 0); }else { - TU_ASSERT(tuh_descriptor_get_hid_report(dev_addr, itf_num, hid_itf->report_desc_type, usbh_get_enum_buf(), hid_itf->report_desc_len, config_get_report_desc_complete)); + TU_ASSERT(tuh_descriptor_get_hid_report(dev_addr, itf_num, hid_itf->report_desc_type, usbh_get_enum_buf(), hid_itf->report_desc_len, config_get_report_desc_complete, 0)); } return true; } -static bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool config_get_report_desc_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) { TU_ASSERT(XFER_RESULT_SUCCESS == result); - uint8_t const itf_num = (uint8_t) request->wIndex; + uint8_t const itf_num = (uint8_t) xfer->request.wIndex; uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); uint8_t const* desc_report = usbh_get_enum_buf(); - uint16_t const desc_len = request->wLength; + uint16_t const desc_len = xfer->request.wLength; config_driver_mount_complete(dev_addr, instance, desc_report, desc_len); diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index e4239e375..c009e5088 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -358,7 +358,7 @@ bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 // MSC Enumeration //--------------------------------------------------------------------+ -static bool config_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool config_get_maxlun_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); @@ -405,27 +405,34 @@ bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) //------------- Get Max Lun -------------// TU_LOG2("MSC Get Max Lun\r\n"); - tusb_control_request_t request = + tuh_control_xfer_t const xfer = { - .bmRequestType_bit = + .request = { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_IN + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_IN + }, + .bRequest = MSC_REQ_GET_MAX_LUN, + .wValue = 0, + .wIndex = itf_num, + .wLength = 1 }, - .bRequest = MSC_REQ_GET_MAX_LUN, - .wValue = 0, - .wIndex = itf_num, - .wLength = 1 + + .buffer = &p_msc->max_lun, + .complete_cb = config_get_maxlun_complete, + .user_arg = 0 }; - TU_ASSERT(tuh_control_xfer(dev_addr, &request, &p_msc->max_lun, config_get_maxlun_complete)); + TU_ASSERT(tuh_control_xfer(dev_addr, &xfer)); return true; } -static bool config_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool config_get_maxlun_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) { - (void) request; + (void) xfer; msch_interface_t* p_msc = get_itf(dev_addr); From a5a565f7eb85c4d1ad43d74b1baf1f61dcf0a5b5 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 12 Mar 2022 14:20:57 +0700 Subject: [PATCH 47/81] rework usbh enumeration process using user arg from control transfer as state --- src/host/hub.c | 30 ++-- src/host/hub.h | 31 +++- src/host/usbh.c | 456 ++++++++++++++++++++++-------------------------- 3 files changed, 251 insertions(+), 266 deletions(-) diff --git a/src/host/hub.c b/src/host/hub.c index a0cf7b7e5..c1909cb5c 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -77,7 +77,8 @@ static char const* const _hub_feature_str[] = //--------------------------------------------------------------------+ // HUB //--------------------------------------------------------------------+ -bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_xfer_cb_t complete_cb) +bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, + tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) { tuh_control_xfer_t const xfer = { @@ -97,7 +98,7 @@ bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, .buffer = NULL, .complete_cb = complete_cb, - .user_arg = 0 + .user_arg = user_arg }; TU_LOG2("HUB Clear Feature: %s, addr = %u port = %u\r\n", _hub_feature_str[feature], hub_addr, hub_port); @@ -105,7 +106,8 @@ bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, return true; } -bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_xfer_cb_t complete_cb) +bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, + tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) { tuh_control_xfer_t const xfer = { @@ -125,7 +127,7 @@ bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, t .buffer = NULL, .complete_cb = complete_cb, - .user_arg = 0 + .user_arg = user_arg }; TU_LOG2("HUB Set Feature: %s, addr = %u port = %u\r\n", _hub_feature_str[feature], hub_addr, hub_port); @@ -133,12 +135,8 @@ bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, t return true; } -bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, tuh_control_xfer_cb_t complete_cb) -{ - return hub_port_set_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET, complete_cb); -} - -bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_control_xfer_cb_t complete_cb) +bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, + tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) { tuh_control_xfer_t const xfer = { @@ -158,7 +156,7 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_con .buffer = resp, .complete_cb = complete_cb, - .user_arg = 0 + .user_arg = user_arg }; TU_LOG2("HUB Get Port Status: addr = %u port = %u\r\n", hub_addr, hub_port); @@ -271,7 +269,7 @@ static bool config_set_port_power (uint8_t dev_addr, tuh_control_xfer_t const * // Set Port Power to be able to detect connection, starting with port 1 uint8_t const hub_port = 1; - return hub_port_set_feature(dev_addr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete); + return hub_port_set_feature(dev_addr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete, 0); } static bool config_port_power_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) @@ -290,7 +288,7 @@ static bool config_port_power_complete (uint8_t dev_addr, tuh_control_xfer_t con { // power next port uint8_t const hub_port = (uint8_t) (xfer->request.wIndex + 1); - return hub_port_set_feature(dev_addr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete); + return hub_port_set_feature(dev_addr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete, 0); } return true; @@ -320,7 +318,7 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32 { if ( tu_bit_test(p_hub->status_change, port) ) { - hub_port_get_status(dev_addr, port, &p_hub->port_status, connection_get_status_complete); + hub_port_get_status(dev_addr, port, &p_hub->port_status, connection_get_status_complete, 0); break; } } @@ -344,7 +342,7 @@ static bool connection_get_status_complete (uint8_t dev_addr, tuh_control_xfer_t //TU_VERIFY(port_status.status_current.port_power && port_status.status_current.port_enable, ); // Acknowledge Port Connection Change - hub_port_clear_feature(dev_addr, port_num, HUB_FEATURE_PORT_CONNECTION_CHANGE, connection_clear_conn_change_complete); + hub_port_clear_feature(dev_addr, port_num, HUB_FEATURE_PORT_CONNECTION_CHANGE, connection_clear_conn_change_complete, 0); }else { // Other changes are: Enable, Suspend, Over Current, Reset, L1 state @@ -368,7 +366,7 @@ static bool connection_clear_conn_change_complete (uint8_t dev_addr, tuh_control if ( p_hub->port_status.status.connection ) { // Reset port if attach event - hub_port_reset(dev_addr, port_num, connection_port_reset_complete); + hub_port_reset(dev_addr, port_num, connection_port_reset_complete, 0); }else { // submit detach event diff --git a/src/host/hub.h b/src/host/hub.h index a5d8704d3..30cf3dd1c 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -171,13 +171,36 @@ typedef struct { TU_VERIFY_STATIC( sizeof(hub_port_status_response_t) == 4, "size is not correct"); -bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_xfer_cb_t complete_cb); -bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_xfer_cb_t complete_cb); +// Clear feature +bool hub_port_clear_feature (uint8_t hub_addr, uint8_t hub_port, uint8_t feature, + tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); -bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, tuh_control_xfer_cb_t complete_cb); -bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_control_xfer_cb_t complete_cb); +// Set feature +bool hub_port_set_feature (uint8_t hub_addr, uint8_t hub_port, uint8_t feature, + tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); + +// Get port status +bool hub_port_get_status (uint8_t hub_addr, uint8_t hub_port, void* resp, + tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); + +// Get status from Interrupt endpoint bool hub_edpt_status_xfer(uint8_t dev_addr); +// Reset a port +static inline bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, + tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) +{ + return hub_port_set_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET, complete_cb, user_arg); +} + +// Clear Reset Change +static inline bool hub_port_clear_reset_change(uint8_t hub_addr, uint8_t hub_port, + tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) +{ + return hub_port_clear_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET_CHANGE, complete_cb, user_arg); +} + + //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ diff --git a/src/host/usbh.c b/src/host/usbh.c index a8692c8e5..6c38c525e 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -974,114 +974,216 @@ static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t h //--------------------------------------------------------------------+ // Enumeration Process // is a lengthy process with a series of control transfer to configure -// newly attached device. Each step is handled by a function in this -// section -// TODO due to the shared _usbh_ctrl_buf, we must complete enumerating +// newly attached device. +// NOTE: due to the shared _usbh_ctrl_buf, we must complete enumerating // one device before enumerating another one. //--------------------------------------------------------------------+ -static bool enum_request_addr0_device_desc(void); -static bool enum_get_addr0_device_desc_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); +enum { + ENUM_IDLE, + ENUM_RESET_1, // 1st reset when attached + //ENUM_HUB_GET_STATUS_1, + ENUM_HUB_CLEAR_RESET_1, + ENUM_ADDR0_DEVICE_DESC, + ENUM_RESET_2, // 2nd reset before set address + ENUM_HUB_GET_STATUS_2, + ENUM_HUB_CLEAR_RESET_2, + ENUM_SET_ADDR, + + ENUM_GET_DEVICE_DESC, + ENUM_GET_9BYTE_CONFIG_DESC, + ENUM_GET_FULL_CONFIG_DESC, + ENUM_SET_CONFIG, + ENUM_CONFIG_DRIVER +}; static bool enum_request_set_addr(void); -static bool enum_set_address_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); -static bool enum_get_device_desc_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); -static bool enum_get_9byte_config_desc_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); -static bool enum_get_config_desc_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); -static bool enum_set_config_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); static bool parse_configuration_descriptor (uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg); - -static uint8_t get_new_address(bool is_hub); static void enum_full_complete(void); -#if CFG_TUH_HUB - -// Enum sequence: -// New device (reset on the way) -> Get Status 0 -> Clear Reset 0 -> Get 8byte Device Descriptor -// -> Port Reset 1 -> reset delay -> Get Status 1 -> Clear Reset 1 -> queue hub interrupt endpoint - -static bool enum_hub_get_status0_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); -static bool enum_hub_clear_reset0_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); -static bool enum_hub_set_reset1_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); -static bool enum_hub_get_status1_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); -static bool enum_hub_clear_reset1_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); - -static bool enum_hub_get_status0_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) +// process device enumeration +static bool process_enumeration(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) { - (void) dev_addr; (void) xfer; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - hub_port_status_response_t port_status; - memcpy(&port_status, _usbh_ctrl_buf, sizeof(hub_port_status_response_t)); - - if ( !port_status.status.connection ) + if (XFER_RESULT_SUCCESS != result) { - // device unplugged while delaying, nothing else to do, queue hub status + // stop enumeration, maybe we could retry this enum_full_complete(); return false; } - _dev0.speed = (port_status.status.high_speed) ? TUSB_SPEED_HIGH : - (port_status.status.low_speed ) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; + uint32_t const state = (uint32_t) xfer->user_arg; - // Acknowledge Port Reset Change - if (port_status.change.reset) + switch(state) { - hub_port_clear_feature(_dev0.hub_addr, _dev0.hub_port, HUB_FEATURE_PORT_RESET_CHANGE, enum_hub_clear_reset0_complete); +#if CFG_TUH_HUB + //case ENUM_HUB_GET_STATUS_1: break; + + case ENUM_HUB_CLEAR_RESET_1: + { + hub_port_status_response_t port_status; + memcpy(&port_status, _usbh_ctrl_buf, sizeof(hub_port_status_response_t)); + + if ( !port_status.status.connection ) + { + // device unplugged while delaying, nothing else to do + enum_full_complete(); + return false; + } + + _dev0.speed = (port_status.status.high_speed) ? TUSB_SPEED_HIGH : + (port_status.status.low_speed ) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; + + // Acknowledge Port Reset Change + if (port_status.change.reset) + { + hub_port_clear_reset_change(_dev0.hub_addr, _dev0.hub_port, process_enumeration, ENUM_ADDR0_DEVICE_DESC); + } + } + break; + + case ENUM_HUB_GET_STATUS_2: + osal_task_delay(RESET_DELAY); + TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, process_enumeration, ENUM_HUB_CLEAR_RESET_2) ); + break; + + case ENUM_HUB_CLEAR_RESET_2: + { + hub_port_status_response_t port_status; + memcpy(&port_status, _usbh_ctrl_buf, sizeof(hub_port_status_response_t)); + + // Acknowledge Port Reset Change if Reset Successful + if (port_status.change.reset) + { + TU_ASSERT( hub_port_clear_reset_change(_dev0.hub_addr, _dev0.hub_port, process_enumeration, ENUM_SET_ADDR) ); + } + } + break; +#endif + + case ENUM_ADDR0_DEVICE_DESC: + { + // TODO probably doesn't need to open/close each enumeration + uint8_t const addr0 = 0; + 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_ASSERT(tuh_descriptor_get_device(addr0, _usbh_ctrl_buf, 8, process_enumeration, ENUM_SET_ADDR)); + } + break; + + case ENUM_RESET_2: + // Reset device again before Set Address + TU_LOG2("Port reset \r\n"); + if (_dev0.hub_addr == 0) + { + // connected directly to roothub + hcd_port_reset( _dev0.rhport ); + osal_task_delay(RESET_DELAY); + + // TODO: fall through to SET ADDRESS, refactor later + } + #if CFG_TUH_HUB + else + { + // after RESET_DELAY the hub_port_reset() already complete + TU_ASSERT( hub_port_reset(_dev0.hub_addr, _dev0.hub_port, process_enumeration, ENUM_HUB_GET_STATUS_2) ); + break; + } + __attribute__((fallthrough)); + #endif + + case ENUM_SET_ADDR: + enum_request_set_addr(); + break; + + case ENUM_GET_DEVICE_DESC: + { + uint8_t const new_addr = (uint8_t const) xfer->request.wValue; + + usbh_device_t* new_dev = get_device(new_addr); + new_dev->addressed = 1; + + // TODO close device 0, may not be needed + hcd_device_close(_dev0.rhport, 0); + + // open control pipe for new address + TU_ASSERT( usbh_edpt_control_open(new_addr, new_dev->ep0_size) ); + + // Get full device descriptor + TU_LOG2("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; + + case ENUM_GET_9BYTE_CONFIG_DESC: + { + tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf; + usbh_device_t* dev = get_device(dev_addr); + + dev->vid = desc_device->idVendor; + dev->pid = desc_device->idProduct; + dev->i_manufacturer = desc_device->iManufacturer; + dev->i_product = desc_device->iProduct; + dev->i_serial = desc_device->iSerialNumber; + + // if (tuh_attach_cb) tuh_attach_cb((tusb_desc_device_t*) _usbh_ctrl_buf); + + // 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_ASSERT( tuh_descriptor_get_configuration(dev_addr, config_idx, _usbh_ctrl_buf, 9, process_enumeration, ENUM_GET_FULL_CONFIG_DESC) ); + } + break; + + case ENUM_GET_FULL_CONFIG_DESC: + { + uint8_t const * desc_config = _usbh_ctrl_buf; + + // Use offsetof to avoid pointer to the odd/misaligned address + uint16_t const total_len = tu_le16toh( tu_unaligned_read16(desc_config + offsetof(tusb_desc_configuration_t, wTotalLength)) ); + + // TODO not enough buffer to hold configuration descriptor + TU_ASSERT(total_len <= CFG_TUH_ENUMERATION_BUFSIZE); + + // Get full configuration descriptor + uint8_t const config_idx = CONFIG_NUM - 1; + TU_LOG2("Get Configuration[0] Descriptor\r\n"); + TU_ASSERT( tuh_descriptor_get_configuration(dev_addr, config_idx, _usbh_ctrl_buf, total_len, process_enumeration, ENUM_SET_CONFIG) ); + } + break; + + case ENUM_SET_CONFIG: + // Parse configuration & set up drivers + // Driver open aren't allowed to make any usb transfer yet + TU_ASSERT( parse_configuration_descriptor(dev_addr, (tusb_desc_configuration_t*) _usbh_ctrl_buf) ); + + TU_ASSERT( tuh_configuration_set(dev_addr, CONFIG_NUM, process_enumeration, ENUM_CONFIG_DRIVER) ); + break; + + case ENUM_CONFIG_DRIVER: + { + TU_LOG2("Device configured\r\n"); + usbh_device_t* dev = get_device(dev_addr); + dev->configured = 1; + + // Start the Set Configuration process for interfaces (itf = DRVID_INVALID) + // Since driver can perform control transfer within its set_config, this is done asynchronously. + // The process continue with next interface when class driver complete its sequence with usbh_driver_set_config_complete() + // TODO use separated API instead of using DRVID_INVALID + usbh_driver_set_config_complete(dev_addr, DRVID_INVALID); + } + break; + + default: + // stop enumeration if unknown state + enum_full_complete(); + break; } return true; } -static bool enum_hub_clear_reset0_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) -{ - (void) dev_addr; (void) xfer; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - enum_request_addr0_device_desc(); - return true; -} - -static bool enum_hub_set_reset1_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) -{ - (void) dev_addr; (void) xfer; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - osal_task_delay(RESET_DELAY); - - TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, enum_hub_get_status1_complete) ); - - return true; -} - -static bool enum_hub_get_status1_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) -{ - (void) dev_addr; (void) xfer; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - hub_port_status_response_t port_status; - memcpy(&port_status, _usbh_ctrl_buf, sizeof(hub_port_status_response_t)); - - // Acknowledge Port Reset Change if Reset Successful - if (port_status.change.reset) - { - TU_ASSERT( hub_port_clear_feature(_dev0.hub_addr, _dev0.hub_port, HUB_FEATURE_PORT_RESET_CHANGE, enum_hub_clear_reset1_complete) ); - } - - return true; -} - -static bool enum_hub_clear_reset1_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) -{ - (void) dev_addr; (void) xfer; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - enum_request_set_addr(); - - return true; -} - -#endif // hub - static bool enum_new_device(hcd_event_t* event) { _dev0.rhport = event->rhport; @@ -1100,7 +1202,14 @@ static bool enum_new_device(hcd_event_t* event) _dev0.speed = hcd_port_speed_get(_dev0.rhport ); TU_LOG2("%s Speed\r\n", tu_str_speed[_dev0.speed]); - enum_request_addr0_device_desc(); + //enum_request_addr0_device_desc(); + tuh_control_xfer_t const xfer = + { + .complete_cb = process_enumeration, + .user_arg = ENUM_ADDR0_DEVICE_DESC + }; + process_enumeration(0, &xfer, XFER_RESULT_SUCCESS); + } #if CFG_TUH_HUB else @@ -1108,61 +1217,27 @@ static bool enum_new_device(hcd_event_t* event) // connected/disconnected via external hub // wait until device is stable osal_task_delay(RESET_DELAY); - TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, enum_hub_get_status0_complete) ); + + // ENUM_HUB_GET_STATUS + //TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, enum_hub_get_status0_complete, 0) ); + TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, process_enumeration, ENUM_HUB_CLEAR_RESET_1) ); } #endif // hub return true; } -static bool enum_request_addr0_device_desc(void) +static uint8_t get_new_address(bool is_hub) { - // TODO probably doesn't need to open/close each enumeration - uint8_t const addr0 = 0; - TU_ASSERT( usbh_edpt_control_open(addr0, 8) ); + uint8_t const start = (is_hub ? CFG_TUH_DEVICE_MAX : 0) + 1; + uint8_t const count = (is_hub ? CFG_TUH_HUB : CFG_TUH_DEVICE_MAX); - // Get first 8 bytes of device descriptor for Control Endpoint size - TU_LOG2("Get 8 byte of Device Descriptor\r\n"); - TU_ASSERT(tuh_descriptor_get_device(addr0, _usbh_ctrl_buf, 8, enum_get_addr0_device_desc_complete, 0)); - return true; -} - -// After Get Device Descriptor of Address 0 -static bool enum_get_addr0_device_desc_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) -{ - (void) xfer; - TU_ASSERT(0 == dev_addr); - - if (XFER_RESULT_SUCCESS != result) + for (uint8_t i=0; i < count; i++) { - // stop enumeration, maybe we could retry this - enum_full_complete(); - return false; + uint8_t const addr = start + i; + if (!get_device(addr)->connected) return addr; } - - tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf; - TU_ASSERT( tu_desc_type(desc_device) == TUSB_DESC_DEVICE ); - - // Reset device again before Set Address - TU_LOG2("Port reset \r\n"); - - if (_dev0.hub_addr == 0) - { - // connected directly to roothub - hcd_port_reset( _dev0.rhport ); - osal_task_delay(RESET_DELAY); - - enum_request_set_addr(); - } -#if CFG_TUH_HUB - else - { - // after RESET_DELAY the hub_port_reset() already complete - TU_ASSERT( hub_port_reset(_dev0.hub_addr, _dev0.hub_port, enum_hub_set_reset1_complete) ); - } -#endif // hub - - return true; + return ADDR_INVALID; } static bool enum_request_set_addr(void) @@ -1201,8 +1276,8 @@ static bool enum_request_set_addr(void) }, .buffer = NULL, - .complete_cb = enum_set_address_complete, - .user_arg = 0 + .complete_cb = process_enumeration, + .user_arg = ENUM_GET_DEVICE_DESC }; uint8_t const addr0 = 0; @@ -1211,104 +1286,6 @@ static bool enum_request_set_addr(void) return true; } -// After SET_ADDRESS is complete -static bool enum_set_address_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) -{ - TU_ASSERT(0 == dev_addr); - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - uint8_t const new_addr = (uint8_t const) xfer->request.wValue; - - usbh_device_t* new_dev = get_device(new_addr); - new_dev->addressed = 1; - - // TODO close device 0, may not be needed - hcd_device_close(_dev0.rhport, 0); - - // open control pipe for new address - TU_ASSERT( usbh_edpt_control_open(new_addr, new_dev->ep0_size) ); - - // Get full device descriptor - TU_LOG2("Get Device Descriptor\r\n"); - - TU_ASSERT(tuh_descriptor_get_device(new_addr, _usbh_ctrl_buf, sizeof(tusb_desc_device_t), enum_get_device_desc_complete, 0)); - return true; -} - -static bool enum_get_device_desc_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) -{ - (void) xfer; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf; - usbh_device_t* dev = get_device(dev_addr); - - dev->vid = desc_device->idVendor; - dev->pid = desc_device->idProduct; - dev->i_manufacturer = desc_device->iManufacturer; - dev->i_product = desc_device->iProduct; - dev->i_serial = desc_device->iSerialNumber; - -// if (tuh_attach_cb) tuh_attach_cb((tusb_desc_device_t*) _usbh_ctrl_buf); - - // 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_ASSERT( tuh_descriptor_get_configuration(dev_addr, config_idx, _usbh_ctrl_buf, 9, enum_get_9byte_config_desc_complete, 0) ); - return true; -} - -static bool enum_get_9byte_config_desc_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) -{ - (void) xfer; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - // TODO not enough buffer to hold configuration descriptor - uint8_t const * desc_config = _usbh_ctrl_buf; - - // Use offsetof to avoid pointer to the odd/misaligned address - uint16_t const total_len = tu_le16toh( tu_unaligned_read16(desc_config + offsetof(tusb_desc_configuration_t, wTotalLength)) ); - - TU_ASSERT(total_len <= CFG_TUH_ENUMERATION_BUFSIZE); - - // Get full configuration descriptor - uint8_t const config_idx = CONFIG_NUM - 1; - TU_LOG2("Get Configuration[0] Descriptor\r\n"); - TU_ASSERT( tuh_descriptor_get_configuration(dev_addr, config_idx, _usbh_ctrl_buf, total_len, enum_get_config_desc_complete, 0) ); - return true; -} - -static bool enum_get_config_desc_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) -{ - (void) xfer; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - // Parse configuration & set up drivers - // Driver open aren't allowed to make any usb transfer yet - TU_ASSERT( parse_configuration_descriptor(dev_addr, (tusb_desc_configuration_t*) _usbh_ctrl_buf) ); - - TU_ASSERT( tuh_configuration_set(dev_addr, CONFIG_NUM, enum_set_config_complete, 0) ); - return true; -} - -static bool enum_set_config_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) -{ - (void) xfer; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - TU_LOG2("Device configured\r\n"); - usbh_device_t* dev = get_device(dev_addr); - dev->configured = 1; - - // Start the Set Configuration process for interfaces (itf = DRVID_INVALID) - // Since driver can perform control transfer within its set_config, this is done asynchronously. - // The process continue with next interface when class driver complete its sequence with usbh_driver_set_config_complete() - // TODO use separated API instead of using DRVID_INVALID - usbh_driver_set_config_complete(dev_addr, DRVID_INVALID); - - return true; -} - static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg) { usbh_device_t* dev = get_device(dev_addr); @@ -1439,17 +1416,4 @@ static void enum_full_complete(void) } -static uint8_t get_new_address(bool is_hub) -{ - uint8_t const start = (is_hub ? CFG_TUH_DEVICE_MAX : 0) + 1; - uint8_t const count = (is_hub ? CFG_TUH_HUB : CFG_TUH_DEVICE_MAX); - - for (uint8_t i=0; i < count; i++) - { - uint8_t const addr = start + i; - if (!get_device(addr)->connected) return addr; - } - return ADDR_INVALID; -} - #endif From ac4483a7c53cd35b61b59cf69168e31ceac977a1 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 12 Mar 2022 14:26:48 +0700 Subject: [PATCH 48/81] misplace fallthrough --- src/host/usbh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index 6c38c525e..16366b33f 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1090,8 +1090,8 @@ static bool process_enumeration(uint8_t dev_addr, tuh_control_xfer_t const * xfe TU_ASSERT( hub_port_reset(_dev0.hub_addr, _dev0.hub_port, process_enumeration, ENUM_HUB_GET_STATUS_2) ); break; } - __attribute__((fallthrough)); #endif + __attribute__((fallthrough)); case ENUM_SET_ADDR: enum_request_set_addr(); From 56695569e7d9ebf39ffb2152aba4b4b9f0801d2d Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 12 Mar 2022 14:28:24 +0700 Subject: [PATCH 49/81] minor changes --- src/host/usbh.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index 16366b33f..7485bb065 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1011,8 +1011,7 @@ static bool process_enumeration(uint8_t dev_addr, tuh_control_xfer_t const * xfe return false; } - uint32_t const state = (uint32_t) xfer->user_arg; - + uintptr_t const state = xfer->user_arg; switch(state) { #if CFG_TUH_HUB From 228e185a1535ed61d3b5eee6219ad1af1b637f4a Mon Sep 17 00:00:00 2001 From: Ha Thach Date: Sat, 12 Mar 2022 16:58:37 +0700 Subject: [PATCH 50/81] Update bug_report.yml --- .github/ISSUE_TEMPLATE/bug_report.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index fc41d8ff1..c0b520e35 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -60,11 +60,12 @@ body: - type: textarea attributes: - label: Debug Log + label: Debug Log as txt file placeholder: | - TinyUSB debug log where the issue occurred as attached txt file, best with comments to explain the actual events. - - Note: To enable logging, add `LOG=3` to to the make command if building with stock examples or set `CFG_TUSB_DEBUG=3` in your tusb_config.h. + Attach your debug log txt file here, where the issue occurred, best with comments to explain the actual events. + + Note1: Please DO NOT paste your lengthy log contents here since it hurts the readibility. + Note2: To enable logging, add `LOG=3` to to the make command if building with stock examples or set `CFG_TUSB_DEBUG=3` in your tusb_config.h. More information can be found at [example's readme](https://github.com/hathach/tinyusb/blob/master/docs/getting_started.md) validations: required: false From 2929afe2fa2fc8425dcd1390cb3119bb1bd3b42b Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 13 Mar 2022 17:45:46 +0700 Subject: [PATCH 51/81] add synchronous (blocking) support for usbh control transfer - add synchronous version of all get descriptor API - update bare example to use sync API for string descriptor - change order of index, language_id in tuh_descriptor_get_string() to match similar API of libusb - add index to tuh_descriptor_get_hid_report() --- examples/host/bare_api/src/main.c | 43 +++----- src/class/hid/hid_host.c | 2 +- src/common/tusb_types.h | 2 + src/host/usbh.c | 172 +++++++++++++++++++++++------- src/host/usbh.h | 98 ++++++++++++----- src/tusb_option.h | 2 +- 6 files changed, 224 insertions(+), 95 deletions(-) diff --git a/examples/host/bare_api/src/main.c b/examples/host/bare_api/src/main.c index 6888d13a2..9e6209991 100644 --- a/examples/host/bare_api/src/main.c +++ b/examples/host/bare_api/src/main.c @@ -66,17 +66,9 @@ int main(void) #define LANGUAGE_ID 0x0409 //uint8_t usb_buf[256] TU_ATTR_ALIGNED(4); +TU_ATTR_ALIGNED(4) tusb_desc_device_t desc_device; -static volatile xfer_result_t _get_string_result; - -static bool _transfer_done_cb(uint8_t daddr, tuh_control_xfer_t const *xfer, xfer_result_t result) { - (void)daddr; - (void)xfer; - _get_string_result = result; - return true; -} - static void _convert_utf16le_to_utf8(const uint16_t *utf16, size_t utf16_len, uint8_t *utf8, size_t utf8_len) { // TODO: Check for runover. (void)utf8_len; @@ -116,14 +108,7 @@ static int _count_utf8_bytes(const uint16_t *buf, size_t len) { return total_bytes; } -static void _wait_and_convert(uint16_t *temp_buf, size_t buf_len) { - while (_get_string_result == 0xff) { - tuh_task(); - } - if (_get_string_result != XFER_RESULT_SUCCESS) { - temp_buf[0] = 0; - return; - } +static void utf16_to_utf8(uint16_t *temp_buf, size_t buf_len) { size_t utf16_len = ((temp_buf[0] & 0xff) - 2) / sizeof(uint16_t); size_t utf8_len = _count_utf8_bytes(temp_buf + 1, utf16_len); _convert_utf16le_to_utf8(temp_buf + 1, utf16_len, (uint8_t *) temp_buf, sizeof(uint16_t) * buf_len); @@ -153,31 +138,29 @@ bool print_device_descriptor(uint8_t daddr, tuh_control_xfer_t const * xfer, xfe printf(" idProduct 0x%04x\r\n" , desc_device.idProduct); printf(" bcdDevice %04x\r\n" , desc_device.bcdDevice); - _get_string_result = 0xff; + uint32_t timeout_ms = 10; uint16_t temp_buf[128]; printf(" iManufacturer %u " , desc_device.iManufacturer); - temp_buf[0] = 0; - if (tuh_descriptor_get_manufacturer_string(daddr, LANGUAGE_ID, temp_buf, TU_ARRAY_SIZE(temp_buf), _transfer_done_cb, 0)) { - _wait_and_convert(temp_buf, TU_ARRAY_SIZE(temp_buf)); + if (XFER_RESULT_SUCCESS == tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, temp_buf, TU_ARRAY_SIZE(temp_buf), timeout_ms) ) + { + utf16_to_utf8(temp_buf, TU_ARRAY_SIZE(temp_buf)); printf((const char*) temp_buf); } printf("\r\n"); printf(" iProduct %u " , desc_device.iProduct); - _get_string_result = 0xff; - temp_buf[0] = 0; - if (tuh_descriptor_get_product_string(daddr, LANGUAGE_ID, temp_buf, TU_ARRAY_SIZE(temp_buf), _transfer_done_cb, 0)) { - _wait_and_convert(temp_buf, TU_ARRAY_SIZE(temp_buf)); + if (XFER_RESULT_SUCCESS == tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, temp_buf, TU_ARRAY_SIZE(temp_buf), timeout_ms)) + { + utf16_to_utf8(temp_buf, TU_ARRAY_SIZE(temp_buf)); printf((const char*) temp_buf); } printf("\r\n"); printf(" iSerialNumber %u " , desc_device.iSerialNumber); - _get_string_result = 0xff; - temp_buf[0] = 0; - if (tuh_descriptor_get_serial_string(daddr, LANGUAGE_ID, temp_buf, TU_ARRAY_SIZE(temp_buf), _transfer_done_cb, 0)) { - _wait_and_convert(temp_buf, TU_ARRAY_SIZE(temp_buf)); + if (XFER_RESULT_SUCCESS == tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, temp_buf, TU_ARRAY_SIZE(temp_buf), timeout_ms)) + { + utf16_to_utf8(temp_buf, TU_ARRAY_SIZE(temp_buf)); printf((const char*) temp_buf); } printf("\r\n"); @@ -192,7 +175,7 @@ void tuh_mount_cb (uint8_t daddr) { printf("Device attached, address = %d\r\n", daddr); - // Get Device Descriptor + // Get Device Descriptor using asynchronous API tuh_descriptor_get_device(daddr, &desc_device, 18, print_device_descriptor, 0); } diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 4de3551c2..a825858ab 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -437,7 +437,7 @@ static bool config_get_report_desc(uint8_t dev_addr, tuh_control_xfer_t const * config_driver_mount_complete(dev_addr, instance, NULL, 0); }else { - TU_ASSERT(tuh_descriptor_get_hid_report(dev_addr, itf_num, hid_itf->report_desc_type, usbh_get_enum_buf(), hid_itf->report_desc_len, config_get_report_desc_complete, 0)); + TU_ASSERT(tuh_descriptor_get_hid_report(dev_addr, itf_num, hid_itf->report_desc_type, 0, usbh_get_enum_buf(), hid_itf->report_desc_len, config_get_report_desc_complete, 0)); } return true; diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index da164145b..e2fa17532 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -228,6 +228,8 @@ typedef enum XFER_RESULT_SUCCESS, XFER_RESULT_FAILED, XFER_RESULT_STALLED, + XFER_RESULT_TIMEOUT, + XFER_RESULT_INVALID }xfer_result_t; enum // TODO remove diff --git a/src/host/usbh.c b/src/host/usbh.c index 7485bb065..c7dfaddf6 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -243,7 +243,7 @@ struct { tuh_control_xfer_t xfer; uint8_t daddr; // device address that is transferring - uint8_t stage; + volatile uint8_t stage; }_ctrl_xfer; //------------- Helper Function -------------// @@ -300,8 +300,8 @@ void osal_task_delay(uint32_t msec) // Descriptors //--------------------------------------------------------------------+ -bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len, - tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) +static bool _get_descriptor(uint8_t daddr, uint8_t type, uint8_t index, uint16_t language_id, void* buffer, uint16_t len, + tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) { tuh_control_xfer_t const xfer = { @@ -315,7 +315,7 @@ bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, void* buffer }, .bRequest = TUSB_REQ_GET_DESCRIPTOR, .wValue = tu_htole16( TU_U16(type, index) ), - .wIndex = 0, + .wIndex = tu_htole16(language_id), .wLength = tu_htole16(len) }, @@ -327,6 +327,12 @@ bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, void* buffer return tuh_control_xfer(daddr, &xfer); } +bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len, + tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) +{ + return _get_descriptor(daddr, type, index, 0x0000, buffer, len, complete_cb, user_arg); +} + bool tuh_descriptor_get_device(uint8_t daddr, void* buffer, uint16_t len, tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) { @@ -340,31 +346,12 @@ bool tuh_descriptor_get_configuration(uint8_t daddr, uint8_t index, void* buffer return tuh_descriptor_get(daddr, TUSB_DESC_CONFIGURATION, index, buffer, len, complete_cb, user_arg); } -bool tuh_descriptor_get_string(uint8_t daddr, uint16_t language_id, uint8_t index, void* buffer, uint16_t len, +//------------- String Descriptor -------------// + +bool tuh_descriptor_get_string(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len, tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) { - tuh_control_xfer_t const xfer = - { - .request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_IN - }, - .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = tu_htole16( TU_U16(TUSB_DESC_STRING, index) ), - .wIndex = tu_htole16(language_id), - .wLength = tu_htole16(len) - }, - - .buffer = buffer, - .complete_cb = complete_cb, - .user_arg = user_arg - }; - - return tuh_control_xfer(daddr, &xfer); + return _get_descriptor(daddr, TUSB_DESC_STRING, index, language_id, buffer, len, complete_cb, user_arg); } // Get manufacturer string descriptor @@ -376,7 +363,7 @@ bool tuh_descriptor_get_manufacturer_string(uint8_t daddr, uint16_t language_id, if (dev->i_manufacturer == 0) { return false; } - return tuh_descriptor_get_string(daddr, language_id, dev->i_manufacturer, buffer, len, complete_cb, user_arg); + return tuh_descriptor_get_string(daddr, dev->i_manufacturer, language_id, buffer, len, complete_cb, user_arg); } // Get product string descriptor @@ -388,7 +375,7 @@ bool tuh_descriptor_get_product_string(uint8_t daddr, uint16_t language_id, void if (dev->i_product == 0) { return false; } - return tuh_descriptor_get_string(daddr, language_id, dev->i_product, buffer, len, complete_cb, user_arg); + return tuh_descriptor_get_string(daddr, dev->i_product, language_id, buffer, len, complete_cb, user_arg); } // Get serial string descriptor @@ -400,11 +387,11 @@ bool tuh_descriptor_get_serial_string(uint8_t daddr, uint16_t language_id, void* if (dev->i_serial == 0) { return false; } - return tuh_descriptor_get_string(daddr, language_id, dev->i_serial, buffer, len, complete_cb, user_arg); + return tuh_descriptor_get_string(daddr, dev->i_serial, language_id, buffer, len, complete_cb, user_arg); } // Get HID report descriptor -bool tuh_descriptor_get_hid_report(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, void* buffer, uint16_t len, +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_control_xfer_cb_t complete_cb, uintptr_t user_arg) { TU_LOG2("HID Get Report Descriptor\r\n"); @@ -419,8 +406,8 @@ bool tuh_descriptor_get_hid_report(uint8_t daddr, uint8_t itf_num, uint8_t desc_ .direction = TUSB_DIR_IN }, .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = tu_htole16(TU_U16(desc_type, 0)), - .wIndex = itf_num, + .wValue = tu_htole16(TU_U16(desc_type, index)), + .wIndex = tu_htole16((uint16_t) itf_num), .wLength = len }, @@ -461,6 +448,58 @@ bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, return tuh_control_xfer(daddr, &xfer); } +//--------------------------------------------------------------------+ +// Asynchronous +//--------------------------------------------------------------------+ + +#define _CONTROL_SYNC_API(_async_func, _timeout, ...) \ + (void) _timeout; \ + xfer_result_t result = XFER_RESULT_INVALID;\ + /* TODO use timeout to wait */ \ + TU_VERIFY(_async_func(__VA_ARGS__, NULL, (uintptr_t) &result), XFER_RESULT_TIMEOUT); \ + return (uint8_t) result + +uint8_t tuh_descriptor_get_sync(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len, uint8_t timeout_ms) +{ + _CONTROL_SYNC_API(tuh_descriptor_get, timeout_ms, daddr, type, index, buffer, len); +} + +uint8_t tuh_descriptor_get_device_sync(uint8_t daddr, void* buffer, uint16_t len, uint8_t timeout_ms) +{ + len = tu_min16(len, sizeof(tusb_desc_device_t)); + return tuh_descriptor_get_sync(daddr, TUSB_DESC_DEVICE, 0, buffer, len, timeout_ms); +} + +uint8_t tuh_descriptor_get_configuration_sync(uint8_t daddr, uint8_t index, void* buffer, uint16_t len, uint8_t timeout_ms) +{ + return tuh_descriptor_get_sync(daddr, TUSB_DESC_CONFIGURATION, index, buffer, len, timeout_ms); +} + +uint8_t tuh_descriptor_get_hid_report_sync(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, uint8_t index, void* buffer, uint16_t len, uint8_t timeout_ms) +{ + _CONTROL_SYNC_API(tuh_descriptor_get_hid_report, timeout_ms, daddr, itf_num, desc_type, index, buffer, len); +} + +uint8_t tuh_descriptor_get_string_sync(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len, uint8_t timeout_ms) +{ + _CONTROL_SYNC_API(tuh_descriptor_get_string, timeout_ms, daddr, index, language_id, buffer, len); +} + +uint8_t tuh_descriptor_get_manufacturer_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, uint8_t timeout_ms) +{ + _CONTROL_SYNC_API(tuh_descriptor_get_manufacturer_string, timeout_ms, daddr, language_id, buffer, len); +} + +uint8_t tuh_descriptor_get_product_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, uint8_t timeout_ms) +{ + _CONTROL_SYNC_API(tuh_descriptor_get_product_string, timeout_ms, daddr, language_id, buffer, len); +} + +uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, uint8_t timeout_ms) +{ + _CONTROL_SYNC_API(tuh_descriptor_get_serial_string, timeout_ms, daddr, language_id, buffer, len); +} + //--------------------------------------------------------------------+ // CLASS-USBD API (don't require to verify parameters) //--------------------------------------------------------------------+ @@ -833,11 +872,22 @@ bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) // Control transfer //--------------------------------------------------------------------+ +static bool _control_blocking_complete_cb(uint8_t daddr, tuh_control_xfer_t const * xfer, xfer_result_t result) +{ + (void) daddr; + + // update result + *((xfer_result_t*) xfer->user_arg) = result; + + return true; +} + bool tuh_control_xfer (uint8_t daddr, tuh_control_xfer_t const* xfer) { // pre-check to help reducing mutex lock TU_VERIFY(_ctrl_xfer.stage == CONTROL_STAGE_IDLE); + // TODO probably better to use semaphore as resource management than mutex usbh_lock(); bool const is_idle = (_ctrl_xfer.stage == CONTROL_STAGE_IDLE); @@ -855,7 +905,52 @@ bool tuh_control_xfer (uint8_t daddr, tuh_control_xfer_t const* xfer) _ctrl_xfer.daddr = daddr; _ctrl_xfer.xfer = (*xfer); - return hcd_setup_send(rhport, daddr, (uint8_t*) &_ctrl_xfer.xfer.request); + + if (xfer->complete_cb) + { + TU_ASSERT( hcd_setup_send(rhport, daddr, (uint8_t*) &_ctrl_xfer.xfer.request) ); + }else + { + // user_arg must point to xfer_result_t to hold result + TU_VERIFY(xfer->user_arg); + + // blocking if complete callback is not provided + // change callback to internal blocking, and result as user argument + volatile xfer_result_t* result = (volatile xfer_result_t*) xfer->user_arg; + + _ctrl_xfer.xfer.complete_cb = _control_blocking_complete_cb; + *result = XFER_RESULT_INVALID; + + TU_ASSERT( hcd_setup_send(rhport, daddr, (uint8_t*) &_ctrl_xfer.xfer.request) ); + + while ((*result) == XFER_RESULT_INVALID) + { + // only need to call task if not preempted RTOS + #if CFG_TUSB_OS == OPT_OS_NONE || CFG_TUSB_OS == OPT_OS_PICO + tuh_task(); + #endif + + // TODO probably some timeout to prevent hanged + } + } + + return true; +} + +uint8_t tuh_control_xfer_sync(uint8_t daddr, tuh_control_xfer_t const* xfer, uint32_t timeout_ms) +{ + (void) timeout_ms; + + xfer_result_t result = XFER_RESULT_INVALID; + tuh_control_xfer_t xfer_sync = (*xfer); + + xfer_sync.complete_cb = NULL; + xfer_sync.user_arg = (uintptr_t) &result; + + // TODO use timeout to wait + TU_VERIFY(tuh_control_xfer(daddr, &xfer_sync), XFER_RESULT_TIMEOUT); + + return result; } TU_ATTR_ALWAYS_INLINE static inline void set_control_xfer_stage(uint8_t stage) @@ -869,15 +964,16 @@ static void _xfer_complete(uint8_t dev_addr, xfer_result_t result) { TU_LOG2("\r\n"); + // duplicate xfer since user can execute control transfer within callback + tuh_control_xfer_t const xfer_temp = _ctrl_xfer.xfer; + usbh_lock(); _ctrl_xfer.stage = CONTROL_STAGE_IDLE; usbh_unlock(); - if (_ctrl_xfer.xfer.complete_cb) + if (xfer_temp.complete_cb) { - // duplicate xfer since user can execute control transfer within callback - tuh_control_xfer_t const xfer_temp = _ctrl_xfer.xfer; - _ctrl_xfer.xfer.complete_cb(dev_addr, &xfer_temp, result); + xfer_temp.complete_cb(dev_addr, &xfer_temp, result); } } diff --git a/src/host/usbh.h b/src/host/usbh.h index d836d9593..3bd40c50d 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -52,6 +52,18 @@ struct tuh_control_xfer_s uintptr_t user_arg; }; +//--------------------------------------------------------------------+ +// APPLICATION CALLBACK +//--------------------------------------------------------------------+ + +//TU_ATTR_WEAK uint8_t tuh_attach_cb (tusb_desc_device_t const *desc_device); + +// Invoked when device is mounted (configured) +TU_ATTR_WEAK void tuh_mount_cb (uint8_t daddr); + +/// Invoked when device is unmounted (bus reset/unplugged) +TU_ATTR_WEAK void tuh_umount_cb(uint8_t daddr); + //--------------------------------------------------------------------+ // APPLICATION API //--------------------------------------------------------------------+ @@ -93,65 +105,101 @@ static inline bool tuh_ready(uint8_t daddr) } // Carry out a control transfer -// true on success, false if there is on-going control transfer -// Note: function is blocking if complete callback is NULL +// true on success, false if there is on-going control transfer or incorrect parameters +// Blocking if complete callback is NULL, in this case 'user_arg' must contain xfer_result_t variable bool tuh_control_xfer (uint8_t daddr, tuh_control_xfer_t const* xfer); -// Carry out a control transfer -// true on success, false if there is on-going control transfer -// Note: function is blocking if complete callback is NULL -//bool tuh_control_xfer (uint8_t daddr, tusb_control_request_t const* request, void* buffer, -// tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); +// Sync (blocking) version of tuh_control_xfer() +// return transfer result +uint8_t tuh_control_xfer_sync(uint8_t daddr, tuh_control_xfer_t const* xfer, uint32_t timeout_ms); -// Set Configuration +// Set Configuration (control transfer) // config_num = 0 will un-configure device. Note: config_num = config_descriptor_index + 1 +// true on success, false if there is on-going control transfer or incorrect parameters +// Blocking if complete callback is NULL, in this case 'user_arg' must contain xfer_result_t variable bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); -//------------- descriptors -------------// +//--------------------------------------------------------------------+ +// Descriptors Asynchronous (non-blocking) +//--------------------------------------------------------------------+ -// Get an descriptor +// Get an descriptor (control transfer) +// true on success, false if there is on-going control transfer or incorrect parameters bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len, tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); -// Get device descriptor +// Get device descriptor (control transfer) +// true on success, false if there is on-going control transfer or incorrect parameters bool tuh_descriptor_get_device(uint8_t daddr, void* buffer, uint16_t len, tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); -// Get configuration descriptor +// Get configuration descriptor (control transfer) +// true on success, false if there is on-going control transfer or incorrect parameters bool tuh_descriptor_get_configuration(uint8_t daddr, uint8_t index, void* buffer, uint16_t len, tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); -// Get HID report descriptor -bool tuh_descriptor_get_hid_report(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, void* buffer, uint16_t len, +// Get HID report descriptor (control transfer) +// true on success, false if there is on-going control transfer or incorrect parameters +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_control_xfer_cb_t complete_cb, uintptr_t user_arg); -// Get string descriptor -bool tuh_descriptor_get_string(uint8_t daddr, uint16_t language_id, uint8_t index, void* buffer, uint16_t len, +// Get string descriptor (control transfer) +// true on success, false if there is on-going control transfer or incorrect parameters +// Blocking if complete callback is NULL, in this case 'user_arg' must contain xfer_result_t variable +bool tuh_descriptor_get_string(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len, tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); -// Get manufacturer string descriptor +// Get manufacturer string descriptor (control transfer) +// true on success, false if there is on-going control transfer or incorrect parameters bool tuh_descriptor_get_manufacturer_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); -// Get product string descriptor +// Get product string descriptor (control transfer) +// true on success, false if there is on-going control transfer or incorrect parameters bool tuh_descriptor_get_product_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); -// Get serial string descriptor +// Get serial string descriptor (control transfer) +// true on success, false if there is on-going control transfer or incorrect parameters bool tuh_descriptor_get_serial_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); //--------------------------------------------------------------------+ -// APPLICATION CALLBACK +// Descriptors Synchronous (blocking) //--------------------------------------------------------------------+ -//TU_ATTR_WEAK uint8_t tuh_attach_cb (tusb_desc_device_t const *desc_device); -// Invoked when device is mounted (configured) -TU_ATTR_WEAK void tuh_mount_cb (uint8_t daddr); +// Sync (blocking) version of tuh_descriptor_get() +// return transfer result +uint8_t tuh_descriptor_get_sync(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len, uint8_t timeout_ms); -/// Invoked when device is unmounted (bus reset/unplugged) -TU_ATTR_WEAK void tuh_umount_cb(uint8_t daddr); +// Sync (blocking) version of tuh_descriptor_get_device() +// return transfer result +uint8_t tuh_descriptor_get_device_sync(uint8_t daddr, void* buffer, uint16_t len, uint8_t timeout_ms); + +// Sync (blocking) version of tuh_descriptor_get_configuration() +// return transfer result +uint8_t tuh_descriptor_get_configuration_sync(uint8_t daddr, uint8_t index, void* buffer, uint16_t len, uint8_t timeout_ms); + +// Sync (blocking) version of tuh_descriptor_get_hid_report() +// return transfer result +uint8_t tuh_descriptor_get_hid_report_sync(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, uint8_t index, void* buffer, uint16_t len, uint8_t timeout_ms); + +// Sync (blocking) version of tuh_descriptor_get_string() +// return transfer result +uint8_t tuh_descriptor_get_string_sync(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len, uint8_t timeout_ms); + +// Sync (blocking) version of tuh_descriptor_get_manufacturer_string() +// return transfer result +uint8_t tuh_descriptor_get_manufacturer_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, uint8_t timeout_ms); + +// Sync (blocking) version of tuh_descriptor_get_product_string() +// return transfer result +uint8_t tuh_descriptor_get_product_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, uint8_t timeout_ms); + +// Sync (blocking) version of tuh_descriptor_get_serial_string() +// return transfer result +uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, uint8_t timeout_ms); #ifdef __cplusplus } diff --git a/src/tusb_option.h b/src/tusb_option.h index e5351b1c4..0352faaed 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -285,7 +285,7 @@ #define CFG_TUSB_OS_INC_PATH #endif -// mutex is only needed for RTOS +// mutex is only needed for RTOS TODO also required with multiple core MCUs #define TUSB_OPT_MUTEX (CFG_TUSB_OS != OPT_OS_NONE) //-------------------------------------------------------------------- From fd2ea2605e67673d4264b56649612b34fa93807d Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 16 Mar 2022 10:55:18 +0700 Subject: [PATCH 52/81] fix -Wnull-dereference warnings --- src/host/usbh.c | 86 +++++++++++++++++++++++++++---------------------- src/host/usbh.h | 4 +++ 2 files changed, 51 insertions(+), 39 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index c7dfaddf6..418642891 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -251,7 +251,7 @@ struct TU_ATTR_ALWAYS_INLINE static inline usbh_device_t* get_device(uint8_t dev_addr) { - TU_ASSERT(dev_addr, NULL); + TU_VERIFY(dev_addr > 0 && dev_addr <= TOTAL_DEVICES, NULL); return &_usbh_devices[dev_addr-1]; } @@ -265,15 +265,15 @@ static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t //--------------------------------------------------------------------+ bool tuh_mounted(uint8_t dev_addr) { - return get_device(dev_addr)->configured; + usbh_device_t* dev = get_device(dev_addr); + TU_VERIFY(dev); + return dev->configured; } bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t* vid, uint16_t* pid) { - *vid = *pid = 0; - - TU_VERIFY(tuh_mounted(dev_addr)); usbh_device_t const* dev = get_device(dev_addr); + TU_VERIFY(dev && dev->configured); *vid = dev->vid; *pid = dev->pid; @@ -283,7 +283,8 @@ bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t* vid, uint16_t* pid) tusb_speed_t tuh_speed_get (uint8_t dev_addr) { - return (tusb_speed_t) (dev_addr ? get_device(dev_addr)->speed : _dev0.speed); + usbh_device_t* dev = get_device(dev_addr); + return (tusb_speed_t) (dev ? get_device(dev_addr)->speed : _dev0.speed); } #if CFG_TUSB_OS == OPT_OS_NONE @@ -358,11 +359,8 @@ bool tuh_descriptor_get_string(uint8_t daddr, uint8_t index, uint16_t language_i bool tuh_descriptor_get_manufacturer_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) { - TU_VERIFY(tuh_mounted(daddr)); usbh_device_t const* dev = get_device(daddr); - if (dev->i_manufacturer == 0) { - return false; - } + TU_VERIFY(dev && dev->i_manufacturer); return tuh_descriptor_get_string(daddr, dev->i_manufacturer, language_id, buffer, len, complete_cb, user_arg); } @@ -370,11 +368,8 @@ bool tuh_descriptor_get_manufacturer_string(uint8_t daddr, uint16_t language_id, bool tuh_descriptor_get_product_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) { - TU_VERIFY(tuh_mounted(daddr)); usbh_device_t const* dev = get_device(daddr); - if (dev->i_product == 0) { - return false; - } + TU_VERIFY(dev && dev->i_product); return tuh_descriptor_get_string(daddr, dev->i_product, language_id, buffer, len, complete_cb, user_arg); } @@ -382,11 +377,8 @@ bool tuh_descriptor_get_product_string(uint8_t daddr, uint16_t language_id, void bool tuh_descriptor_get_serial_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) { - TU_VERIFY(tuh_mounted(daddr)); usbh_device_t const* dev = get_device(daddr); - if (dev->i_serial == 0) { - return false; - } + TU_VERIFY(dev && dev->i_serial); return tuh_descriptor_get_string(daddr, dev->i_serial, language_id, buffer, len, complete_cb, user_arg); } @@ -629,6 +621,8 @@ void tuh_task(void) else { usbh_device_t* dev = get_device(event.dev_addr); + TU_ASSERT(dev, ); + dev->ep_status[epnum][ep_dir].busy = 0; dev->ep_status[epnum][ep_dir].claimed = 0; @@ -662,7 +656,8 @@ void tuh_task(void) uint8_t usbh_get_rhport(uint8_t dev_addr) { - return (dev_addr == 0) ? _dev0.rhport : get_device(dev_addr)->rhport; + usbh_device_t* dev = get_device(dev_addr); + return dev ? dev->rhport : _dev0.rhport; } uint8_t* usbh_get_enum_buf(void) @@ -688,10 +683,10 @@ void usbh_int_set(bool enabled) void hcd_devtree_get_info(uint8_t dev_addr, hcd_devtree_info_t* devtree_info) { - if (dev_addr) - { - usbh_device_t const* dev = get_device(dev_addr); + usbh_device_t const* dev = get_device(dev_addr); + if (dev) + { devtree_info->rhport = dev->rhport; devtree_info->hub_addr = dev->hub_addr; devtree_info->hub_port = dev->hub_port; @@ -768,10 +763,11 @@ void hcd_event_device_remove(uint8_t hostid, bool in_isr) // TODO has some duplication code with device, refactor later bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) { - // addr0 is always available - if (dev_addr == 0) return true; - usbh_device_t* dev = get_device(dev_addr); + + // addr0 only use tuh_control_xfer + TU_ASSERT(dev); + uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); tu_edpt_state_t* ep_state = &dev->ep_status[epnum][dir]; @@ -804,11 +800,12 @@ bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) // TODO has some duplication code with device, refactor later bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { + usbh_device_t* dev = get_device(dev_addr); + TU_VERIFY(dev); + uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - usbh_device_t* dev = get_device(dev_addr); - TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); // Attempt to transfer on a busy endpoint, sound like an race condition ! @@ -827,7 +824,7 @@ bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_ // HCD error, mark endpoint as ready to allow next transfer dev->ep_status[epnum][dir].busy = false; dev->ep_status[epnum][dir].claimed = 0; - TU_LOG2("failed\r\n"); + TU_LOG1("failed\r\n"); TU_BREAKPOINT(); return false; } @@ -852,9 +849,7 @@ static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep) { - usbh_device_t* dev = get_device(dev_addr); - TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) dev->speed)); - + TU_ASSERT( tu_edpt_validate(desc_ep, tuh_speed_get(dev_addr)) ); return hcd_edpt_open(rhport, dev_addr, desc_ep); } @@ -864,6 +859,7 @@ bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) uint8_t const dir = tu_edpt_dir(ep_addr); usbh_device_t* dev = get_device(dev_addr); + TU_VERIFY(dev); return dev->ep_status[epnum][dir].busy; } @@ -1094,7 +1090,7 @@ enum { }; static bool enum_request_set_addr(void); -static bool parse_configuration_descriptor (uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg); +static bool parse_configuration_descriptor (uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg); static void enum_full_complete(void); // process device enumeration @@ -1194,9 +1190,10 @@ static bool process_enumeration(uint8_t dev_addr, tuh_control_xfer_t const * xfe case ENUM_GET_DEVICE_DESC: { - uint8_t const new_addr = (uint8_t const) xfer->request.wValue; + uint8_t const new_addr = (uint8_t) tu_le16toh(xfer->request.wValue); usbh_device_t* new_dev = get_device(new_addr); + TU_ASSERT(new_dev); new_dev->addressed = 1; // TODO close device 0, may not be needed @@ -1215,6 +1212,7 @@ static bool process_enumeration(uint8_t dev_addr, tuh_control_xfer_t const * xfe { tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf; usbh_device_t* dev = get_device(dev_addr); + TU_ASSERT(dev); dev->vid = desc_device->idVendor; dev->pid = desc_device->idProduct; @@ -1260,6 +1258,8 @@ static bool process_enumeration(uint8_t dev_addr, tuh_control_xfer_t const * xfe { TU_LOG2("Device configured\r\n"); usbh_device_t* dev = get_device(dev_addr); + TU_ASSERT(dev); + dev->configured = 1; // Start the Set Configuration process for interfaces (itf = DRVID_INVALID) @@ -1324,13 +1324,21 @@ static bool enum_new_device(hcd_event_t* event) static uint8_t get_new_address(bool is_hub) { - uint8_t const start = (is_hub ? CFG_TUH_DEVICE_MAX : 0) + 1; - uint8_t const count = (is_hub ? CFG_TUH_HUB : CFG_TUH_DEVICE_MAX); - - for (uint8_t i=0; i < count; i++) + uint8_t start; + uint8_t end; + if ( is_hub ) { - uint8_t const addr = start + i; - if (!get_device(addr)->connected) return addr; + start = CFG_TUH_DEVICE_MAX; + end = start + CFG_TUH_HUB; + }else + { + start = 0; + end = start + CFG_TUH_DEVICE_MAX; + } + + for ( uint8_t idx = start; idx < end; idx++) + { + if (!_usbh_devices[idx].connected) return (idx+1); } return ADDR_INVALID; } diff --git a/src/host/usbh.h b/src/host/usbh.h index 3bd40c50d..fc0590190 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -201,6 +201,10 @@ uint8_t tuh_descriptor_get_product_string_sync(uint8_t daddr, uint16_t language_ // return transfer result uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, uint8_t timeout_ms); +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + #ifdef __cplusplus } #endif From 98d4ed05845e3a2efb32b0817d635457698b8cc9 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 16 Mar 2022 15:12:59 +0700 Subject: [PATCH 53/81] update hid host to use new control xfer for set config --- src/class/hid/hid_host.c | 211 +++++++++++++++++++-------------------- src/class/msc/msc_host.c | 2 +- src/host/usbh.c | 10 +- 3 files changed, 108 insertions(+), 115 deletions(-) diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index a825858ab..6bcd2f5d3 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -119,11 +119,9 @@ static bool set_protocol_complete(uint8_t dev_addr, tuh_control_xfer_t const * x return true; } -bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) -{ - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - TU_VERIFY(hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE); +static bool _hidh_set_protocol(uint8_t dev_addr, uint8_t itf_num, uint8_t protocol, tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) +{ TU_LOG2("HID Set Protocol = %d\r\n", protocol); tuh_control_xfer_t const xfer = @@ -138,19 +136,27 @@ bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) }, .bRequest = HID_REQ_CONTROL_SET_PROTOCOL, .wValue = protocol, - .wIndex = hid_itf->itf_num, + .wIndex = itf_num, .wLength = 0 }, .buffer = NULL, - .complete_cb = set_protocol_complete, - .user_arg = 0 + .complete_cb = complete_cb, + .user_arg = user_arg }; TU_ASSERT( tuh_control_xfer(dev_addr, &xfer) ); return true; } +bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) +{ + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + TU_VERIFY(hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE); + + return _hidh_set_protocol(dev_addr, hid_itf->itf_num, protocol, set_protocol_complete, 0); +} + static bool set_report_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) { TU_LOG2("HID Set Report complete\r\n"); @@ -199,6 +205,36 @@ bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, u return true; } +static bool _hidh_set_idle(uint8_t dev_addr, uint8_t itf_num, uint16_t idle_rate, tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) +{ + // SET IDLE request, device can stall if not support this request + TU_LOG2("HID Set Idle \r\n"); + tuh_control_xfer_t const xfer = + { + .request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HID_REQ_CONTROL_SET_IDLE, + .wValue = idle_rate, + .wIndex = itf_num, + .wLength = 0 + }, + + .buffer = NULL, + .complete_cb = complete_cb, + .user_arg = user_arg + }; + + TU_ASSERT( tuh_control_xfer(dev_addr, &xfer) ); + + return true; +} + //--------------------------------------------------------------------+ // Interrupt Endpoint API //--------------------------------------------------------------------+ @@ -270,12 +306,6 @@ void hidh_close(uint8_t dev_addr) // Enumeration //--------------------------------------------------------------------+ -static bool config_set_protocol (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); -static bool config_get_report_desc (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); -static bool config_get_report_desc_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); - -static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len); - bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) { (void) max_len; @@ -341,123 +371,88 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de return true; } +//--------------------------------------------------------------------+ +// Set Configure +//--------------------------------------------------------------------+ + +enum { + CONFG_SET_IDLE, + CONFIG_SET_PROTOCOL, + CONFIG_GET_REPORT_DESC, + CONFIG_COMPLETE +}; + +static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len); +static bool process_set_config(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); + bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) { - uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + tuh_control_xfer_t xfer; + xfer.request.wIndex = tu_htole16((uint16_t) itf_num); + xfer.user_arg = CONFG_SET_IDLE; - // Idle rate = 0 mean only report when there is changes - uint16_t const idle_rate = 0; - - // SET IDLE request, device can stall if not support this request - TU_LOG2("HID Set Idle \r\n"); - tuh_control_xfer_t const xfer = - { - .request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = HID_REQ_CONTROL_SET_IDLE, - .wValue = idle_rate, - .wIndex = itf_num, - .wLength = 0 - }, - - .buffer = NULL, - .complete_cb = (hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE) ? config_set_protocol : config_get_report_desc, - .user_arg = 0 - }; - - TU_ASSERT( tuh_control_xfer(dev_addr, &xfer) ); - - return true; + // start the set config process + return process_set_config(dev_addr, &xfer, XFER_RESULT_SUCCESS); } -// Force device to work in BOOT protocol -static bool config_set_protocol(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) +static bool process_set_config(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) { // Stall is a valid response for SET_IDLE, therefore we could ignore its result - (void) result; - - uint8_t const itf_num = (uint8_t) xfer->request.wIndex; - uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - - TU_LOG2("HID Set Protocol to Boot Mode\r\n"); - hid_itf->protocol_mode = HID_PROTOCOL_BOOT; - tuh_control_xfer_t const new_xfer = - { - .request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = HID_REQ_CONTROL_SET_PROTOCOL, - .wValue = HID_PROTOCOL_BOOT, - .wIndex = hid_itf->itf_num, - .wLength = 0 - }, - - .buffer = NULL, - .complete_cb = config_get_report_desc, - .user_arg = 0 - }; - - TU_ASSERT( tuh_control_xfer(dev_addr, &new_xfer) ); - return true; -} - -static bool config_get_report_desc(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) -{ - // We can be here after SET_IDLE or SET_PROTOCOL (boot device) - // Trigger assert if result is not successful with set protocol if ( xfer->request.bRequest != HID_REQ_CONTROL_SET_IDLE ) { TU_ASSERT(result == XFER_RESULT_SUCCESS); } - uint8_t const itf_num = (uint8_t) xfer->request.wIndex; + uintptr_t const state = xfer->user_arg; + uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->request.wIndex); uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - // Get Report Descriptor if possible - // using usbh enumeration buffer since report descriptor can be very long - if( hid_itf->report_desc_len > CFG_TUH_ENUMERATION_BUFSIZE ) + switch(state) { - TU_LOG2("HID Skip Report Descriptor since it is too large %u bytes\r\n", hid_itf->report_desc_len); + case CONFG_SET_IDLE: + { + // Idle rate = 0 mean only report when there is changes + const uint16_t idle_rate = 0; + const uintptr_t next_state = (hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE) ? CONFIG_SET_PROTOCOL : CONFIG_GET_REPORT_DESC; + TU_VERIFY( _hidh_set_idle(dev_addr, itf_num, idle_rate, process_set_config, next_state) ); + } + break; - // Driver is mounted without report descriptor - config_driver_mount_complete(dev_addr, instance, NULL, 0); - }else - { - TU_ASSERT(tuh_descriptor_get_hid_report(dev_addr, itf_num, hid_itf->report_desc_type, 0, usbh_get_enum_buf(), hid_itf->report_desc_len, config_get_report_desc_complete, 0)); + case CONFIG_SET_PROTOCOL: + TU_VERIFY(_hidh_set_protocol(dev_addr, hid_itf->itf_num, HID_PROTOCOL_BOOT, process_set_config, CONFIG_GET_REPORT_DESC)); + break; + + case CONFIG_GET_REPORT_DESC: + // Get Report Descriptor if possible + // using usbh enumeration buffer since report descriptor can be very long + if( hid_itf->report_desc_len > CFG_TUH_ENUMERATION_BUFSIZE ) + { + TU_LOG2("HID Skip Report Descriptor since it is too large %u bytes\r\n", hid_itf->report_desc_len); + + // Driver is mounted without report descriptor + config_driver_mount_complete(dev_addr, instance, NULL, 0); + }else + { + TU_ASSERT(tuh_descriptor_get_hid_report(dev_addr, itf_num, hid_itf->report_desc_type, 0, usbh_get_enum_buf(), hid_itf->report_desc_len, process_set_config, CONFIG_COMPLETE)); + } + break; + + case CONFIG_COMPLETE: + { + uint8_t const* desc_report = usbh_get_enum_buf(); + uint16_t const desc_len = xfer->request.wLength; + + config_driver_mount_complete(dev_addr, instance, desc_report, desc_len); + } + break; + + default: break; } return true; } -static bool config_get_report_desc_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) -{ - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - uint8_t const itf_num = (uint8_t) xfer->request.wIndex; - uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); - - uint8_t const* desc_report = usbh_get_enum_buf(); - uint16_t const desc_len = xfer->request.wLength; - - config_driver_mount_complete(dev_addr, instance, desc_report, desc_len); - - return true; -} - static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index c009e5088..b3af65942 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -483,7 +483,7 @@ static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw // Capacity response field: Block size and Last LBA are both Big-Endian scsi_read_capacity10_resp_t* resp = (scsi_read_capacity10_resp_t*) ((void*) _msch_buffer); p_msc->capacity[cbw->lun].block_count = tu_ntohl(resp->last_lba) + 1; - p_msc->capacity[cbw->lun].block_size = tu_ntohl(resp->block_size); + p_msc->capacity[cbw->lun].block_size = tu_ntohl(resp->block_size); // Mark enumeration is complete p_msc->mounted = true; diff --git a/src/host/usbh.c b/src/host/usbh.c index 418642891..83bca2205 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1297,12 +1297,10 @@ static bool enum_new_device(hcd_event_t* event) _dev0.speed = hcd_port_speed_get(_dev0.rhport ); TU_LOG2("%s Speed\r\n", tu_str_speed[_dev0.speed]); - //enum_request_addr0_device_desc(); - tuh_control_xfer_t const xfer = - { - .complete_cb = process_enumeration, - .user_arg = ENUM_ADDR0_DEVICE_DESC - }; + // start the enumeration process + tuh_control_xfer_t xfer; + xfer.user_arg = ENUM_ADDR0_DEVICE_DESC; + process_enumeration(0, &xfer, XFER_RESULT_SUCCESS); } From 68bfd048a54d1ff2def4cb1ee5285eacdb55f143 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 17 Mar 2022 12:53:52 +0700 Subject: [PATCH 54/81] change tuh_control_xfer_t struct --- src/class/cdc/cdc_host.c | 30 ++++--- src/class/hid/hid_host.c | 115 +++++++++++++------------ src/class/msc/msc_host.c | 30 ++++--- src/host/hub.c | 130 +++++++++++++++------------- src/host/usbh.c | 182 ++++++++++++++++++++++++--------------- src/host/usbh.h | 27 ++++-- 6 files changed, 292 insertions(+), 222 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 8ca3dfbcb..9838df818 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -124,22 +124,24 @@ bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_co { cdch_data_t const * p_cdc = get_itf(dev_addr); + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE, + .wValue = (rts ? 2 : 0) | (dtr ? 1 : 0), + .wIndex = p_cdc->itf_num, + .wLength = 0 + }; + tuh_control_xfer_t const xfer = { - .request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE, - .wValue = (rts ? 2 : 0) | (dtr ? 1 : 0), - .wIndex = p_cdc->itf_num, - .wLength = 0 - }, - + .ep_addr = 0, + .setup = &request, .buffer = NULL, .complete_cb = complete_cb, .user_arg = 0 diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 6bcd2f5d3..8c1a5ebc9 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -105,11 +105,11 @@ uint8_t tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance) static bool set_protocol_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) { - uint8_t const itf_num = (uint8_t) xfer->request.wIndex; + uint8_t const itf_num = (uint8_t) xfer->setup->wIndex; uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - if (XFER_RESULT_SUCCESS == result) hid_itf->protocol_mode = (uint8_t) xfer->request.wValue; + if (XFER_RESULT_SUCCESS == result) hid_itf->protocol_mode = (uint8_t) xfer->setup->wValue; if (tuh_hid_set_protocol_complete_cb) { @@ -124,22 +124,24 @@ static bool _hidh_set_protocol(uint8_t dev_addr, uint8_t itf_num, uint8_t protoc { TU_LOG2("HID Set Protocol = %d\r\n", protocol); + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HID_REQ_CONTROL_SET_PROTOCOL, + .wValue = protocol, + .wIndex = itf_num, + .wLength = 0 + }; + tuh_control_xfer_t const xfer = { - .request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = HID_REQ_CONTROL_SET_PROTOCOL, - .wValue = protocol, - .wIndex = itf_num, - .wLength = 0 - }, - + .ep_addr = 0, + .setup = &request, .buffer = NULL, .complete_cb = complete_cb, .user_arg = user_arg @@ -163,13 +165,13 @@ static bool set_report_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfe if (tuh_hid_set_report_complete_cb) { - uint8_t const itf_num = (uint8_t) xfer->request.wIndex; + uint8_t const itf_num = (uint8_t) xfer->setup->wIndex; uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); - uint8_t const report_type = tu_u16_high(xfer->request.wValue); - uint8_t const report_id = tu_u16_low(xfer->request.wValue); + uint8_t const report_type = tu_u16_high(xfer->setup->wValue); + uint8_t const report_id = tu_u16_low(xfer->setup->wValue); - tuh_hid_set_report_complete_cb(dev_addr, instance, report_id, report_type, (result == XFER_RESULT_SUCCESS) ? xfer->request.wLength : 0); + tuh_hid_set_report_complete_cb(dev_addr, instance, report_id, report_type, (result == XFER_RESULT_SUCCESS) ? xfer->setup->wLength : 0); } return true; @@ -180,22 +182,24 @@ bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, u hidh_interface_t* hid_itf = get_instance(dev_addr, instance); TU_LOG2("HID Set Report: id = %u, type = %u, len = %u\r\n", report_id, report_type, len); + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HID_REQ_CONTROL_SET_REPORT, + .wValue = tu_u16(report_type, report_id), + .wIndex = hid_itf->itf_num, + .wLength = len + }; + tuh_control_xfer_t const xfer = { - .request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = HID_REQ_CONTROL_SET_REPORT, - .wValue = tu_u16(report_type, report_id), - .wIndex = hid_itf->itf_num, - .wLength = len - }, - + .ep_addr = 0, + .setup = &request, .buffer = report, .complete_cb = set_report_complete, .user_arg = 0 @@ -209,22 +213,24 @@ static bool _hidh_set_idle(uint8_t dev_addr, uint8_t itf_num, uint16_t idle_rate { // SET IDLE request, device can stall if not support this request TU_LOG2("HID Set Idle \r\n"); + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HID_REQ_CONTROL_SET_IDLE, + .wValue = idle_rate, + .wIndex = itf_num, + .wLength = 0 + }; + tuh_control_xfer_t const xfer = { - .request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = HID_REQ_CONTROL_SET_IDLE, - .wValue = idle_rate, - .wIndex = itf_num, - .wLength = 0 - }, - + .ep_addr = 0, + .setup = &request, .buffer = NULL, .complete_cb = complete_cb, .user_arg = user_arg @@ -387,24 +393,27 @@ static bool process_set_config(uint8_t dev_addr, tuh_control_xfer_t const * xfer bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) { + tusb_control_request_t request; + request.wIndex = tu_htole16((uint16_t) itf_num); + tuh_control_xfer_t xfer; - xfer.request.wIndex = tu_htole16((uint16_t) itf_num); + xfer.setup = &request; xfer.user_arg = CONFG_SET_IDLE; - // start the set config process + // fake request to start the set config process return process_set_config(dev_addr, &xfer, XFER_RESULT_SUCCESS); } static bool process_set_config(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) { // Stall is a valid response for SET_IDLE, therefore we could ignore its result - if ( xfer->request.bRequest != HID_REQ_CONTROL_SET_IDLE ) + if ( xfer->setup->bRequest != HID_REQ_CONTROL_SET_IDLE ) { TU_ASSERT(result == XFER_RESULT_SUCCESS); } uintptr_t const state = xfer->user_arg; - uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->request.wIndex); + uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); hidh_interface_t* hid_itf = get_instance(dev_addr, instance); @@ -441,7 +450,7 @@ static bool process_set_config(uint8_t dev_addr, tuh_control_xfer_t const * xfer case CONFIG_COMPLETE: { uint8_t const* desc_report = usbh_get_enum_buf(); - uint16_t const desc_len = xfer->request.wLength; + uint16_t const desc_len = xfer->setup->wLength; config_driver_mount_complete(dev_addr, instance, desc_report, desc_len); } diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index b3af65942..d8910db0f 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -405,22 +405,24 @@ bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) //------------- Get Max Lun -------------// TU_LOG2("MSC Get Max Lun\r\n"); + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_IN + }, + .bRequest = MSC_REQ_GET_MAX_LUN, + .wValue = 0, + .wIndex = itf_num, + .wLength = 1 + }; + tuh_control_xfer_t const xfer = { - .request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_IN - }, - .bRequest = MSC_REQ_GET_MAX_LUN, - .wValue = 0, - .wIndex = itf_num, - .wLength = 1 - }, - + .ep_addr = 0, + .setup = &request, .buffer = &p_msc->max_lun, .complete_cb = config_get_maxlun_complete, .user_arg = 0 diff --git a/src/host/hub.c b/src/host/hub.c index c1909cb5c..6ce9e4cc6 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -80,22 +80,24 @@ static char const* const _hub_feature_str[] = bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) { + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_OTHER, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HUB_REQUEST_CLEAR_FEATURE, + .wValue = feature, + .wIndex = hub_port, + .wLength = 0 + }; + tuh_control_xfer_t const xfer = { - .request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_OTHER, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = HUB_REQUEST_CLEAR_FEATURE, - .wValue = feature, - .wIndex = hub_port, - .wLength = 0 - }, - + .ep_addr = 0, + .setup = &request, .buffer = NULL, .complete_cb = complete_cb, .user_arg = user_arg @@ -109,22 +111,24 @@ bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) { + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_OTHER, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HUB_REQUEST_SET_FEATURE, + .wValue = feature, + .wIndex = hub_port, + .wLength = 0 + }; + tuh_control_xfer_t const xfer = { - .request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_OTHER, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = HUB_REQUEST_SET_FEATURE, - .wValue = feature, - .wIndex = hub_port, - .wLength = 0 - }, - + .ep_addr = 0, + .setup = &request, .buffer = NULL, .complete_cb = complete_cb, .user_arg = user_arg @@ -138,22 +142,24 @@ bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) { + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_OTHER, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_IN + }, + .bRequest = HUB_REQUEST_GET_STATUS, + .wValue = 0, + .wIndex = hub_port, + .wLength = 4 + }; + tuh_control_xfer_t const xfer = { - .request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_OTHER, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_IN - }, - .bRequest = HUB_REQUEST_GET_STATUS, - .wValue = 0, - .wIndex = hub_port, - .wLength = 4 - }, - + .ep_addr = 0, + .setup = &request, .buffer = resp, .complete_cb = complete_cb, .user_arg = user_arg @@ -228,22 +234,24 @@ bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) TU_ASSERT(itf_num == p_hub->itf_num); // Get Hub Descriptor + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_IN + }, + .bRequest = HUB_REQUEST_GET_DESCRIPTOR, + .wValue = 0, + .wIndex = 0, + .wLength = sizeof(descriptor_hub_desc_t) + }; + tuh_control_xfer_t const xfer = { - .request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_IN - }, - .bRequest = HUB_REQUEST_GET_DESCRIPTOR, - .wValue = 0, - .wIndex = 0, - .wLength = sizeof(descriptor_hub_desc_t) - }, - + .ep_addr = 0, + .setup = &request, .buffer = _hub_buffer, .complete_cb = config_set_port_power, .user_arg = 0 @@ -277,7 +285,7 @@ static bool config_port_power_complete (uint8_t dev_addr, tuh_control_xfer_t con TU_ASSERT(XFER_RESULT_SUCCESS == result); hub_interface_t* p_hub = get_itf(dev_addr); - if (xfer->request.wIndex == p_hub->port_count) + if (xfer->setup->wIndex == p_hub->port_count) { // All ports are power -> queue notification status endpoint and // complete the SET CONFIGURATION @@ -287,7 +295,7 @@ static bool config_port_power_complete (uint8_t dev_addr, tuh_control_xfer_t con }else { // power next port - uint8_t const hub_port = (uint8_t) (xfer->request.wIndex + 1); + uint8_t const hub_port = (uint8_t) (xfer->setup->wIndex + 1); return hub_port_set_feature(dev_addr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete, 0); } @@ -333,7 +341,7 @@ static bool connection_get_status_complete (uint8_t dev_addr, tuh_control_xfer_t TU_ASSERT(result == XFER_RESULT_SUCCESS); hub_interface_t* p_hub = get_itf(dev_addr); - uint8_t const port_num = (uint8_t) xfer->request.wIndex; + uint8_t const port_num = (uint8_t) xfer->setup->wIndex; // Connection change if (p_hub->port_status.change.connection) @@ -361,7 +369,7 @@ static bool connection_clear_conn_change_complete (uint8_t dev_addr, tuh_control TU_ASSERT(result == XFER_RESULT_SUCCESS); hub_interface_t* p_hub = get_itf(dev_addr); - uint8_t const port_num = (uint8_t) xfer->request.wIndex; + uint8_t const port_num = (uint8_t) xfer->setup->wIndex; if ( p_hub->port_status.status.connection ) { @@ -392,7 +400,7 @@ static bool connection_port_reset_complete (uint8_t dev_addr, tuh_control_xfer_t TU_ASSERT(result == XFER_RESULT_SUCCESS); // hub_interface_t* p_hub = get_itf(dev_addr); - uint8_t const port_num = (uint8_t) xfer->request.wIndex; + uint8_t const port_num = (uint8_t) xfer->setup->wIndex; // submit attach event hcd_event_t event = diff --git a/src/host/usbh.c b/src/host/usbh.c index 83bca2205..d2d819ec2 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -109,6 +109,10 @@ typedef struct { tu_edpt_state_t ep_status[CFG_TUH_ENDPOINT_MAX][2]; +#if CFG_TUH_BARE + +#endif + } usbh_device_t; //--------------------------------------------------------------------+ @@ -241,7 +245,11 @@ static uint8_t _usbh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSIZE]; // We will only execute control transfer one at a time. struct { - tuh_control_xfer_t xfer; + tusb_control_request_t request TU_ATTR_ALIGNED(4); + uint8_t* buffer; + tuh_control_xfer_cb_t complete_cb; + uintptr_t user_arg; + uint8_t daddr; // device address that is transferring volatile uint8_t stage; }_ctrl_xfer; @@ -304,22 +312,24 @@ void osal_task_delay(uint32_t msec) static bool _get_descriptor(uint8_t daddr, uint8_t type, uint8_t index, uint16_t language_id, void* buffer, uint16_t len, tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) { + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_IN + }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = tu_htole16( TU_U16(type, index) ), + .wIndex = tu_htole16(language_id), + .wLength = tu_htole16(len) + }; + tuh_control_xfer_t const xfer = { - .request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_IN - }, - .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = tu_htole16( TU_U16(type, index) ), - .wIndex = tu_htole16(language_id), - .wLength = tu_htole16(len) - }, - + .ep_addr = 0, + .setup = &request, .buffer = buffer, .complete_cb = complete_cb, .user_arg = user_arg @@ -387,22 +397,24 @@ bool tuh_descriptor_get_hid_report(uint8_t daddr, uint8_t itf_num, uint8_t desc_ tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) { TU_LOG2("HID Get Report Descriptor\r\n"); + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_IN + }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = tu_htole16(TU_U16(desc_type, index)), + .wIndex = tu_htole16((uint16_t) itf_num), + .wLength = len + }; + tuh_control_xfer_t const xfer = { - .request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_IN - }, - .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = tu_htole16(TU_U16(desc_type, index)), - .wIndex = tu_htole16((uint16_t) itf_num), - .wLength = len - }, - + .ep_addr = 0, + .setup = &request, .buffer = buffer, .complete_cb = complete_cb, .user_arg = user_arg @@ -416,22 +428,24 @@ bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, { TU_LOG2("Set Configuration = %d\r\n", config_num); + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_OUT + }, + .bRequest = TUSB_REQ_SET_CONFIGURATION, + .wValue = tu_htole16(config_num), + .wIndex = 0, + .wLength = 0 + }; + tuh_control_xfer_t const xfer = { - .request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_OUT - }, - .bRequest = TUSB_REQ_SET_CONFIGURATION, - .wValue = tu_htole16(config_num), - .wIndex = 0, - .wLength = 0 - }, - + .ep_addr = 0, + .setup = &request, .buffer = NULL, .complete_cb = complete_cb, .user_arg = user_arg @@ -895,16 +909,19 @@ bool tuh_control_xfer (uint8_t daddr, tuh_control_xfer_t const* xfer) const uint8_t rhport = usbh_get_rhport(daddr); - TU_LOG2("[%u:%u] %s: ", rhport, daddr, xfer->request.bRequest <= TUSB_REQ_SYNCH_FRAME ? tu_str_std_request[xfer->request.bRequest] : "Unknown Request"); - TU_LOG2_VAR(&xfer->request); + 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("\r\n"); - _ctrl_xfer.daddr = daddr; - _ctrl_xfer.xfer = (*xfer); + _ctrl_xfer.daddr = daddr; + _ctrl_xfer.request = (*xfer->setup); + _ctrl_xfer.buffer = xfer->buffer; + _ctrl_xfer.complete_cb = xfer->complete_cb; + _ctrl_xfer.user_arg = xfer->user_arg; if (xfer->complete_cb) { - TU_ASSERT( hcd_setup_send(rhport, daddr, (uint8_t*) &_ctrl_xfer.xfer.request) ); + TU_ASSERT( hcd_setup_send(rhport, daddr, (uint8_t*) &_ctrl_xfer.request) ); }else { // user_arg must point to xfer_result_t to hold result @@ -914,10 +931,10 @@ bool tuh_control_xfer (uint8_t daddr, tuh_control_xfer_t const* xfer) // change callback to internal blocking, and result as user argument volatile xfer_result_t* result = (volatile xfer_result_t*) xfer->user_arg; - _ctrl_xfer.xfer.complete_cb = _control_blocking_complete_cb; + _ctrl_xfer.complete_cb = _control_blocking_complete_cb; *result = XFER_RESULT_INVALID; - TU_ASSERT( hcd_setup_send(rhport, daddr, (uint8_t*) &_ctrl_xfer.xfer.request) ); + TU_ASSERT( hcd_setup_send(rhport, daddr, (uint8_t*) &_ctrl_xfer.request) ); while ((*result) == XFER_RESULT_INVALID) { @@ -961,7 +978,16 @@ static void _xfer_complete(uint8_t dev_addr, xfer_result_t result) TU_LOG2("\r\n"); // duplicate xfer since user can execute control transfer within callback - tuh_control_xfer_t const xfer_temp = _ctrl_xfer.xfer; + tusb_control_request_t const request = _ctrl_xfer.request; + tuh_control_xfer_t const xfer_temp = + { + .ep_addr = 0, + .setup = &request, + .actual_len = 0, + .buffer = _ctrl_xfer.buffer, + .complete_cb = _ctrl_xfer.complete_cb, + .user_arg = _ctrl_xfer.user_arg + }; usbh_lock(); _ctrl_xfer.stage = CONTROL_STAGE_IDLE; @@ -979,7 +1005,7 @@ static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result (void) xferred_bytes; const uint8_t rhport = usbh_get_rhport(dev_addr); - tusb_control_request_t const * request = &_ctrl_xfer.xfer.request; + tusb_control_request_t const * request = &_ctrl_xfer.request; if (XFER_RESULT_SUCCESS != result) { @@ -996,7 +1022,7 @@ static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result { // DATA stage: initial data toggle is always 1 set_control_xfer_stage(CONTROL_STAGE_DATA); - return hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.xfer.buffer, request->wLength); + return hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.buffer, request->wLength); } __attribute__((fallthrough)); @@ -1004,7 +1030,7 @@ static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result if (request->wLength) { TU_LOG2("[%u:%u] Control data:\r\n", rhport, dev_addr); - TU_LOG2_MEM(_ctrl_xfer.xfer.buffer, request->wLength, 2); + TU_LOG2_MEM(_ctrl_xfer.buffer, request->wLength, 2); } // ACK stage: toggle is always 1 @@ -1190,7 +1216,7 @@ static bool process_enumeration(uint8_t dev_addr, tuh_control_xfer_t const * xfe case ENUM_GET_DEVICE_DESC: { - uint8_t const new_addr = (uint8_t) tu_le16toh(xfer->request.wValue); + uint8_t const new_addr = (uint8_t) tu_le16toh(xfer->setup->wValue); usbh_device_t* new_dev = get_device(new_addr); TU_ASSERT(new_dev); @@ -1320,6 +1346,12 @@ static bool enum_new_device(hcd_event_t* event) return true; } +TU_ATTR_ALWAYS_INLINE +static inline bool is_hub_addr(uint8_t daddr) +{ + return daddr > CFG_TUH_DEVICE_MAX; +} + static uint8_t get_new_address(bool is_hub) { uint8_t start; @@ -1360,22 +1392,24 @@ static bool enum_request_set_addr(void) new_dev->connected = 1; new_dev->ep0_size = desc_device->bMaxPacketSize0; + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_OUT + }, + .bRequest = TUSB_REQ_SET_ADDRESS, + .wValue = tu_htole16(new_addr), + .wIndex = 0, + .wLength = 0 + }; + tuh_control_xfer_t const xfer = { - .request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_OUT - }, - .bRequest = TUSB_REQ_SET_ADDRESS, - .wValue = tu_htole16(new_addr), - .wIndex = 0, - .wLength = 0 - }, - + .ep_addr = 0, + .setup = &request, .buffer = NULL, .complete_cb = process_enumeration, .user_arg = ENUM_GET_DEVICE_DESC @@ -1503,8 +1537,14 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) { enum_full_complete(); - // Invoke callback if available - if (tuh_mount_cb) tuh_mount_cb(dev_addr); +#if CFG_TUH_HUB + // skip device mount callback for hub + if ( !is_hub_addr(dev_addr) ) +#endif + { + // Invoke callback if available + if (tuh_mount_cb) tuh_mount_cb(dev_addr); + } } } diff --git a/src/host/usbh.h b/src/host/usbh.h index fc0590190..7dffcb453 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -46,7 +46,10 @@ typedef bool (*tuh_control_xfer_cb_t)(uint8_t daddr, tuh_control_xfer_t const * struct tuh_control_xfer_s { - tusb_control_request_t request TU_ATTR_ALIGNED(4); + uint8_t ep_addr; + tusb_control_request_t const* setup; + uint32_t actual_len; + uint8_t* buffer; tuh_control_xfer_cb_t complete_cb; uintptr_t user_arg; @@ -104,14 +107,16 @@ static inline bool tuh_ready(uint8_t daddr) return tuh_mounted(daddr) && !tuh_suspended(daddr); } +//--------------------------------------------------------------------+ +// Endpoint Asynchronous (non-blocking) +//--------------------------------------------------------------------+ + // Carry out a control transfer // true on success, false if there is on-going control transfer or incorrect parameters // Blocking if complete callback is NULL, in this case 'user_arg' must contain xfer_result_t variable -bool tuh_control_xfer (uint8_t daddr, tuh_control_xfer_t const* xfer); +bool tuh_control_xfer(uint8_t daddr, tuh_control_xfer_t const* xfer); -// Sync (blocking) version of tuh_control_xfer() -// return transfer result -uint8_t tuh_control_xfer_sync(uint8_t daddr, tuh_control_xfer_t const* xfer, uint32_t timeout_ms); +//bool tuh_edpt_xfer(uint8_t daddr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); // Set Configuration (control transfer) // config_num = 0 will un-configure device. Note: config_num = config_descriptor_index + 1 @@ -120,6 +125,14 @@ uint8_t tuh_control_xfer_sync(uint8_t daddr, tuh_control_xfer_t const* xfer, uin bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); +//--------------------------------------------------------------------+ +// Endpoint Synchronous (blocking) +//--------------------------------------------------------------------+ + +// Sync (blocking) version of tuh_control_xfer() +// return transfer result +uint8_t tuh_control_xfer_sync(uint8_t daddr, tuh_control_xfer_t const* xfer, uint32_t timeout_ms); + //--------------------------------------------------------------------+ // Descriptors Asynchronous (non-blocking) //--------------------------------------------------------------------+ @@ -201,10 +214,6 @@ uint8_t tuh_descriptor_get_product_string_sync(uint8_t daddr, uint16_t language_ // return transfer result uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, uint8_t timeout_ms); -//--------------------------------------------------------------------+ -// -//--------------------------------------------------------------------+ - #ifdef __cplusplus } #endif From 6df420f7f31b4fbf9b95987211e9ed9fef58ac00 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 17 Mar 2022 16:24:43 +0700 Subject: [PATCH 55/81] move result into transfer struct --- examples/host/bare_api/src/main.c | 6 ++---- src/class/hid/hid_host.c | 20 +++++++++++--------- src/class/msc/msc_host.c | 8 +++----- src/host/hub.c | 31 +++++++++++++++---------------- src/host/usbh.c | 26 +++++++++++++------------- src/host/usbh.h | 6 +++++- 6 files changed, 49 insertions(+), 48 deletions(-) diff --git a/examples/host/bare_api/src/main.c b/examples/host/bare_api/src/main.c index 9e6209991..8da7f6a0c 100644 --- a/examples/host/bare_api/src/main.c +++ b/examples/host/bare_api/src/main.c @@ -115,11 +115,9 @@ static void utf16_to_utf8(uint16_t *temp_buf, size_t buf_len) { ((uint8_t*) temp_buf)[utf8_len] = '\0'; } -bool print_device_descriptor(uint8_t daddr, tuh_control_xfer_t const * xfer, xfer_result_t result) +bool print_device_descriptor(uint8_t daddr, tuh_control_xfer_t const * xfer) { - (void) xfer; - - if ( XFER_RESULT_SUCCESS != result ) + if ( XFER_RESULT_SUCCESS != xfer->result ) { printf("Failed to get device descriptor\r\n"); return false; diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 8c1a5ebc9..564b927e2 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -103,13 +103,13 @@ uint8_t tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance) return hid_itf->protocol_mode; } -static bool set_protocol_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) +static bool set_protocol_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer) { uint8_t const itf_num = (uint8_t) xfer->setup->wIndex; uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - if (XFER_RESULT_SUCCESS == result) hid_itf->protocol_mode = (uint8_t) xfer->setup->wValue; + if (XFER_RESULT_SUCCESS == xfer->result) hid_itf->protocol_mode = (uint8_t) xfer->setup->wValue; if (tuh_hid_set_protocol_complete_cb) { @@ -159,7 +159,7 @@ bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) return _hidh_set_protocol(dev_addr, hid_itf->itf_num, protocol, set_protocol_complete, 0); } -static bool set_report_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) +static bool set_report_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer) { TU_LOG2("HID Set Report complete\r\n"); @@ -171,7 +171,8 @@ static bool set_report_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfe uint8_t const report_type = tu_u16_high(xfer->setup->wValue); uint8_t const report_id = tu_u16_low(xfer->setup->wValue); - tuh_hid_set_report_complete_cb(dev_addr, instance, report_id, report_type, (result == XFER_RESULT_SUCCESS) ? xfer->setup->wLength : 0); + tuh_hid_set_report_complete_cb(dev_addr, instance, report_id, report_type, + (xfer->result == XFER_RESULT_SUCCESS) ? xfer->setup->wLength : 0); } return true; @@ -389,7 +390,7 @@ enum { }; static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len); -static bool process_set_config(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); +static bool process_set_config(uint8_t dev_addr, tuh_control_xfer_t const * xfer); bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) { @@ -397,19 +398,20 @@ bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) request.wIndex = tu_htole16((uint16_t) itf_num); tuh_control_xfer_t xfer; + xfer.result = XFER_RESULT_SUCCESS; xfer.setup = &request; xfer.user_arg = CONFG_SET_IDLE; - // fake request to start the set config process - return process_set_config(dev_addr, &xfer, XFER_RESULT_SUCCESS); + // fake request to kick-off the set config process + return process_set_config(dev_addr, &xfer); } -static bool process_set_config(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) +static bool process_set_config(uint8_t dev_addr, tuh_control_xfer_t const * xfer) { // Stall is a valid response for SET_IDLE, therefore we could ignore its result if ( xfer->setup->bRequest != HID_REQ_CONTROL_SET_IDLE ) { - TU_ASSERT(result == XFER_RESULT_SUCCESS); + TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS); } uintptr_t const state = xfer->user_arg; diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index d8910db0f..ca1080eba 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -358,7 +358,7 @@ bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 // MSC Enumeration //--------------------------------------------------------------------+ -static bool config_get_maxlun_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); +static bool config_get_maxlun_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer); static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); @@ -432,14 +432,12 @@ bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) return true; } -static bool config_get_maxlun_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) +static bool config_get_maxlun_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer) { - (void) xfer; - msch_interface_t* p_msc = get_itf(dev_addr); // STALL means zero - p_msc->max_lun = (XFER_RESULT_SUCCESS == result) ? _msch_buffer[0] : 0; + p_msc->max_lun = (XFER_RESULT_SUCCESS == xfer->result) ? _msch_buffer[0] : 0; p_msc->max_lun++; // MAX LUN is minus 1 by specs // TODO multiple LUN support diff --git a/src/host/hub.c b/src/host/hub.c index 6ce9e4cc6..5255fdf7c 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -225,8 +225,8 @@ bool hub_edpt_status_xfer(uint8_t dev_addr) // Set Configure //--------------------------------------------------------------------+ -static bool config_set_port_power (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); -static bool config_port_power_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); +static bool config_set_port_power (uint8_t dev_addr, tuh_control_xfer_t const * xfer); +static bool config_port_power_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer); bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) { @@ -262,10 +262,9 @@ bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) return true; } -static bool config_set_port_power (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) +static bool config_set_port_power (uint8_t dev_addr, tuh_control_xfer_t const * xfer) { - (void) xfer; - TU_ASSERT(XFER_RESULT_SUCCESS == result); + TU_ASSERT(XFER_RESULT_SUCCESS == xfer->result); hub_interface_t* p_hub = get_itf(dev_addr); @@ -280,9 +279,9 @@ static bool config_set_port_power (uint8_t dev_addr, tuh_control_xfer_t const * return hub_port_set_feature(dev_addr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete, 0); } -static bool config_port_power_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) +static bool config_port_power_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer) { - TU_ASSERT(XFER_RESULT_SUCCESS == result); + TU_ASSERT(XFER_RESULT_SUCCESS == xfer->result); hub_interface_t* p_hub = get_itf(dev_addr); if (xfer->setup->wIndex == p_hub->port_count) @@ -306,9 +305,9 @@ static bool config_port_power_complete (uint8_t dev_addr, tuh_control_xfer_t con // Connection Changes //--------------------------------------------------------------------+ -static bool connection_get_status_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); -static bool connection_clear_conn_change_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); -static bool connection_port_reset_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result); +static bool connection_get_status_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer); +static bool connection_clear_conn_change_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer); +static bool connection_port_reset_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer); // callback as response of interrupt endpoint polling bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) @@ -336,9 +335,9 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32 return true; } -static bool connection_get_status_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) +static bool connection_get_status_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer) { - TU_ASSERT(result == XFER_RESULT_SUCCESS); + TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS); hub_interface_t* p_hub = get_itf(dev_addr); uint8_t const port_num = (uint8_t) xfer->setup->wIndex; @@ -364,9 +363,9 @@ static bool connection_get_status_complete (uint8_t dev_addr, tuh_control_xfer_t return true; } -static bool connection_clear_conn_change_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) +static bool connection_clear_conn_change_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer) { - TU_ASSERT(result == XFER_RESULT_SUCCESS); + TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS); hub_interface_t* p_hub = get_itf(dev_addr); uint8_t const port_num = (uint8_t) xfer->setup->wIndex; @@ -395,9 +394,9 @@ static bool connection_clear_conn_change_complete (uint8_t dev_addr, tuh_control return true; } -static bool connection_port_reset_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) +static bool connection_port_reset_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer) { - TU_ASSERT(result == XFER_RESULT_SUCCESS); + TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS); // hub_interface_t* p_hub = get_itf(dev_addr); uint8_t const port_num = (uint8_t) xfer->setup->wIndex; diff --git a/src/host/usbh.c b/src/host/usbh.c index d2d819ec2..00afe609f 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -882,12 +882,12 @@ bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) // Control transfer //--------------------------------------------------------------------+ -static bool _control_blocking_complete_cb(uint8_t daddr, tuh_control_xfer_t const * xfer, xfer_result_t result) +static bool _control_blocking_complete_cb(uint8_t daddr, tuh_control_xfer_t const * xfer) { (void) daddr; // update result - *((xfer_result_t*) xfer->user_arg) = result; + *((xfer_result_t*) xfer->user_arg) = xfer->result; return true; } @@ -924,19 +924,17 @@ bool tuh_control_xfer (uint8_t daddr, tuh_control_xfer_t const* xfer) TU_ASSERT( hcd_setup_send(rhport, daddr, (uint8_t*) &_ctrl_xfer.request) ); }else { - // user_arg must point to xfer_result_t to hold result - TU_VERIFY(xfer->user_arg); - // blocking if complete callback is not provided // change callback to internal blocking, and result as user argument - volatile xfer_result_t* result = (volatile xfer_result_t*) xfer->user_arg; + volatile xfer_result_t result = XFER_RESULT_INVALID; + // use user_arg to point to xfer_result_t + _ctrl_xfer.user_arg = (uintptr_t) &result; _ctrl_xfer.complete_cb = _control_blocking_complete_cb; - *result = XFER_RESULT_INVALID; TU_ASSERT( hcd_setup_send(rhport, daddr, (uint8_t*) &_ctrl_xfer.request) ); - while ((*result) == XFER_RESULT_INVALID) + while (result == XFER_RESULT_INVALID) { // only need to call task if not preempted RTOS #if CFG_TUSB_OS == OPT_OS_NONE || CFG_TUSB_OS == OPT_OS_PICO @@ -982,6 +980,7 @@ static void _xfer_complete(uint8_t dev_addr, xfer_result_t result) tuh_control_xfer_t const xfer_temp = { .ep_addr = 0, + .result = result, .setup = &request, .actual_len = 0, .buffer = _ctrl_xfer.buffer, @@ -995,7 +994,7 @@ static void _xfer_complete(uint8_t dev_addr, xfer_result_t result) if (xfer_temp.complete_cb) { - xfer_temp.complete_cb(dev_addr, &xfer_temp, result); + xfer_temp.complete_cb(dev_addr, &xfer_temp); } } @@ -1120,9 +1119,9 @@ static bool parse_configuration_descriptor (uint8_t dev_addr, tusb_desc_configur static void enum_full_complete(void); // process device enumeration -static bool process_enumeration(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result) +static bool process_enumeration(uint8_t dev_addr, tuh_control_xfer_t const * xfer) { - if (XFER_RESULT_SUCCESS != result) + if (XFER_RESULT_SUCCESS != xfer->result) { // stop enumeration, maybe we could retry this enum_full_complete(); @@ -1323,11 +1322,12 @@ static bool enum_new_device(hcd_event_t* event) _dev0.speed = hcd_port_speed_get(_dev0.rhport ); TU_LOG2("%s Speed\r\n", tu_str_speed[_dev0.speed]); - // start the enumeration process + // fake transfer to kick-off the enumeration process tuh_control_xfer_t xfer; + xfer.result = XFER_RESULT_SUCCESS; xfer.user_arg = ENUM_ADDR0_DEVICE_DESC; - process_enumeration(0, &xfer, XFER_RESULT_SUCCESS); + process_enumeration(0, &xfer); } #if CFG_TUH_HUB diff --git a/src/host/usbh.h b/src/host/usbh.h index 7dffcb453..a2372ad01 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -42,15 +42,19 @@ struct tuh_control_xfer_s; typedef struct tuh_control_xfer_s tuh_control_xfer_t; -typedef bool (*tuh_control_xfer_cb_t)(uint8_t daddr, tuh_control_xfer_t const * xfer, xfer_result_t result); +typedef bool (*tuh_control_xfer_cb_t)(uint8_t daddr, tuh_control_xfer_t const * xfer); struct tuh_control_xfer_s { uint8_t ep_addr; + xfer_result_t result; + tusb_control_request_t const* setup; uint32_t actual_len; uint8_t* buffer; + + tuh_control_xfer_cb_t complete_cb; uintptr_t user_arg; }; From deab8c276a41577eef3d4f4bd3663a5e1860a76a Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 17 Mar 2022 16:53:54 +0700 Subject: [PATCH 56/81] remove const in xfer callback --- src/class/hid/hid_host.c | 8 ++++---- src/class/msc/msc_host.c | 4 ++-- src/host/hub.c | 20 ++++++++++---------- src/host/usbh.c | 11 +++++++---- src/host/usbh.h | 4 ++-- 5 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 564b927e2..45090d193 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -103,7 +103,7 @@ uint8_t tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance) return hid_itf->protocol_mode; } -static bool set_protocol_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer) +static bool set_protocol_complete(uint8_t dev_addr, tuh_control_xfer_t* xfer) { uint8_t const itf_num = (uint8_t) xfer->setup->wIndex; uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); @@ -159,7 +159,7 @@ bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) return _hidh_set_protocol(dev_addr, hid_itf->itf_num, protocol, set_protocol_complete, 0); } -static bool set_report_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer) +static bool set_report_complete(uint8_t dev_addr, tuh_control_xfer_t* xfer) { TU_LOG2("HID Set Report complete\r\n"); @@ -390,7 +390,7 @@ enum { }; static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len); -static bool process_set_config(uint8_t dev_addr, tuh_control_xfer_t const * xfer); +static bool process_set_config(uint8_t dev_addr, tuh_control_xfer_t* xfer); bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) { @@ -406,7 +406,7 @@ bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) return process_set_config(dev_addr, &xfer); } -static bool process_set_config(uint8_t dev_addr, tuh_control_xfer_t const * xfer) +static bool process_set_config(uint8_t dev_addr, tuh_control_xfer_t* xfer) { // Stall is a valid response for SET_IDLE, therefore we could ignore its result if ( xfer->setup->bRequest != HID_REQ_CONTROL_SET_IDLE ) diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index ca1080eba..0a3deb2c9 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -358,7 +358,7 @@ bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 // MSC Enumeration //--------------------------------------------------------------------+ -static bool config_get_maxlun_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer); +static bool config_get_maxlun_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer); static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); @@ -432,7 +432,7 @@ bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) return true; } -static bool config_get_maxlun_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer) +static bool config_get_maxlun_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer) { msch_interface_t* p_msc = get_itf(dev_addr); diff --git a/src/host/hub.c b/src/host/hub.c index 5255fdf7c..75596d748 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -225,8 +225,8 @@ bool hub_edpt_status_xfer(uint8_t dev_addr) // Set Configure //--------------------------------------------------------------------+ -static bool config_set_port_power (uint8_t dev_addr, tuh_control_xfer_t const * xfer); -static bool config_port_power_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer); +static bool config_set_port_power (uint8_t dev_addr, tuh_control_xfer_t* xfer); +static bool config_port_power_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer); bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) { @@ -262,7 +262,7 @@ bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) return true; } -static bool config_set_port_power (uint8_t dev_addr, tuh_control_xfer_t const * xfer) +static bool config_set_port_power (uint8_t dev_addr, tuh_control_xfer_t* xfer) { TU_ASSERT(XFER_RESULT_SUCCESS == xfer->result); @@ -279,7 +279,7 @@ static bool config_set_port_power (uint8_t dev_addr, tuh_control_xfer_t const * return hub_port_set_feature(dev_addr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete, 0); } -static bool config_port_power_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer) +static bool config_port_power_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer) { TU_ASSERT(XFER_RESULT_SUCCESS == xfer->result); hub_interface_t* p_hub = get_itf(dev_addr); @@ -305,9 +305,9 @@ static bool config_port_power_complete (uint8_t dev_addr, tuh_control_xfer_t con // Connection Changes //--------------------------------------------------------------------+ -static bool connection_get_status_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer); -static bool connection_clear_conn_change_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer); -static bool connection_port_reset_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer); +static bool connection_get_status_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer); +static bool connection_clear_conn_change_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer); +static bool connection_port_reset_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer); // callback as response of interrupt endpoint polling bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) @@ -335,7 +335,7 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32 return true; } -static bool connection_get_status_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer) +static bool connection_get_status_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer) { TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS); @@ -363,7 +363,7 @@ static bool connection_get_status_complete (uint8_t dev_addr, tuh_control_xfer_t return true; } -static bool connection_clear_conn_change_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer) +static bool connection_clear_conn_change_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer) { TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS); @@ -394,7 +394,7 @@ static bool connection_clear_conn_change_complete (uint8_t dev_addr, tuh_control return true; } -static bool connection_port_reset_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer) +static bool connection_port_reset_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer) { TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS); diff --git a/src/host/usbh.c b/src/host/usbh.c index 00afe609f..09b4c0487 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -882,7 +882,7 @@ bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) // Control transfer //--------------------------------------------------------------------+ -static bool _control_blocking_complete_cb(uint8_t daddr, tuh_control_xfer_t const * xfer) +static bool _control_blocking_complete_cb(uint8_t daddr, tuh_control_xfer_t* xfer) { (void) daddr; @@ -943,12 +943,15 @@ bool tuh_control_xfer (uint8_t daddr, tuh_control_xfer_t const* xfer) // TODO probably some timeout to prevent hanged } + + // update result + //xfer->result = result; } return true; } -uint8_t tuh_control_xfer_sync(uint8_t daddr, tuh_control_xfer_t const* xfer, uint32_t timeout_ms) +bool tuh_control_xfer_sync(uint8_t daddr, tuh_control_xfer_t* xfer, uint32_t timeout_ms) { (void) timeout_ms; @@ -977,7 +980,7 @@ static void _xfer_complete(uint8_t dev_addr, xfer_result_t result) // duplicate xfer since user can execute control transfer within callback tusb_control_request_t const request = _ctrl_xfer.request; - tuh_control_xfer_t const xfer_temp = + tuh_control_xfer_t xfer_temp = { .ep_addr = 0, .result = result, @@ -1119,7 +1122,7 @@ static bool parse_configuration_descriptor (uint8_t dev_addr, tusb_desc_configur static void enum_full_complete(void); // process device enumeration -static bool process_enumeration(uint8_t dev_addr, tuh_control_xfer_t const * xfer) +static bool process_enumeration(uint8_t dev_addr, tuh_control_xfer_t* xfer) { if (XFER_RESULT_SUCCESS != xfer->result) { diff --git a/src/host/usbh.h b/src/host/usbh.h index a2372ad01..e5f86d73d 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -42,7 +42,7 @@ struct tuh_control_xfer_s; typedef struct tuh_control_xfer_s tuh_control_xfer_t; -typedef bool (*tuh_control_xfer_cb_t)(uint8_t daddr, tuh_control_xfer_t const * xfer); +typedef bool (*tuh_control_xfer_cb_t)(uint8_t daddr, tuh_control_xfer_t* xfer); struct tuh_control_xfer_s { @@ -135,7 +135,7 @@ bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, // Sync (blocking) version of tuh_control_xfer() // return transfer result -uint8_t tuh_control_xfer_sync(uint8_t daddr, tuh_control_xfer_t const* xfer, uint32_t timeout_ms); +bool tuh_control_xfer_sync(uint8_t daddr, tuh_control_xfer_t * xfer, uint32_t timeout_ms); //--------------------------------------------------------------------+ // Descriptors Asynchronous (non-blocking) From 66942b814b6e24ecfe7db567b29f2e1d114071c1 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 17 Mar 2022 16:55:29 +0700 Subject: [PATCH 57/81] change return type of callback to void --- src/class/hid/hid_host.c | 35 ++++++++++++++-------------- src/class/msc/msc_host.c | 6 ++--- src/host/hub.c | 50 +++++++++++++++++----------------------- src/host/usbh.c | 43 +++++++++++++++------------------- src/host/usbh.h | 2 +- 5 files changed, 60 insertions(+), 76 deletions(-) diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 45090d193..7986ffc1a 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -103,20 +103,21 @@ uint8_t tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance) return hid_itf->protocol_mode; } -static bool set_protocol_complete(uint8_t dev_addr, tuh_control_xfer_t* xfer) +static void set_protocol_complete(uint8_t dev_addr, tuh_control_xfer_t* xfer) { - uint8_t const itf_num = (uint8_t) xfer->setup->wIndex; + uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - if (XFER_RESULT_SUCCESS == xfer->result) hid_itf->protocol_mode = (uint8_t) xfer->setup->wValue; + if (XFER_RESULT_SUCCESS == xfer->result) + { + hid_itf->protocol_mode = (uint8_t) tu_le16toh(xfer->setup->wValue); + } if (tuh_hid_set_protocol_complete_cb) { tuh_hid_set_protocol_complete_cb(dev_addr, instance, hid_itf->protocol_mode); } - - return true; } @@ -159,13 +160,13 @@ bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) return _hidh_set_protocol(dev_addr, hid_itf->itf_num, protocol, set_protocol_complete, 0); } -static bool set_report_complete(uint8_t dev_addr, tuh_control_xfer_t* xfer) +static void set_report_complete(uint8_t dev_addr, tuh_control_xfer_t* xfer) { TU_LOG2("HID Set Report complete\r\n"); if (tuh_hid_set_report_complete_cb) { - uint8_t const itf_num = (uint8_t) xfer->setup->wIndex; + uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); uint8_t const report_type = tu_u16_high(xfer->setup->wValue); @@ -174,8 +175,6 @@ static bool set_report_complete(uint8_t dev_addr, tuh_control_xfer_t* xfer) tuh_hid_set_report_complete_cb(dev_addr, instance, report_id, report_type, (xfer->result == XFER_RESULT_SUCCESS) ? xfer->setup->wLength : 0); } - - return true; } bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, void* report, uint16_t len) @@ -390,7 +389,7 @@ enum { }; static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len); -static bool process_set_config(uint8_t dev_addr, tuh_control_xfer_t* xfer); +static void process_set_config(uint8_t dev_addr, tuh_control_xfer_t* xfer); bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) { @@ -403,15 +402,17 @@ bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) xfer.user_arg = CONFG_SET_IDLE; // fake request to kick-off the set config process - return process_set_config(dev_addr, &xfer); + process_set_config(dev_addr, &xfer); + + return true; } -static bool process_set_config(uint8_t dev_addr, tuh_control_xfer_t* xfer) +static void process_set_config(uint8_t dev_addr, tuh_control_xfer_t* xfer) { // Stall is a valid response for SET_IDLE, therefore we could ignore its result if ( xfer->setup->bRequest != HID_REQ_CONTROL_SET_IDLE ) { - TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS); + TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); } uintptr_t const state = xfer->user_arg; @@ -426,12 +427,12 @@ static bool process_set_config(uint8_t dev_addr, tuh_control_xfer_t* xfer) // Idle rate = 0 mean only report when there is changes const uint16_t idle_rate = 0; const uintptr_t next_state = (hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE) ? CONFIG_SET_PROTOCOL : CONFIG_GET_REPORT_DESC; - TU_VERIFY( _hidh_set_idle(dev_addr, itf_num, idle_rate, process_set_config, next_state) ); + _hidh_set_idle(dev_addr, itf_num, idle_rate, process_set_config, next_state); } break; case CONFIG_SET_PROTOCOL: - TU_VERIFY(_hidh_set_protocol(dev_addr, hid_itf->itf_num, HID_PROTOCOL_BOOT, process_set_config, CONFIG_GET_REPORT_DESC)); + _hidh_set_protocol(dev_addr, hid_itf->itf_num, HID_PROTOCOL_BOOT, process_set_config, CONFIG_GET_REPORT_DESC); break; case CONFIG_GET_REPORT_DESC: @@ -445,7 +446,7 @@ static bool process_set_config(uint8_t dev_addr, tuh_control_xfer_t* xfer) config_driver_mount_complete(dev_addr, instance, NULL, 0); }else { - TU_ASSERT(tuh_descriptor_get_hid_report(dev_addr, itf_num, hid_itf->report_desc_type, 0, usbh_get_enum_buf(), hid_itf->report_desc_len, process_set_config, CONFIG_COMPLETE)); + tuh_descriptor_get_hid_report(dev_addr, itf_num, hid_itf->report_desc_type, 0, usbh_get_enum_buf(), hid_itf->report_desc_len, process_set_config, CONFIG_COMPLETE); } break; @@ -460,8 +461,6 @@ static bool process_set_config(uint8_t dev_addr, tuh_control_xfer_t* xfer) default: break; } - - return true; } static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 0a3deb2c9..ca51d63fa 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -358,7 +358,7 @@ bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 // MSC Enumeration //--------------------------------------------------------------------+ -static bool config_get_maxlun_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer); +static void config_get_maxlun_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer); static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); @@ -432,7 +432,7 @@ bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) return true; } -static bool config_get_maxlun_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer) +static void config_get_maxlun_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer) { msch_interface_t* p_msc = get_itf(dev_addr); @@ -444,8 +444,6 @@ static bool config_get_maxlun_complete (uint8_t dev_addr, tuh_control_xfer_t* xf TU_LOG2("SCSI Test Unit Ready\r\n"); uint8_t const lun = 0; tuh_msc_test_unit_ready(dev_addr, lun, config_test_unit_ready_complete); - - return true; } static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) diff --git a/src/host/hub.c b/src/host/hub.c index 75596d748..9f17b7eda 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -225,8 +225,8 @@ bool hub_edpt_status_xfer(uint8_t dev_addr) // Set Configure //--------------------------------------------------------------------+ -static bool config_set_port_power (uint8_t dev_addr, tuh_control_xfer_t* xfer); -static bool config_port_power_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer); +static void config_set_port_power (uint8_t dev_addr, tuh_control_xfer_t* xfer); +static void config_port_power_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer); bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) { @@ -262,9 +262,9 @@ bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) return true; } -static bool config_set_port_power (uint8_t dev_addr, tuh_control_xfer_t* xfer) +static void config_set_port_power (uint8_t dev_addr, tuh_control_xfer_t* xfer) { - TU_ASSERT(XFER_RESULT_SUCCESS == xfer->result); + TU_ASSERT(XFER_RESULT_SUCCESS == xfer->result, ); hub_interface_t* p_hub = get_itf(dev_addr); @@ -276,38 +276,36 @@ static bool config_set_port_power (uint8_t dev_addr, tuh_control_xfer_t* xfer) // Set Port Power to be able to detect connection, starting with port 1 uint8_t const hub_port = 1; - return hub_port_set_feature(dev_addr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete, 0); + hub_port_set_feature(dev_addr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete, 0); } -static bool config_port_power_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer) +static void config_port_power_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer) { - TU_ASSERT(XFER_RESULT_SUCCESS == xfer->result); + TU_ASSERT(XFER_RESULT_SUCCESS == xfer->result, ); hub_interface_t* p_hub = get_itf(dev_addr); if (xfer->setup->wIndex == p_hub->port_count) { // All ports are power -> queue notification status endpoint and // complete the SET CONFIGURATION - TU_ASSERT( usbh_edpt_xfer(dev_addr, p_hub->ep_in, &p_hub->status_change, 1) ); + TU_ASSERT( usbh_edpt_xfer(dev_addr, p_hub->ep_in, &p_hub->status_change, 1), ); usbh_driver_set_config_complete(dev_addr, p_hub->itf_num); }else { // power next port uint8_t const hub_port = (uint8_t) (xfer->setup->wIndex + 1); - return hub_port_set_feature(dev_addr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete, 0); + hub_port_set_feature(dev_addr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete, 0); } - - return true; } //--------------------------------------------------------------------+ // Connection Changes //--------------------------------------------------------------------+ -static bool connection_get_status_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer); -static bool connection_clear_conn_change_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer); -static bool connection_port_reset_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer); +static void connection_get_status_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer); +static void connection_clear_conn_change_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer); +static void connection_port_reset_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer); // callback as response of interrupt endpoint polling bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) @@ -335,12 +333,12 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32 return true; } -static bool connection_get_status_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer) +static void connection_get_status_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer) { - TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS); + TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); hub_interface_t* p_hub = get_itf(dev_addr); - uint8_t const port_num = (uint8_t) xfer->setup->wIndex; + uint8_t const port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); // Connection change if (p_hub->port_status.change.connection) @@ -359,16 +357,14 @@ static bool connection_get_status_complete (uint8_t dev_addr, tuh_control_xfer_t // TODO continue with status_change, or maybe we can do it again with status hub_edpt_status_xfer(dev_addr); } - - return true; } -static bool connection_clear_conn_change_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer) +static void connection_clear_conn_change_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer) { - TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS); + TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); hub_interface_t* p_hub = get_itf(dev_addr); - uint8_t const port_num = (uint8_t) xfer->setup->wIndex; + uint8_t const port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); if ( p_hub->port_status.status.connection ) { @@ -390,16 +386,14 @@ static bool connection_clear_conn_change_complete (uint8_t dev_addr, tuh_control hcd_event_handler(&event, false); } - - return true; } -static bool connection_port_reset_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer) +static void connection_port_reset_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer) { - TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS); + TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); // hub_interface_t* p_hub = get_itf(dev_addr); - uint8_t const port_num = (uint8_t) xfer->setup->wIndex; + uint8_t const port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); // submit attach event hcd_event_t event = @@ -414,8 +408,6 @@ static bool connection_port_reset_complete (uint8_t dev_addr, tuh_control_xfer_t }; hcd_event_handler(&event, false); - - return true; } #endif diff --git a/src/host/usbh.c b/src/host/usbh.c index 09b4c0487..3ab72ac0e 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -882,14 +882,11 @@ bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) // Control transfer //--------------------------------------------------------------------+ -static bool _control_blocking_complete_cb(uint8_t daddr, tuh_control_xfer_t* xfer) +static void _control_blocking_complete_cb(uint8_t daddr, tuh_control_xfer_t* xfer) { (void) daddr; - // update result *((xfer_result_t*) xfer->user_arg) = xfer->result; - - return true; } bool tuh_control_xfer (uint8_t daddr, tuh_control_xfer_t const* xfer) @@ -1122,13 +1119,13 @@ static bool parse_configuration_descriptor (uint8_t dev_addr, tusb_desc_configur static void enum_full_complete(void); // process device enumeration -static bool process_enumeration(uint8_t dev_addr, tuh_control_xfer_t* xfer) +static void process_enumeration(uint8_t dev_addr, tuh_control_xfer_t* xfer) { if (XFER_RESULT_SUCCESS != xfer->result) { // stop enumeration, maybe we could retry this enum_full_complete(); - return false; + return; } uintptr_t const state = xfer->user_arg; @@ -1146,7 +1143,7 @@ static bool process_enumeration(uint8_t dev_addr, tuh_control_xfer_t* xfer) { // device unplugged while delaying, nothing else to do enum_full_complete(); - return false; + return; } _dev0.speed = (port_status.status.high_speed) ? TUSB_SPEED_HIGH : @@ -1162,7 +1159,7 @@ static bool process_enumeration(uint8_t dev_addr, tuh_control_xfer_t* xfer) case ENUM_HUB_GET_STATUS_2: osal_task_delay(RESET_DELAY); - TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, process_enumeration, ENUM_HUB_CLEAR_RESET_2) ); + TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, process_enumeration, ENUM_HUB_CLEAR_RESET_2), ); break; case ENUM_HUB_CLEAR_RESET_2: @@ -1173,7 +1170,7 @@ static bool process_enumeration(uint8_t dev_addr, tuh_control_xfer_t* xfer) // Acknowledge Port Reset Change if Reset Successful if (port_status.change.reset) { - TU_ASSERT( hub_port_clear_reset_change(_dev0.hub_addr, _dev0.hub_port, process_enumeration, ENUM_SET_ADDR) ); + TU_ASSERT( hub_port_clear_reset_change(_dev0.hub_addr, _dev0.hub_port, process_enumeration, ENUM_SET_ADDR), ); } } break; @@ -1183,11 +1180,11 @@ static bool process_enumeration(uint8_t dev_addr, tuh_control_xfer_t* xfer) { // TODO probably doesn't need to open/close each enumeration uint8_t const addr0 = 0; - TU_ASSERT( usbh_edpt_control_open(addr0, 8) ); + 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_ASSERT(tuh_descriptor_get_device(addr0, _usbh_ctrl_buf, 8, process_enumeration, ENUM_SET_ADDR)); + TU_ASSERT(tuh_descriptor_get_device(addr0, _usbh_ctrl_buf, 8, process_enumeration, ENUM_SET_ADDR), ); } break; @@ -1206,7 +1203,7 @@ static bool process_enumeration(uint8_t dev_addr, tuh_control_xfer_t* xfer) else { // after RESET_DELAY the hub_port_reset() already complete - TU_ASSERT( hub_port_reset(_dev0.hub_addr, _dev0.hub_port, process_enumeration, ENUM_HUB_GET_STATUS_2) ); + TU_ASSERT( hub_port_reset(_dev0.hub_addr, _dev0.hub_port, process_enumeration, ENUM_HUB_GET_STATUS_2), ); break; } #endif @@ -1221,18 +1218,18 @@ static bool process_enumeration(uint8_t dev_addr, tuh_control_xfer_t* xfer) uint8_t const new_addr = (uint8_t) tu_le16toh(xfer->setup->wValue); usbh_device_t* new_dev = get_device(new_addr); - TU_ASSERT(new_dev); + TU_ASSERT(new_dev, ); new_dev->addressed = 1; // TODO close device 0, may not be needed hcd_device_close(_dev0.rhport, 0); // open control pipe for new address - TU_ASSERT( usbh_edpt_control_open(new_addr, new_dev->ep0_size) ); + TU_ASSERT( usbh_edpt_control_open(new_addr, new_dev->ep0_size), ); // Get full device descriptor TU_LOG2("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)); + TU_ASSERT(tuh_descriptor_get_device(new_addr, _usbh_ctrl_buf, sizeof(tusb_desc_device_t), process_enumeration, ENUM_GET_9BYTE_CONFIG_DESC), ); } break; @@ -1240,7 +1237,7 @@ static bool process_enumeration(uint8_t dev_addr, tuh_control_xfer_t* xfer) { tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf; usbh_device_t* dev = get_device(dev_addr); - TU_ASSERT(dev); + TU_ASSERT(dev, ); dev->vid = desc_device->idVendor; dev->pid = desc_device->idProduct; @@ -1253,7 +1250,7 @@ static bool process_enumeration(uint8_t dev_addr, tuh_control_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_ASSERT( tuh_descriptor_get_configuration(dev_addr, config_idx, _usbh_ctrl_buf, 9, process_enumeration, ENUM_GET_FULL_CONFIG_DESC) ); + TU_ASSERT( tuh_descriptor_get_configuration(dev_addr, config_idx, _usbh_ctrl_buf, 9, process_enumeration, ENUM_GET_FULL_CONFIG_DESC), ); } break; @@ -1265,28 +1262,28 @@ static bool process_enumeration(uint8_t dev_addr, tuh_control_xfer_t* xfer) uint16_t const total_len = tu_le16toh( tu_unaligned_read16(desc_config + offsetof(tusb_desc_configuration_t, wTotalLength)) ); // TODO not enough buffer to hold configuration descriptor - TU_ASSERT(total_len <= CFG_TUH_ENUMERATION_BUFSIZE); + TU_ASSERT(total_len <= CFG_TUH_ENUMERATION_BUFSIZE, ); // Get full configuration descriptor uint8_t const config_idx = CONFIG_NUM - 1; TU_LOG2("Get Configuration[0] Descriptor\r\n"); - TU_ASSERT( tuh_descriptor_get_configuration(dev_addr, config_idx, _usbh_ctrl_buf, total_len, process_enumeration, ENUM_SET_CONFIG) ); + TU_ASSERT( tuh_descriptor_get_configuration(dev_addr, config_idx, _usbh_ctrl_buf, total_len, process_enumeration, ENUM_SET_CONFIG), ); } break; case ENUM_SET_CONFIG: // Parse configuration & set up drivers // Driver open aren't allowed to make any usb transfer yet - TU_ASSERT( parse_configuration_descriptor(dev_addr, (tusb_desc_configuration_t*) _usbh_ctrl_buf) ); + TU_ASSERT( parse_configuration_descriptor(dev_addr, (tusb_desc_configuration_t*) _usbh_ctrl_buf), ); - TU_ASSERT( tuh_configuration_set(dev_addr, CONFIG_NUM, process_enumeration, ENUM_CONFIG_DRIVER) ); + TU_ASSERT( tuh_configuration_set(dev_addr, CONFIG_NUM, process_enumeration, ENUM_CONFIG_DRIVER), ); break; case ENUM_CONFIG_DRIVER: { TU_LOG2("Device configured\r\n"); usbh_device_t* dev = get_device(dev_addr); - TU_ASSERT(dev); + TU_ASSERT(dev, ); dev->configured = 1; @@ -1303,8 +1300,6 @@ static bool process_enumeration(uint8_t dev_addr, tuh_control_xfer_t* xfer) enum_full_complete(); break; } - - return true; } static bool enum_new_device(hcd_event_t* event) diff --git a/src/host/usbh.h b/src/host/usbh.h index e5f86d73d..ec6be67dc 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -42,7 +42,7 @@ struct tuh_control_xfer_s; typedef struct tuh_control_xfer_s tuh_control_xfer_t; -typedef bool (*tuh_control_xfer_cb_t)(uint8_t daddr, tuh_control_xfer_t* xfer); +typedef void (*tuh_control_xfer_cb_t)(uint8_t daddr, tuh_control_xfer_t* xfer); struct tuh_control_xfer_s { From 1ee699d49d6da7ce8b92cde1636e34ed90ff6396 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 17 Mar 2022 16:56:56 +0700 Subject: [PATCH 58/81] update example --- examples/host/bare_api/src/main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/examples/host/bare_api/src/main.c b/examples/host/bare_api/src/main.c index 8da7f6a0c..3f0b9ef22 100644 --- a/examples/host/bare_api/src/main.c +++ b/examples/host/bare_api/src/main.c @@ -115,12 +115,12 @@ static void utf16_to_utf8(uint16_t *temp_buf, size_t buf_len) { ((uint8_t*) temp_buf)[utf8_len] = '\0'; } -bool print_device_descriptor(uint8_t daddr, tuh_control_xfer_t const * xfer) +void print_device_descriptor(uint8_t daddr, tuh_control_xfer_t* xfer) { if ( XFER_RESULT_SUCCESS != xfer->result ) { printf("Failed to get device descriptor\r\n"); - return false; + return; } printf("Device %u: ID %04x:%04x\r\n", daddr, desc_device.idVendor, desc_device.idProduct); @@ -164,8 +164,6 @@ bool print_device_descriptor(uint8_t daddr, tuh_control_xfer_t const * xfer) printf("\r\n"); printf(" bNumConfigurations %u\r\n" , desc_device.bNumConfigurations); - - return true; } // Invoked when device is mounted (configured) From 8aedb2ff37901d2d08c28308e2527d73ab179f5c Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 17 Mar 2022 17:25:53 +0700 Subject: [PATCH 59/81] slightly change the signature of tuh_control_xfer --- src/class/cdc/cdc_host.c | 2 +- src/class/hid/hid_host.c | 6 +++--- src/class/msc/msc_host.c | 2 +- src/host/hub.c | 8 ++++---- src/host/usbh.c | 10 +++++----- src/host/usbh.h | 4 +--- 6 files changed, 15 insertions(+), 17 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 9838df818..7ae8af77a 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -138,7 +138,7 @@ bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_co .wLength = 0 }; - tuh_control_xfer_t const xfer = + tuh_control_xfer_t xfer = { .ep_addr = 0, .setup = &request, diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 7986ffc1a..65fccd32a 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -139,7 +139,7 @@ static bool _hidh_set_protocol(uint8_t dev_addr, uint8_t itf_num, uint8_t protoc .wLength = 0 }; - tuh_control_xfer_t const xfer = + tuh_control_xfer_t xfer = { .ep_addr = 0, .setup = &request, @@ -196,7 +196,7 @@ bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, u .wLength = len }; - tuh_control_xfer_t const xfer = + tuh_control_xfer_t xfer = { .ep_addr = 0, .setup = &request, @@ -227,7 +227,7 @@ static bool _hidh_set_idle(uint8_t dev_addr, uint8_t itf_num, uint16_t idle_rate .wLength = 0 }; - tuh_control_xfer_t const xfer = + tuh_control_xfer_t xfer = { .ep_addr = 0, .setup = &request, diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index ca51d63fa..fea587386 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -419,7 +419,7 @@ bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) .wLength = 1 }; - tuh_control_xfer_t const xfer = + tuh_control_xfer_t xfer = { .ep_addr = 0, .setup = &request, diff --git a/src/host/hub.c b/src/host/hub.c index 9f17b7eda..36f27398f 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -94,7 +94,7 @@ bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, .wLength = 0 }; - tuh_control_xfer_t const xfer = + tuh_control_xfer_t xfer = { .ep_addr = 0, .setup = &request, @@ -125,7 +125,7 @@ bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, .wLength = 0 }; - tuh_control_xfer_t const xfer = + tuh_control_xfer_t xfer = { .ep_addr = 0, .setup = &request, @@ -156,7 +156,7 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, .wLength = 4 }; - tuh_control_xfer_t const xfer = + tuh_control_xfer_t xfer = { .ep_addr = 0, .setup = &request, @@ -248,7 +248,7 @@ bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) .wLength = sizeof(descriptor_hub_desc_t) }; - tuh_control_xfer_t const xfer = + tuh_control_xfer_t xfer = { .ep_addr = 0, .setup = &request, diff --git a/src/host/usbh.c b/src/host/usbh.c index 3ab72ac0e..2d01c9144 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -326,7 +326,7 @@ static bool _get_descriptor(uint8_t daddr, uint8_t type, uint8_t index, uint16_t .wLength = tu_htole16(len) }; - tuh_control_xfer_t const xfer = + tuh_control_xfer_t xfer = { .ep_addr = 0, .setup = &request, @@ -411,7 +411,7 @@ bool tuh_descriptor_get_hid_report(uint8_t daddr, uint8_t itf_num, uint8_t desc_ .wLength = len }; - tuh_control_xfer_t const xfer = + tuh_control_xfer_t xfer = { .ep_addr = 0, .setup = &request, @@ -442,7 +442,7 @@ bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, .wLength = 0 }; - tuh_control_xfer_t const xfer = + tuh_control_xfer_t xfer = { .ep_addr = 0, .setup = &request, @@ -889,7 +889,7 @@ static void _control_blocking_complete_cb(uint8_t daddr, tuh_control_xfer_t* xfe *((xfer_result_t*) xfer->user_arg) = xfer->result; } -bool tuh_control_xfer (uint8_t daddr, tuh_control_xfer_t const* xfer) +bool tuh_control_xfer (uint8_t daddr, tuh_control_xfer_t* xfer) { // pre-check to help reducing mutex lock TU_VERIFY(_ctrl_xfer.stage == CONTROL_STAGE_IDLE); @@ -1404,7 +1404,7 @@ static bool enum_request_set_addr(void) .wLength = 0 }; - tuh_control_xfer_t const xfer = + tuh_control_xfer_t xfer = { .ep_addr = 0, .setup = &request, diff --git a/src/host/usbh.h b/src/host/usbh.h index ec6be67dc..801938a39 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -53,8 +53,6 @@ struct tuh_control_xfer_s uint32_t actual_len; uint8_t* buffer; - - tuh_control_xfer_cb_t complete_cb; uintptr_t user_arg; }; @@ -118,7 +116,7 @@ static inline bool tuh_ready(uint8_t daddr) // Carry out a control transfer // true on success, false if there is on-going control transfer or incorrect parameters // Blocking if complete callback is NULL, in this case 'user_arg' must contain xfer_result_t variable -bool tuh_control_xfer(uint8_t daddr, tuh_control_xfer_t const* xfer); +bool tuh_control_xfer(uint8_t daddr, tuh_control_xfer_t* xfer); //bool tuh_edpt_xfer(uint8_t daddr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); From 102b99a0e8b30a03bae917028fd064ff1480275b Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 17 Mar 2022 20:48:32 +0700 Subject: [PATCH 60/81] add actual_len supported --- src/host/usbh.c | 46 ++++++++++++++++++++++++++-------------------- src/host/usbh.h | 8 ++++---- 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index 2d01c9144..96dd390b0 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -250,6 +250,7 @@ struct tuh_control_xfer_cb_t complete_cb; uintptr_t user_arg; + volatile uint16_t actual_len; uint8_t daddr; // device address that is transferring volatile uint8_t stage; }_ctrl_xfer; @@ -306,7 +307,7 @@ void osal_task_delay(uint32_t msec) #endif //--------------------------------------------------------------------+ -// Descriptors +// Descriptors Async //--------------------------------------------------------------------+ static bool _get_descriptor(uint8_t daddr, uint8_t type, uint8_t index, uint16_t language_id, void* buffer, uint16_t len, @@ -455,7 +456,7 @@ bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, } //--------------------------------------------------------------------+ -// Asynchronous +// Descriptor Sync //--------------------------------------------------------------------+ #define _CONTROL_SYNC_API(_async_func, _timeout, ...) \ @@ -903,13 +904,13 @@ bool tuh_control_xfer (uint8_t daddr, tuh_control_xfer_t* xfer) usbh_unlock(); 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_VAR(&xfer->setup); TU_LOG2("\r\n"); + _ctrl_xfer.actual_len = 0; _ctrl_xfer.daddr = daddr; _ctrl_xfer.request = (*xfer->setup); _ctrl_xfer.buffer = xfer->buffer; @@ -941,8 +942,15 @@ bool tuh_control_xfer (uint8_t daddr, tuh_control_xfer_t* xfer) // TODO probably some timeout to prevent hanged } - // update result - //xfer->result = result; + // update xfer result + xfer->result = result; + if ( xfer->user_arg ) + { + // if user_arg is not NULL, it is also updated + *((xfer_result_t*) xfer->user_arg) = result; + } + + xfer->actual_len = _ctrl_xfer.actual_len; } return true; @@ -952,19 +960,16 @@ bool tuh_control_xfer_sync(uint8_t daddr, tuh_control_xfer_t* xfer, uint32_t tim { (void) timeout_ms; - xfer_result_t result = XFER_RESULT_INVALID; - tuh_control_xfer_t xfer_sync = (*xfer); - - xfer_sync.complete_cb = NULL; - xfer_sync.user_arg = (uintptr_t) &result; + // clear callback for sync + xfer->complete_cb = NULL; // TODO use timeout to wait - TU_VERIFY(tuh_control_xfer(daddr, &xfer_sync), XFER_RESULT_TIMEOUT); + TU_VERIFY(tuh_control_xfer(daddr, xfer)); - return result; + return true; } -TU_ATTR_ALWAYS_INLINE static inline void set_control_xfer_stage(uint8_t stage) +TU_ATTR_ALWAYS_INLINE static inline void _set_control_xfer_stage(uint8_t stage) { usbh_lock(); _ctrl_xfer.stage = stage; @@ -982,7 +987,7 @@ static void _xfer_complete(uint8_t dev_addr, xfer_result_t result) .ep_addr = 0, .result = result, .setup = &request, - .actual_len = 0, + .actual_len = (uint32_t) _ctrl_xfer.actual_len, .buffer = _ctrl_xfer.buffer, .complete_cb = _ctrl_xfer.complete_cb, .user_arg = _ctrl_xfer.user_arg @@ -1001,7 +1006,6 @@ static void _xfer_complete(uint8_t dev_addr, xfer_result_t result) static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { (void) ep_addr; - (void) xferred_bytes; const uint8_t rhport = usbh_get_rhport(dev_addr); tusb_control_request_t const * request = &_ctrl_xfer.request; @@ -1020,20 +1024,22 @@ static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result if (request->wLength) { // DATA stage: initial data toggle is always 1 - set_control_xfer_stage(CONTROL_STAGE_DATA); + _set_control_xfer_stage(CONTROL_STAGE_DATA); return hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.buffer, request->wLength); } __attribute__((fallthrough)); case CONTROL_STAGE_DATA: - if (request->wLength) + if (xferred_bytes) { TU_LOG2("[%u:%u] Control data:\r\n", rhport, dev_addr); - TU_LOG2_MEM(_ctrl_xfer.buffer, request->wLength, 2); + TU_LOG2_MEM(_ctrl_xfer.buffer, xferred_bytes, 2); } + _ctrl_xfer.actual_len = xferred_bytes; + // ACK stage: toggle is always 1 - set_control_xfer_stage(CONTROL_STAGE_ACK); + _set_control_xfer_stage(CONTROL_STAGE_ACK); hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, 1-request->bmRequestType_bit.direction), NULL, 0); break; @@ -1083,7 +1089,7 @@ static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t h hcd_device_close(rhport, dev_addr); clear_device(dev); // abort on-going control xfer if any - if (_ctrl_xfer.daddr == dev_addr) set_control_xfer_stage(CONTROL_STAGE_IDLE); + if (_ctrl_xfer.daddr == dev_addr) _set_control_xfer_stage(CONTROL_STAGE_IDLE); } } } diff --git a/src/host/usbh.h b/src/host/usbh.h index 801938a39..e6897d8d8 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -50,7 +50,7 @@ struct tuh_control_xfer_s xfer_result_t result; tusb_control_request_t const* setup; - uint32_t actual_len; + uint32_t actual_len; // excluding setup packet uint8_t* buffer; tuh_control_xfer_cb_t complete_cb; @@ -115,7 +115,8 @@ static inline bool tuh_ready(uint8_t daddr) // Carry out a control transfer // true on success, false if there is on-going control transfer or incorrect parameters -// Blocking if complete callback is NULL, in this case 'user_arg' must contain xfer_result_t variable +// Note: blocking if complete callback is NULL. In this case 'xfer->result' will be updated +// and if 'user_arg' point to a xfer_result_t variable, it will be updated as well. bool tuh_control_xfer(uint8_t daddr, tuh_control_xfer_t* xfer); //bool tuh_edpt_xfer(uint8_t daddr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); @@ -123,7 +124,6 @@ bool tuh_control_xfer(uint8_t daddr, tuh_control_xfer_t* xfer); // Set Configuration (control transfer) // config_num = 0 will un-configure device. Note: config_num = config_descriptor_index + 1 // true on success, false if there is on-going control transfer or incorrect parameters -// Blocking if complete callback is NULL, in this case 'user_arg' must contain xfer_result_t variable bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); @@ -132,7 +132,7 @@ bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, //--------------------------------------------------------------------+ // Sync (blocking) version of tuh_control_xfer() -// return transfer result +// xfer contents will be updated to reflect the transfer bool tuh_control_xfer_sync(uint8_t daddr, tuh_control_xfer_t * xfer, uint32_t timeout_ms); //--------------------------------------------------------------------+ From 55428d7dd215eb2e69a1f654ccc4730525b509d6 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 17 Mar 2022 20:52:16 +0700 Subject: [PATCH 61/81] rename tuh_control_xfer_t to tuh_xfer_t --- examples/host/bare_api/src/main.c | 2 +- src/class/cdc/cdc_host.c | 4 +-- src/class/cdc/cdc_host.h | 6 ++--- src/class/hid/hid_host.c | 20 +++++++------- src/class/msc/msc_host.c | 6 ++--- src/host/hub.c | 34 ++++++++++++------------ src/host/hub.h | 10 +++---- src/host/usbh.c | 44 +++++++++++++++---------------- src/host/usbh.h | 32 +++++++++++----------- 9 files changed, 79 insertions(+), 79 deletions(-) diff --git a/examples/host/bare_api/src/main.c b/examples/host/bare_api/src/main.c index 3f0b9ef22..feb94a6fe 100644 --- a/examples/host/bare_api/src/main.c +++ b/examples/host/bare_api/src/main.c @@ -115,7 +115,7 @@ static void utf16_to_utf8(uint16_t *temp_buf, size_t buf_len) { ((uint8_t*) temp_buf)[utf8_len] = '\0'; } -void print_device_descriptor(uint8_t daddr, tuh_control_xfer_t* xfer) +void print_device_descriptor(uint8_t daddr, tuh_xfer_t* xfer) { if ( XFER_RESULT_SUCCESS != xfer->result ) { diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 7ae8af77a..a811eb667 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -120,7 +120,7 @@ bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is return usbh_edpt_xfer(dev_addr, ep_in, p_buffer, length); } -bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_control_xfer_cb_t complete_cb) +bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_xfer_cb_t complete_cb) { cdch_data_t const * p_cdc = get_itf(dev_addr); @@ -138,7 +138,7 @@ bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_co .wLength = 0 }; - tuh_control_xfer_t xfer = + tuh_xfer_t xfer = { .ep_addr = 0, .setup = &request, diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index 67162a0ca..33dbd2efb 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -42,14 +42,14 @@ * \defgroup CDC_Serial_Host Host * @{ */ -bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_control_xfer_cb_t complete_cb); +bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_xfer_cb_t complete_cb); -static inline bool tuh_cdc_connect(uint8_t dev_addr, tuh_control_xfer_cb_t complete_cb) +static inline bool tuh_cdc_connect(uint8_t dev_addr, tuh_xfer_cb_t complete_cb) { return tuh_cdc_set_control_line_state(dev_addr, true, true, complete_cb); } -static inline bool tuh_cdc_disconnect(uint8_t dev_addr, tuh_control_xfer_cb_t complete_cb) +static inline bool tuh_cdc_disconnect(uint8_t dev_addr, tuh_xfer_cb_t complete_cb) { return tuh_cdc_set_control_line_state(dev_addr, false, false, complete_cb); } diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 65fccd32a..705b73c67 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -103,7 +103,7 @@ uint8_t tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance) return hid_itf->protocol_mode; } -static void set_protocol_complete(uint8_t dev_addr, tuh_control_xfer_t* xfer) +static void set_protocol_complete(uint8_t dev_addr, tuh_xfer_t* xfer) { uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); @@ -121,7 +121,7 @@ static void set_protocol_complete(uint8_t dev_addr, tuh_control_xfer_t* xfer) } -static bool _hidh_set_protocol(uint8_t dev_addr, uint8_t itf_num, uint8_t protocol, tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) +static bool _hidh_set_protocol(uint8_t dev_addr, uint8_t itf_num, uint8_t protocol, tuh_xfer_cb_t complete_cb, uintptr_t user_arg) { TU_LOG2("HID Set Protocol = %d\r\n", protocol); @@ -139,7 +139,7 @@ static bool _hidh_set_protocol(uint8_t dev_addr, uint8_t itf_num, uint8_t protoc .wLength = 0 }; - tuh_control_xfer_t xfer = + tuh_xfer_t xfer = { .ep_addr = 0, .setup = &request, @@ -160,7 +160,7 @@ bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) return _hidh_set_protocol(dev_addr, hid_itf->itf_num, protocol, set_protocol_complete, 0); } -static void set_report_complete(uint8_t dev_addr, tuh_control_xfer_t* xfer) +static void set_report_complete(uint8_t dev_addr, tuh_xfer_t* xfer) { TU_LOG2("HID Set Report complete\r\n"); @@ -196,7 +196,7 @@ bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, u .wLength = len }; - tuh_control_xfer_t xfer = + tuh_xfer_t xfer = { .ep_addr = 0, .setup = &request, @@ -209,7 +209,7 @@ bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, u return true; } -static bool _hidh_set_idle(uint8_t dev_addr, uint8_t itf_num, uint16_t idle_rate, tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) +static bool _hidh_set_idle(uint8_t dev_addr, uint8_t itf_num, uint16_t idle_rate, tuh_xfer_cb_t complete_cb, uintptr_t user_arg) { // SET IDLE request, device can stall if not support this request TU_LOG2("HID Set Idle \r\n"); @@ -227,7 +227,7 @@ static bool _hidh_set_idle(uint8_t dev_addr, uint8_t itf_num, uint16_t idle_rate .wLength = 0 }; - tuh_control_xfer_t xfer = + tuh_xfer_t xfer = { .ep_addr = 0, .setup = &request, @@ -389,14 +389,14 @@ enum { }; static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len); -static void process_set_config(uint8_t dev_addr, tuh_control_xfer_t* xfer); +static void process_set_config(uint8_t dev_addr, tuh_xfer_t* xfer); bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) { tusb_control_request_t request; request.wIndex = tu_htole16((uint16_t) itf_num); - tuh_control_xfer_t xfer; + tuh_xfer_t xfer; xfer.result = XFER_RESULT_SUCCESS; xfer.setup = &request; xfer.user_arg = CONFG_SET_IDLE; @@ -407,7 +407,7 @@ bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) return true; } -static void process_set_config(uint8_t dev_addr, tuh_control_xfer_t* xfer) +static void process_set_config(uint8_t dev_addr, tuh_xfer_t* xfer) { // Stall is a valid response for SET_IDLE, therefore we could ignore its result if ( xfer->setup->bRequest != HID_REQ_CONTROL_SET_IDLE ) diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index fea587386..789ae9c1a 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -358,7 +358,7 @@ bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 // MSC Enumeration //--------------------------------------------------------------------+ -static void config_get_maxlun_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer); +static void config_get_maxlun_complete (uint8_t dev_addr, tuh_xfer_t* xfer); static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); @@ -419,7 +419,7 @@ bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) .wLength = 1 }; - tuh_control_xfer_t xfer = + tuh_xfer_t xfer = { .ep_addr = 0, .setup = &request, @@ -432,7 +432,7 @@ bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) return true; } -static void config_get_maxlun_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer) +static void config_get_maxlun_complete (uint8_t dev_addr, tuh_xfer_t* xfer) { msch_interface_t* p_msc = get_itf(dev_addr); diff --git a/src/host/hub.c b/src/host/hub.c index 36f27398f..03cf0ecb4 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -78,7 +78,7 @@ static char const* const _hub_feature_str[] = // HUB //--------------------------------------------------------------------+ bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, - tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) + tuh_xfer_cb_t complete_cb, uintptr_t user_arg) { tusb_control_request_t const request = { @@ -94,7 +94,7 @@ bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, .wLength = 0 }; - tuh_control_xfer_t xfer = + tuh_xfer_t xfer = { .ep_addr = 0, .setup = &request, @@ -109,7 +109,7 @@ bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, } bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, - tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) + tuh_xfer_cb_t complete_cb, uintptr_t user_arg) { tusb_control_request_t const request = { @@ -125,7 +125,7 @@ bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, .wLength = 0 }; - tuh_control_xfer_t xfer = + tuh_xfer_t xfer = { .ep_addr = 0, .setup = &request, @@ -140,7 +140,7 @@ bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, } bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, - tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) + tuh_xfer_cb_t complete_cb, uintptr_t user_arg) { tusb_control_request_t const request = { @@ -156,7 +156,7 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, .wLength = 4 }; - tuh_control_xfer_t xfer = + tuh_xfer_t xfer = { .ep_addr = 0, .setup = &request, @@ -225,8 +225,8 @@ bool hub_edpt_status_xfer(uint8_t dev_addr) // Set Configure //--------------------------------------------------------------------+ -static void config_set_port_power (uint8_t dev_addr, tuh_control_xfer_t* xfer); -static void config_port_power_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer); +static void config_set_port_power (uint8_t dev_addr, tuh_xfer_t* xfer); +static void config_port_power_complete (uint8_t dev_addr, tuh_xfer_t* xfer); bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) { @@ -248,7 +248,7 @@ bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) .wLength = sizeof(descriptor_hub_desc_t) }; - tuh_control_xfer_t xfer = + tuh_xfer_t xfer = { .ep_addr = 0, .setup = &request, @@ -262,7 +262,7 @@ bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) return true; } -static void config_set_port_power (uint8_t dev_addr, tuh_control_xfer_t* xfer) +static void config_set_port_power (uint8_t dev_addr, tuh_xfer_t* xfer) { TU_ASSERT(XFER_RESULT_SUCCESS == xfer->result, ); @@ -279,7 +279,7 @@ static void config_set_port_power (uint8_t dev_addr, tuh_control_xfer_t* xfer) hub_port_set_feature(dev_addr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete, 0); } -static void config_port_power_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer) +static void config_port_power_complete (uint8_t dev_addr, tuh_xfer_t* xfer) { TU_ASSERT(XFER_RESULT_SUCCESS == xfer->result, ); hub_interface_t* p_hub = get_itf(dev_addr); @@ -303,9 +303,9 @@ static void config_port_power_complete (uint8_t dev_addr, tuh_control_xfer_t* xf // Connection Changes //--------------------------------------------------------------------+ -static void connection_get_status_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer); -static void connection_clear_conn_change_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer); -static void connection_port_reset_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer); +static void connection_get_status_complete (uint8_t dev_addr, tuh_xfer_t* xfer); +static void connection_clear_conn_change_complete (uint8_t dev_addr, tuh_xfer_t* xfer); +static void connection_port_reset_complete (uint8_t dev_addr, tuh_xfer_t* xfer); // callback as response of interrupt endpoint polling bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) @@ -333,7 +333,7 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32 return true; } -static void connection_get_status_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer) +static void connection_get_status_complete (uint8_t dev_addr, tuh_xfer_t* xfer) { TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); @@ -359,7 +359,7 @@ static void connection_get_status_complete (uint8_t dev_addr, tuh_control_xfer_t } } -static void connection_clear_conn_change_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer) +static void connection_clear_conn_change_complete (uint8_t dev_addr, tuh_xfer_t* xfer) { TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); @@ -388,7 +388,7 @@ static void connection_clear_conn_change_complete (uint8_t dev_addr, tuh_control } } -static void connection_port_reset_complete (uint8_t dev_addr, tuh_control_xfer_t* xfer) +static void connection_port_reset_complete (uint8_t dev_addr, tuh_xfer_t* xfer) { TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); diff --git a/src/host/hub.h b/src/host/hub.h index 30cf3dd1c..e5e22102a 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -173,29 +173,29 @@ TU_VERIFY_STATIC( sizeof(hub_port_status_response_t) == 4, "size is not correct" // Clear feature bool hub_port_clear_feature (uint8_t hub_addr, uint8_t hub_port, uint8_t feature, - tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); + tuh_xfer_cb_t complete_cb, uintptr_t user_arg); // Set feature bool hub_port_set_feature (uint8_t hub_addr, uint8_t hub_port, uint8_t feature, - tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); + tuh_xfer_cb_t complete_cb, uintptr_t user_arg); // Get port status bool hub_port_get_status (uint8_t hub_addr, uint8_t hub_port, void* resp, - tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); + tuh_xfer_cb_t complete_cb, uintptr_t user_arg); // Get status from Interrupt endpoint bool hub_edpt_status_xfer(uint8_t dev_addr); // Reset a port static inline bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, - tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) + tuh_xfer_cb_t complete_cb, uintptr_t user_arg) { return hub_port_set_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET, complete_cb, user_arg); } // Clear Reset Change static inline bool hub_port_clear_reset_change(uint8_t hub_addr, uint8_t hub_port, - tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) + tuh_xfer_cb_t complete_cb, uintptr_t user_arg) { return hub_port_clear_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET_CHANGE, complete_cb, user_arg); } diff --git a/src/host/usbh.c b/src/host/usbh.c index 96dd390b0..534f2458b 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -247,7 +247,7 @@ struct { tusb_control_request_t request TU_ATTR_ALIGNED(4); uint8_t* buffer; - tuh_control_xfer_cb_t complete_cb; + tuh_xfer_cb_t complete_cb; uintptr_t user_arg; volatile uint16_t actual_len; @@ -311,7 +311,7 @@ void osal_task_delay(uint32_t msec) //--------------------------------------------------------------------+ static bool _get_descriptor(uint8_t daddr, uint8_t type, uint8_t index, uint16_t language_id, void* buffer, uint16_t len, - tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) + tuh_xfer_cb_t complete_cb, uintptr_t user_arg) { tusb_control_request_t const request = { @@ -327,7 +327,7 @@ static bool _get_descriptor(uint8_t daddr, uint8_t type, uint8_t index, uint16_t .wLength = tu_htole16(len) }; - tuh_control_xfer_t xfer = + tuh_xfer_t xfer = { .ep_addr = 0, .setup = &request, @@ -340,20 +340,20 @@ static bool _get_descriptor(uint8_t daddr, uint8_t type, uint8_t index, uint16_t } bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len, - tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) + tuh_xfer_cb_t complete_cb, uintptr_t user_arg) { return _get_descriptor(daddr, type, index, 0x0000, buffer, len, complete_cb, user_arg); } bool tuh_descriptor_get_device(uint8_t daddr, void* buffer, uint16_t len, - tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) + tuh_xfer_cb_t complete_cb, uintptr_t user_arg) { len = tu_min16(len, sizeof(tusb_desc_device_t)); return tuh_descriptor_get(daddr, TUSB_DESC_DEVICE, 0, buffer, len, complete_cb, user_arg); } bool tuh_descriptor_get_configuration(uint8_t daddr, uint8_t index, void* buffer, uint16_t len, - tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) + tuh_xfer_cb_t complete_cb, uintptr_t user_arg) { return tuh_descriptor_get(daddr, TUSB_DESC_CONFIGURATION, index, buffer, len, complete_cb, user_arg); } @@ -361,14 +361,14 @@ bool tuh_descriptor_get_configuration(uint8_t daddr, uint8_t index, void* buffer //------------- String Descriptor -------------// bool tuh_descriptor_get_string(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len, - tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) + tuh_xfer_cb_t complete_cb, uintptr_t user_arg) { return _get_descriptor(daddr, TUSB_DESC_STRING, index, language_id, buffer, len, complete_cb, user_arg); } // Get manufacturer string descriptor bool tuh_descriptor_get_manufacturer_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, - tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) + tuh_xfer_cb_t complete_cb, uintptr_t user_arg) { usbh_device_t const* dev = get_device(daddr); TU_VERIFY(dev && dev->i_manufacturer); @@ -377,7 +377,7 @@ bool tuh_descriptor_get_manufacturer_string(uint8_t daddr, uint16_t language_id, // Get product string descriptor bool tuh_descriptor_get_product_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, - tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) + tuh_xfer_cb_t complete_cb, uintptr_t user_arg) { usbh_device_t const* dev = get_device(daddr); TU_VERIFY(dev && dev->i_product); @@ -386,7 +386,7 @@ bool tuh_descriptor_get_product_string(uint8_t daddr, uint16_t language_id, void // Get serial string descriptor bool tuh_descriptor_get_serial_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, - tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg) + tuh_xfer_cb_t complete_cb, uintptr_t user_arg) { usbh_device_t const* dev = get_device(daddr); TU_VERIFY(dev && dev->i_serial); @@ -395,7 +395,7 @@ bool tuh_descriptor_get_serial_string(uint8_t daddr, uint16_t language_id, void* // Get HID report descriptor 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_control_xfer_cb_t complete_cb, uintptr_t user_arg) + tuh_xfer_cb_t complete_cb, uintptr_t user_arg) { TU_LOG2("HID Get Report Descriptor\r\n"); tusb_control_request_t const request = @@ -412,7 +412,7 @@ bool tuh_descriptor_get_hid_report(uint8_t daddr, uint8_t itf_num, uint8_t desc_ .wLength = len }; - tuh_control_xfer_t xfer = + tuh_xfer_t xfer = { .ep_addr = 0, .setup = &request, @@ -425,7 +425,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_control_xfer_cb_t complete_cb, uintptr_t user_arg) + tuh_xfer_cb_t complete_cb, uintptr_t user_arg) { TU_LOG2("Set Configuration = %d\r\n", config_num); @@ -443,7 +443,7 @@ bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, .wLength = 0 }; - tuh_control_xfer_t xfer = + tuh_xfer_t xfer = { .ep_addr = 0, .setup = &request, @@ -531,7 +531,7 @@ bool tuh_init(uint8_t rhport) TU_LOG2("USBH init\r\n"); TU_LOG2_INT(sizeof(usbh_device_t)); TU_LOG2_INT(sizeof(hcd_event_t)); - TU_LOG2_INT(sizeof(tuh_control_xfer_t)); + TU_LOG2_INT(sizeof(tuh_xfer_t)); // Event queue _usbh_q = osal_queue_create( &_usbh_qdef ); @@ -883,14 +883,14 @@ bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) // Control transfer //--------------------------------------------------------------------+ -static void _control_blocking_complete_cb(uint8_t daddr, tuh_control_xfer_t* xfer) +static void _control_blocking_complete_cb(uint8_t daddr, tuh_xfer_t* xfer) { (void) daddr; // update result *((xfer_result_t*) xfer->user_arg) = xfer->result; } -bool tuh_control_xfer (uint8_t daddr, tuh_control_xfer_t* xfer) +bool tuh_control_xfer (uint8_t daddr, tuh_xfer_t* xfer) { // pre-check to help reducing mutex lock TU_VERIFY(_ctrl_xfer.stage == CONTROL_STAGE_IDLE); @@ -956,7 +956,7 @@ bool tuh_control_xfer (uint8_t daddr, tuh_control_xfer_t* xfer) return true; } -bool tuh_control_xfer_sync(uint8_t daddr, tuh_control_xfer_t* xfer, uint32_t timeout_ms) +bool tuh_control_xfer_sync(uint8_t daddr, tuh_xfer_t* xfer, uint32_t timeout_ms) { (void) timeout_ms; @@ -982,7 +982,7 @@ static void _xfer_complete(uint8_t dev_addr, xfer_result_t result) // duplicate xfer since user can execute control transfer within callback tusb_control_request_t const request = _ctrl_xfer.request; - tuh_control_xfer_t xfer_temp = + tuh_xfer_t xfer_temp = { .ep_addr = 0, .result = result, @@ -1125,7 +1125,7 @@ static bool parse_configuration_descriptor (uint8_t dev_addr, tusb_desc_configur static void enum_full_complete(void); // process device enumeration -static void process_enumeration(uint8_t dev_addr, tuh_control_xfer_t* xfer) +static void process_enumeration(uint8_t dev_addr, tuh_xfer_t* xfer) { if (XFER_RESULT_SUCCESS != xfer->result) { @@ -1327,7 +1327,7 @@ static bool enum_new_device(hcd_event_t* event) TU_LOG2("%s Speed\r\n", tu_str_speed[_dev0.speed]); // fake transfer to kick-off the enumeration process - tuh_control_xfer_t xfer; + tuh_xfer_t xfer; xfer.result = XFER_RESULT_SUCCESS; xfer.user_arg = ENUM_ADDR0_DEVICE_DESC; @@ -1410,7 +1410,7 @@ static bool enum_request_set_addr(void) .wLength = 0 }; - tuh_control_xfer_t xfer = + tuh_xfer_t xfer = { .ep_addr = 0, .setup = &request, diff --git a/src/host/usbh.h b/src/host/usbh.h index e6897d8d8..73fe2e08f 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -39,12 +39,12 @@ //--------------------------------------------------------------------+ // forward declaration -struct tuh_control_xfer_s; -typedef struct tuh_control_xfer_s tuh_control_xfer_t; +struct tuh_xfer_s; +typedef struct tuh_xfer_s tuh_xfer_t; -typedef void (*tuh_control_xfer_cb_t)(uint8_t daddr, tuh_control_xfer_t* xfer); +typedef void (*tuh_xfer_cb_t)(uint8_t daddr, tuh_xfer_t* xfer); -struct tuh_control_xfer_s +struct tuh_xfer_s { uint8_t ep_addr; xfer_result_t result; @@ -53,7 +53,7 @@ struct tuh_control_xfer_s uint32_t actual_len; // excluding setup packet uint8_t* buffer; - tuh_control_xfer_cb_t complete_cb; + tuh_xfer_cb_t complete_cb; uintptr_t user_arg; }; @@ -117,7 +117,7 @@ static inline bool tuh_ready(uint8_t daddr) // true on success, false if there is on-going control transfer or incorrect parameters // Note: blocking if complete callback is NULL. In this case 'xfer->result' will be updated // and if 'user_arg' point to a xfer_result_t variable, it will be updated as well. -bool tuh_control_xfer(uint8_t daddr, tuh_control_xfer_t* xfer); +bool tuh_control_xfer(uint8_t daddr, tuh_xfer_t* xfer); //bool tuh_edpt_xfer(uint8_t daddr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); @@ -125,7 +125,7 @@ bool tuh_control_xfer(uint8_t daddr, tuh_control_xfer_t* xfer); // config_num = 0 will un-configure device. Note: config_num = config_descriptor_index + 1 // true on success, false if there is on-going control transfer or incorrect parameters bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, - tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); + tuh_xfer_cb_t complete_cb, uintptr_t user_arg); //--------------------------------------------------------------------+ // Endpoint Synchronous (blocking) @@ -133,7 +133,7 @@ bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, // Sync (blocking) version of tuh_control_xfer() // xfer contents will be updated to reflect the transfer -bool tuh_control_xfer_sync(uint8_t daddr, tuh_control_xfer_t * xfer, uint32_t timeout_ms); +bool tuh_control_xfer_sync(uint8_t daddr, tuh_xfer_t * xfer, uint32_t timeout_ms); //--------------------------------------------------------------------+ // Descriptors Asynchronous (non-blocking) @@ -142,43 +142,43 @@ bool tuh_control_xfer_sync(uint8_t daddr, tuh_control_xfer_t * xfer, uint32_t ti // Get an descriptor (control transfer) // true on success, false if there is on-going control transfer or incorrect parameters bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len, - tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); + tuh_xfer_cb_t complete_cb, uintptr_t user_arg); // Get device descriptor (control transfer) // true on success, false if there is on-going control transfer or incorrect parameters bool tuh_descriptor_get_device(uint8_t daddr, void* buffer, uint16_t len, - tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); + tuh_xfer_cb_t complete_cb, uintptr_t user_arg); // Get configuration descriptor (control transfer) // true on success, false if there is on-going control transfer or incorrect parameters bool tuh_descriptor_get_configuration(uint8_t daddr, uint8_t index, void* buffer, uint16_t len, - tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); + tuh_xfer_cb_t complete_cb, uintptr_t user_arg); // Get HID report descriptor (control transfer) // true on success, false if there is on-going control transfer or incorrect parameters 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_control_xfer_cb_t complete_cb, uintptr_t user_arg); + tuh_xfer_cb_t complete_cb, uintptr_t user_arg); // Get string descriptor (control transfer) // true on success, false if there is on-going control transfer or incorrect parameters // Blocking if complete callback is NULL, in this case 'user_arg' must contain xfer_result_t variable bool tuh_descriptor_get_string(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len, - tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); + tuh_xfer_cb_t complete_cb, uintptr_t user_arg); // Get manufacturer string descriptor (control transfer) // true on success, false if there is on-going control transfer or incorrect parameters bool tuh_descriptor_get_manufacturer_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, - tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); + tuh_xfer_cb_t complete_cb, uintptr_t user_arg); // Get product string descriptor (control transfer) // true on success, false if there is on-going control transfer or incorrect parameters bool tuh_descriptor_get_product_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, - tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); + tuh_xfer_cb_t complete_cb, uintptr_t user_arg); // Get serial string descriptor (control transfer) // true on success, false if there is on-going control transfer or incorrect parameters bool tuh_descriptor_get_serial_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, - tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); + tuh_xfer_cb_t complete_cb, uintptr_t user_arg); //--------------------------------------------------------------------+ // Descriptors Synchronous (blocking) From 9dd2f11f4a08c337096776eacd919faec3cc939e Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 17 Mar 2022 21:20:20 +0700 Subject: [PATCH 62/81] add CFG_TUH_API_EDPT_XFER to enable generic edpt xfer --- examples/host/bare_api/src/tusb_config.h | 8 ++-- src/host/usbh.c | 47 ++++++++++++++++-------- src/host/usbh.h | 8 +++- src/tusb_option.h | 4 ++ 4 files changed, 46 insertions(+), 21 deletions(-) diff --git a/examples/host/bare_api/src/tusb_config.h b/examples/host/bare_api/src/tusb_config.h index 234eca402..9b789290d 100644 --- a/examples/host/bare_api/src/tusb_config.h +++ b/examples/host/bare_api/src/tusb_config.h @@ -81,11 +81,11 @@ // 1 hub typically has 4 ports #define CFG_TUH_DEVICE_MAX (CFG_TUH_HUB ? 4 : 1) -#define CFG_TUH_ENDPOINT_MAX 8 +// Max endpoint per device +#define CFG_TUH_ENDPOINT_MAX 8 -//------------- HID -------------// - -#define CFG_TUH_HID_EP_BUFSIZE 64 +// Enable tuh_edpt_xfer() API +#define CFG_TUH_API_EDPT_XFER 1 #ifdef __cplusplus } diff --git a/src/host/usbh.c b/src/host/usbh.c index 534f2458b..689634ecd 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -109,8 +109,15 @@ typedef struct { tu_edpt_state_t ep_status[CFG_TUH_ENDPOINT_MAX][2]; -#if CFG_TUH_BARE - +#if CFG_TUH_API_EDPT_XFER +// struct +// { +// uint8_t* buffer; +// tuh_xfer_cb_t complete_cb; +// uintptr_t user_arg; +// +// volatile uint16_t actual_len; +// }ep_xfer; #endif } usbh_device_t; @@ -240,6 +247,16 @@ static osal_queue_t _usbh_q; CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSIZE]; +//// internal version of tuh_xfer_t +//typedef struct +//{ +// uint8_t* buffer; +// tuh_xfer_cb_t complete_cb; +// uintptr_t user_arg; +// +// volatile uint16_t actual_len; +//}usbh_xfer_t; + // 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. @@ -890,6 +907,19 @@ static void _control_blocking_complete_cb(uint8_t daddr, tuh_xfer_t* xfer) *((xfer_result_t*) xfer->user_arg) = xfer->result; } +bool tuh_control_xfer_sync(uint8_t daddr, tuh_xfer_t* xfer, uint32_t timeout_ms) +{ + (void) timeout_ms; + + // clear callback for sync + xfer->complete_cb = NULL; + + // TODO use timeout to wait + TU_VERIFY(tuh_control_xfer(daddr, xfer)); + + return true; +} + bool tuh_control_xfer (uint8_t daddr, tuh_xfer_t* xfer) { // pre-check to help reducing mutex lock @@ -956,19 +986,6 @@ bool tuh_control_xfer (uint8_t daddr, tuh_xfer_t* xfer) return true; } -bool tuh_control_xfer_sync(uint8_t daddr, tuh_xfer_t* xfer, uint32_t timeout_ms) -{ - (void) timeout_ms; - - // clear callback for sync - xfer->complete_cb = NULL; - - // TODO use timeout to wait - TU_VERIFY(tuh_control_xfer(daddr, xfer)); - - return true; -} - TU_ATTR_ALWAYS_INLINE static inline void _set_control_xfer_stage(uint8_t stage) { usbh_lock(); diff --git a/src/host/usbh.h b/src/host/usbh.h index 73fe2e08f..2021545ba 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -113,13 +113,17 @@ static inline bool tuh_ready(uint8_t daddr) // Endpoint Asynchronous (non-blocking) //--------------------------------------------------------------------+ -// Carry out a control transfer +// Submit a control transfer // true on success, false if there is on-going control transfer or incorrect parameters // Note: blocking if complete callback is NULL. In this case 'xfer->result' will be updated // and if 'user_arg' point to a xfer_result_t variable, it will be updated as well. bool tuh_control_xfer(uint8_t daddr, tuh_xfer_t* xfer); -//bool tuh_edpt_xfer(uint8_t daddr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); +// Submit a bulk/interrupt transfer +// true on success, false if there is on-going control transfer or incorrect parameters +// Note: blocking if complete callback is NULL. In this case 'xfer->result' will be updated +// and if 'user_arg' point to a xfer_result_t variable, it will be updated as well. +bool tuh_edpt_xfer(uint8_t daddr, tuh_xfer_t* xfer); // Set Configuration (control transfer) // config_num = 0 will un-configure device. Note: config_num = config_descriptor_index + 1 diff --git a/src/tusb_option.h b/src/tusb_option.h index 0352faaed..bd87a953c 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -392,6 +392,10 @@ #define CFG_TUH_VENDOR 0 #endif +#ifndef CFG_TUH_API_EDPT_XFER +#define CFG_TUH_API_EDPT_XFER 0 +#endif + //------------------------------------------------------------------ // Configuration Validation //------------------------------------------------------------------ From f89ff939d8088135cedaa4e4f3885f88d1670529 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 17 Mar 2022 22:37:51 +0700 Subject: [PATCH 63/81] rename user_arg to user_data --- src/class/cdc/cdc_host.c | 2 +- src/class/hid/hid_host.c | 18 ++++---- src/class/msc/msc_host.c | 2 +- src/host/hub.c | 14 +++--- src/host/hub.h | 14 +++--- src/host/usbh.c | 93 ++++++++++++++++++++++------------------ src/host/usbh.h | 37 ++++++++-------- 7 files changed, 95 insertions(+), 85 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index a811eb667..2795750ed 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -144,7 +144,7 @@ bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_xf .setup = &request, .buffer = NULL, .complete_cb = complete_cb, - .user_arg = 0 + .user_data = 0 }; return tuh_control_xfer(dev_addr, &xfer); diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 705b73c67..0ad917815 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -121,7 +121,7 @@ static void set_protocol_complete(uint8_t dev_addr, tuh_xfer_t* xfer) } -static bool _hidh_set_protocol(uint8_t dev_addr, uint8_t itf_num, uint8_t protocol, tuh_xfer_cb_t complete_cb, uintptr_t user_arg) +static bool _hidh_set_protocol(uint8_t dev_addr, uint8_t itf_num, uint8_t protocol, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_LOG2("HID Set Protocol = %d\r\n", protocol); @@ -145,7 +145,7 @@ static bool _hidh_set_protocol(uint8_t dev_addr, uint8_t itf_num, uint8_t protoc .setup = &request, .buffer = NULL, .complete_cb = complete_cb, - .user_arg = user_arg + .user_data = user_data }; TU_ASSERT( tuh_control_xfer(dev_addr, &xfer) ); @@ -202,14 +202,14 @@ bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, u .setup = &request, .buffer = report, .complete_cb = set_report_complete, - .user_arg = 0 + .user_data = 0 }; TU_ASSERT( tuh_control_xfer(dev_addr, &xfer) ); return true; } -static bool _hidh_set_idle(uint8_t dev_addr, uint8_t itf_num, uint16_t idle_rate, tuh_xfer_cb_t complete_cb, uintptr_t user_arg) +static bool _hidh_set_idle(uint8_t dev_addr, uint8_t itf_num, uint16_t idle_rate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { // SET IDLE request, device can stall if not support this request TU_LOG2("HID Set Idle \r\n"); @@ -233,7 +233,7 @@ static bool _hidh_set_idle(uint8_t dev_addr, uint8_t itf_num, uint16_t idle_rate .setup = &request, .buffer = NULL, .complete_cb = complete_cb, - .user_arg = user_arg + .user_data = user_data }; TU_ASSERT( tuh_control_xfer(dev_addr, &xfer) ); @@ -397,9 +397,9 @@ bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) request.wIndex = tu_htole16((uint16_t) itf_num); tuh_xfer_t xfer; - xfer.result = XFER_RESULT_SUCCESS; - xfer.setup = &request; - xfer.user_arg = CONFG_SET_IDLE; + xfer.result = XFER_RESULT_SUCCESS; + xfer.setup = &request; + xfer.user_data = CONFG_SET_IDLE; // fake request to kick-off the set config process process_set_config(dev_addr, &xfer); @@ -415,7 +415,7 @@ static void process_set_config(uint8_t dev_addr, tuh_xfer_t* xfer) TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); } - uintptr_t const state = xfer->user_arg; + uintptr_t const state = xfer->user_data; uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); hidh_interface_t* hid_itf = get_instance(dev_addr, instance); diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 789ae9c1a..5a34f2d56 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -425,7 +425,7 @@ bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) .setup = &request, .buffer = &p_msc->max_lun, .complete_cb = config_get_maxlun_complete, - .user_arg = 0 + .user_data = 0 }; TU_ASSERT(tuh_control_xfer(dev_addr, &xfer)); diff --git a/src/host/hub.c b/src/host/hub.c index 03cf0ecb4..ac24988d8 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -78,7 +78,7 @@ static char const* const _hub_feature_str[] = // HUB //--------------------------------------------------------------------+ bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, - tuh_xfer_cb_t complete_cb, uintptr_t user_arg) + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { tusb_control_request_t const request = { @@ -100,7 +100,7 @@ bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, .setup = &request, .buffer = NULL, .complete_cb = complete_cb, - .user_arg = user_arg + .user_data = user_data }; TU_LOG2("HUB Clear Feature: %s, addr = %u port = %u\r\n", _hub_feature_str[feature], hub_addr, hub_port); @@ -109,7 +109,7 @@ bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, } bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, - tuh_xfer_cb_t complete_cb, uintptr_t user_arg) + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { tusb_control_request_t const request = { @@ -131,7 +131,7 @@ bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, .setup = &request, .buffer = NULL, .complete_cb = complete_cb, - .user_arg = user_arg + .user_data = user_data }; TU_LOG2("HUB Set Feature: %s, addr = %u port = %u\r\n", _hub_feature_str[feature], hub_addr, hub_port); @@ -140,7 +140,7 @@ bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, } bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, - tuh_xfer_cb_t complete_cb, uintptr_t user_arg) + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { tusb_control_request_t const request = { @@ -162,7 +162,7 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, .setup = &request, .buffer = resp, .complete_cb = complete_cb, - .user_arg = user_arg + .user_data = user_data }; TU_LOG2("HUB Get Port Status: addr = %u port = %u\r\n", hub_addr, hub_port); @@ -254,7 +254,7 @@ bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) .setup = &request, .buffer = _hub_buffer, .complete_cb = config_set_port_power, - .user_arg = 0 + .user_data = 0 }; TU_ASSERT( tuh_control_xfer(dev_addr, &xfer) ); diff --git a/src/host/hub.h b/src/host/hub.h index e5e22102a..390740e1f 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -173,31 +173,31 @@ TU_VERIFY_STATIC( sizeof(hub_port_status_response_t) == 4, "size is not correct" // Clear feature bool hub_port_clear_feature (uint8_t hub_addr, uint8_t hub_port, uint8_t feature, - tuh_xfer_cb_t complete_cb, uintptr_t user_arg); + tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Set feature bool hub_port_set_feature (uint8_t hub_addr, uint8_t hub_port, uint8_t feature, - tuh_xfer_cb_t complete_cb, uintptr_t user_arg); + tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Get port status bool hub_port_get_status (uint8_t hub_addr, uint8_t hub_port, void* resp, - tuh_xfer_cb_t complete_cb, uintptr_t user_arg); + tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Get status from Interrupt endpoint bool hub_edpt_status_xfer(uint8_t dev_addr); // Reset a port static inline bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, - tuh_xfer_cb_t complete_cb, uintptr_t user_arg) + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - return hub_port_set_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET, complete_cb, user_arg); + return hub_port_set_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET, complete_cb, user_data); } // Clear Reset Change static inline bool hub_port_clear_reset_change(uint8_t hub_addr, uint8_t hub_port, - tuh_xfer_cb_t complete_cb, uintptr_t user_arg) + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - return hub_port_clear_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET_CHANGE, complete_cb, user_arg); + return hub_port_clear_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET_CHANGE, complete_cb, user_data); } diff --git a/src/host/usbh.c b/src/host/usbh.c index 689634ecd..69543854d 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -110,14 +110,14 @@ typedef struct { tu_edpt_state_t ep_status[CFG_TUH_ENDPOINT_MAX][2]; #if CFG_TUH_API_EDPT_XFER -// struct -// { -// uint8_t* buffer; -// tuh_xfer_cb_t complete_cb; -// uintptr_t user_arg; -// -// volatile uint16_t actual_len; -// }ep_xfer; + struct + { + uint8_t* buffer; + tuh_xfer_cb_t complete_cb; + uintptr_t user_data; + uint16_t buflen; + volatile uint16_t actual_len; + }ep_xfer; #endif } usbh_device_t; @@ -252,7 +252,7 @@ static uint8_t _usbh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSIZE]; //{ // uint8_t* buffer; // tuh_xfer_cb_t complete_cb; -// uintptr_t user_arg; +// uintptr_t user_data; // // volatile uint16_t actual_len; //}usbh_xfer_t; @@ -265,7 +265,7 @@ struct tusb_control_request_t request TU_ATTR_ALIGNED(4); uint8_t* buffer; tuh_xfer_cb_t complete_cb; - uintptr_t user_arg; + uintptr_t user_data; volatile uint16_t actual_len; uint8_t daddr; // device address that is transferring @@ -328,7 +328,7 @@ void osal_task_delay(uint32_t msec) //--------------------------------------------------------------------+ static bool _get_descriptor(uint8_t daddr, uint8_t type, uint8_t index, uint16_t language_id, void* buffer, uint16_t len, - tuh_xfer_cb_t complete_cb, uintptr_t user_arg) + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { tusb_control_request_t const request = { @@ -350,69 +350,69 @@ static bool _get_descriptor(uint8_t daddr, uint8_t type, uint8_t index, uint16_t .setup = &request, .buffer = buffer, .complete_cb = complete_cb, - .user_arg = user_arg + .user_data = user_data }; return tuh_control_xfer(daddr, &xfer); } bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len, - tuh_xfer_cb_t complete_cb, uintptr_t user_arg) + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - return _get_descriptor(daddr, type, index, 0x0000, buffer, len, complete_cb, user_arg); + return _get_descriptor(daddr, type, index, 0x0000, buffer, len, complete_cb, user_data); } bool tuh_descriptor_get_device(uint8_t daddr, void* buffer, uint16_t len, - tuh_xfer_cb_t complete_cb, uintptr_t user_arg) + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { len = tu_min16(len, sizeof(tusb_desc_device_t)); - return tuh_descriptor_get(daddr, TUSB_DESC_DEVICE, 0, buffer, len, complete_cb, user_arg); + return tuh_descriptor_get(daddr, TUSB_DESC_DEVICE, 0, buffer, len, complete_cb, user_data); } bool tuh_descriptor_get_configuration(uint8_t daddr, uint8_t index, void* buffer, uint16_t len, - tuh_xfer_cb_t complete_cb, uintptr_t user_arg) + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - return tuh_descriptor_get(daddr, TUSB_DESC_CONFIGURATION, index, buffer, len, complete_cb, user_arg); + return tuh_descriptor_get(daddr, TUSB_DESC_CONFIGURATION, index, buffer, len, complete_cb, user_data); } //------------- String Descriptor -------------// bool tuh_descriptor_get_string(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len, - tuh_xfer_cb_t complete_cb, uintptr_t user_arg) + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - return _get_descriptor(daddr, TUSB_DESC_STRING, index, language_id, buffer, len, complete_cb, user_arg); + return _get_descriptor(daddr, TUSB_DESC_STRING, index, language_id, buffer, len, complete_cb, user_data); } // Get manufacturer string descriptor bool tuh_descriptor_get_manufacturer_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, - tuh_xfer_cb_t complete_cb, uintptr_t user_arg) + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { usbh_device_t const* dev = get_device(daddr); TU_VERIFY(dev && dev->i_manufacturer); - return tuh_descriptor_get_string(daddr, dev->i_manufacturer, language_id, buffer, len, complete_cb, user_arg); + return tuh_descriptor_get_string(daddr, dev->i_manufacturer, language_id, buffer, len, complete_cb, user_data); } // Get product string descriptor bool tuh_descriptor_get_product_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, - tuh_xfer_cb_t complete_cb, uintptr_t user_arg) + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { usbh_device_t const* dev = get_device(daddr); TU_VERIFY(dev && dev->i_product); - return tuh_descriptor_get_string(daddr, dev->i_product, language_id, buffer, len, complete_cb, user_arg); + return tuh_descriptor_get_string(daddr, dev->i_product, language_id, buffer, len, complete_cb, user_data); } // Get serial string descriptor bool tuh_descriptor_get_serial_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, - tuh_xfer_cb_t complete_cb, uintptr_t user_arg) + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { usbh_device_t const* dev = get_device(daddr); TU_VERIFY(dev && dev->i_serial); - return tuh_descriptor_get_string(daddr, dev->i_serial, language_id, buffer, len, complete_cb, user_arg); + return tuh_descriptor_get_string(daddr, dev->i_serial, language_id, buffer, len, complete_cb, user_data); } // Get HID report descriptor 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_arg) + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_LOG2("HID Get Report Descriptor\r\n"); tusb_control_request_t const request = @@ -435,14 +435,14 @@ bool tuh_descriptor_get_hid_report(uint8_t daddr, uint8_t itf_num, uint8_t desc_ .setup = &request, .buffer = buffer, .complete_cb = complete_cb, - .user_arg = user_arg + .user_data = user_data }; return tuh_control_xfer(daddr, &xfer); } bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, - tuh_xfer_cb_t complete_cb, uintptr_t user_arg) + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_LOG2("Set Configuration = %d\r\n", config_num); @@ -466,7 +466,7 @@ bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, .setup = &request, .buffer = NULL, .complete_cb = complete_cb, - .user_arg = user_arg + .user_data = user_data }; return tuh_control_xfer(daddr, &xfer); @@ -904,7 +904,7 @@ static void _control_blocking_complete_cb(uint8_t daddr, tuh_xfer_t* xfer) { (void) daddr; // update result - *((xfer_result_t*) xfer->user_arg) = xfer->result; + *((xfer_result_t*) xfer->user_data) = xfer->result; } bool tuh_control_xfer_sync(uint8_t daddr, tuh_xfer_t* xfer, uint32_t timeout_ms) @@ -945,7 +945,7 @@ bool tuh_control_xfer (uint8_t daddr, tuh_xfer_t* xfer) _ctrl_xfer.request = (*xfer->setup); _ctrl_xfer.buffer = xfer->buffer; _ctrl_xfer.complete_cb = xfer->complete_cb; - _ctrl_xfer.user_arg = xfer->user_arg; + _ctrl_xfer.user_data = xfer->user_data; if (xfer->complete_cb) { @@ -956,8 +956,8 @@ bool tuh_control_xfer (uint8_t daddr, tuh_xfer_t* xfer) // change callback to internal blocking, and result as user argument volatile xfer_result_t result = XFER_RESULT_INVALID; - // use user_arg to point to xfer_result_t - _ctrl_xfer.user_arg = (uintptr_t) &result; + // use user_data to point to xfer_result_t + _ctrl_xfer.user_data = (uintptr_t) &result; _ctrl_xfer.complete_cb = _control_blocking_complete_cb; TU_ASSERT( hcd_setup_send(rhport, daddr, (uint8_t*) &_ctrl_xfer.request) ); @@ -974,10 +974,10 @@ bool tuh_control_xfer (uint8_t daddr, tuh_xfer_t* xfer) // update xfer result xfer->result = result; - if ( xfer->user_arg ) + if ( xfer->user_data ) { - // if user_arg is not NULL, it is also updated - *((xfer_result_t*) xfer->user_arg) = result; + // if user_data is not NULL, it is also updated + *((xfer_result_t*) xfer->user_data) = result; } xfer->actual_len = _ctrl_xfer.actual_len; @@ -1007,7 +1007,7 @@ static void _xfer_complete(uint8_t dev_addr, xfer_result_t result) .actual_len = (uint32_t) _ctrl_xfer.actual_len, .buffer = _ctrl_xfer.buffer, .complete_cb = _ctrl_xfer.complete_cb, - .user_arg = _ctrl_xfer.user_arg + .user_data = _ctrl_xfer.user_data }; usbh_lock(); @@ -1075,6 +1075,15 @@ static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result // //--------------------------------------------------------------------+ +bool tuh_edpt_xfer(uint8_t daddr, tuh_xfer_t* xfer) +{ + return true; +} + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + // a device unplugged from rhport:hub_addr:hub_port static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) { @@ -1151,7 +1160,7 @@ static void process_enumeration(uint8_t dev_addr, tuh_xfer_t* xfer) return; } - uintptr_t const state = xfer->user_arg; + uintptr_t const state = xfer->user_data; switch(state) { #if CFG_TUH_HUB @@ -1345,8 +1354,8 @@ static bool enum_new_device(hcd_event_t* event) // fake transfer to kick-off the enumeration process tuh_xfer_t xfer; - xfer.result = XFER_RESULT_SUCCESS; - xfer.user_arg = ENUM_ADDR0_DEVICE_DESC; + xfer.result = XFER_RESULT_SUCCESS; + xfer.user_data = ENUM_ADDR0_DEVICE_DESC; process_enumeration(0, &xfer); @@ -1433,7 +1442,7 @@ static bool enum_request_set_addr(void) .setup = &request, .buffer = NULL, .complete_cb = process_enumeration, - .user_arg = ENUM_GET_DEVICE_DESC + .user_data = ENUM_GET_DEVICE_DESC }; uint8_t const addr0 = 0; diff --git a/src/host/usbh.h b/src/host/usbh.h index 2021545ba..30868d2f2 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -47,14 +47,15 @@ typedef void (*tuh_xfer_cb_t)(uint8_t daddr, tuh_xfer_t* xfer); struct tuh_xfer_s { uint8_t ep_addr; - xfer_result_t result; - - tusb_control_request_t const* setup; - uint32_t actual_len; // excluding setup packet - + tusb_control_request_t const* setup; // pointer to setup packet if control transfer + uint32_t buflen; uint8_t* buffer; tuh_xfer_cb_t complete_cb; - uintptr_t user_arg; + uintptr_t user_data; + + // will be updated when transfer is complete + xfer_result_t result; + uint32_t actual_len; // excluding setup packet }; //--------------------------------------------------------------------+ @@ -116,20 +117,20 @@ static inline bool tuh_ready(uint8_t daddr) // Submit a control transfer // true on success, false if there is on-going control transfer or incorrect parameters // Note: blocking if complete callback is NULL. In this case 'xfer->result' will be updated -// and if 'user_arg' point to a xfer_result_t variable, it will be updated as well. +// and if 'user_data' point to a xfer_result_t variable, it will be updated as well. bool tuh_control_xfer(uint8_t daddr, tuh_xfer_t* xfer); // Submit a bulk/interrupt transfer // true on success, false if there is on-going control transfer or incorrect parameters // Note: blocking if complete callback is NULL. In this case 'xfer->result' will be updated -// and if 'user_arg' point to a xfer_result_t variable, it will be updated as well. +// and if 'user_data' point to a xfer_result_t variable, it will be updated as well. bool tuh_edpt_xfer(uint8_t daddr, tuh_xfer_t* xfer); // Set Configuration (control transfer) // config_num = 0 will un-configure device. Note: config_num = config_descriptor_index + 1 // true on success, false if there is on-going control transfer or incorrect parameters bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, - tuh_xfer_cb_t complete_cb, uintptr_t user_arg); + tuh_xfer_cb_t complete_cb, uintptr_t user_data); //--------------------------------------------------------------------+ // Endpoint Synchronous (blocking) @@ -146,43 +147,43 @@ bool tuh_control_xfer_sync(uint8_t daddr, tuh_xfer_t * xfer, uint32_t timeout_ms // Get an descriptor (control transfer) // true on success, false if there is on-going control transfer or incorrect parameters bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len, - tuh_xfer_cb_t complete_cb, uintptr_t user_arg); + tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Get device descriptor (control transfer) // true on success, false if there is on-going control transfer or incorrect parameters bool tuh_descriptor_get_device(uint8_t daddr, void* buffer, uint16_t len, - tuh_xfer_cb_t complete_cb, uintptr_t user_arg); + tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Get configuration descriptor (control transfer) // true on success, false if there is on-going control transfer or incorrect parameters bool tuh_descriptor_get_configuration(uint8_t daddr, uint8_t index, void* buffer, uint16_t len, - tuh_xfer_cb_t complete_cb, uintptr_t user_arg); + tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Get HID report descriptor (control transfer) // true on success, false if there is on-going control transfer or incorrect parameters 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_arg); + tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Get string descriptor (control transfer) // true on success, false if there is on-going control transfer or incorrect parameters -// Blocking if complete callback is NULL, in this case 'user_arg' must contain xfer_result_t variable +// Blocking if complete callback is NULL, in this case 'user_data' must contain xfer_result_t variable bool tuh_descriptor_get_string(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len, - tuh_xfer_cb_t complete_cb, uintptr_t user_arg); + tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Get manufacturer string descriptor (control transfer) // true on success, false if there is on-going control transfer or incorrect parameters bool tuh_descriptor_get_manufacturer_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, - tuh_xfer_cb_t complete_cb, uintptr_t user_arg); + tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Get product string descriptor (control transfer) // true on success, false if there is on-going control transfer or incorrect parameters bool tuh_descriptor_get_product_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, - tuh_xfer_cb_t complete_cb, uintptr_t user_arg); + tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Get serial string descriptor (control transfer) // true on success, false if there is on-going control transfer or incorrect parameters bool tuh_descriptor_get_serial_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, - tuh_xfer_cb_t complete_cb, uintptr_t user_arg); + tuh_xfer_cb_t complete_cb, uintptr_t user_data); //--------------------------------------------------------------------+ // Descriptors Synchronous (blocking) From c063ab49443924afec43a295871205ed61535622 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 18 Mar 2022 00:56:51 +0700 Subject: [PATCH 64/81] try to fix ci --- src/host/usbh.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index 69543854d..6808a24a1 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -268,7 +268,7 @@ struct uintptr_t user_data; volatile uint16_t actual_len; - uint8_t daddr; // device address that is transferring + uint8_t daddr; // transferring device volatile uint8_t stage; }_ctrl_xfer; @@ -548,7 +548,7 @@ bool tuh_init(uint8_t rhport) TU_LOG2("USBH init\r\n"); TU_LOG2_INT(sizeof(usbh_device_t)); TU_LOG2_INT(sizeof(hcd_event_t)); - TU_LOG2_INT(sizeof(tuh_xfer_t)); + TU_LOG2_INT(sizeof(_ctrl_xfer)); // Event queue _usbh_q = osal_queue_create( &_usbh_qdef ); @@ -1077,6 +1077,8 @@ static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result bool tuh_edpt_xfer(uint8_t daddr, tuh_xfer_t* xfer) { + (void) daddr; + (void) xfer; return true; } From 85c6d6d37d3696680b650e211ef8dd279b1f9f26 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 18 Mar 2022 12:51:12 +0700 Subject: [PATCH 65/81] minor update for control xfer --- src/host/usbh.c | 66 +++++++++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index 6808a24a1..a45ab8efa 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -110,14 +110,14 @@ typedef struct { tu_edpt_state_t ep_status[CFG_TUH_ENDPOINT_MAX][2]; #if CFG_TUH_API_EDPT_XFER - struct - { - uint8_t* buffer; - tuh_xfer_cb_t complete_cb; - uintptr_t user_data; - uint16_t buflen; - volatile uint16_t actual_len; - }ep_xfer; +// struct +// { +// uint8_t* buffer; +// tuh_xfer_cb_t complete_cb; +// uintptr_t user_data; +// uint16_t buflen; +// volatile uint16_t actual_len; +// }ep_xfer[[]]; #endif } usbh_device_t; @@ -247,16 +247,6 @@ static osal_queue_t _usbh_q; CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSIZE]; -//// internal version of tuh_xfer_t -//typedef struct -//{ -// uint8_t* buffer; -// tuh_xfer_cb_t complete_cb; -// uintptr_t user_data; -// -// volatile uint16_t actual_len; -//}usbh_xfer_t; - // 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. @@ -267,9 +257,9 @@ struct tuh_xfer_cb_t complete_cb; uintptr_t user_data; - volatile uint16_t actual_len; - uint8_t daddr; // transferring device + uint8_t daddr; volatile uint8_t stage; + volatile uint16_t actual_len; }_ctrl_xfer; //------------- Helper Function -------------// @@ -298,6 +288,8 @@ bool tuh_mounted(uint8_t dev_addr) bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t* vid, uint16_t* pid) { + *vid = *pid = 0; + usbh_device_t const* dev = get_device(dev_addr); TU_VERIFY(dev && dev->configured); @@ -327,6 +319,8 @@ void osal_task_delay(uint32_t msec) // Descriptors Async //--------------------------------------------------------------------+ +// generic helper to get a descriptor +// if blocking, user_data could be pointed to xfer_result static bool _get_descriptor(uint8_t daddr, uint8_t type, uint8_t index, uint16_t language_id, void* buffer, uint16_t len, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { @@ -353,7 +347,15 @@ static bool _get_descriptor(uint8_t daddr, uint8_t type, uint8_t index, uint16_t .user_data = user_data }; - return tuh_control_xfer(daddr, &xfer); + bool const ret = tuh_control_xfer(daddr, &xfer); + + // if blocking, user_data could be pointed to xfer_result + if ( !complete_cb && user_data ) + { + *((xfer_result_t*) user_data) = xfer.result; + } + + return ret; } bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len, @@ -411,6 +413,7 @@ bool tuh_descriptor_get_serial_string(uint8_t daddr, uint16_t language_id, void* } // Get HID report descriptor +// if blocking, user_data could be pointed to xfer_result 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) { @@ -438,7 +441,15 @@ bool tuh_descriptor_get_hid_report(uint8_t daddr, uint8_t itf_num, uint8_t desc_ .user_data = user_data }; - return tuh_control_xfer(daddr, &xfer); + bool const ret = tuh_control_xfer(daddr, &xfer); + + // if blocking, user_data could be pointed to xfer_result + if ( !complete_cb && user_data ) + { + *((xfer_result_t*) user_data) = xfer.result; + } + + return ret; } bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, @@ -549,6 +560,7 @@ bool tuh_init(uint8_t rhport) 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)); // Event queue _usbh_q = osal_queue_create( &_usbh_qdef ); @@ -972,14 +984,8 @@ bool tuh_control_xfer (uint8_t daddr, tuh_xfer_t* xfer) // TODO probably some timeout to prevent hanged } - // update xfer result - xfer->result = result; - if ( xfer->user_data ) - { - // if user_data is not NULL, it is also updated - *((xfer_result_t*) xfer->user_data) = result; - } - + // update transfer result + xfer->result = result; xfer->actual_len = _ctrl_xfer.actual_len; } From 2ff8978dde779607ddf01ba8e9d8dfeb70bfbd03 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 18 Mar 2022 13:38:30 +0700 Subject: [PATCH 66/81] update sync API, move timeout into xfer struct remove tuh_control_xfer_sync() --- examples/host/bare_api/src/main.c | 7 ++--- src/host/usbh.c | 51 +++++++++++-------------------- src/host/usbh.h | 48 ++++++++++++++--------------- 3 files changed, 44 insertions(+), 62 deletions(-) diff --git a/examples/host/bare_api/src/main.c b/examples/host/bare_api/src/main.c index feb94a6fe..b472c40c4 100644 --- a/examples/host/bare_api/src/main.c +++ b/examples/host/bare_api/src/main.c @@ -136,11 +136,10 @@ void print_device_descriptor(uint8_t daddr, tuh_xfer_t* xfer) printf(" idProduct 0x%04x\r\n" , desc_device.idProduct); printf(" bcdDevice %04x\r\n" , desc_device.bcdDevice); - uint32_t timeout_ms = 10; uint16_t temp_buf[128]; printf(" iManufacturer %u " , desc_device.iManufacturer); - if (XFER_RESULT_SUCCESS == tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, temp_buf, TU_ARRAY_SIZE(temp_buf), timeout_ms) ) + if (XFER_RESULT_SUCCESS == tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, temp_buf, TU_ARRAY_SIZE(temp_buf)) ) { utf16_to_utf8(temp_buf, TU_ARRAY_SIZE(temp_buf)); printf((const char*) temp_buf); @@ -148,7 +147,7 @@ void print_device_descriptor(uint8_t daddr, tuh_xfer_t* xfer) printf("\r\n"); printf(" iProduct %u " , desc_device.iProduct); - if (XFER_RESULT_SUCCESS == tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, temp_buf, TU_ARRAY_SIZE(temp_buf), timeout_ms)) + if (XFER_RESULT_SUCCESS == tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, temp_buf, TU_ARRAY_SIZE(temp_buf))) { utf16_to_utf8(temp_buf, TU_ARRAY_SIZE(temp_buf)); printf((const char*) temp_buf); @@ -156,7 +155,7 @@ void print_device_descriptor(uint8_t daddr, tuh_xfer_t* xfer) printf("\r\n"); printf(" iSerialNumber %u " , desc_device.iSerialNumber); - if (XFER_RESULT_SUCCESS == tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, temp_buf, TU_ARRAY_SIZE(temp_buf), timeout_ms)) + if (XFER_RESULT_SUCCESS == tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, temp_buf, TU_ARRAY_SIZE(temp_buf))) { utf16_to_utf8(temp_buf, TU_ARRAY_SIZE(temp_buf)); printf((const char*) temp_buf); diff --git a/src/host/usbh.c b/src/host/usbh.c index a45ab8efa..c801707d9 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -487,52 +487,49 @@ bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, // Descriptor Sync //--------------------------------------------------------------------+ -#define _CONTROL_SYNC_API(_async_func, _timeout, ...) \ - (void) _timeout; \ +#define _CONTROL_SYNC_API(_async_func, ...) \ xfer_result_t result = XFER_RESULT_INVALID;\ - /* TODO use timeout to wait */ \ TU_VERIFY(_async_func(__VA_ARGS__, NULL, (uintptr_t) &result), XFER_RESULT_TIMEOUT); \ return (uint8_t) result -uint8_t tuh_descriptor_get_sync(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len, uint8_t timeout_ms) +uint8_t tuh_descriptor_get_sync(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len) { - _CONTROL_SYNC_API(tuh_descriptor_get, timeout_ms, daddr, type, index, buffer, len); + _CONTROL_SYNC_API(tuh_descriptor_get, daddr, type, index, buffer, len); } -uint8_t tuh_descriptor_get_device_sync(uint8_t daddr, void* buffer, uint16_t len, uint8_t timeout_ms) +uint8_t tuh_descriptor_get_device_sync(uint8_t daddr, void* buffer, uint16_t len) { - len = tu_min16(len, sizeof(tusb_desc_device_t)); - return tuh_descriptor_get_sync(daddr, TUSB_DESC_DEVICE, 0, buffer, len, timeout_ms); + _CONTROL_SYNC_API(tuh_descriptor_get_device, daddr, buffer, len); } -uint8_t tuh_descriptor_get_configuration_sync(uint8_t daddr, uint8_t index, void* buffer, uint16_t len, uint8_t timeout_ms) +uint8_t tuh_descriptor_get_configuration_sync(uint8_t daddr, uint8_t index, void* buffer, uint16_t len) { - return tuh_descriptor_get_sync(daddr, TUSB_DESC_CONFIGURATION, index, buffer, len, timeout_ms); + _CONTROL_SYNC_API(tuh_descriptor_get_configuration, daddr, index, buffer, len); } -uint8_t tuh_descriptor_get_hid_report_sync(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, uint8_t index, void* buffer, uint16_t len, uint8_t timeout_ms) +uint8_t tuh_descriptor_get_hid_report_sync(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, uint8_t index, void* buffer, uint16_t len) { - _CONTROL_SYNC_API(tuh_descriptor_get_hid_report, timeout_ms, daddr, itf_num, desc_type, index, buffer, len); + _CONTROL_SYNC_API(tuh_descriptor_get_hid_report, daddr, itf_num, desc_type, index, buffer, len); } -uint8_t tuh_descriptor_get_string_sync(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len, uint8_t timeout_ms) +uint8_t tuh_descriptor_get_string_sync(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len) { - _CONTROL_SYNC_API(tuh_descriptor_get_string, timeout_ms, daddr, index, language_id, buffer, len); + _CONTROL_SYNC_API(tuh_descriptor_get_string, daddr, index, language_id, buffer, len); } -uint8_t tuh_descriptor_get_manufacturer_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, uint8_t timeout_ms) +uint8_t tuh_descriptor_get_manufacturer_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len) { - _CONTROL_SYNC_API(tuh_descriptor_get_manufacturer_string, timeout_ms, daddr, language_id, buffer, len); + _CONTROL_SYNC_API(tuh_descriptor_get_manufacturer_string, daddr, language_id, buffer, len); } -uint8_t tuh_descriptor_get_product_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, uint8_t timeout_ms) +uint8_t tuh_descriptor_get_product_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len) { - _CONTROL_SYNC_API(tuh_descriptor_get_product_string, timeout_ms, daddr, language_id, buffer, len); + _CONTROL_SYNC_API(tuh_descriptor_get_product_string, daddr, language_id, buffer, len); } -uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, uint8_t timeout_ms) +uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len) { - _CONTROL_SYNC_API(tuh_descriptor_get_serial_string, timeout_ms, daddr, language_id, buffer, len); + _CONTROL_SYNC_API(tuh_descriptor_get_serial_string, daddr, language_id, buffer, len); } //--------------------------------------------------------------------+ @@ -919,19 +916,7 @@ static void _control_blocking_complete_cb(uint8_t daddr, tuh_xfer_t* xfer) *((xfer_result_t*) xfer->user_data) = xfer->result; } -bool tuh_control_xfer_sync(uint8_t daddr, tuh_xfer_t* xfer, uint32_t timeout_ms) -{ - (void) timeout_ms; - - // clear callback for sync - xfer->complete_cb = NULL; - - // TODO use timeout to wait - TU_VERIFY(tuh_control_xfer(daddr, xfer)); - - return true; -} - +// TODO timeout_ms is not supported yet bool tuh_control_xfer (uint8_t daddr, tuh_xfer_t* xfer) { // pre-check to help reducing mutex lock diff --git a/src/host/usbh.h b/src/host/usbh.h index 30868d2f2..21ef86d5d 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -46,16 +46,23 @@ typedef void (*tuh_xfer_cb_t)(uint8_t daddr, tuh_xfer_t* xfer); struct tuh_xfer_s { + uint8_t daddr; uint8_t ep_addr; - tusb_control_request_t const* setup; // pointer to setup packet if control transfer - uint32_t buflen; + + xfer_result_t result; + uint32_t actual_len; // excluding setup packet + + union + { + tusb_control_request_t const* setup; // setup packet if control transfer + uint32_t buflen; // length if not control transfer + }; + uint8_t* buffer; tuh_xfer_cb_t complete_cb; uintptr_t user_data; - // will be updated when transfer is complete - xfer_result_t result; - uint32_t actual_len; // excluding setup packet + uint32_t timeout_ms; }; //--------------------------------------------------------------------+ @@ -116,14 +123,13 @@ static inline bool tuh_ready(uint8_t daddr) // Submit a control transfer // true on success, false if there is on-going control transfer or incorrect parameters -// Note: blocking if complete callback is NULL. In this case 'xfer->result' will be updated -// and if 'user_data' point to a xfer_result_t variable, it will be updated as well. +// Note: blocking if complete callback is NULL. +// xfer contents will be updated to reflect the result bool tuh_control_xfer(uint8_t daddr, tuh_xfer_t* xfer); // Submit a bulk/interrupt transfer // true on success, false if there is on-going control transfer or incorrect parameters -// Note: blocking if complete callback is NULL. In this case 'xfer->result' will be updated -// and if 'user_data' point to a xfer_result_t variable, it will be updated as well. +// Note: blocking if complete callback is NULL. bool tuh_edpt_xfer(uint8_t daddr, tuh_xfer_t* xfer); // Set Configuration (control transfer) @@ -132,14 +138,6 @@ bool tuh_edpt_xfer(uint8_t daddr, tuh_xfer_t* xfer); bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -//--------------------------------------------------------------------+ -// Endpoint Synchronous (blocking) -//--------------------------------------------------------------------+ - -// Sync (blocking) version of tuh_control_xfer() -// xfer contents will be updated to reflect the transfer -bool tuh_control_xfer_sync(uint8_t daddr, tuh_xfer_t * xfer, uint32_t timeout_ms); - //--------------------------------------------------------------------+ // Descriptors Asynchronous (non-blocking) //--------------------------------------------------------------------+ @@ -191,35 +189,35 @@ bool tuh_descriptor_get_serial_string(uint8_t daddr, uint16_t language_id, void* // Sync (blocking) version of tuh_descriptor_get() // return transfer result -uint8_t tuh_descriptor_get_sync(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len, uint8_t timeout_ms); +uint8_t tuh_descriptor_get_sync(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len); // Sync (blocking) version of tuh_descriptor_get_device() // return transfer result -uint8_t tuh_descriptor_get_device_sync(uint8_t daddr, void* buffer, uint16_t len, uint8_t timeout_ms); +uint8_t tuh_descriptor_get_device_sync(uint8_t daddr, void* buffer, uint16_t len); // Sync (blocking) version of tuh_descriptor_get_configuration() // return transfer result -uint8_t tuh_descriptor_get_configuration_sync(uint8_t daddr, uint8_t index, void* buffer, uint16_t len, uint8_t timeout_ms); +uint8_t tuh_descriptor_get_configuration_sync(uint8_t daddr, uint8_t index, void* buffer, uint16_t len); // Sync (blocking) version of tuh_descriptor_get_hid_report() // return transfer result -uint8_t tuh_descriptor_get_hid_report_sync(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, uint8_t index, void* buffer, uint16_t len, uint8_t timeout_ms); +uint8_t tuh_descriptor_get_hid_report_sync(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, uint8_t index, void* buffer, uint16_t len); // Sync (blocking) version of tuh_descriptor_get_string() // return transfer result -uint8_t tuh_descriptor_get_string_sync(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len, uint8_t timeout_ms); +uint8_t tuh_descriptor_get_string_sync(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len); // Sync (blocking) version of tuh_descriptor_get_manufacturer_string() // return transfer result -uint8_t tuh_descriptor_get_manufacturer_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, uint8_t timeout_ms); +uint8_t tuh_descriptor_get_manufacturer_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len); // Sync (blocking) version of tuh_descriptor_get_product_string() // return transfer result -uint8_t tuh_descriptor_get_product_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, uint8_t timeout_ms); +uint8_t tuh_descriptor_get_product_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len); // Sync (blocking) version of tuh_descriptor_get_serial_string() // return transfer result -uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, uint8_t timeout_ms); +uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len); #ifdef __cplusplus } From 8750e3b57756e4377bb737c578e2742b653c314c Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 18 Mar 2022 16:39:35 +0700 Subject: [PATCH 67/81] move daddr into xfer struct --- examples/host/bare_api/src/main.c | 4 +- src/class/cdc/cdc_host.c | 3 +- src/class/hid/hid_host.c | 53 +++++++++++++---------- src/class/msc/msc_host.c | 12 +++--- src/host/hub.c | 70 +++++++++++++++++------------- src/host/usbh.c | 71 ++++++++++++++++++------------- src/host/usbh.h | 18 ++++---- 7 files changed, 132 insertions(+), 99 deletions(-) diff --git a/examples/host/bare_api/src/main.c b/examples/host/bare_api/src/main.c index b472c40c4..e2e0f4ff3 100644 --- a/examples/host/bare_api/src/main.c +++ b/examples/host/bare_api/src/main.c @@ -115,7 +115,7 @@ static void utf16_to_utf8(uint16_t *temp_buf, size_t buf_len) { ((uint8_t*) temp_buf)[utf8_len] = '\0'; } -void print_device_descriptor(uint8_t daddr, tuh_xfer_t* xfer) +void print_device_descriptor(tuh_xfer_t* xfer) { if ( XFER_RESULT_SUCCESS != xfer->result ) { @@ -123,6 +123,8 @@ void print_device_descriptor(uint8_t daddr, tuh_xfer_t* xfer) return; } + uint8_t const daddr = xfer->daddr; + printf("Device %u: ID %04x:%04x\r\n", daddr, desc_device.idVendor, desc_device.idProduct); printf("Device Descriptor:\r\n"); printf(" bLength %u\r\n" , desc_device.bLength); diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 2795750ed..f946974e8 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -140,6 +140,7 @@ bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_xf tuh_xfer_t xfer = { + .daddr = dev_addr, .ep_addr = 0, .setup = &request, .buffer = NULL, @@ -147,7 +148,7 @@ bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_xf .user_data = 0 }; - return tuh_control_xfer(dev_addr, &xfer); + return tuh_control_xfer(&xfer); } //--------------------------------------------------------------------+ diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 0ad917815..fa99b37fe 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -103,11 +103,12 @@ uint8_t tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance) return hid_itf->protocol_mode; } -static void set_protocol_complete(uint8_t dev_addr, tuh_xfer_t* xfer) +static void set_protocol_complete(tuh_xfer_t* xfer) { uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); - uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + uint8_t const daddr = xfer->daddr; + uint8_t const instance = get_instance_id_by_itfnum(daddr, itf_num); + hidh_interface_t* hid_itf = get_instance(daddr, instance); if (XFER_RESULT_SUCCESS == xfer->result) { @@ -116,7 +117,7 @@ static void set_protocol_complete(uint8_t dev_addr, tuh_xfer_t* xfer) if (tuh_hid_set_protocol_complete_cb) { - tuh_hid_set_protocol_complete_cb(dev_addr, instance, hid_itf->protocol_mode); + tuh_hid_set_protocol_complete_cb(daddr, instance, hid_itf->protocol_mode); } } @@ -141,6 +142,7 @@ static bool _hidh_set_protocol(uint8_t dev_addr, uint8_t itf_num, uint8_t protoc tuh_xfer_t xfer = { + .daddr = dev_addr, .ep_addr = 0, .setup = &request, .buffer = NULL, @@ -148,7 +150,7 @@ static bool _hidh_set_protocol(uint8_t dev_addr, uint8_t itf_num, uint8_t protoc .user_data = user_data }; - TU_ASSERT( tuh_control_xfer(dev_addr, &xfer) ); + TU_ASSERT( tuh_control_xfer(&xfer) ); return true; } @@ -160,19 +162,19 @@ bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) return _hidh_set_protocol(dev_addr, hid_itf->itf_num, protocol, set_protocol_complete, 0); } -static void set_report_complete(uint8_t dev_addr, tuh_xfer_t* xfer) +static void set_report_complete(tuh_xfer_t* xfer) { TU_LOG2("HID Set Report complete\r\n"); if (tuh_hid_set_report_complete_cb) { uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); - uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); + uint8_t const instance = get_instance_id_by_itfnum(xfer->daddr, itf_num); uint8_t const report_type = tu_u16_high(xfer->setup->wValue); uint8_t const report_id = tu_u16_low(xfer->setup->wValue); - tuh_hid_set_report_complete_cb(dev_addr, instance, report_id, report_type, + tuh_hid_set_report_complete_cb(xfer->daddr, instance, report_id, report_type, (xfer->result == XFER_RESULT_SUCCESS) ? xfer->setup->wLength : 0); } } @@ -198,6 +200,7 @@ bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, u tuh_xfer_t xfer = { + .daddr = dev_addr, .ep_addr = 0, .setup = &request, .buffer = report, @@ -205,7 +208,7 @@ bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, u .user_data = 0 }; - TU_ASSERT( tuh_control_xfer(dev_addr, &xfer) ); + TU_ASSERT( tuh_control_xfer(&xfer) ); return true; } @@ -229,6 +232,7 @@ static bool _hidh_set_idle(uint8_t dev_addr, uint8_t itf_num, uint16_t idle_rate tuh_xfer_t xfer = { + .daddr = dev_addr, .ep_addr = 0, .setup = &request, .buffer = NULL, @@ -236,7 +240,7 @@ static bool _hidh_set_idle(uint8_t dev_addr, uint8_t itf_num, uint16_t idle_rate .user_data = user_data }; - TU_ASSERT( tuh_control_xfer(dev_addr, &xfer) ); + TU_ASSERT( tuh_control_xfer(&xfer) ); return true; } @@ -389,7 +393,7 @@ enum { }; static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len); -static void process_set_config(uint8_t dev_addr, tuh_xfer_t* xfer); +static void process_set_config(tuh_xfer_t* xfer); bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) { @@ -397,17 +401,18 @@ bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) request.wIndex = tu_htole16((uint16_t) itf_num); tuh_xfer_t xfer; + xfer.daddr = dev_addr; xfer.result = XFER_RESULT_SUCCESS; xfer.setup = &request; xfer.user_data = CONFG_SET_IDLE; // fake request to kick-off the set config process - process_set_config(dev_addr, &xfer); + process_set_config(&xfer); return true; } -static void process_set_config(uint8_t dev_addr, tuh_xfer_t* xfer) +static void process_set_config(tuh_xfer_t* xfer) { // Stall is a valid response for SET_IDLE, therefore we could ignore its result if ( xfer->setup->bRequest != HID_REQ_CONTROL_SET_IDLE ) @@ -415,10 +420,12 @@ static void process_set_config(uint8_t dev_addr, tuh_xfer_t* xfer) TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); } - uintptr_t const state = xfer->user_data; - uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); - uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + uintptr_t const state = xfer->user_data; + uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); + uint8_t const daddr = xfer->daddr; + + uint8_t const instance = get_instance_id_by_itfnum(daddr, itf_num); + hidh_interface_t* hid_itf = get_instance(daddr, instance); switch(state) { @@ -427,12 +434,12 @@ static void process_set_config(uint8_t dev_addr, tuh_xfer_t* xfer) // Idle rate = 0 mean only report when there is changes const uint16_t idle_rate = 0; const uintptr_t next_state = (hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE) ? CONFIG_SET_PROTOCOL : CONFIG_GET_REPORT_DESC; - _hidh_set_idle(dev_addr, itf_num, idle_rate, process_set_config, next_state); + _hidh_set_idle(daddr, itf_num, idle_rate, process_set_config, next_state); } break; case CONFIG_SET_PROTOCOL: - _hidh_set_protocol(dev_addr, hid_itf->itf_num, HID_PROTOCOL_BOOT, process_set_config, CONFIG_GET_REPORT_DESC); + _hidh_set_protocol(daddr, hid_itf->itf_num, HID_PROTOCOL_BOOT, process_set_config, CONFIG_GET_REPORT_DESC); break; case CONFIG_GET_REPORT_DESC: @@ -443,19 +450,19 @@ static void process_set_config(uint8_t dev_addr, tuh_xfer_t* xfer) TU_LOG2("HID Skip Report Descriptor since it is too large %u bytes\r\n", hid_itf->report_desc_len); // Driver is mounted without report descriptor - config_driver_mount_complete(dev_addr, instance, NULL, 0); + config_driver_mount_complete(daddr, instance, NULL, 0); }else { - tuh_descriptor_get_hid_report(dev_addr, itf_num, hid_itf->report_desc_type, 0, usbh_get_enum_buf(), hid_itf->report_desc_len, process_set_config, CONFIG_COMPLETE); + tuh_descriptor_get_hid_report(daddr, itf_num, hid_itf->report_desc_type, 0, usbh_get_enum_buf(), hid_itf->report_desc_len, process_set_config, CONFIG_COMPLETE); } break; case CONFIG_COMPLETE: { uint8_t const* desc_report = usbh_get_enum_buf(); - uint16_t const desc_len = xfer->setup->wLength; + uint16_t const desc_len = tu_le16toh(xfer->setup->wLength); - config_driver_mount_complete(dev_addr, instance, desc_report, desc_len); + config_driver_mount_complete(daddr, instance, desc_report, desc_len); } break; diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 5a34f2d56..06af781f5 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -358,7 +358,7 @@ bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 // MSC Enumeration //--------------------------------------------------------------------+ -static void config_get_maxlun_complete (uint8_t dev_addr, tuh_xfer_t* xfer); +static void config_get_maxlun_complete (tuh_xfer_t* xfer); static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); @@ -421,20 +421,22 @@ bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) tuh_xfer_t xfer = { + .daddr = dev_addr, .ep_addr = 0, .setup = &request, .buffer = &p_msc->max_lun, .complete_cb = config_get_maxlun_complete, .user_data = 0 }; - TU_ASSERT(tuh_control_xfer(dev_addr, &xfer)); + TU_ASSERT(tuh_control_xfer(&xfer)); return true; } -static void config_get_maxlun_complete (uint8_t dev_addr, tuh_xfer_t* xfer) +static void config_get_maxlun_complete (tuh_xfer_t* xfer) { - msch_interface_t* p_msc = get_itf(dev_addr); + uint8_t const daddr = xfer->daddr; + msch_interface_t* p_msc = get_itf(daddr); // STALL means zero p_msc->max_lun = (XFER_RESULT_SUCCESS == xfer->result) ? _msch_buffer[0] : 0; @@ -443,7 +445,7 @@ static void config_get_maxlun_complete (uint8_t dev_addr, tuh_xfer_t* xfer) // TODO multiple LUN support TU_LOG2("SCSI Test Unit Ready\r\n"); uint8_t const lun = 0; - tuh_msc_test_unit_ready(dev_addr, lun, config_test_unit_ready_complete); + tuh_msc_test_unit_ready(daddr, lun, config_test_unit_ready_complete); } static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) diff --git a/src/host/hub.c b/src/host/hub.c index ac24988d8..da4f6fe3a 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -96,6 +96,7 @@ bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_xfer_t xfer = { + .daddr = hub_addr, .ep_addr = 0, .setup = &request, .buffer = NULL, @@ -104,7 +105,7 @@ bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, }; TU_LOG2("HUB Clear Feature: %s, addr = %u port = %u\r\n", _hub_feature_str[feature], hub_addr, hub_port); - TU_ASSERT( tuh_control_xfer(hub_addr, &xfer) ); + TU_ASSERT( tuh_control_xfer(&xfer) ); return true; } @@ -127,6 +128,7 @@ bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_xfer_t xfer = { + .daddr = hub_addr, .ep_addr = 0, .setup = &request, .buffer = NULL, @@ -135,7 +137,7 @@ bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, }; TU_LOG2("HUB Set Feature: %s, addr = %u port = %u\r\n", _hub_feature_str[feature], hub_addr, hub_port); - TU_ASSERT( tuh_control_xfer(hub_addr, &xfer) ); + TU_ASSERT( tuh_control_xfer(&xfer) ); return true; } @@ -158,6 +160,7 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_xfer_t xfer = { + .daddr = hub_addr, .ep_addr = 0, .setup = &request, .buffer = resp, @@ -166,7 +169,7 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, }; TU_LOG2("HUB Get Port Status: addr = %u port = %u\r\n", hub_addr, hub_port); - TU_ASSERT( tuh_control_xfer( hub_addr, &xfer) ); + TU_ASSERT( tuh_control_xfer(&xfer) ); return true; } @@ -225,8 +228,8 @@ bool hub_edpt_status_xfer(uint8_t dev_addr) // Set Configure //--------------------------------------------------------------------+ -static void config_set_port_power (uint8_t dev_addr, tuh_xfer_t* xfer); -static void config_port_power_complete (uint8_t dev_addr, tuh_xfer_t* xfer); +static void config_set_port_power (tuh_xfer_t* xfer); +static void config_port_power_complete (tuh_xfer_t* xfer); bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) { @@ -250,6 +253,7 @@ bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) tuh_xfer_t xfer = { + .daddr = dev_addr, .ep_addr = 0, .setup = &request, .buffer = _hub_buffer, @@ -257,16 +261,17 @@ bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) .user_data = 0 }; - TU_ASSERT( tuh_control_xfer(dev_addr, &xfer) ); + TU_ASSERT( tuh_control_xfer(&xfer) ); return true; } -static void config_set_port_power (uint8_t dev_addr, tuh_xfer_t* xfer) +static void config_set_port_power (tuh_xfer_t* xfer) { TU_ASSERT(XFER_RESULT_SUCCESS == xfer->result, ); - hub_interface_t* p_hub = get_itf(dev_addr); + uint8_t const daddr = xfer->daddr; + hub_interface_t* p_hub = get_itf(daddr); // only use number of ports in hub descriptor descriptor_hub_desc_t const* desc_hub = (descriptor_hub_desc_t const*) _hub_buffer; @@ -276,26 +281,28 @@ static void config_set_port_power (uint8_t dev_addr, tuh_xfer_t* xfer) // Set Port Power to be able to detect connection, starting with port 1 uint8_t const hub_port = 1; - hub_port_set_feature(dev_addr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete, 0); + hub_port_set_feature(daddr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete, 0); } -static void config_port_power_complete (uint8_t dev_addr, tuh_xfer_t* xfer) +static void config_port_power_complete (tuh_xfer_t* xfer) { TU_ASSERT(XFER_RESULT_SUCCESS == xfer->result, ); - hub_interface_t* p_hub = get_itf(dev_addr); + + uint8_t const daddr = xfer->daddr; + hub_interface_t* p_hub = get_itf(daddr); if (xfer->setup->wIndex == p_hub->port_count) { // All ports are power -> queue notification status endpoint and // complete the SET CONFIGURATION - TU_ASSERT( usbh_edpt_xfer(dev_addr, p_hub->ep_in, &p_hub->status_change, 1), ); + TU_ASSERT( usbh_edpt_xfer(daddr, p_hub->ep_in, &p_hub->status_change, 1), ); - usbh_driver_set_config_complete(dev_addr, p_hub->itf_num); + usbh_driver_set_config_complete(daddr, p_hub->itf_num); }else { // power next port uint8_t const hub_port = (uint8_t) (xfer->setup->wIndex + 1); - hub_port_set_feature(dev_addr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete, 0); + hub_port_set_feature(daddr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete, 0); } } @@ -303,9 +310,9 @@ static void config_port_power_complete (uint8_t dev_addr, tuh_xfer_t* xfer) // Connection Changes //--------------------------------------------------------------------+ -static void connection_get_status_complete (uint8_t dev_addr, tuh_xfer_t* xfer); -static void connection_clear_conn_change_complete (uint8_t dev_addr, tuh_xfer_t* xfer); -static void connection_port_reset_complete (uint8_t dev_addr, tuh_xfer_t* xfer); +static void connection_get_status_complete (tuh_xfer_t* xfer); +static void connection_clear_conn_change_complete (tuh_xfer_t* xfer); +static void connection_port_reset_complete (tuh_xfer_t* xfer); // callback as response of interrupt endpoint polling bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) @@ -333,11 +340,12 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32 return true; } -static void connection_get_status_complete (uint8_t dev_addr, tuh_xfer_t* xfer) +static void connection_get_status_complete (tuh_xfer_t* xfer) { TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); - hub_interface_t* p_hub = get_itf(dev_addr); + uint8_t const daddr = xfer->daddr; + hub_interface_t* p_hub = get_itf(daddr); uint8_t const port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); // Connection change @@ -347,7 +355,7 @@ static void connection_get_status_complete (uint8_t dev_addr, tuh_xfer_t* xfer) //TU_VERIFY(port_status.status_current.port_power && port_status.status_current.port_enable, ); // Acknowledge Port Connection Change - hub_port_clear_feature(dev_addr, port_num, HUB_FEATURE_PORT_CONNECTION_CHANGE, connection_clear_conn_change_complete, 0); + hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_CONNECTION_CHANGE, connection_clear_conn_change_complete, 0); }else { // Other changes are: Enable, Suspend, Over Current, Reset, L1 state @@ -355,31 +363,32 @@ static void connection_get_status_complete (uint8_t dev_addr, tuh_xfer_t* xfer) // prepare for next hub status // TODO continue with status_change, or maybe we can do it again with status - hub_edpt_status_xfer(dev_addr); + hub_edpt_status_xfer(daddr); } } -static void connection_clear_conn_change_complete (uint8_t dev_addr, tuh_xfer_t* xfer) +static void connection_clear_conn_change_complete (tuh_xfer_t* xfer) { TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); - hub_interface_t* p_hub = get_itf(dev_addr); + uint8_t const daddr = xfer->daddr; + hub_interface_t* p_hub = get_itf(daddr); uint8_t const port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); if ( p_hub->port_status.status.connection ) { // Reset port if attach event - hub_port_reset(dev_addr, port_num, connection_port_reset_complete, 0); + hub_port_reset(daddr, port_num, connection_port_reset_complete, 0); }else { // submit detach event hcd_event_t event = { - .rhport = usbh_get_rhport(dev_addr), + .rhport = usbh_get_rhport(daddr), .event_id = HCD_EVENT_DEVICE_REMOVE, .connection = { - .hub_addr = dev_addr, + .hub_addr = daddr, .hub_port = port_num } }; @@ -388,21 +397,22 @@ static void connection_clear_conn_change_complete (uint8_t dev_addr, tuh_xfer_t* } } -static void connection_port_reset_complete (uint8_t dev_addr, tuh_xfer_t* xfer) +static void connection_port_reset_complete (tuh_xfer_t* xfer) { TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); - // hub_interface_t* p_hub = get_itf(dev_addr); + uint8_t const daddr = xfer->daddr; + // hub_interface_t* p_hub = get_itf(daddr); uint8_t const port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); // submit attach event hcd_event_t event = { - .rhport = usbh_get_rhport(dev_addr), + .rhport = usbh_get_rhport(daddr), .event_id = HCD_EVENT_DEVICE_ATTACH, .connection = { - .hub_addr = dev_addr, + .hub_addr = daddr, .hub_port = port_num } }; diff --git a/src/host/usbh.c b/src/host/usbh.c index c801707d9..36774d3dc 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -340,6 +340,7 @@ static bool _get_descriptor(uint8_t daddr, uint8_t type, uint8_t index, uint16_t tuh_xfer_t xfer = { + .daddr = daddr, .ep_addr = 0, .setup = &request, .buffer = buffer, @@ -347,7 +348,7 @@ static bool _get_descriptor(uint8_t daddr, uint8_t type, uint8_t index, uint16_t .user_data = user_data }; - bool const ret = tuh_control_xfer(daddr, &xfer); + bool const ret = tuh_control_xfer(&xfer); // if blocking, user_data could be pointed to xfer_result if ( !complete_cb && user_data ) @@ -434,6 +435,7 @@ bool tuh_descriptor_get_hid_report(uint8_t daddr, uint8_t itf_num, uint8_t desc_ tuh_xfer_t xfer = { + .daddr = daddr, .ep_addr = 0, .setup = &request, .buffer = buffer, @@ -441,7 +443,7 @@ bool tuh_descriptor_get_hid_report(uint8_t daddr, uint8_t itf_num, uint8_t desc_ .user_data = user_data }; - bool const ret = tuh_control_xfer(daddr, &xfer); + bool const ret = tuh_control_xfer(&xfer); // if blocking, user_data could be pointed to xfer_result if ( !complete_cb && user_data ) @@ -473,6 +475,7 @@ bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, tuh_xfer_t xfer = { + .daddr = daddr, .ep_addr = 0, .setup = &request, .buffer = NULL, @@ -480,7 +483,7 @@ bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, .user_data = user_data }; - return tuh_control_xfer(daddr, &xfer); + return tuh_control_xfer(&xfer); } //--------------------------------------------------------------------+ @@ -909,24 +912,38 @@ bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) // Control transfer //--------------------------------------------------------------------+ -static void _control_blocking_complete_cb(uint8_t daddr, tuh_xfer_t* xfer) +static void _control_blocking_complete_cb(tuh_xfer_t* xfer) { - (void) daddr; // update result *((xfer_result_t*) xfer->user_data) = xfer->result; } // TODO timeout_ms is not supported yet -bool tuh_control_xfer (uint8_t daddr, tuh_xfer_t* xfer) +bool tuh_control_xfer (tuh_xfer_t* xfer) { + // EP0 with setup packet + TU_VERIFY(xfer->ep_addr == 0 && xfer->setup); + // pre-check to help reducing mutex lock TU_VERIFY(_ctrl_xfer.stage == CONTROL_STAGE_IDLE); + uint8_t const daddr = xfer->daddr; + // TODO probably better to use semaphore as resource management than mutex usbh_lock(); bool const is_idle = (_ctrl_xfer.stage == CONTROL_STAGE_IDLE); - if (is_idle) _ctrl_xfer.stage = CONTROL_STAGE_SETUP; + if (is_idle) + { + _ctrl_xfer.stage = CONTROL_STAGE_SETUP; + _ctrl_xfer.daddr = daddr; + _ctrl_xfer.actual_len = 0; + + _ctrl_xfer.request = (*xfer->setup); + _ctrl_xfer.buffer = xfer->buffer; + _ctrl_xfer.complete_cb = xfer->complete_cb; + _ctrl_xfer.user_data = xfer->user_data; + } usbh_unlock(); @@ -937,13 +954,6 @@ bool tuh_control_xfer (uint8_t daddr, tuh_xfer_t* xfer) TU_LOG2_VAR(&xfer->setup); TU_LOG2("\r\n"); - _ctrl_xfer.actual_len = 0; - _ctrl_xfer.daddr = daddr; - _ctrl_xfer.request = (*xfer->setup); - _ctrl_xfer.buffer = xfer->buffer; - _ctrl_xfer.complete_cb = xfer->complete_cb; - _ctrl_xfer.user_data = xfer->user_data; - if (xfer->complete_cb) { TU_ASSERT( hcd_setup_send(rhport, daddr, (uint8_t*) &_ctrl_xfer.request) ); @@ -984,7 +994,7 @@ TU_ATTR_ALWAYS_INLINE static inline void _set_control_xfer_stage(uint8_t stage) usbh_unlock(); } -static void _xfer_complete(uint8_t dev_addr, xfer_result_t result) +static void _xfer_complete(uint8_t daddr, xfer_result_t result) { TU_LOG2("\r\n"); @@ -992,6 +1002,7 @@ static void _xfer_complete(uint8_t dev_addr, xfer_result_t result) tusb_control_request_t const request = _ctrl_xfer.request; tuh_xfer_t xfer_temp = { + .daddr = daddr, .ep_addr = 0, .result = result, .setup = &request, @@ -1007,7 +1018,7 @@ static void _xfer_complete(uint8_t dev_addr, xfer_result_t result) if (xfer_temp.complete_cb) { - xfer_temp.complete_cb(dev_addr, &xfer_temp); + xfer_temp.complete_cb(&xfer_temp); } } @@ -1066,9 +1077,8 @@ static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result // //--------------------------------------------------------------------+ -bool tuh_edpt_xfer(uint8_t daddr, tuh_xfer_t* xfer) +bool tuh_edpt_xfer(tuh_xfer_t* xfer) { - (void) daddr; (void) xfer; return true; } @@ -1144,7 +1154,7 @@ static bool parse_configuration_descriptor (uint8_t dev_addr, tusb_desc_configur static void enum_full_complete(void); // process device enumeration -static void process_enumeration(uint8_t dev_addr, tuh_xfer_t* xfer) +static void process_enumeration(tuh_xfer_t* xfer) { if (XFER_RESULT_SUCCESS != xfer->result) { @@ -1153,7 +1163,9 @@ static void process_enumeration(uint8_t dev_addr, tuh_xfer_t* xfer) return; } + uint8_t const daddr = xfer->daddr; uintptr_t const state = xfer->user_data; + switch(state) { #if CFG_TUH_HUB @@ -1261,7 +1273,7 @@ static void process_enumeration(uint8_t dev_addr, tuh_xfer_t* xfer) case ENUM_GET_9BYTE_CONFIG_DESC: { tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf; - usbh_device_t* dev = get_device(dev_addr); + usbh_device_t* dev = get_device(daddr); TU_ASSERT(dev, ); dev->vid = desc_device->idVendor; @@ -1275,7 +1287,7 @@ static void process_enumeration(uint8_t dev_addr, 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_ASSERT( tuh_descriptor_get_configuration(dev_addr, config_idx, _usbh_ctrl_buf, 9, process_enumeration, ENUM_GET_FULL_CONFIG_DESC), ); + TU_ASSERT( tuh_descriptor_get_configuration(daddr, config_idx, _usbh_ctrl_buf, 9, process_enumeration, ENUM_GET_FULL_CONFIG_DESC), ); } break; @@ -1292,22 +1304,22 @@ static void process_enumeration(uint8_t dev_addr, 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_ASSERT( tuh_descriptor_get_configuration(dev_addr, config_idx, _usbh_ctrl_buf, total_len, process_enumeration, ENUM_SET_CONFIG), ); + TU_ASSERT( tuh_descriptor_get_configuration(daddr, config_idx, _usbh_ctrl_buf, total_len, process_enumeration, ENUM_SET_CONFIG), ); } break; case ENUM_SET_CONFIG: // Parse configuration & set up drivers // Driver open aren't allowed to make any usb transfer yet - TU_ASSERT( parse_configuration_descriptor(dev_addr, (tusb_desc_configuration_t*) _usbh_ctrl_buf), ); + TU_ASSERT( parse_configuration_descriptor(daddr, (tusb_desc_configuration_t*) _usbh_ctrl_buf), ); - TU_ASSERT( tuh_configuration_set(dev_addr, CONFIG_NUM, process_enumeration, ENUM_CONFIG_DRIVER), ); + TU_ASSERT( tuh_configuration_set(daddr, CONFIG_NUM, process_enumeration, ENUM_CONFIG_DRIVER), ); break; case ENUM_CONFIG_DRIVER: { TU_LOG2("Device configured\r\n"); - usbh_device_t* dev = get_device(dev_addr); + usbh_device_t* dev = get_device(daddr); TU_ASSERT(dev, ); dev->configured = 1; @@ -1316,7 +1328,7 @@ static void process_enumeration(uint8_t dev_addr, tuh_xfer_t* xfer) // Since driver can perform control transfer within its set_config, this is done asynchronously. // The process continue with next interface when class driver complete its sequence with usbh_driver_set_config_complete() // TODO use separated API instead of using DRVID_INVALID - usbh_driver_set_config_complete(dev_addr, DRVID_INVALID); + usbh_driver_set_config_complete(daddr, DRVID_INVALID); } break; @@ -1347,10 +1359,11 @@ static bool enum_new_device(hcd_event_t* event) // fake transfer to kick-off the enumeration process tuh_xfer_t xfer; + xfer.daddr = 0; xfer.result = XFER_RESULT_SUCCESS; xfer.user_data = ENUM_ADDR0_DEVICE_DESC; - process_enumeration(0, &xfer); + process_enumeration(&xfer); } #if CFG_TUH_HUB @@ -1431,6 +1444,7 @@ static bool enum_request_set_addr(void) tuh_xfer_t xfer = { + .daddr = 0, // dev0 .ep_addr = 0, .setup = &request, .buffer = NULL, @@ -1438,8 +1452,7 @@ static bool enum_request_set_addr(void) .user_data = ENUM_GET_DEVICE_DESC }; - uint8_t const addr0 = 0; - TU_ASSERT( tuh_control_xfer(addr0, &xfer) ); + TU_ASSERT( tuh_control_xfer(&xfer) ); return true; } diff --git a/src/host/usbh.h b/src/host/usbh.h index 21ef86d5d..f79c5cdc8 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -42,7 +42,7 @@ struct tuh_xfer_s; typedef struct tuh_xfer_s tuh_xfer_t; -typedef void (*tuh_xfer_cb_t)(uint8_t daddr, tuh_xfer_t* xfer); +typedef void (*tuh_xfer_cb_t)(tuh_xfer_t* xfer); struct tuh_xfer_s { @@ -54,7 +54,7 @@ struct tuh_xfer_s union { - tusb_control_request_t const* setup; // setup packet if control transfer + tusb_control_request_t const* setup; // setup packet pointer if control transfer uint32_t buflen; // length if not control transfer }; @@ -62,7 +62,7 @@ struct tuh_xfer_s tuh_xfer_cb_t complete_cb; uintptr_t user_data; - uint32_t timeout_ms; + uint32_t timeout_ms; // place holder, not supported yet }; //--------------------------------------------------------------------+ @@ -118,19 +118,17 @@ static inline bool tuh_ready(uint8_t daddr) } //--------------------------------------------------------------------+ -// Endpoint Asynchronous (non-blocking) +// Transfer API //--------------------------------------------------------------------+ // Submit a control transfer -// true on success, false if there is on-going control transfer or incorrect parameters -// Note: blocking if complete callback is NULL. -// xfer contents will be updated to reflect the result -bool tuh_control_xfer(uint8_t daddr, tuh_xfer_t* xfer); +// Note: blocking if complete callback is NULL, in this case xfer contents will be updated to reflect the result +bool tuh_control_xfer(tuh_xfer_t* xfer); // Submit a bulk/interrupt transfer -// true on success, false if there is on-going control transfer or incorrect parameters +// xfer memory must exist until transfer is complete. // Note: blocking if complete callback is NULL. -bool tuh_edpt_xfer(uint8_t daddr, tuh_xfer_t* xfer); +bool tuh_edpt_xfer(tuh_xfer_t* xfer); // Set Configuration (control transfer) // config_num = 0 will un-configure device. Note: config_num = config_descriptor_index + 1 From 9ae0304b1ecd8d10f96a39c5c88a43d6b7c43681 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 18 Mar 2022 18:04:25 +0700 Subject: [PATCH 68/81] move code around --- src/host/usbh.c | 1109 +++++++++++++++++++++++------------------------ 1 file changed, 553 insertions(+), 556 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index 36774d3dc..8aa9c4a16 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -110,14 +110,7 @@ typedef struct { tu_edpt_state_t ep_status[CFG_TUH_ENDPOINT_MAX][2]; #if CFG_TUH_API_EDPT_XFER -// struct -// { -// uint8_t* buffer; -// tuh_xfer_cb_t complete_cb; -// uintptr_t user_data; -// uint16_t buflen; -// volatile uint16_t actual_len; -// }ep_xfer[[]]; + // ep_xfer[]; #endif } usbh_device_t; @@ -315,6 +308,558 @@ void osal_task_delay(uint32_t msec) } #endif +//--------------------------------------------------------------------+ +// CLASS-USBD API (don't require to verify parameters) +//--------------------------------------------------------------------+ + +static void clear_device(usbh_device_t* dev) +{ + tu_memclr(dev, sizeof(usbh_device_t)); + memset(dev->itf2drv, DRVID_INVALID, sizeof(dev->itf2drv)); // invalid mapping + memset(dev->ep2drv , DRVID_INVALID, sizeof(dev->ep2drv )); // invalid mapping +} + +bool tuh_inited(void) +{ + return _usbh_initialized; +} + +bool tuh_init(uint8_t rhport) +{ + // skip if already initialized + if (_usbh_initialized) return _usbh_initialized; + + TU_LOG2("USBH init\r\n"); + 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)); + + // Event queue + _usbh_q = osal_queue_create( &_usbh_qdef ); + TU_ASSERT(_usbh_q != NULL); + +#if TUSB_OPT_MUTEX + // Mutex + _usbh_mutex = osal_mutex_create(&_usbh_mutexdef); + TU_ASSERT(_usbh_mutex); +#endif + + // Device + tu_memclr(&_dev0, sizeof(_dev0)); + tu_memclr(_usbh_devices, sizeof(_usbh_devices)); + tu_memclr(&_ctrl_xfer, sizeof(_ctrl_xfer)); + + for(uint8_t i=0; iep_status[epnum][ep_dir].busy = 0; + dev->ep_status[epnum][ep_dir].claimed = 0; + + if ( 0 == epnum ) + { + usbh_control_xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + }else + { + uint8_t drv_id = dev->ep2drv[epnum][ep_dir]; + TU_ASSERT(drv_id < USBH_CLASS_DRIVER_COUNT, ); + + TU_LOG2("%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); + } + } + } + break; + + case USBH_EVENT_FUNC_CALL: + if ( event.func_call.func ) event.func_call.func(event.func_call.param); + break; + + default: break; + } + } +} + +//--------------------------------------------------------------------+ +// Control transfer +//--------------------------------------------------------------------+ + +static void _control_blocking_complete_cb(tuh_xfer_t* xfer) +{ + // update result + *((xfer_result_t*) xfer->user_data) = xfer->result; +} + +// TODO timeout_ms is not supported yet +bool tuh_control_xfer (tuh_xfer_t* xfer) +{ + // EP0 with setup packet + TU_VERIFY(xfer->ep_addr == 0 && xfer->setup); + + // pre-check to help reducing mutex lock + TU_VERIFY(_ctrl_xfer.stage == CONTROL_STAGE_IDLE); + + uint8_t const daddr = xfer->daddr; + + // TODO probably better to use semaphore as resource management than mutex + usbh_lock(); + + bool const is_idle = (_ctrl_xfer.stage == CONTROL_STAGE_IDLE); + if (is_idle) + { + _ctrl_xfer.stage = CONTROL_STAGE_SETUP; + _ctrl_xfer.daddr = daddr; + _ctrl_xfer.actual_len = 0; + + _ctrl_xfer.request = (*xfer->setup); + _ctrl_xfer.buffer = xfer->buffer; + _ctrl_xfer.complete_cb = xfer->complete_cb; + _ctrl_xfer.user_data = xfer->user_data; + } + + usbh_unlock(); + + 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_VAR(&xfer->setup); + TU_LOG2("\r\n"); + + if (xfer->complete_cb) + { + TU_ASSERT( hcd_setup_send(rhport, daddr, (uint8_t*) &_ctrl_xfer.request) ); + }else + { + // blocking if complete callback is not provided + // change callback to internal blocking, and result as user argument + volatile xfer_result_t result = XFER_RESULT_INVALID; + + // use user_data to point to xfer_result_t + _ctrl_xfer.user_data = (uintptr_t) &result; + _ctrl_xfer.complete_cb = _control_blocking_complete_cb; + + TU_ASSERT( hcd_setup_send(rhport, daddr, (uint8_t*) &_ctrl_xfer.request) ); + + while (result == XFER_RESULT_INVALID) + { + // only need to call task if not preempted RTOS + #if CFG_TUSB_OS == OPT_OS_NONE || CFG_TUSB_OS == OPT_OS_PICO + tuh_task(); + #endif + + // TODO probably some timeout to prevent hanged + } + + // update transfer result + xfer->result = result; + xfer->actual_len = _ctrl_xfer.actual_len; + } + + return true; +} + +TU_ATTR_ALWAYS_INLINE static inline void _set_control_xfer_stage(uint8_t stage) +{ + usbh_lock(); + _ctrl_xfer.stage = stage; + usbh_unlock(); +} + +static void _xfer_complete(uint8_t daddr, xfer_result_t result) +{ + TU_LOG2("\r\n"); + + // duplicate xfer since user can execute control transfer within callback + tusb_control_request_t const request = _ctrl_xfer.request; + tuh_xfer_t xfer_temp = + { + .daddr = daddr, + .ep_addr = 0, + .result = result, + .setup = &request, + .actual_len = (uint32_t) _ctrl_xfer.actual_len, + .buffer = _ctrl_xfer.buffer, + .complete_cb = _ctrl_xfer.complete_cb, + .user_data = _ctrl_xfer.user_data + }; + + usbh_lock(); + _ctrl_xfer.stage = CONTROL_STAGE_IDLE; + usbh_unlock(); + + if (xfer_temp.complete_cb) + { + xfer_temp.complete_cb(&xfer_temp); + } +} + +static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void) ep_addr; + + const uint8_t rhport = usbh_get_rhport(dev_addr); + tusb_control_request_t const * request = &_ctrl_xfer.request; + + if (XFER_RESULT_SUCCESS != result) + { + TU_LOG2("[%u:%u] Control %s\r\n", rhport, dev_addr, result == XFER_RESULT_STALLED ? "STALLED" : "FAILED"); + + // terminate transfer if any stage failed + _xfer_complete(dev_addr, result); + }else + { + switch(_ctrl_xfer.stage) + { + case CONTROL_STAGE_SETUP: + if (request->wLength) + { + // DATA stage: initial data toggle is always 1 + _set_control_xfer_stage(CONTROL_STAGE_DATA); + return hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.buffer, request->wLength); + } + __attribute__((fallthrough)); + + case CONTROL_STAGE_DATA: + if (xferred_bytes) + { + TU_LOG2("[%u:%u] Control data:\r\n", rhport, dev_addr); + TU_LOG2_MEM(_ctrl_xfer.buffer, xferred_bytes, 2); + } + + _ctrl_xfer.actual_len = xferred_bytes; + + // ACK stage: toggle is always 1 + _set_control_xfer_stage(CONTROL_STAGE_ACK); + hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, 1-request->bmRequestType_bit.direction), NULL, 0); + break; + + case CONTROL_STAGE_ACK: + _xfer_complete(dev_addr, result); + break; + + default: return false; + } + } + + return true; +} + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + +bool tuh_edpt_xfer(tuh_xfer_t* xfer) +{ + TU_VERIFY(xfer->daddr && xfer->ep_addr); + + + + return true; +} + +//--------------------------------------------------------------------+ +// USBH API For Class Driver +//--------------------------------------------------------------------+ + +uint8_t usbh_get_rhport(uint8_t dev_addr) +{ + usbh_device_t* dev = get_device(dev_addr); + return dev ? dev->rhport : _dev0.rhport; +} + +uint8_t* usbh_get_enum_buf(void) +{ + return _usbh_ctrl_buf; +} + +void usbh_int_set(bool enabled) +{ + // TODO all host controller + if (enabled) + { + hcd_int_enable(TUH_OPT_RHPORT); + }else + { + hcd_int_disable(TUH_OPT_RHPORT); + } +} + +//--------------------------------------------------------------------+ +// Endpoint API +//--------------------------------------------------------------------+ + +// TODO has some duplication code with device, refactor later +bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) +{ + usbh_device_t* dev = get_device(dev_addr); + + // addr0 only use tuh_control_xfer + TU_ASSERT(dev); + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + tu_edpt_state_t* ep_state = &dev->ep_status[epnum][dir]; + +#if TUSB_OPT_MUTEX + return tu_edpt_claim(ep_state, _usbh_mutex); +#else + return tu_edpt_claim(ep_state, NULL); +#endif +} + +// TODO has some duplication code with device, refactor later +bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) +{ + // addr0 is always available + if (dev_addr == 0) return true; + + usbh_device_t* dev = get_device(dev_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + tu_edpt_state_t* ep_state = &dev->ep_status[epnum][dir]; + +#if TUSB_OPT_MUTEX + return tu_edpt_release(ep_state, _usbh_mutex); +#else + return tu_edpt_release(ep_state, NULL); +#endif +} + +// TODO has some duplication code with device, refactor later +bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +{ + usbh_device_t* dev = get_device(dev_addr); + TU_VERIFY(dev); + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); + + // Attempt to transfer on a busy endpoint, sound like an race condition ! + TU_ASSERT(dev->ep_status[epnum][dir].busy == 0); + + // Set busy first since the actual transfer can be complete before hcd_edpt_xfer() + // could return and USBH task can preempt and clear the busy + dev->ep_status[epnum][dir].busy = true; + + if ( hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes) ) + { + TU_LOG2("OK\r\n"); + return true; + }else + { + // HCD error, mark endpoint as ready to allow next transfer + dev->ep_status[epnum][dir].busy = false; + dev->ep_status[epnum][dir].claimed = 0; + TU_LOG1("failed\r\n"); + TU_BREAKPOINT(); + return false; + } +} + +static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) +{ + TU_LOG2("Open EP0 with Size = %u (addr = %u)\r\n", max_packet_size, dev_addr); + + tusb_desc_endpoint_t ep0_desc = + { + .bLength = sizeof(tusb_desc_endpoint_t), + .bDescriptorType = TUSB_DESC_ENDPOINT, + .bEndpointAddress = 0, + .bmAttributes = { .xfer = TUSB_XFER_CONTROL }, + .wMaxPacketSize = max_packet_size, + .bInterval = 0 + }; + + return hcd_edpt_open(usbh_get_rhport(dev_addr), dev_addr, &ep0_desc); +} + +bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep) +{ + TU_ASSERT( tu_edpt_validate(desc_ep, tuh_speed_get(dev_addr)) ); + return hcd_edpt_open(rhport, dev_addr, desc_ep); +} + +bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + usbh_device_t* dev = get_device(dev_addr); + TU_VERIFY(dev); + + return dev->ep_status[epnum][dir].busy; +} + +//--------------------------------------------------------------------+ +// HCD Event Handler +//--------------------------------------------------------------------+ + +void hcd_devtree_get_info(uint8_t dev_addr, hcd_devtree_info_t* devtree_info) +{ + usbh_device_t const* dev = get_device(dev_addr); + + if (dev) + { + devtree_info->rhport = dev->rhport; + devtree_info->hub_addr = dev->hub_addr; + devtree_info->hub_port = dev->hub_port; + devtree_info->speed = dev->speed; + }else + { + devtree_info->rhport = _dev0.rhport; + devtree_info->hub_addr = _dev0.hub_addr; + devtree_info->hub_port = _dev0.hub_port; + devtree_info->speed = _dev0.speed; + } +} + +void hcd_event_handler(hcd_event_t const* event, bool in_isr) +{ + switch (event->event_id) + { + default: + osal_queue_send(_usbh_q, event, in_isr); + break; + } +} + +void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred_bytes, xfer_result_t result, bool in_isr) +{ + hcd_event_t event = + { + .rhport = 0, // TODO correct rhport + .event_id = HCD_EVENT_XFER_COMPLETE, + .dev_addr = dev_addr, + .xfer_complete = + { + .ep_addr = ep_addr, + .result = result, + .len = xferred_bytes + } + }; + + hcd_event_handler(&event, in_isr); +} + +void hcd_event_device_attach(uint8_t rhport, bool in_isr) +{ + hcd_event_t event = + { + .rhport = rhport, + .event_id = HCD_EVENT_DEVICE_ATTACH + }; + + event.connection.hub_addr = 0; + event.connection.hub_port = 0; + + hcd_event_handler(&event, in_isr); +} + +void hcd_event_device_remove(uint8_t hostid, bool in_isr) +{ + hcd_event_t event = + { + .rhport = hostid, + .event_id = HCD_EVENT_DEVICE_REMOVE + }; + + event.connection.hub_addr = 0; + event.connection.hub_port = 0; + + hcd_event_handler(&event, in_isr); +} + //--------------------------------------------------------------------+ // Descriptors Async //--------------------------------------------------------------------+ @@ -535,554 +1080,6 @@ uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_i _CONTROL_SYNC_API(tuh_descriptor_get_serial_string, daddr, language_id, buffer, len); } -//--------------------------------------------------------------------+ -// CLASS-USBD API (don't require to verify parameters) -//--------------------------------------------------------------------+ - -static void clear_device(usbh_device_t* dev) -{ - tu_memclr(dev, sizeof(usbh_device_t)); - memset(dev->itf2drv, DRVID_INVALID, sizeof(dev->itf2drv)); // invalid mapping - memset(dev->ep2drv , DRVID_INVALID, sizeof(dev->ep2drv )); // invalid mapping -} - -bool tuh_inited(void) -{ - return _usbh_initialized; -} - -bool tuh_init(uint8_t rhport) -{ - // skip if already initialized - if (_usbh_initialized) return _usbh_initialized; - - TU_LOG2("USBH init\r\n"); - 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)); - - // Event queue - _usbh_q = osal_queue_create( &_usbh_qdef ); - TU_ASSERT(_usbh_q != NULL); - -#if TUSB_OPT_MUTEX - // Mutex - _usbh_mutex = osal_mutex_create(&_usbh_mutexdef); - TU_ASSERT(_usbh_mutex); -#endif - - // Device - tu_memclr(&_dev0, sizeof(_dev0)); - tu_memclr(_usbh_devices, sizeof(_usbh_devices)); - tu_memclr(&_ctrl_xfer, sizeof(_ctrl_xfer)); - - for(uint8_t i=0; iep_status[epnum][ep_dir].busy = 0; - dev->ep_status[epnum][ep_dir].claimed = 0; - - if ( 0 == epnum ) - { - usbh_control_xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); - }else - { - uint8_t drv_id = dev->ep2drv[epnum][ep_dir]; - TU_ASSERT(drv_id < USBH_CLASS_DRIVER_COUNT, ); - - TU_LOG2("%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); - } - } - } - break; - - case USBH_EVENT_FUNC_CALL: - if ( event.func_call.func ) event.func_call.func(event.func_call.param); - break; - - default: break; - } - } -} - -//--------------------------------------------------------------------+ -// USBH API For Class Driver -//--------------------------------------------------------------------+ - -uint8_t usbh_get_rhport(uint8_t dev_addr) -{ - usbh_device_t* dev = get_device(dev_addr); - return dev ? dev->rhport : _dev0.rhport; -} - -uint8_t* usbh_get_enum_buf(void) -{ - return _usbh_ctrl_buf; -} - -void usbh_int_set(bool enabled) -{ - // TODO all host controller - if (enabled) - { - hcd_int_enable(TUH_OPT_RHPORT); - }else - { - hcd_int_disable(TUH_OPT_RHPORT); - } -} - -//--------------------------------------------------------------------+ -// HCD Event Handler -//--------------------------------------------------------------------+ - -void hcd_devtree_get_info(uint8_t dev_addr, hcd_devtree_info_t* devtree_info) -{ - usbh_device_t const* dev = get_device(dev_addr); - - if (dev) - { - devtree_info->rhport = dev->rhport; - devtree_info->hub_addr = dev->hub_addr; - devtree_info->hub_port = dev->hub_port; - devtree_info->speed = dev->speed; - }else - { - devtree_info->rhport = _dev0.rhport; - devtree_info->hub_addr = _dev0.hub_addr; - devtree_info->hub_port = _dev0.hub_port; - devtree_info->speed = _dev0.speed; - } -} - -void hcd_event_handler(hcd_event_t const* event, bool in_isr) -{ - switch (event->event_id) - { - default: - osal_queue_send(_usbh_q, event, in_isr); - break; - } -} - -void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred_bytes, xfer_result_t result, bool in_isr) -{ - hcd_event_t event = - { - .rhport = 0, // TODO correct rhport - .event_id = HCD_EVENT_XFER_COMPLETE, - .dev_addr = dev_addr, - .xfer_complete = - { - .ep_addr = ep_addr, - .result = result, - .len = xferred_bytes - } - }; - - hcd_event_handler(&event, in_isr); -} - -void hcd_event_device_attach(uint8_t rhport, bool in_isr) -{ - hcd_event_t event = - { - .rhport = rhport, - .event_id = HCD_EVENT_DEVICE_ATTACH - }; - - event.connection.hub_addr = 0; - event.connection.hub_port = 0; - - hcd_event_handler(&event, in_isr); -} - -void hcd_event_device_remove(uint8_t hostid, bool in_isr) -{ - hcd_event_t event = - { - .rhport = hostid, - .event_id = HCD_EVENT_DEVICE_REMOVE - }; - - event.connection.hub_addr = 0; - event.connection.hub_port = 0; - - hcd_event_handler(&event, in_isr); -} - -//--------------------------------------------------------------------+ -// Endpoint API -//--------------------------------------------------------------------+ - -// TODO has some duplication code with device, refactor later -bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) -{ - usbh_device_t* dev = get_device(dev_addr); - - // addr0 only use tuh_control_xfer - TU_ASSERT(dev); - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - tu_edpt_state_t* ep_state = &dev->ep_status[epnum][dir]; - -#if TUSB_OPT_MUTEX - return tu_edpt_claim(ep_state, _usbh_mutex); -#else - return tu_edpt_claim(ep_state, NULL); -#endif -} - -// TODO has some duplication code with device, refactor later -bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) -{ - // addr0 is always available - if (dev_addr == 0) return true; - - usbh_device_t* dev = get_device(dev_addr); - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - tu_edpt_state_t* ep_state = &dev->ep_status[epnum][dir]; - -#if TUSB_OPT_MUTEX - return tu_edpt_release(ep_state, _usbh_mutex); -#else - return tu_edpt_release(ep_state, NULL); -#endif -} - -// TODO has some duplication code with device, refactor later -bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) -{ - usbh_device_t* dev = get_device(dev_addr); - TU_VERIFY(dev); - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); - - // Attempt to transfer on a busy endpoint, sound like an race condition ! - TU_ASSERT(dev->ep_status[epnum][dir].busy == 0); - - // Set busy first since the actual transfer can be complete before hcd_edpt_xfer() - // could return and USBH task can preempt and clear the busy - dev->ep_status[epnum][dir].busy = true; - - if ( hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes) ) - { - TU_LOG2("OK\r\n"); - return true; - }else - { - // HCD error, mark endpoint as ready to allow next transfer - dev->ep_status[epnum][dir].busy = false; - dev->ep_status[epnum][dir].claimed = 0; - TU_LOG1("failed\r\n"); - TU_BREAKPOINT(); - return false; - } -} - -static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) -{ - TU_LOG2("Open EP0 with Size = %u (addr = %u)\r\n", max_packet_size, dev_addr); - - tusb_desc_endpoint_t ep0_desc = - { - .bLength = sizeof(tusb_desc_endpoint_t), - .bDescriptorType = TUSB_DESC_ENDPOINT, - .bEndpointAddress = 0, - .bmAttributes = { .xfer = TUSB_XFER_CONTROL }, - .wMaxPacketSize = max_packet_size, - .bInterval = 0 - }; - - return hcd_edpt_open(usbh_get_rhport(dev_addr), dev_addr, &ep0_desc); -} - -bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep) -{ - TU_ASSERT( tu_edpt_validate(desc_ep, tuh_speed_get(dev_addr)) ); - return hcd_edpt_open(rhport, dev_addr, desc_ep); -} - -bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - usbh_device_t* dev = get_device(dev_addr); - TU_VERIFY(dev); - - return dev->ep_status[epnum][dir].busy; -} - -//--------------------------------------------------------------------+ -// Control transfer -//--------------------------------------------------------------------+ - -static void _control_blocking_complete_cb(tuh_xfer_t* xfer) -{ - // update result - *((xfer_result_t*) xfer->user_data) = xfer->result; -} - -// TODO timeout_ms is not supported yet -bool tuh_control_xfer (tuh_xfer_t* xfer) -{ - // EP0 with setup packet - TU_VERIFY(xfer->ep_addr == 0 && xfer->setup); - - // pre-check to help reducing mutex lock - TU_VERIFY(_ctrl_xfer.stage == CONTROL_STAGE_IDLE); - - uint8_t const daddr = xfer->daddr; - - // TODO probably better to use semaphore as resource management than mutex - usbh_lock(); - - bool const is_idle = (_ctrl_xfer.stage == CONTROL_STAGE_IDLE); - if (is_idle) - { - _ctrl_xfer.stage = CONTROL_STAGE_SETUP; - _ctrl_xfer.daddr = daddr; - _ctrl_xfer.actual_len = 0; - - _ctrl_xfer.request = (*xfer->setup); - _ctrl_xfer.buffer = xfer->buffer; - _ctrl_xfer.complete_cb = xfer->complete_cb; - _ctrl_xfer.user_data = xfer->user_data; - } - - usbh_unlock(); - - 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_VAR(&xfer->setup); - TU_LOG2("\r\n"); - - if (xfer->complete_cb) - { - TU_ASSERT( hcd_setup_send(rhport, daddr, (uint8_t*) &_ctrl_xfer.request) ); - }else - { - // blocking if complete callback is not provided - // change callback to internal blocking, and result as user argument - volatile xfer_result_t result = XFER_RESULT_INVALID; - - // use user_data to point to xfer_result_t - _ctrl_xfer.user_data = (uintptr_t) &result; - _ctrl_xfer.complete_cb = _control_blocking_complete_cb; - - TU_ASSERT( hcd_setup_send(rhport, daddr, (uint8_t*) &_ctrl_xfer.request) ); - - while (result == XFER_RESULT_INVALID) - { - // only need to call task if not preempted RTOS - #if CFG_TUSB_OS == OPT_OS_NONE || CFG_TUSB_OS == OPT_OS_PICO - tuh_task(); - #endif - - // TODO probably some timeout to prevent hanged - } - - // update transfer result - xfer->result = result; - xfer->actual_len = _ctrl_xfer.actual_len; - } - - return true; -} - -TU_ATTR_ALWAYS_INLINE static inline void _set_control_xfer_stage(uint8_t stage) -{ - usbh_lock(); - _ctrl_xfer.stage = stage; - usbh_unlock(); -} - -static void _xfer_complete(uint8_t daddr, xfer_result_t result) -{ - TU_LOG2("\r\n"); - - // duplicate xfer since user can execute control transfer within callback - tusb_control_request_t const request = _ctrl_xfer.request; - tuh_xfer_t xfer_temp = - { - .daddr = daddr, - .ep_addr = 0, - .result = result, - .setup = &request, - .actual_len = (uint32_t) _ctrl_xfer.actual_len, - .buffer = _ctrl_xfer.buffer, - .complete_cb = _ctrl_xfer.complete_cb, - .user_data = _ctrl_xfer.user_data - }; - - usbh_lock(); - _ctrl_xfer.stage = CONTROL_STAGE_IDLE; - usbh_unlock(); - - if (xfer_temp.complete_cb) - { - xfer_temp.complete_cb(&xfer_temp); - } -} - -static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) ep_addr; - - const uint8_t rhport = usbh_get_rhport(dev_addr); - tusb_control_request_t const * request = &_ctrl_xfer.request; - - if (XFER_RESULT_SUCCESS != result) - { - TU_LOG2("[%u:%u] Control %s\r\n", rhport, dev_addr, result == XFER_RESULT_STALLED ? "STALLED" : "FAILED"); - - // terminate transfer if any stage failed - _xfer_complete(dev_addr, result); - }else - { - switch(_ctrl_xfer.stage) - { - case CONTROL_STAGE_SETUP: - if (request->wLength) - { - // DATA stage: initial data toggle is always 1 - _set_control_xfer_stage(CONTROL_STAGE_DATA); - return hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.buffer, request->wLength); - } - __attribute__((fallthrough)); - - case CONTROL_STAGE_DATA: - if (xferred_bytes) - { - TU_LOG2("[%u:%u] Control data:\r\n", rhport, dev_addr); - TU_LOG2_MEM(_ctrl_xfer.buffer, xferred_bytes, 2); - } - - _ctrl_xfer.actual_len = xferred_bytes; - - // ACK stage: toggle is always 1 - _set_control_xfer_stage(CONTROL_STAGE_ACK); - hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, 1-request->bmRequestType_bit.direction), NULL, 0); - break; - - case CONTROL_STAGE_ACK: - _xfer_complete(dev_addr, result); - break; - - default: return false; - } - } - - return true; -} - -//--------------------------------------------------------------------+ -// -//--------------------------------------------------------------------+ - -bool tuh_edpt_xfer(tuh_xfer_t* xfer) -{ - (void) xfer; - return true; -} - //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ From ba1185bf28331da718cca38e6598361889fce54d Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 18 Mar 2022 22:22:21 +0700 Subject: [PATCH 69/81] implement tuh_edpt_xfer() for non-control --- examples/host/bare_api/src/main.c | 193 ++++++++++++++++-------------- src/class/hid/hid_host.c | 8 +- src/host/usbh.c | 104 +++++++++++----- src/host/usbh.h | 10 +- src/host/usbh_classdriver.h | 12 +- 5 files changed, 201 insertions(+), 126 deletions(-) diff --git a/examples/host/bare_api/src/main.c b/examples/host/bare_api/src/main.c index e2e0f4ff3..06ae03ecb 100644 --- a/examples/host/bare_api/src/main.c +++ b/examples/host/bare_api/src/main.c @@ -40,6 +40,8 @@ //--------------------------------------------------------------------+ void led_blinking_task(void); +static void print_utf16(uint16_t *temp_buf, size_t buf_len); + /*------------- MAIN -------------*/ int main(void) { @@ -65,10 +67,108 @@ int main(void) // English #define LANGUAGE_ID 0x0409 -//uint8_t usb_buf[256] TU_ATTR_ALIGNED(4); -TU_ATTR_ALIGNED(4) tusb_desc_device_t desc_device; +//void parse_config_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg) +//{ +// uint8_t const* desc_end = ((uint8_t const*) desc_cfg) + tu_le16toh(desc_cfg->wTotalLength); +// uint8_t const* p_desc = tu_desc_next(desc_cfg); +//} + +void print_device_descriptor(tuh_xfer_t* xfer) +{ + if ( XFER_RESULT_SUCCESS != xfer->result ) + { + printf("Failed to get device descriptor\r\n"); + return; + } + + uint8_t const daddr = xfer->daddr; + + printf("Device %u: ID %04x:%04x\r\n", daddr, desc_device.idVendor, desc_device.idProduct); + printf("Device Descriptor:\r\n"); + printf(" bLength %u\r\n" , desc_device.bLength); + printf(" bDescriptorType %u\r\n" , desc_device.bDescriptorType); + printf(" bcdUSB %04x\r\n" , desc_device.bcdUSB); + printf(" bDeviceClass %u\r\n" , desc_device.bDeviceClass); + printf(" bDeviceSubClass %u\r\n" , desc_device.bDeviceSubClass); + printf(" bDeviceProtocol %u\r\n" , desc_device.bDeviceProtocol); + printf(" bMaxPacketSize0 %u\r\n" , desc_device.bMaxPacketSize0); + printf(" idVendor 0x%04x\r\n" , desc_device.idVendor); + printf(" idProduct 0x%04x\r\n" , desc_device.idProduct); + printf(" bcdDevice %04x\r\n" , desc_device.bcdDevice); + + // Get String descriptor using Sync API + uint16_t temp_buf[128]; + + printf(" iManufacturer %u " , desc_device.iManufacturer); + if (XFER_RESULT_SUCCESS == tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, temp_buf, sizeof(temp_buf)) ) + { + print_utf16(temp_buf, TU_ARRAY_SIZE(temp_buf)); + } + printf("\r\n"); + + printf(" iProduct %u " , desc_device.iProduct); + if (XFER_RESULT_SUCCESS == tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, temp_buf, sizeof(temp_buf))) + { + print_utf16(temp_buf, TU_ARRAY_SIZE(temp_buf)); + } + printf("\r\n"); + + printf(" iSerialNumber %u " , desc_device.iSerialNumber); + if (XFER_RESULT_SUCCESS == tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, temp_buf, sizeof(temp_buf))) + { + print_utf16(temp_buf, TU_ARRAY_SIZE(temp_buf)); + } + printf("\r\n"); + + printf(" bNumConfigurations %u\r\n" , desc_device.bNumConfigurations); + + // Get configuration descriptor with sync API +// if (XFER_RESULT_SUCCESS == tuh_descriptor_get_configuration_sync(daddr, 0, temp_buf, sizeof(temp_buf)) ) +// { +// parse_config_descriptor(daddr, (tusb_desc_configuration_t*) temp_buf); +// } +} + +// Invoked when device is mounted (configured) +void tuh_mount_cb (uint8_t daddr) +{ + printf("Device attached, address = %d\r\n", daddr); + + // Get Device Descriptor sync API + // TODO: invoking control trannsfer now has issue with mounting hub with multiple devices attached, fix later + tuh_descriptor_get_device(daddr, &desc_device, 18, print_device_descriptor, 0); +} + +/// Invoked when device is unmounted (bus reset/unplugged) +void tuh_umount_cb(uint8_t daddr) +{ + printf("Device removed, address = %d\r\n", daddr); +} + +//--------------------------------------------------------------------+ +// Blinking Task +//--------------------------------------------------------------------+ +void led_blinking_task(void) +{ + const uint32_t interval_ms = 1000; + static uint32_t start_ms = 0; + + static bool led_state = false; + + // Blink every interval ms + if ( board_millis() - start_ms < interval_ms) return; // not enough time + start_ms += interval_ms; + + board_led_write(led_state); + led_state = 1 - led_state; // toggle +} + +//--------------------------------------------------------------------+ +// Helper +//--------------------------------------------------------------------+ + static void _convert_utf16le_to_utf8(const uint16_t *utf16, size_t utf16_len, uint8_t *utf8, size_t utf8_len) { // TODO: Check for runover. (void)utf8_len; @@ -108,94 +208,11 @@ static int _count_utf8_bytes(const uint16_t *buf, size_t len) { return total_bytes; } -static void utf16_to_utf8(uint16_t *temp_buf, size_t buf_len) { +static void print_utf16(uint16_t *temp_buf, size_t buf_len) { size_t utf16_len = ((temp_buf[0] & 0xff) - 2) / sizeof(uint16_t); size_t utf8_len = _count_utf8_bytes(temp_buf + 1, utf16_len); _convert_utf16le_to_utf8(temp_buf + 1, utf16_len, (uint8_t *) temp_buf, sizeof(uint16_t) * buf_len); ((uint8_t*) temp_buf)[utf8_len] = '\0'; -} - -void print_device_descriptor(tuh_xfer_t* xfer) -{ - if ( XFER_RESULT_SUCCESS != xfer->result ) - { - printf("Failed to get device descriptor\r\n"); - return; - } - - uint8_t const daddr = xfer->daddr; - - printf("Device %u: ID %04x:%04x\r\n", daddr, desc_device.idVendor, desc_device.idProduct); - printf("Device Descriptor:\r\n"); - printf(" bLength %u\r\n" , desc_device.bLength); - printf(" bDescriptorType %u\r\n" , desc_device.bDescriptorType); - printf(" bcdUSB %04x\r\n" , desc_device.bcdUSB); - printf(" bDeviceClass %u\r\n" , desc_device.bDeviceClass); - printf(" bDeviceSubClass %u\r\n" , desc_device.bDeviceSubClass); - printf(" bDeviceProtocol %u\r\n" , desc_device.bDeviceProtocol); - printf(" bMaxPacketSize0 %u\r\n" , desc_device.bMaxPacketSize0); - printf(" idVendor 0x%04x\r\n" , desc_device.idVendor); - printf(" idProduct 0x%04x\r\n" , desc_device.idProduct); - printf(" bcdDevice %04x\r\n" , desc_device.bcdDevice); - - uint16_t temp_buf[128]; - - printf(" iManufacturer %u " , desc_device.iManufacturer); - if (XFER_RESULT_SUCCESS == tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, temp_buf, TU_ARRAY_SIZE(temp_buf)) ) - { - utf16_to_utf8(temp_buf, TU_ARRAY_SIZE(temp_buf)); - printf((const char*) temp_buf); - } - printf("\r\n"); - - printf(" iProduct %u " , desc_device.iProduct); - if (XFER_RESULT_SUCCESS == tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, temp_buf, TU_ARRAY_SIZE(temp_buf))) - { - utf16_to_utf8(temp_buf, TU_ARRAY_SIZE(temp_buf)); - printf((const char*) temp_buf); - } - printf("\r\n"); - - printf(" iSerialNumber %u " , desc_device.iSerialNumber); - if (XFER_RESULT_SUCCESS == tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, temp_buf, TU_ARRAY_SIZE(temp_buf))) - { - utf16_to_utf8(temp_buf, TU_ARRAY_SIZE(temp_buf)); - printf((const char*) temp_buf); - } - printf("\r\n"); - - printf(" bNumConfigurations %u\r\n" , desc_device.bNumConfigurations); -} - -// Invoked when device is mounted (configured) -void tuh_mount_cb (uint8_t daddr) -{ - printf("Device attached, address = %d\r\n", daddr); - - // Get Device Descriptor using asynchronous API - tuh_descriptor_get_device(daddr, &desc_device, 18, print_device_descriptor, 0); -} - -/// Invoked when device is unmounted (bus reset/unplugged) -void tuh_umount_cb(uint8_t daddr) -{ - printf("Device removed, address = %d\r\n", daddr); -} - -//--------------------------------------------------------------------+ -// Blinking Task -//--------------------------------------------------------------------+ -void led_blinking_task(void) -{ - const uint32_t interval_ms = 1000; - static uint32_t start_ms = 0; - - static bool led_state = false; - - // Blink every interval ms - if ( board_millis() - start_ms < interval_ms) return; // not enough time - start_ms += interval_ms; - - board_led_write(led_state); - led_state = 1 - led_state; // toggle + + printf((char*)temp_buf); } diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index fa99b37fe..2bdd1db79 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -256,7 +256,13 @@ bool tuh_hid_receive_report(uint8_t dev_addr, uint8_t instance) // claim endpoint TU_VERIFY( usbh_edpt_claim(dev_addr, hid_itf->ep_in) ); - return usbh_edpt_xfer(dev_addr, hid_itf->ep_in, hid_itf->epin_buf, hid_itf->epin_size); + if ( !usbh_edpt_xfer(dev_addr, hid_itf->ep_in, hid_itf->epin_buf, hid_itf->epin_size) ) + { + usbh_edpt_claim(dev_addr, hid_itf->ep_in); + return false; + } + + return true; } //bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance) diff --git a/src/host/usbh.c b/src/host/usbh.c index 8aa9c4a16..497badfde 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -82,8 +82,7 @@ typedef struct { uint8_t speed; // Device State - struct TU_ATTR_PACKED - { + struct TU_ATTR_PACKED { volatile uint8_t connected : 1; volatile uint8_t addressed : 1; volatile uint8_t configured : 1; @@ -110,7 +109,11 @@ typedef struct { tu_edpt_state_t ep_status[CFG_TUH_ENDPOINT_MAX][2]; #if CFG_TUH_API_EDPT_XFER - // ep_xfer[]; + // TODO array can be CFG_TUH_ENDPOINT_MAX-1 + struct { + tuh_xfer_cb_t complete_cb; + uintptr_t user_data; + }ep_callback[CFG_TUH_ENDPOINT_MAX][2]; #endif } usbh_device_t; @@ -227,6 +230,8 @@ TU_ATTR_ALWAYS_INLINE static inline void usbh_unlock(void) #else +#define _usbh_mutex NULL + #define usbh_lock() #define usbh_unlock() @@ -449,10 +454,38 @@ void tuh_task(void) }else { uint8_t drv_id = dev->ep2drv[epnum][ep_dir]; - TU_ASSERT(drv_id < USBH_CLASS_DRIVER_COUNT, ); + if(drv_id < USBH_CLASS_DRIVER_COUNT) + { + TU_LOG2("%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 + { +#if CFG_TUH_API_EDPT_XFER + tuh_xfer_cb_t complete_cb = dev->ep_callback[epnum][ep_dir].complete_cb; + if ( complete_cb ) + { + tuh_xfer_t xfer = + { + .daddr = event.dev_addr, + .ep_addr = ep_addr, + .result = event.xfer_complete.result, + .actual_len = event.xfer_complete.len, + .buflen = 0, // not available + .buffer = NULL, // not available + .complete_cb = complete_cb, + .user_data = dev->ep_callback[epnum][ep_dir].user_data + }; - TU_LOG2("%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); + complete_cb(&xfer); + }else +#endif + { + // no driver/callback responsible for this transfer + TU_ASSERT(false, ); + } + + } } } } @@ -638,9 +671,18 @@ static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result bool tuh_edpt_xfer(tuh_xfer_t* xfer) { - TU_VERIFY(xfer->daddr && xfer->ep_addr); + uint8_t const daddr = xfer->daddr; + uint8_t const ep_addr = xfer->ep_addr; + TU_VERIFY(daddr && ep_addr); + TU_VERIFY(usbh_edpt_claim(daddr, ep_addr)); + + if ( !usbh_edpt_xfer_with_callback(daddr, ep_addr, xfer->buffer, xfer->buflen, xfer->complete_cb, xfer->user_data) ) + { + usbh_edpt_release(daddr, ep_addr); + return false; + } return true; } @@ -687,50 +729,50 @@ bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - tu_edpt_state_t* ep_state = &dev->ep_status[epnum][dir]; - -#if TUSB_OPT_MUTEX - return tu_edpt_claim(ep_state, _usbh_mutex); -#else - return tu_edpt_claim(ep_state, NULL); -#endif + return tu_edpt_claim(&dev->ep_status[epnum][dir], _usbh_mutex); } // TODO has some duplication code with device, refactor later bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) { - // addr0 is always available - if (dev_addr == 0) return true; + usbh_device_t* dev = get_device(dev_addr); - usbh_device_t* dev = get_device(dev_addr); - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - tu_edpt_state_t* ep_state = &dev->ep_status[epnum][dir]; + // addr0 only use tuh_control_xfer + TU_ASSERT(dev); -#if TUSB_OPT_MUTEX - return tu_edpt_release(ep_state, _usbh_mutex); -#else - return tu_edpt_release(ep_state, NULL); -#endif + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + return tu_edpt_release(&dev->ep_status[epnum][dir], _usbh_mutex); } // TODO has some duplication code with device, refactor later -bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +bool usbh_edpt_xfer_with_callback(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + (void) complete_cb; + (void) user_data; + usbh_device_t* dev = get_device(dev_addr); TU_VERIFY(dev); uint8_t const epnum = tu_edpt_number(ep_addr); 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); // Attempt to transfer on a busy endpoint, sound like an race condition ! - TU_ASSERT(dev->ep_status[epnum][dir].busy == 0); + TU_ASSERT(ep_state->busy == 0); // Set busy first since the actual transfer can be complete before hcd_edpt_xfer() // could return and USBH task can preempt and clear the busy - dev->ep_status[epnum][dir].busy = true; + ep_state->busy = 1; + +#if CFG_TUH_API_EDPT_XFER + dev->ep_callback[epnum][dir].complete_cb = complete_cb; + dev->ep_callback[epnum][dir].user_data = user_data; +#endif if ( hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes) ) { @@ -739,9 +781,9 @@ bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_ }else { // HCD error, mark endpoint as ready to allow next transfer - dev->ep_status[epnum][dir].busy = false; - dev->ep_status[epnum][dir].claimed = 0; - TU_LOG1("failed\r\n"); + ep_state->busy = 0; + ep_state->claimed = 0; + TU_LOG1("Failed\r\n"); TU_BREAKPOINT(); return false; } diff --git a/src/host/usbh.h b/src/host/usbh.h index f79c5cdc8..772c4cfd6 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -44,25 +44,27 @@ typedef struct tuh_xfer_s tuh_xfer_t; typedef void (*tuh_xfer_cb_t)(tuh_xfer_t* xfer); +// Note: layout and order of this will be changed in near future +// it is advised to initialize it using member name struct tuh_xfer_s { uint8_t daddr; uint8_t ep_addr; xfer_result_t result; - uint32_t actual_len; // excluding setup packet + uint32_t actual_len; // excluding setup packet union { tusb_control_request_t const* setup; // setup packet pointer if control transfer - uint32_t buflen; // length if not control transfer + uint32_t buflen; // expected length if not control transfer (not available in callback) }; - uint8_t* buffer; + uint8_t* buffer; // not available in callback if not control transfer tuh_xfer_cb_t complete_cb; uintptr_t user_data; - uint32_t timeout_ms; // place holder, not supported yet + // uint32_t timeout_ms; // place holder, not supported yet }; //--------------------------------------------------------------------+ diff --git a/src/host/usbh_classdriver.h b/src/host/usbh_classdriver.h index 0435eae70..30e97535d 100644 --- a/src/host/usbh_classdriver.h +++ b/src/host/usbh_classdriver.h @@ -66,8 +66,16 @@ void usbh_int_set(bool enabled); // Open an endpoint bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep); -// Submit a usb transfer -bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); +// Submit a usb transfer with callback support, require CFG_TUH_API_EDPT_XFER +bool usbh_edpt_xfer_with_callback(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, + tuh_xfer_cb_t complete_cb, uintptr_t user_data); + +TU_ATTR_ALWAYS_INLINE +static inline bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +{ + return usbh_edpt_xfer_with_callback(dev_addr, ep_addr, buffer, total_bytes, NULL, 0); +} + // Claim an endpoint before submitting a transfer. // If caller does not make any transfer, it must release endpoint for others. From 4795cca04ac60d58fbc78d554cd7af7039cd310a Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 19 Mar 2022 00:43:31 +0700 Subject: [PATCH 70/81] add parse config descriptor to example move usbh_edpt_open() to public API, remove rhport from its signature --- examples/host/bare_api/src/main.c | 154 +++++++++++++++++++++++++----- src/class/cdc/cdc_host.c | 5 +- src/class/hid/hid.h | 2 +- src/class/hid/hid_host.c | 3 +- src/class/msc/msc_host.c | 3 +- src/host/hub.c | 4 +- src/host/usbh.c | 11 ++- src/host/usbh.h | 14 ++- src/host/usbh_classdriver.h | 3 - src/portable/ehci/ehci.c | 25 ++++- src/tusb.h | 2 + 11 files changed, 180 insertions(+), 46 deletions(-) diff --git a/examples/host/bare_api/src/main.c b/examples/host/bare_api/src/main.c index 06ae03ecb..3b23dd43b 100644 --- a/examples/host/bare_api/src/main.c +++ b/examples/host/bare_api/src/main.c @@ -35,12 +35,19 @@ #include "bsp/board.h" #include "tusb.h" +// English +#define LANGUAGE_ID 0x0409 + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ void led_blinking_task(void); static void print_utf16(uint16_t *temp_buf, size_t buf_len); +void print_device_descriptor(tuh_xfer_t* xfer); +void parse_config_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg); + +tusb_desc_device_t desc_device; /*------------- MAIN -------------*/ int main(void) @@ -60,21 +67,28 @@ int main(void) return 0; } +/*------------- TinyUSB Callbacks -------------*/ + +// Invoked when device is mounted (configured) +void tuh_mount_cb (uint8_t daddr) +{ + printf("Device attached, address = %d\r\n", daddr); + + // Get Device Descriptor sync API + // TODO: invoking control trannsfer now has issue with mounting hub with multiple devices attached, fix later + tuh_descriptor_get_device(daddr, &desc_device, 18, print_device_descriptor, 0); +} + +/// Invoked when device is unmounted (bus reset/unplugged) +void tuh_umount_cb(uint8_t daddr) +{ + printf("Device removed, address = %d\r\n", daddr); +} + //--------------------------------------------------------------------+ -// TinyUSB Callbacks +// Device Descriptor //--------------------------------------------------------------------+ -// English -#define LANGUAGE_ID 0x0409 - -tusb_desc_device_t desc_device; - -//void parse_config_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg) -//{ -// uint8_t const* desc_end = ((uint8_t const*) desc_cfg) + tu_le16toh(desc_cfg->wTotalLength); -// uint8_t const* p_desc = tu_desc_next(desc_cfg); -//} - void print_device_descriptor(tuh_xfer_t* xfer) { if ( XFER_RESULT_SUCCESS != xfer->result ) @@ -125,28 +139,118 @@ void print_device_descriptor(tuh_xfer_t* xfer) printf(" bNumConfigurations %u\r\n" , desc_device.bNumConfigurations); // Get configuration descriptor with sync API -// if (XFER_RESULT_SUCCESS == tuh_descriptor_get_configuration_sync(daddr, 0, temp_buf, sizeof(temp_buf)) ) -// { -// parse_config_descriptor(daddr, (tusb_desc_configuration_t*) temp_buf); -// } + if (XFER_RESULT_SUCCESS == tuh_descriptor_get_configuration_sync(daddr, 0, temp_buf, sizeof(temp_buf)) ) + { + parse_config_descriptor(daddr, (tusb_desc_configuration_t*) temp_buf); + } } -// Invoked when device is mounted (configured) -void tuh_mount_cb (uint8_t daddr) + +//--------------------------------------------------------------------+ +// Configuration Descriptor +//--------------------------------------------------------------------+ + +// count total length of an interface +uint16_t count_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len); + +void open_hid_interface(uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) { - printf("Device attached, address = %d\r\n", daddr); + // len = interface + hid + n*endpoints + uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); - // Get Device Descriptor sync API - // TODO: invoking control trannsfer now has issue with mounting hub with multiple devices attached, fix later - tuh_descriptor_get_device(daddr, &desc_device, 18, print_device_descriptor, 0); + // corrupted descriptor + if (max_len < drv_len) return; + + uint8_t const *p_desc = (uint8_t const *) desc_itf; + + // HID descriptor + p_desc = tu_desc_next(p_desc); + + // Endpoint descriptor + tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; + + for(int i = 0; i < desc_itf->bNumEndpoints; i++) + { + if (TUSB_DESC_ENDPOINT != desc_ep->bDescriptorType) return; + + if(tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) + { + //usbh_edpt_open(rhport, dev_addr, desc_ep); + } + } } -/// Invoked when device is unmounted (bus reset/unplugged) -void tuh_umount_cb(uint8_t daddr) +// simple configuration parser to open and listen to HID Endpoint IN +void parse_config_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg) { - printf("Device removed, address = %d\r\n", daddr); + uint8_t const* desc_end = ((uint8_t const*) desc_cfg) + tu_le16toh(desc_cfg->wTotalLength); + uint8_t const* p_desc = tu_desc_next(desc_cfg); + + // parse each interfaces + while( p_desc < desc_end ) + { + uint8_t assoc_itf_count = 1; + + // Class will always starts with Interface Association (if any) and then Interface descriptor + if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) ) + { + tusb_desc_interface_assoc_t const * desc_iad = (tusb_desc_interface_assoc_t const *) p_desc; + assoc_itf_count = desc_iad->bInterfaceCount; + + p_desc = tu_desc_next(p_desc); // next to Interface + } + + // must be interface from now + if( TUSB_DESC_INTERFACE != tu_desc_type(p_desc) ) return; + tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; + + uint16_t const drv_len = count_interface_total_len(desc_itf, assoc_itf_count, desc_end-p_desc); + + // probably corrupted descriptor + if(drv_len < sizeof(tusb_desc_interface_t)) return; + + // only open and listen to HID endpoint IN + if (desc_itf->bInterfaceClass == TUSB_CLASS_HID) + { + open_hid_interface(dev_addr, desc_itf, drv_len); + } + + // next Interface or IAD descriptor + p_desc += drv_len; + } } +uint16_t count_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len) +{ + uint8_t const* p_desc = (uint8_t const*) desc_itf; + uint16_t len = 0; + + while (itf_count--) + { + // Next on interface desc + len += tu_desc_len(desc_itf); + p_desc = tu_desc_next(p_desc); + + while (len < max_len) + { + // return on IAD regardless of itf count + if ( tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION ) return len; + + if ( (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) && + ((tusb_desc_interface_t const*) p_desc)->bAlternateSetting == 0 ) + { + break; + } + + len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + } + + return len; +} + + //--------------------------------------------------------------------+ // Blinking Task //--------------------------------------------------------------------+ diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index f946974e8..82cf911cf 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -161,6 +161,7 @@ void cdch_init(void) bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { + (void) rhport; (void) max_len; // Only support ACM subclass @@ -196,7 +197,7 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it // notification endpoint tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); + TU_ASSERT( usbh_edpt_open(dev_addr, desc_ep) ); p_cdc->ep_notif = desc_ep->bEndpointAddress; drv_len += tu_desc_len(p_desc); @@ -217,7 +218,7 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc; TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_BULK == desc_ep->bmAttributes.xfer); - TU_ASSERT(usbh_edpt_open(rhport, dev_addr, desc_ep)); + TU_ASSERT(usbh_edpt_open(dev_addr, desc_ep)); if ( tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN ) { diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 940454bd9..44a464be1 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -43,7 +43,7 @@ /** \defgroup ClassDriver_HID_Common Common Definitions * @{ */ - /// USB HID Descriptor +/// USB HID Descriptor typedef struct TU_ATTR_PACKED { uint8_t bLength; /**< Numeric expression that is the total size of the HID descriptor */ diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 2bdd1db79..2280e87b4 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -324,6 +324,7 @@ void hidh_close(uint8_t dev_addr) bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) { + (void) rhport; (void) max_len; TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); @@ -355,7 +356,7 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de for(int i = 0; i < desc_itf->bNumEndpoints; i++) { TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); - TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); + TU_ASSERT( usbh_edpt_open(dev_addr, desc_ep) ); if(tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) { diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 06af781f5..4033cc429 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -365,6 +365,7 @@ static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) { + (void) rhport; TU_VERIFY (MSC_SUBCLASS_SCSI == desc_itf->bInterfaceSubClass && MSC_PROTOCOL_BOT == desc_itf->bInterfaceProtocol); @@ -378,7 +379,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de for(uint32_t i=0; i<2; i++) { TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); - TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc)); + TU_ASSERT(usbh_edpt_open(dev_addr, ep_desc)); if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) { diff --git a/src/host/hub.c b/src/host/hub.c index da4f6fe3a..b4d369aca 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -183,6 +183,8 @@ void hub_init(void) bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { + (void) rhport; + TU_VERIFY(TUSB_CLASS_HUB == itf_desc->bInterfaceClass && 0 == itf_desc->bInterfaceSubClass); @@ -199,7 +201,7 @@ bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0); - TU_ASSERT(usbh_edpt_open(rhport, dev_addr, desc_ep)); + TU_ASSERT(usbh_edpt_open(dev_addr, desc_ep)); hub_interface_t* p_hub = get_itf(dev_addr); diff --git a/src/host/usbh.c b/src/host/usbh.c index 497badfde..466e5decd 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -806,10 +806,11 @@ static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) return hcd_edpt_open(usbh_get_rhport(dev_addr), dev_addr, &ep0_desc); } -bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep) +bool usbh_edpt_open(uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep) { TU_ASSERT( tu_edpt_validate(desc_ep, tuh_speed_get(dev_addr)) ); - return hcd_edpt_open(rhport, dev_addr, desc_ep); + + return hcd_edpt_open(usbh_get_rhport(dev_addr), dev_addr, desc_ep); } bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) @@ -1189,7 +1190,7 @@ enum { }; static bool enum_request_set_addr(void); -static bool parse_configuration_descriptor (uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg); +static bool _parse_configuration_descriptor (uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg); static void enum_full_complete(void); // process device enumeration @@ -1350,7 +1351,7 @@ static void process_enumeration(tuh_xfer_t* xfer) case ENUM_SET_CONFIG: // Parse configuration & set up drivers // Driver open aren't allowed to make any usb transfer yet - TU_ASSERT( parse_configuration_descriptor(daddr, (tusb_desc_configuration_t*) _usbh_ctrl_buf), ); + TU_ASSERT( _parse_configuration_descriptor(daddr, (tusb_desc_configuration_t*) _usbh_ctrl_buf), ); TU_ASSERT( tuh_configuration_set(daddr, CONFIG_NUM, process_enumeration, ENUM_CONFIG_DRIVER), ); break; @@ -1496,7 +1497,7 @@ static bool enum_request_set_addr(void) return true; } -static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg) +static bool _parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg) { usbh_device_t* dev = get_device(dev_addr); diff --git a/src/host/usbh.h b/src/host/usbh.h index 772c4cfd6..a2df0153e 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -44,8 +44,10 @@ typedef struct tuh_xfer_s tuh_xfer_t; typedef void (*tuh_xfer_cb_t)(tuh_xfer_t* xfer); -// Note: layout and order of this will be changed in near future +// Note1: layout and order of this will be changed in near future // it is advised to initialize it using member name +// Note2: not all field is available/meaningful in callback, some info is not saved by +// usbh to save SRAM struct tuh_xfer_s { uint8_t daddr; @@ -124,14 +126,18 @@ static inline bool tuh_ready(uint8_t daddr) //--------------------------------------------------------------------+ // Submit a control transfer -// Note: blocking if complete callback is NULL, in this case xfer contents will be updated to reflect the result +// - async: complete callback invoked when finished. +// - sync : blocking if complete callback is NULL. bool tuh_control_xfer(tuh_xfer_t* xfer); // Submit a bulk/interrupt transfer -// xfer memory must exist until transfer is complete. -// Note: blocking if complete callback is NULL. +// - async: complete callback invoked when finished. +// - sync : blocking if complete callback is NULL. bool tuh_edpt_xfer(tuh_xfer_t* xfer); +// Open an endpoint +bool usbh_edpt_open(uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep); + // Set Configuration (control transfer) // config_num = 0 will un-configure device. Note: config_num = config_descriptor_index + 1 // true on success, false if there is on-going control transfer or incorrect parameters diff --git a/src/host/usbh_classdriver.h b/src/host/usbh_classdriver.h index 30e97535d..c156afea0 100644 --- a/src/host/usbh_classdriver.h +++ b/src/host/usbh_classdriver.h @@ -63,9 +63,6 @@ void usbh_int_set(bool enabled); // USBH Endpoint API //--------------------------------------------------------------------+ -// Open an endpoint -bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep); - // Submit a usb transfer with callback support, require CFG_TUH_API_EDPT_XFER bool usbh_edpt_xfer_with_callback(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, tuh_xfer_cb_t complete_cb, uintptr_t user_data); diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 8d420f26a..665f2380b 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -656,6 +656,26 @@ static void xfer_error_isr(uint8_t hostid) } } +#if CFG_TUSB_DEBUG >= EHCI_DBG + +static inline void print_portsc(ehci_registers_t* regs) +{ + TU_LOG_HEX(EHCI_DBG, regs->portsc); + TU_LOG(EHCI_DBG, " Current Connect Status: %u\r\n", regs->portsc_bm.current_connect_status); + TU_LOG(EHCI_DBG, " Connect Status Change : %u\r\n", regs->portsc_bm.connect_status_change); + TU_LOG(EHCI_DBG, " Port Enabled : %u\r\n", regs->portsc_bm.port_enabled); + TU_LOG(EHCI_DBG, " Port Enabled Change : %u\r\n", regs->portsc_bm.port_enable_change); + + TU_LOG(EHCI_DBG, " Port Reset : %u\r\n", regs->portsc_bm.port_reset); + TU_LOG(EHCI_DBG, " Port Power : %u\r\n", regs->portsc_bm.port_power); +} + +#else + +#define print_portsc(_reg) + +#endif + //------------- Host Controller Driver's Interrupt Handler -------------// void hcd_int_handler(uint8_t rhport) { @@ -675,9 +695,8 @@ void hcd_int_handler(uint8_t rhport) if (int_status & EHCI_INT_MASK_PORT_CHANGE) { - uint32_t port_status = regs->portsc & EHCI_PORTSC_MASK_ALL; - - TU_LOG_HEX(EHCI_DBG, regs->portsc); + uint32_t const port_status = regs->portsc & EHCI_PORTSC_MASK_ALL; + print_portsc(regs); if (regs->portsc_bm.connect_status_change) { diff --git a/src/tusb.h b/src/tusb.h index 222855fcb..b776d7d01 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -38,6 +38,8 @@ #include "osal/osal.h" #include "common/tusb_fifo.h" +#include "class/hid/hid.h" + //------------- HOST -------------// #if CFG_TUH_ENABLED #include "host/usbh.h" From a4b976f095ae36ab90cfc5394211598626ff895e Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 19 Mar 2022 14:57:43 +0700 Subject: [PATCH 71/81] get bare example working with hid device --- examples/host/bare_api/src/main.c | 86 +++++++++++++++++++++++++++++-- 1 file changed, 83 insertions(+), 3 deletions(-) diff --git a/examples/host/bare_api/src/main.c b/examples/host/bare_api/src/main.c index 3b23dd43b..3f3d1d488 100644 --- a/examples/host/bare_api/src/main.c +++ b/examples/host/bare_api/src/main.c @@ -49,6 +49,11 @@ void parse_config_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* tusb_desc_device_t desc_device; +#define BUF_COUNT 4 + +uint8_t buf_pool[BUF_COUNT][64]; +uint8_t buf_owner[BUF_COUNT] = { 0 }; // device address that owns buffer + /*------------- MAIN -------------*/ int main(void) { @@ -139,7 +144,7 @@ void print_device_descriptor(tuh_xfer_t* xfer) printf(" bNumConfigurations %u\r\n" , desc_device.bNumConfigurations); // Get configuration descriptor with sync API - if (XFER_RESULT_SUCCESS == tuh_descriptor_get_configuration_sync(daddr, 0, temp_buf, sizeof(temp_buf)) ) + if (XFER_RESULT_SUCCESS == tuh_descriptor_get_configuration_sync(daddr, 0, temp_buf, sizeof(temp_buf))) { parse_config_descriptor(daddr, (tusb_desc_configuration_t*) temp_buf); } @@ -150,10 +155,60 @@ void print_device_descriptor(tuh_xfer_t* xfer) // Configuration Descriptor //--------------------------------------------------------------------+ +// get an buffer from pool +uint8_t* get_hid_buf(uint8_t daddr) +{ + for(size_t i=0; ibuffer is NULL. We have used user_data to store buffer when submitted callback + uint8_t* buf = (uint8_t*) xfer->user_data; + + if (xfer->result == XFER_RESULT_SUCCESS) + { + printf("[dev %u: ep %02x] HID Report:", xfer->daddr, xfer->ep_addr); + for(uint32_t i=0; iactual_len; i++) + { + if (i%16 == 0) printf("\r\n "); + printf("%02X ", buf[i]); + } + printf("\r\n"); + } + + // continue to submit transfer, with updated buffer + // other field remain the same + xfer->buflen = 64; + xfer->buffer = buf; + + tuh_edpt_xfer(xfer); +} + // count total length of an interface uint16_t count_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len); -void open_hid_interface(uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) +void open_hid_interface(uint8_t daddr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) { // len = interface + hid + n*endpoints uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); @@ -165,8 +220,11 @@ void open_hid_interface(uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, // HID descriptor p_desc = tu_desc_next(p_desc); + tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; + if(HID_DESC_TYPE_HID != desc_hid->bDescriptorType) return; // Endpoint descriptor + p_desc = tu_desc_next(p_desc); tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; for(int i = 0; i < desc_itf->bNumEndpoints; i++) @@ -175,8 +233,30 @@ void open_hid_interface(uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, if(tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) { - //usbh_edpt_open(rhport, dev_addr, desc_ep); + // skip if failed to open endpoint + if ( ! usbh_edpt_open(daddr, desc_ep) ) return; + + uint8_t* buf = get_hid_buf(daddr); + if (!buf) return; // out of memory + + tuh_xfer_t xfer = + { + .daddr = daddr, + .ep_addr = desc_ep->bEndpointAddress, + .buflen = 64, + .buffer = buf, + .complete_cb = hid_report_received, + .user_data = (uintptr_t) buf, // since buffer is not available in callback, use user data to store the buffer + }; + + // submit transfer for this EP + tuh_edpt_xfer(&xfer); + + printf("Listen to [dev %u: ep %02x]\r\n", daddr, desc_ep->bEndpointAddress); } + + p_desc = tu_desc_next(p_desc); + desc_ep = (tusb_desc_endpoint_t const *) p_desc; } } From 821be65b034bd69210834ae7400527149cb66e43 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 19 Mar 2022 14:59:31 +0700 Subject: [PATCH 72/81] rename usbh_edpt_open() to tuh_edpt_open() --- examples/host/bare_api/src/main.c | 2 +- src/class/cdc/cdc_host.c | 4 ++-- src/class/hid/hid_host.c | 2 +- src/class/msc/msc_host.c | 2 +- src/host/hub.c | 2 +- src/host/usbh.c | 2 +- src/host/usbh.h | 4 ++-- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/host/bare_api/src/main.c b/examples/host/bare_api/src/main.c index 3f3d1d488..fa50c7af3 100644 --- a/examples/host/bare_api/src/main.c +++ b/examples/host/bare_api/src/main.c @@ -234,7 +234,7 @@ void open_hid_interface(uint8_t daddr, tusb_desc_interface_t const *desc_itf, ui if(tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) { // skip if failed to open endpoint - if ( ! usbh_edpt_open(daddr, desc_ep) ) return; + if ( ! tuh_edpt_open(daddr, desc_ep) ) return; uint8_t* buf = get_hid_buf(daddr); if (!buf) return; // out of memory diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 82cf911cf..044085e81 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -197,7 +197,7 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it // notification endpoint tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT( usbh_edpt_open(dev_addr, desc_ep) ); + TU_ASSERT( tuh_edpt_open(dev_addr, desc_ep) ); p_cdc->ep_notif = desc_ep->bEndpointAddress; drv_len += tu_desc_len(p_desc); @@ -218,7 +218,7 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc; TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_BULK == desc_ep->bmAttributes.xfer); - TU_ASSERT(usbh_edpt_open(dev_addr, desc_ep)); + TU_ASSERT(tuh_edpt_open(dev_addr, desc_ep)); if ( tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN ) { diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 2280e87b4..ce3d1598c 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -356,7 +356,7 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de for(int i = 0; i < desc_itf->bNumEndpoints; i++) { TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); - TU_ASSERT( usbh_edpt_open(dev_addr, desc_ep) ); + TU_ASSERT( tuh_edpt_open(dev_addr, desc_ep) ); if(tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) { diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 4033cc429..c54a63f37 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -379,7 +379,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de for(uint32_t i=0; i<2; i++) { TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); - TU_ASSERT(usbh_edpt_open(dev_addr, ep_desc)); + TU_ASSERT(tuh_edpt_open(dev_addr, ep_desc)); if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) { diff --git a/src/host/hub.c b/src/host/hub.c index b4d369aca..9e546f6f7 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -201,7 +201,7 @@ bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0); - TU_ASSERT(usbh_edpt_open(dev_addr, desc_ep)); + TU_ASSERT(tuh_edpt_open(dev_addr, desc_ep)); hub_interface_t* p_hub = get_itf(dev_addr); diff --git a/src/host/usbh.c b/src/host/usbh.c index 466e5decd..f534070de 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -806,7 +806,7 @@ static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) return hcd_edpt_open(usbh_get_rhport(dev_addr), dev_addr, &ep0_desc); } -bool usbh_edpt_open(uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep) +bool tuh_edpt_open(uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep) { TU_ASSERT( tu_edpt_validate(desc_ep, tuh_speed_get(dev_addr)) ); diff --git a/src/host/usbh.h b/src/host/usbh.h index a2df0153e..e883ac90b 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -135,8 +135,8 @@ bool tuh_control_xfer(tuh_xfer_t* xfer); // - sync : blocking if complete callback is NULL. bool tuh_edpt_xfer(tuh_xfer_t* xfer); -// Open an endpoint -bool usbh_edpt_open(uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep); +// Open an non-control endpoint +bool tuh_edpt_open(uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep); // Set Configuration (control transfer) // config_num = 0 will un-configure device. Note: config_num = config_descriptor_index + 1 From a270d8d6236124244f5a1447d57b35f4cfa4909c Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 19 Mar 2022 15:06:12 +0700 Subject: [PATCH 73/81] move code around --- examples/host/bare_api/src/main.c | 232 ++++++++++++++++-------------- 1 file changed, 123 insertions(+), 109 deletions(-) diff --git a/examples/host/bare_api/src/main.c b/examples/host/bare_api/src/main.c index fa50c7af3..eb3f7d8d7 100644 --- a/examples/host/bare_api/src/main.c +++ b/examples/host/bare_api/src/main.c @@ -37,6 +37,13 @@ // English #define LANGUAGE_ID 0x0409 +#define BUF_COUNT 4 + + +tusb_desc_device_t desc_device; + +uint8_t buf_pool[BUF_COUNT][64]; +uint8_t buf_owner[BUF_COUNT] = { 0 }; // device address that owns buffer //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES @@ -47,12 +54,8 @@ static void print_utf16(uint16_t *temp_buf, size_t buf_len); void print_device_descriptor(tuh_xfer_t* xfer); void parse_config_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg); -tusb_desc_device_t desc_device; - -#define BUF_COUNT 4 - -uint8_t buf_pool[BUF_COUNT][64]; -uint8_t buf_owner[BUF_COUNT] = { 0 }; // device address that owns buffer +uint8_t* get_hid_buf(uint8_t daddr); +void free_hid_buf(uint8_t daddr); /*------------- MAIN -------------*/ int main(void) @@ -88,6 +91,7 @@ void tuh_mount_cb (uint8_t daddr) void tuh_umount_cb(uint8_t daddr) { printf("Device removed, address = %d\r\n", daddr); + free_hid_buf(daddr); } //--------------------------------------------------------------------+ @@ -150,115 +154,14 @@ void print_device_descriptor(tuh_xfer_t* xfer) } } - //--------------------------------------------------------------------+ // Configuration Descriptor //--------------------------------------------------------------------+ -// get an buffer from pool -uint8_t* get_hid_buf(uint8_t daddr) -{ - for(size_t i=0; ibuffer is NULL. We have used user_data to store buffer when submitted callback - uint8_t* buf = (uint8_t*) xfer->user_data; - - if (xfer->result == XFER_RESULT_SUCCESS) - { - printf("[dev %u: ep %02x] HID Report:", xfer->daddr, xfer->ep_addr); - for(uint32_t i=0; iactual_len; i++) - { - if (i%16 == 0) printf("\r\n "); - printf("%02X ", buf[i]); - } - printf("\r\n"); - } - - // continue to submit transfer, with updated buffer - // other field remain the same - xfer->buflen = 64; - xfer->buffer = buf; - - tuh_edpt_xfer(xfer); -} - // count total length of an interface uint16_t count_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len); -void open_hid_interface(uint8_t daddr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) -{ - // len = interface + hid + n*endpoints - uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); - - // corrupted descriptor - if (max_len < drv_len) return; - - uint8_t const *p_desc = (uint8_t const *) desc_itf; - - // HID descriptor - p_desc = tu_desc_next(p_desc); - tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; - if(HID_DESC_TYPE_HID != desc_hid->bDescriptorType) return; - - // Endpoint descriptor - p_desc = tu_desc_next(p_desc); - tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - - for(int i = 0; i < desc_itf->bNumEndpoints; i++) - { - if (TUSB_DESC_ENDPOINT != desc_ep->bDescriptorType) return; - - if(tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) - { - // skip if failed to open endpoint - if ( ! tuh_edpt_open(daddr, desc_ep) ) return; - - uint8_t* buf = get_hid_buf(daddr); - if (!buf) return; // out of memory - - tuh_xfer_t xfer = - { - .daddr = daddr, - .ep_addr = desc_ep->bEndpointAddress, - .buflen = 64, - .buffer = buf, - .complete_cb = hid_report_received, - .user_data = (uintptr_t) buf, // since buffer is not available in callback, use user data to store the buffer - }; - - // submit transfer for this EP - tuh_edpt_xfer(&xfer); - - printf("Listen to [dev %u: ep %02x]\r\n", daddr, desc_ep->bEndpointAddress); - } - - p_desc = tu_desc_next(p_desc); - desc_ep = (tusb_desc_endpoint_t const *) p_desc; - } -} +void open_hid_interface(uint8_t daddr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); // simple configuration parser to open and listen to HID Endpoint IN void parse_config_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg) @@ -330,6 +233,117 @@ uint16_t count_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_ return len; } +//--------------------------------------------------------------------+ +// HID Interface +//--------------------------------------------------------------------+ + +void hid_report_received(tuh_xfer_t* xfer); + +void open_hid_interface(uint8_t daddr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) +{ + // len = interface + hid + n*endpoints + uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); + + // corrupted descriptor + if (max_len < drv_len) return; + + uint8_t const *p_desc = (uint8_t const *) desc_itf; + + // HID descriptor + p_desc = tu_desc_next(p_desc); + tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; + if(HID_DESC_TYPE_HID != desc_hid->bDescriptorType) return; + + // Endpoint descriptor + p_desc = tu_desc_next(p_desc); + tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; + + for(int i = 0; i < desc_itf->bNumEndpoints; i++) + { + if (TUSB_DESC_ENDPOINT != desc_ep->bDescriptorType) return; + + if(tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) + { + // skip if failed to open endpoint + if ( ! tuh_edpt_open(daddr, desc_ep) ) return; + + uint8_t* buf = get_hid_buf(daddr); + if (!buf) return; // out of memory + + tuh_xfer_t xfer = + { + .daddr = daddr, + .ep_addr = desc_ep->bEndpointAddress, + .buflen = 64, + .buffer = buf, + .complete_cb = hid_report_received, + .user_data = (uintptr_t) buf, // since buffer is not available in callback, use user data to store the buffer + }; + + // submit transfer for this EP + tuh_edpt_xfer(&xfer); + + printf("Listen to [dev %u: ep %02x]\r\n", daddr, desc_ep->bEndpointAddress); + } + + p_desc = tu_desc_next(p_desc); + desc_ep = (tusb_desc_endpoint_t const *) p_desc; + } +} + +void hid_report_received(tuh_xfer_t* xfer) +{ + // Note: not all field in xfer is available for use (i.e filled by tinyusb stack) in callback to save sram + // For instance, xfer->buffer is NULL. We have used user_data to store buffer when submitted callback + uint8_t* buf = (uint8_t*) xfer->user_data; + + if (xfer->result == XFER_RESULT_SUCCESS) + { + printf("[dev %u: ep %02x] HID Report:", xfer->daddr, xfer->ep_addr); + for(uint32_t i=0; iactual_len; i++) + { + if (i%16 == 0) printf("\r\n "); + printf("%02X ", buf[i]); + } + printf("\r\n"); + } + + // continue to submit transfer, with updated buffer + // other field remain the same + xfer->buflen = 64; + xfer->buffer = buf; + + tuh_edpt_xfer(xfer); +} + +//--------------------------------------------------------------------+ +// Buffer helper +//--------------------------------------------------------------------+ + +// get an buffer from pool +uint8_t* get_hid_buf(uint8_t daddr) +{ + for(size_t i=0; i Date: Mon, 28 Mar 2022 12:47:32 +0700 Subject: [PATCH 74/81] remove cxd56 __pycache-_ folder --- .../tools/__pycache__/xmodem.cpython-36.pyc | Bin 15257 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 hw/mcu/sony/cxd56/tools/__pycache__/xmodem.cpython-36.pyc diff --git a/hw/mcu/sony/cxd56/tools/__pycache__/xmodem.cpython-36.pyc b/hw/mcu/sony/cxd56/tools/__pycache__/xmodem.cpython-36.pyc deleted file mode 100644 index cfa917f71d3dbe945ac710d5b292db2daa36426e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15257 zcmeHO2Y4LSwVtxOT8&o4w%iR2V6Ya{ZNMl-*p_85*s>#uwv_c~&q!Kni!?K9Nt;zd zA`?s!6Q_rS^g>AQJ*0>9O4_6Y2~m1NDoODB&z;#K*~agSpWpYr?|UoHKX+zsJ@>!& zo^$T?#@bq~Wgxi!b9*J}A*tdQKzJ)I+XavmlSq!qq>wtI#1sm|R0_rd6r!qBFcuW| zP%I?wRk14E!>Mq(I#w-9;++=L%-~oJRnN(>h*?Y8h>TDjLNy{(k5EK}8W5@#p(O~_ ziO^Dn>P2W7LJcC+h|m%dT7HE@OKI6biI$lw=G53qv)WuqjkNr*5?e(pXyrjEw%S}n ztHu@UJ7(3`T66WBG$*5GRRdCVwJ~2ON!n#k{L}R7_w3!#yGI{RrcB+jjEp^OTKa^Q zb+UZHlF)>eJ}E?Tc?gQH1X$3H_)B^}c;QhG8ykuuX}#xa~^Hlt^U{jypIuOEyz z`wtygi$~qakj7Qn)6?JMN3e4f6IsjAhqIP`gI7z$(qmo_MNOC)N@hk{i(l>0Y%WFG zkf{$FNh>v@n}$83JK1tgbOUvCylRdbiE$nEakG zZRO{R&z?joBY1C0QHmleM=8G1v>hl-A5LYbbaUEZ`RmC{B9&t?>852tl9rjs9x$z$ zlXYzcZ#3;n(?U+%xwe<9FEDPLD6Sb&5}ko48(W4_S;!W`u#FM3RoexLi&{WBEM{ja ztEaQJqbIWIGG%!w_U-8H=g`T2{k=WCyRPl+_fnobz87OlON-vO?P{;Iy;th(9s15*ojdnNRQ6__ z+qXEcmX>Z2fARYhJ#!flX}OF}edmtTUB*UzXV2*_W0Ssf`{^#@B7NsJzl`>F^vAwE zy?b}wxS(rJr9XQ24xXsn7QFvY%kY`s(lPFHzFEiU!Js7b1nlP_@xMI+dOU6pUcZ3< z?VXz-aMYHsir;@K3(jJI%c$W0X)B|G|Lv8;sc6!vwBxk%W>0b&Gjj*z!z;F4nmM=g zjDMn;vpAjpKYvc8ZwGiCsNj#7Y>piU`YD%DF@IK4l$V`iai>zoY3Hb~D{eQO#Hc>V zDs4Jx+pK~PKqKLMQ-@I4qE9f_6**hHpCWfF=Bbkgd13C+n^-x*80)fzqUANZUEjGA zif6Vpq4!<08_K}OieB+@K9#;XY2Ew?qKf5OE!IwoG^xn$RB9!dkJ)*F=5RX7!00M! z4*%DfU(^;)_votV(vt=ku|#m!V{PSJQkl(v$`Vb>pL<<$EW>Nko-C1RVd&^v(nj9g zIx*vnwr5(i)<}1LeNT2`#!8NiIv8J3y|cZeT|XvW{_KUZIxgMZq4$jDVAAZ&TK14> zjl|SFy9V>Y_STK9o%8S`NPSV+t(q__CuyYI&@?Mj>3JC+<`o8ZI?RU{8W@%{tYYW^ zByg2~NVFACb^!@Z39bnVZV4G~3AiXIK*A+KVX7vLYA8Z*B~U#z&=PhPuycSN1GI`( z(;8Y!>*x$Rlg=WY&ZcwdTv|`((fPE2nkY&a(1p}YE!0YF)J`4LNgHVsT|^htCA66? zr7n6BZK2Dkn=YrVw2ih?5AC2{+DTW?m9&elqN`~)?V&!}OZ(`_)K3F6NY~J{bRAt! zH&Bdjq?_nwx`pDjp9~tJ1fgeWm_}%nk~Bu+l%h0cC`%JGNfz1UP>v4J6iw3%<>@I@ zpjmn`{?8J3Hl^`iat%Bq0iFi=zjVYA>3Evs>M}@=PKOS;97!fDV{mrT3pL;HR8D%_jS0I<641d4fn`^)N}@z z=!QHK*|-I46!X1rGVk*pMEWR(T*|bX;cu8Q6ENX1?y^H;2(shFG7Zv)t!!FoiXeiMTiGeoM(aV?rxpTVK(j)O?EPGHtS9@ZDw=MWgXEj5v3Jw6#iMJle03yxxyBI zUp8YFzc0vYB8RNlOL5YyxV#f)CC0OUneQNK;tDqFoOe|7s@{dMZ=^-dyY!v8OhUN4 zgajPROdcpYk33oEHeMQOQPVDGX2SFnCX7_d7)p6f@w4Po7G^2DbZNM;Jbx4lfm>#A zhF-GcWyo#m@>^1J^m(QqOV+E87YVt-$>LShYv6=IUHU$QghMGYibf~k?BlLZ8{_Co zcv&XkS2IC`w9voGZ*-P$MUzEVoP{Sri)YK^*_a=b+jT&q9dHm+Ve$?80H50rcw_<) zemWrfJit}20gS&3@SINq-u4Z^SAPch{T~4xO92hwZPM-p^q&KGUq9f5+W~*G0N)t` zT>1jQsyV<@-UEoe4)C#W0q*`Z;OL`(A3p>bS`X;i1kf>^C*?-KF9>kI19<%oz-@zo zu{Qv&ejlLeHbC`@0KfY=;A?*Yy!Eqy!`}uBTnw zoq!uZ0Lb41Sp5>f=Gy^3`5WNzM*y$*F5sj013q&l;OEx^o;eD*XBx0I3^1_LB$Xz> zxtjrB{sQ2)-v``@r7QW4e*mt$1CYE6pxq0&@I!#V!~hRm1^7T7@ZvGRK4HM z2w>Yfz}tTdc<#RezxfK_D?b8U@HRlr#{i>;0lQuSc*#=%@6Q0feGA~veSl@%fX-IH zlg|W9zyqFq)ltBGzX$y2CxCx_4Y2m(fUb7{Zg>@7`niBZOsRXBTwi2L{hG-YVM?_y zx%!w=Sti%5py)h4O36<#MIU0a2AHDfF+{j zrqnG=u6HSbBTUvu&jEas$$HUtKqHfNY6x&Gll50jsV_0P-o%u;gUOX)O6_HGH8Z7Z znOqMtML)eB@M@;$(*uBErsx#}SkDv8NvuDfmre2~c%e+2MUCf6DF1GX@^ zzQq*%6O;9MOwo5TS+8S?9$>OAXNqoOvhHR|rI}oHOsO^|*XNm1^GvR1F{R$ZnE6^KVz~!gDLttChIIy>Lw=FoRWZ>brNHU zw~|U*Io{4r&$hneUI54CpICA@RHg&sBJSX(3=g%L!AJQ$40p_%NhfsJ5O@)dSe} zoUP6@IyGYv(wy3YHYX3uE5x>A0o$XONV8Ris)8~ew6>$R#*?8f`$&I-;;#98jFs9h!T)@$({ z=ZM%`+I#&p^;CEHf;i5qLOs=PExpS$6k}H8gdQlUs5$z;SuJYzc%eqLtj1YW2s&%W z*3EH!|5XSUB88el)to9?FM8{UVht8$TM=8aE~t#{Nga7yjPgrzhb+&adTs^xz!7=! z;>@7vy9UuRzsDBjdh35P*Cmy?E-EuZON(C%wG>*3E$kK2Z0+R3*GbdY3i+HV$`{;R zAQ{E_J9yb#Y_H!c#d=^-31?7av4kVa zoLSxn>=z~s?{jL`;F`2^iG*nn=ThEge9?0$b~SezDVrlEGkU_XVXX|8T8a(t zRL;U)Yw3+|K6v%$(g&fL`^_qwXIxXyhGM&iHh!~ck=TtFTe6sxd6zzAQmNFUJiWVTM(9H(78y4cwL&XB0hlmQcp&lVW4CT++b67@ z=?sH(aYahS9j7XjxuofI>AQyY_GUhPAh?2a2$^AsB#T~wyUK!DiwGSe0%akuOxBNy z)oVsXUR!;y8ymynvDn(8l|q50^~TQNw`|FE-{+*lvg^g);@* zb~`zeF<^U}sBrPfN6t2xu#n}6b0}`u+c*u9v%z&3rB3TFg%s!9zm)!XwU9Fu}yut35^m zpQZ2~Dh7iXHpLveL|!Fxo(q`26>EEvHJYd*^gTE1HN0ayziwLwy?nq(B}vR9`V=~a zkHDmoCJC*?Vm%@s!2u3-D3H!diR=b=SnkZ9E5>qffB)Wo-xY%xa0<6!&!$-)0h!LT zqq4P@v#8;?+?j9|&qINg=2eg*@;FlQ6Ic6{S zf~#F?q;g(Z=(nzlnn7pl@3B^+U2aeeI9Ii2Y&YbMHdjq$N8F&OsjFr!vRJ!z1MIJI z13WU_U}`LfnU6JOH;g__#1mG+t@T3wK@wj(#QubZ9S4Wp z8XToc!6k;hC)*A8_+Fk^)s$gn&=0N(8AKaA{Sq}~-w^aqo>N7Kxj`}1MK#2@c56Id z#@VIf)>M!YajZmK=>4Gtmz{D0>|=@5E+BBMb^*QJa8WUaoZ&2URphc*p@jjFp>IMQ z_I&{9EJfzOkQ|Zg-6X!OG zab@ukNK|pl@Z(-*YorI4{QyiblA%+}(5YqU)E|XbqC&%kr8p)P0;C8HR~>+1#+n** z-oRRETtZk_Cv&pxIO$#LuY@JAFf9DK4|M7B-Ds)0K_Pzgr4NJM1%J2Y2j!QYvHgIygdKR zUy#?sct*a^C~+9F^hOhJ&J-=H5$(~??y!SW5p#0^d0CyMk{>R>8*TSH5emar2+zq* z-B>+UABJ{YtdlRxhgp_$m=QQF>xq6ntC3E~fwl5k9I&i>UM0a6s4YZLwqo5~s4In# z0{V4uC3*xGOR&DcaaJKUc1u>nUZI+9Njxp#ru`Cx`wSkYQP-4d#YB~e?b8&>_AGZzH|Cm)1#A?4_D z1IJj)+H$|QuwXUzHNO8Lg?Z{^3Nu!;1IJaEJ2!6XENiqyg_&K-WsS~rf|nM>k_v5m zCjoh9;3O(Dugv@ti>$v!_6cW%H#3}tNkA;xc_@mB1Nx#x7PEgF=5MjcBK6sbZJon# zE+D^@&rCF(*S=|5-_ot~J(@2cL~JS^NkoiJKSt+t)LPF;{dHVuUBx4)=V5sii#fHO zNAr&#J$iH=*HP;#F7WCiL|2IQ%yaZa@zxEng6anClxa>_O&m{nf-d3^TzisODJ}NB zSa85e7QAMX)y8lk13X`n)dFyXWDeyh382uX4W=-4WAg0lrfS25}f~v%7G4ZG7FOj$DE-nI@yx;?J4Iv%mrW1sW2;fps9>s;W$R}6Q!BTS}B5g&2h>ab+NQjbGqr+FB{sYHzqceCkQcY;JQakLAC|qpPA_566^M<|6{#L0b-{>m{3z}ByChj8k*@Jd<0c)zUU;R+)qc58u?S+>rsJ_QW08Gm}Uq6ENZkHV?G9 z85~2v5$2QhYpEX>^{;PqpL>X$BkX;Mhjb`+<&1OBVWH#SHaV?oi=dtr~Xlv%)O+;MpQ$jn7)i;ed4phvAl&e1~wbtR;#l-Xrpd-@UkSh^HEMdGr4S zh{s(m&Z>AW#oP@rdhKUe+mo0V@ zAHrp0<4Fpy48Xg5Dt~L#hEPLQ!_y?aVY;DKE!DlU6F+6&*b zl#*t>yL<=pULp2Y%d_y(k5!ylIUImKBaa2YZF>)hzT`ys1InE1(fpJJrxV!vzH%?v;mC_RWsf6sq~`%wc5~p|J?-qnVgr z0&AJF)h+T~^8|UXJwe{J$L1}zZO-Tu{K>bS2lIGDzi~@;LKuqOH|ty2JSp%3(Jfq& zOrBBzwtq0k|G^@!w50Q)mKL6ig;yberZ;(ceuO5^#n9~gSUSd|7*SR5br`vn;|4HU zPt0?F=9d)R4~8|8HasEn_K3Y3;F01EpA@r-14>;#@)-1SSP{WYfTY40o#?c?+e8eFPI$G=%*$*xsIQBTu=q0ZhpPqs$k{m}+=xgibf63Wh6v7?A9kf?pXbx&zl7 zm>1la#s6<}1N(OE>$S#_kCg)O(De@nW0N;IVWRn>RVA^y!8pIal&db5KGrtn#Z~4g zF~!d3!!0e|{2*38SD6~}=X_zlAj~R!OtJDVc#V!MO$O0AH;kDI$AWBAR3R4GD<-ae z;!RA$A)&Z8mARUT700|{d(^@9x8y3xtQ+7)dh3nYkmjWiTdb)pGUcM85zFCMA+H>_ z%AXwFfXHkN->gZ70}R5ZVK#Xt2+wLPSoSyz-W7!!XgRFXg_oW;)GcO}g;NYttQu3oZbXIC zj}0>G5{8QyxE*B^E~f6--Rqfp>;<)=05_BsNArZhV_|QV=olBxu&(0>0dqR(ROrTK rT7|cGs!TW2P{=F*%ZD9+u#SXV&vWdtowVRjg<8RXazqX92+RKk`88&w From 95801bf5cc4afa27f9b54c33e74aa74689074a97 Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Wed, 30 Mar 2022 14:15:34 +0100 Subject: [PATCH 75/81] Update requirements.txt --- docs/requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/requirements.txt b/docs/requirements.txt index 8ae9ae73b..15022e147 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,3 +1,4 @@ sphinx~=3.0 furo>=2020.12.30.b24 sphinx-autodoc-typehints>=1.10 +jinja2==3.0.3 From a90839688c11338451729838e45ae3aaa58864fe Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 20 Apr 2022 13:25:38 +0700 Subject: [PATCH 76/81] add msec timeout to osal_queue_receive(), tud_task() and tuh_task() both pending for event queue with timeout of 1 ms --- src/device/usbd.c | 3 +- src/host/usbh.c | 2 +- src/osal/osal.h | 22 +++++++-------- src/osal/osal_freertos.h | 29 ++++++++++--------- src/osal/osal_mynewt.h | 22 ++++++++------- src/osal/osal_none.h | 28 +++++++++--------- src/osal/osal_pico.h | 44 +++++++++++++++-------------- src/osal/osal_rtthread.h | 28 +++++++++--------- src/osal/osal_rtx4.h | 28 +++++++++--------- src/portable/sony/cxd56/dcd_cxd56.c | 2 +- src/tusb_option.h | 2 +- 11 files changed, 109 insertions(+), 101 deletions(-) diff --git a/src/device/usbd.c b/src/device/usbd.c index 7ab2660f4..36b9c7cff 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -475,8 +475,7 @@ void tud_task (void) while (1) { dcd_event_t event; - - if ( !osal_queue_receive(_usbd_q, &event) ) return; + if ( !osal_queue_receive(_usbd_q, &event, 1) ) return; #if CFG_TUSB_DEBUG >= 2 if (event.event_id == DCD_EVENT_SETUP_RECEIVED) TU_LOG2("\r\n"); // extra line for setup diff --git a/src/host/usbh.c b/src/host/usbh.c index f534070de..ad90a1b1b 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -401,7 +401,7 @@ void tuh_task(void) while (1) { hcd_event_t event; - if ( !osal_queue_receive(_usbh_q, &event) ) return; + if ( !osal_queue_receive(_usbh_q, &event, 1) ) return; switch (event.event_id) { diff --git a/src/osal/osal.h b/src/osal/osal.h index 7111bbdb2..9d11866df 100644 --- a/src/osal/osal.h +++ b/src/osal/osal.h @@ -66,19 +66,19 @@ typedef void (*osal_task_func_t)( void * ); // OSAL Porting API // Should be implemented as static inline function in osal_port.h header /* - static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef); - static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr); - static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec); - static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl); // TODO removed + osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef); + bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr); + bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec); + void osal_semaphore_reset(osal_semaphore_t sem_hdl); // TODO removed - static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef); - static inline bool osal_mutex_lock (osal_mutex_t sem_hdl, uint32_t msec); - static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl); + osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef); + bool osal_mutex_lock (osal_mutex_t sem_hdl, uint32_t msec); + bool osal_mutex_unlock(osal_mutex_t mutex_hdl); - static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef); - static inline bool osal_queue_receive(osal_queue_t qhdl, void* data); - static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr); - static inline bool osal_queue_empty(osal_queue_t qhdl); + osal_queue_t osal_queue_create(osal_queue_def_t* qdef); + bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec); + bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr); + bool osal_queue_empty(osal_queue_t qhdl); */ //--------------------------------------------------------------------+ diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h index 69a026df5..c3a0756e1 100644 --- a/src/osal/osal_freertos.h +++ b/src/osal/osal_freertos.h @@ -40,7 +40,7 @@ extern "C" { //--------------------------------------------------------------------+ // TASK API //--------------------------------------------------------------------+ -static inline void osal_task_delay(uint32_t msec) +TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { vTaskDelay( pdMS_TO_TICKS(msec) ); } @@ -51,12 +51,12 @@ static inline void osal_task_delay(uint32_t msec) typedef StaticSemaphore_t osal_semaphore_def_t; typedef SemaphoreHandle_t osal_semaphore_t; -static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) +TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) { return xSemaphoreCreateBinaryStatic(semdef); } -static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) +TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) { if ( !in_isr ) { @@ -78,13 +78,13 @@ static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) } } -static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) +TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) { uint32_t const ticks = (msec == OSAL_TIMEOUT_WAIT_FOREVER) ? portMAX_DELAY : pdMS_TO_TICKS(msec); return xSemaphoreTake(sem_hdl, ticks); } -static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl) +TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl) { xQueueReset(sem_hdl); } @@ -95,17 +95,17 @@ static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl) typedef StaticSemaphore_t osal_mutex_def_t; typedef SemaphoreHandle_t osal_mutex_t; -static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) +TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) { return xSemaphoreCreateMutexStatic(mdef); } -static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) +TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) { return osal_semaphore_wait(mutex_hdl, msec); } -static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) +TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) { return xSemaphoreGive(mutex_hdl); } @@ -114,7 +114,7 @@ static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) // QUEUE API //--------------------------------------------------------------------+ -// role device/host is used by OS NONE for mutex (disable usb isr) only +// _int_set is not used with an RTOS #define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \ static _type _name##_##buf[_depth];\ osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf }; @@ -130,17 +130,18 @@ typedef struct typedef QueueHandle_t osal_queue_t; -static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) +TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) { return xQueueCreateStatic(qdef->depth, qdef->item_sz, (uint8_t*) qdef->buf, &qdef->sq); } -static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) { - return xQueueReceive(qhdl, data, portMAX_DELAY); + uint32_t const ticks = (msec == OSAL_TIMEOUT_WAIT_FOREVER) ? portMAX_DELAY : pdMS_TO_TICKS(msec); + return xQueueReceive(qhdl, data, ticks); } -static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) { if ( !in_isr ) { @@ -162,7 +163,7 @@ static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in } } -static inline bool osal_queue_empty(osal_queue_t qhdl) +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) { return uxQueueMessagesWaiting(qhdl) == 0; } diff --git a/src/osal/osal_mynewt.h b/src/osal/osal_mynewt.h index 78a257cd6..b8ea2087c 100644 --- a/src/osal/osal_mynewt.h +++ b/src/osal/osal_mynewt.h @@ -36,7 +36,7 @@ //--------------------------------------------------------------------+ // TASK API //--------------------------------------------------------------------+ -static inline void osal_task_delay(uint32_t msec) +TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { os_time_delay( os_time_ms_to_ticks32(msec) ); } @@ -47,18 +47,18 @@ static inline void osal_task_delay(uint32_t msec) typedef struct os_sem osal_semaphore_def_t; typedef struct os_sem* osal_semaphore_t; -static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) +TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) { return (os_sem_init(semdef, 0) == OS_OK) ? (osal_semaphore_t) semdef : NULL; } -static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) +TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) { (void) in_isr; return os_sem_release(sem_hdl) == OS_OK; } -static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) +TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) { uint32_t const ticks = (msec == OSAL_TIMEOUT_WAIT_FOREVER) ? OS_TIMEOUT_NEVER : os_time_ms_to_ticks32(msec); return os_sem_pend(sem_hdl, ticks) == OS_OK; @@ -75,18 +75,18 @@ static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) typedef struct os_mutex osal_mutex_def_t; typedef struct os_mutex* osal_mutex_t; -static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) +TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) { return (os_mutex_init(mdef) == OS_OK) ? (osal_mutex_t) mdef : NULL; } -static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec) +TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec) { uint32_t const ticks = (msec == OSAL_TIMEOUT_WAIT_FOREVER) ? OS_TIMEOUT_NEVER : os_time_ms_to_ticks32(msec); return os_mutex_pend(mutex_hdl, ticks) == OS_OK; } -static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) +TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) { return os_mutex_release(mutex_hdl) == OS_OK; } @@ -116,7 +116,7 @@ typedef struct typedef osal_queue_def_t* osal_queue_t; -static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) +TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) { if ( OS_OK != os_mempool_init(&qdef->mpool, qdef->depth, qdef->item_sz, qdef->buf, "usbd queue") ) return NULL; if ( OS_OK != os_mempool_init(&qdef->epool, qdef->depth, sizeof(struct os_event), qdef->evbuf, "usbd evqueue") ) return NULL; @@ -125,8 +125,10 @@ static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) return (osal_queue_t) qdef; } -static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) { + (void) msec; // os_eventq_get() does not take timeout, always behave as msec = WAIT_FOREVER + struct os_event* ev; ev = os_eventq_get(&qhdl->evq); @@ -161,7 +163,7 @@ static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in return true; } -static inline bool osal_queue_empty(osal_queue_t qhdl) +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) { return STAILQ_EMPTY(&qhdl->evq.evq_list); } diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index 4217f0422..9c80e4548 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -46,13 +46,13 @@ typedef struct typedef osal_semaphore_def_t* osal_semaphore_t; -static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) +TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) { semdef->count = 0; return semdef; } -static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) +TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) { (void) in_isr; sem_hdl->count++; @@ -60,7 +60,7 @@ static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) } // TODO blocking for now -static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) +TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) { (void) msec; @@ -70,7 +70,7 @@ static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) return true; } -static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) +TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) { sem_hdl->count = 0; } @@ -82,18 +82,18 @@ static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) typedef osal_semaphore_def_t osal_mutex_def_t; typedef osal_semaphore_t osal_mutex_t; -static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) +TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) { mdef->count = 1; return mdef; } -static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) +TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) { return osal_semaphore_wait(mutex_hdl, msec); } -static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) +TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) { return osal_semaphore_post(mutex_hdl, false); } @@ -120,27 +120,29 @@ typedef osal_queue_def_t* osal_queue_t; } // lock queue by disable USB interrupt -static inline void _osal_q_lock(osal_queue_t qhdl) +TU_ATTR_ALWAYS_INLINE static inline void _osal_q_lock(osal_queue_t qhdl) { // disable dcd/hcd interrupt qhdl->interrupt_set(false); } // unlock queue -static inline void _osal_q_unlock(osal_queue_t qhdl) +TU_ATTR_ALWAYS_INLINE static inline void _osal_q_unlock(osal_queue_t qhdl) { // enable dcd/hcd interrupt qhdl->interrupt_set(true); } -static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) +TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) { tu_fifo_clear(&qdef->ff); return (osal_queue_t) qdef; } -static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) { + (void) msec; // not used, always behave as msec = 0 + _osal_q_lock(qhdl); bool success = tu_fifo_read(&qhdl->ff, data); _osal_q_unlock(qhdl); @@ -148,7 +150,7 @@ static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) return success; } -static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) { if (!in_isr) { _osal_q_lock(qhdl); @@ -165,7 +167,7 @@ static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in return success; } -static inline bool osal_queue_empty(osal_queue_t qhdl) +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) { // Skip queue lock/unlock since this function is primarily called // with interrupt disabled before going into low power mode diff --git a/src/osal/osal_pico.h b/src/osal/osal_pico.h index 70432d22b..abef286b4 100644 --- a/src/osal/osal_pico.h +++ b/src/osal/osal_pico.h @@ -39,7 +39,7 @@ //--------------------------------------------------------------------+ // TASK API //--------------------------------------------------------------------+ -static inline void osal_task_delay(uint32_t msec) +TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { sleep_ms(msec); } @@ -49,25 +49,25 @@ static inline void osal_task_delay(uint32_t msec) //--------------------------------------------------------------------+ typedef struct semaphore osal_semaphore_def_t, *osal_semaphore_t; -static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) +TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) { sem_init(semdef, 0, 255); return semdef; } -static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) +TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) { (void) in_isr; sem_release(sem_hdl); return true; } -static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) +TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) { return sem_acquire_timeout_ms(sem_hdl, msec); } -static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) +TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) { sem_reset(sem_hdl, 0); } @@ -78,21 +78,21 @@ static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) //--------------------------------------------------------------------+ typedef struct mutex osal_mutex_def_t, *osal_mutex_t; -static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) +TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) { - mutex_init(mdef); - return mdef; + mutex_init(mdef); + return mdef; } -static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) +TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) { - return mutex_enter_timeout_ms(mutex_hdl, msec); + return mutex_enter_timeout_ms(mutex_hdl, msec); } -static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) +TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) { - mutex_exit(mutex_hdl); - return true; + mutex_exit(mutex_hdl); + return true; } //--------------------------------------------------------------------+ @@ -121,26 +121,28 @@ typedef osal_queue_def_t* osal_queue_t; } // lock queue by disable USB interrupt -static inline void _osal_q_lock(osal_queue_t qhdl) +TU_ATTR_ALWAYS_INLINE static inline void _osal_q_lock(osal_queue_t qhdl) { - critical_section_enter_blocking(&qhdl->critsec); + critical_section_enter_blocking(&qhdl->critsec); } // unlock queue -static inline void _osal_q_unlock(osal_queue_t qhdl) +TU_ATTR_ALWAYS_INLINE static inline void _osal_q_unlock(osal_queue_t qhdl) { - critical_section_exit(&qhdl->critsec); + critical_section_exit(&qhdl->critsec); } -static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) +TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) { critical_section_init(&qdef->critsec); tu_fifo_clear(&qdef->ff); return (osal_queue_t) qdef; } -static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) { + (void) msec; // not used, always behave as msec = 0 + // TODO: revisit... docs say that mutexes are never used from IRQ context, // however osal_queue_recieve may be. therefore my assumption is that // the fifo mutex is not populated for queues used from an IRQ context @@ -153,7 +155,7 @@ static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) return success; } -static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) { // TODO: revisit... docs say that mutexes are never used from IRQ context, // however osal_queue_recieve may be. therefore my assumption is that @@ -170,7 +172,7 @@ static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in return success; } -static inline bool osal_queue_empty(osal_queue_t qhdl) +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) { // TODO: revisit; whether this is true or not currently, tu_fifo_empty is a single // volatile read. diff --git a/src/osal/osal_rtthread.h b/src/osal/osal_rtthread.h index 0845175b8..a790a5e27 100644 --- a/src/osal/osal_rtthread.h +++ b/src/osal/osal_rtthread.h @@ -37,7 +37,7 @@ extern "C" { //--------------------------------------------------------------------+ // TASK API //--------------------------------------------------------------------+ -static inline void osal_task_delay(uint32_t msec) { +TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { rt_thread_mdelay(msec); } @@ -47,22 +47,22 @@ static inline void osal_task_delay(uint32_t msec) { typedef struct rt_semaphore osal_semaphore_def_t; typedef rt_sem_t osal_semaphore_t; -static inline osal_semaphore_t +TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t *semdef) { rt_sem_init(semdef, "tusb", 0, RT_IPC_FLAG_FIFO); return semdef; } -static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) { +TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) { (void) in_isr; return rt_sem_release(sem_hdl) == RT_EOK; } -static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) { +TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) { return rt_sem_take(sem_hdl, rt_tick_from_millisecond(msec)) == RT_EOK; } -static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl) { +TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl) { // TODO: implement } @@ -72,16 +72,16 @@ static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl) { typedef struct rt_mutex osal_mutex_def_t; typedef rt_mutex_t osal_mutex_t; -static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t *mdef) { +TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t *mdef) { rt_mutex_init(mdef, "tusb", RT_IPC_FLAG_FIFO); return mdef; } -static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec) { +TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec) { return rt_mutex_take(mutex_hdl, rt_tick_from_millisecond(msec)) == RT_EOK; } -static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) { +TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) { return rt_mutex_release(mutex_hdl) == RT_EOK; } @@ -104,22 +104,24 @@ typedef struct { typedef rt_mq_t osal_queue_t; -static inline osal_queue_t osal_queue_create(osal_queue_def_t *qdef) { +TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t *qdef) { rt_mq_init(&(qdef->sq), "tusb", qdef->buf, qdef->item_sz, qdef->item_sz * qdef->depth, RT_IPC_FLAG_FIFO); return &(qdef->sq); } -static inline bool osal_queue_receive(osal_queue_t qhdl, void *data) { - return rt_mq_recv(qhdl, data, qhdl->msg_size, RT_WAITING_FOREVER) == RT_EOK; +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void *data, uint32_t msec) { + + rt_tick_t tick = rt_tick_from_millisecond((rt_int32_t) msec)); + return rt_mq_recv(qhdl, data, qhdl->msg_size, tick) == RT_EOK; } -static inline bool osal_queue_send(osal_queue_t qhdl, void const *data, bool in_isr) { +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const *data, bool in_isr) { (void) in_isr; return rt_mq_send(qhdl, (void *)data, qhdl->msg_size) == RT_EOK; } -static inline bool osal_queue_empty(osal_queue_t qhdl) { +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) { return (qhdl->entry) == 0; } diff --git a/src/osal/osal_rtx4.h b/src/osal/osal_rtx4.h index 1856a5d9a..dea1c12c8 100644 --- a/src/osal/osal_rtx4.h +++ b/src/osal/osal_rtx4.h @@ -37,7 +37,7 @@ extern "C" { //--------------------------------------------------------------------+ // TASK API //--------------------------------------------------------------------+ -static inline void osal_task_delay(uint32_t msec) +TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { uint16_t hi = msec >> 16; uint16_t lo = msec; @@ -47,7 +47,7 @@ static inline void osal_task_delay(uint32_t msec) os_dly_wait(lo); } -static inline uint16_t msec2wait(uint32_t msec) { +TU_ATTR_ALWAYS_INLINE static inline uint16_t msec2wait(uint32_t msec) { if (msec == OSAL_TIMEOUT_WAIT_FOREVER) return 0xFFFF; else if (msec >= 0xFFFE) @@ -62,12 +62,12 @@ static inline uint16_t msec2wait(uint32_t msec) { typedef OS_SEM osal_semaphore_def_t; typedef OS_ID osal_semaphore_t; -static inline OS_ID osal_semaphore_create(osal_semaphore_def_t* semdef) { +TU_ATTR_ALWAYS_INLINE static inline OS_ID osal_semaphore_create(osal_semaphore_def_t* semdef) { os_sem_init(semdef, 0); return semdef; } -static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) { +TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) { if ( !in_isr ) { os_sem_send(sem_hdl); } else { @@ -76,11 +76,11 @@ static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) { return true; } -static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) { +TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) { return os_sem_wait(sem_hdl, msec2wait(msec)) != OS_R_TMO; } -static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl) { +TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl) { // TODO: implement } @@ -90,18 +90,18 @@ static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl) { typedef OS_MUT osal_mutex_def_t; typedef OS_ID osal_mutex_t; -static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) +TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) { os_mut_init(mdef); return mdef; } -static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) +TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) { return os_mut_wait(mutex_hdl, msec2wait(msec)) != OS_R_TMO; } -static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) +TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) { return os_mut_release(mutex_hdl) == OS_R_OK; } @@ -127,23 +127,23 @@ typedef struct typedef osal_queue_def_t* osal_queue_t; -static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) +TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) { os_mbx_init(qdef->mbox, (qdef->depth + 4) * 4); _init_box(qdef->pool, ((qdef->item_sz+3)/4)*(qdef->depth) + 3, qdef->item_sz); return qdef; } -static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) { void* buf; - os_mbx_wait(qhdl->mbox, &buf, 0xFFFF); + os_mbx_wait(qhdl->mbox, &buf, msec2wait(msec)); memcpy(data, buf, qhdl->item_sz); _free_box(qhdl->pool, buf); return true; } -static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) { void* buf = _alloc_box(qhdl->pool); memcpy(buf, data, qhdl->item_sz); @@ -158,7 +158,7 @@ static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in return true; } -static inline bool osal_queue_empty(osal_queue_t qhdl) +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) { return os_mbx_check(qhdl->mbox) == qhdl->depth; } diff --git a/src/portable/sony/cxd56/dcd_cxd56.c b/src/portable/sony/cxd56/dcd_cxd56.c index fbea03b1d..d3154e58f 100644 --- a/src/portable/sony/cxd56/dcd_cxd56.c +++ b/src/portable/sony/cxd56/dcd_cxd56.c @@ -363,7 +363,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to if (usbdcd_driver.setup_processed) { - if (osal_queue_receive(usbdcd_driver.setup_queue, &ctrl)) + if (osal_queue_receive(usbdcd_driver.setup_queue, &ctrl, 100)) { usbdcd_driver.setup_processed = false; dcd_event_setup_received(0, (uint8_t *)&ctrl, false); diff --git a/src/tusb_option.h b/src/tusb_option.h index bd87a953c..9cacedd4c 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -286,7 +286,7 @@ #endif // mutex is only needed for RTOS TODO also required with multiple core MCUs -#define TUSB_OPT_MUTEX (CFG_TUSB_OS != OPT_OS_NONE) +#define TUSB_OPT_MUTEX (CFG_TUSB_OS != OPT_OS_NONE) //-------------------------------------------------------------------- // DEVICE OPTIONS From 669e36d674d4b67b56127d8b41928a6dd3bdca7b Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 20 Apr 2022 14:37:42 +0700 Subject: [PATCH 77/81] fix freertos issue when 1 tick > 1 ms --- examples/device/cdc_msc_freertos/src/main.c | 6 ++---- src/osal/osal_freertos.h | 20 ++++++++++++++++---- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/examples/device/cdc_msc_freertos/src/main.c b/examples/device/cdc_msc_freertos/src/main.c index 0a1c964ae..c0fc722f4 100644 --- a/examples/device/cdc_msc_freertos/src/main.c +++ b/examples/device/cdc_msc_freertos/src/main.c @@ -132,6 +132,8 @@ void usb_device_task(void* param) { // tinyusb device task tud_task(); + + tud_cdc_write_flush(); } } @@ -194,12 +196,8 @@ void cdc_task(void* params) // for throughput test e.g // $ dd if=/dev/zero of=/dev/ttyACM0 count=10000 tud_cdc_write(buf, count); - tud_cdc_write_flush(); } } - - // For ESP32-S2 this delay is essential to allow idle how to run and reset wdt - vTaskDelay(pdMS_TO_TICKS(10)); } } diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h index c3a0756e1..52db336f5 100644 --- a/src/osal/osal_freertos.h +++ b/src/osal/osal_freertos.h @@ -37,6 +37,20 @@ extern "C" { #endif +TU_ATTR_ALWAYS_INLINE static inline uint32_t _osal_ms2tick(uint32_t msec) +{ + if (msec == OSAL_TIMEOUT_WAIT_FOREVER) return portMAX_DELAY; + if (msec == 0) return 0; + + uint32_t ticks = pdMS_TO_TICKS(msec); + + // configTICK_RATE_HZ is less than 1000 and 1 tick > 1 ms + // we still need to delay at least 1 tick + if (ticks == 0) ticks =1 ; + + return ticks; +} + //--------------------------------------------------------------------+ // TASK API //--------------------------------------------------------------------+ @@ -80,8 +94,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t se TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) { - uint32_t const ticks = (msec == OSAL_TIMEOUT_WAIT_FOREVER) ? portMAX_DELAY : pdMS_TO_TICKS(msec); - return xSemaphoreTake(sem_hdl, ticks); + return xSemaphoreTake(sem_hdl, _osal_ms2tick(msec)); } TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl) @@ -137,8 +150,7 @@ TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_de TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) { - uint32_t const ticks = (msec == OSAL_TIMEOUT_WAIT_FOREVER) ? portMAX_DELAY : pdMS_TO_TICKS(msec); - return xQueueReceive(qhdl, data, ticks); + return xQueueReceive(qhdl, data, _osal_ms2tick(msec)); } TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) From ccafb42c8261d8304fce0af46c0ddc3adf6da56f Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 20 Apr 2022 14:40:55 +0700 Subject: [PATCH 78/81] disable blank issues, add online docs link --- .github/ISSUE_TEMPLATE/config.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 735a5ef22..28fd27467 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,4 +1,8 @@ +blank_issues_enabled: false contact_links: - name: TinyUSB Discussion url: https://github.com/hathach/tinyusb/discussions about: If you have other questions or need help, post it here. + - name: TinyUSB Docs + url: https://docs.tinyusb.org/ + about: Online documentation From b034c18077ef1350f2678f245ed1b885e9be79fc Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 20 Apr 2022 18:29:41 +0700 Subject: [PATCH 79/81] add tud_task_ext(), tuh_task_ext() as exteneded version that take timeout and in_isr also allow exit tud_task,tuh_task after processing all events for running other background task for user --- examples/device/cdc_msc_freertos/src/main.c | 3 +++ src/common/tusb_verify.h | 10 +++++----- src/device/usbd.c | 11 +++++++++-- src/device/usbd.h | 11 ++++++++++- src/host/usbh.c | 11 +++++++++-- src/host/usbh.h | 19 ++++++++++++++----- 6 files changed, 50 insertions(+), 15 deletions(-) diff --git a/examples/device/cdc_msc_freertos/src/main.c b/examples/device/cdc_msc_freertos/src/main.c index c0fc722f4..0d40782ef 100644 --- a/examples/device/cdc_msc_freertos/src/main.c +++ b/examples/device/cdc_msc_freertos/src/main.c @@ -198,6 +198,9 @@ void cdc_task(void* params) tud_cdc_write(buf, count); } } + + // For ESP32-Sx this delay is essential to allow idle how to run and reset watchdog + vTaskDelay(1); } } diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index f4a08ce2f..568bac8cc 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -99,8 +99,8 @@ *------------------------------------------------------------------*/ // Helper to implement optional parameter for TU_VERIFY Macro family -#define GET_3RD_ARG(arg1, arg2, arg3, ...) arg3 -#define GET_4TH_ARG(arg1, arg2, arg3, arg4, ...) arg4 +#define _GET_3RD_ARG(arg1, arg2, arg3, ...) arg3 +#define _GET_4TH_ARG(arg1, arg2, arg3, arg4, ...) arg4 /*------------- Generator for TU_VERIFY and TU_VERIFY_HDLR -------------*/ #define TU_VERIFY_DEFINE(_cond, _handler, _ret) do \ @@ -116,7 +116,7 @@ #define TU_VERIFY_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, , false) #define TU_VERIFY_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, , _ret) -#define TU_VERIFY(...) GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, UNUSED)(__VA_ARGS__) +#define TU_VERIFY(...) _GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, UNUSED)(__VA_ARGS__) /*------------------------------------------------------------------*/ @@ -127,7 +127,7 @@ #define TU_VERIFY_HDLR_2ARGS(_cond, _handler) TU_VERIFY_DEFINE(_cond, _handler, false) #define TU_VERIFY_HDLR_3ARGS(_cond, _handler, _ret) TU_VERIFY_DEFINE(_cond, _handler, _ret) -#define TU_VERIFY_HDLR(...) GET_4TH_ARG(__VA_ARGS__, TU_VERIFY_HDLR_3ARGS, TU_VERIFY_HDLR_2ARGS,UNUSED)(__VA_ARGS__) +#define TU_VERIFY_HDLR(...) _GET_4TH_ARG(__VA_ARGS__, TU_VERIFY_HDLR_3ARGS, TU_VERIFY_HDLR_2ARGS,UNUSED)(__VA_ARGS__) /*------------------------------------------------------------------*/ /* ASSERT @@ -139,7 +139,7 @@ #define ASSERT_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); TU_BREAKPOINT(), _ret) #ifndef TU_ASSERT -#define TU_ASSERT(...) GET_3RD_ARG(__VA_ARGS__, ASSERT_2ARGS, ASSERT_1ARGS,UNUSED)(__VA_ARGS__) +#define TU_ASSERT(...) _GET_3RD_ARG(__VA_ARGS__, ASSERT_2ARGS, ASSERT_1ARGS,UNUSED)(__VA_ARGS__) #endif /*------------------------------------------------------------------*/ diff --git a/src/device/usbd.c b/src/device/usbd.c index 36b9c7cff..167a053e2 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -466,8 +466,10 @@ bool tud_task_event_ready(void) } @endcode */ -void tud_task (void) +void tud_task_ext(uint32_t timeout_ms, bool in_isr) { + (void) in_isr; // not implemented yet + // Skip if stack is not initialized if ( !tusb_inited() ) return; @@ -475,7 +477,7 @@ void tud_task (void) while (1) { dcd_event_t event; - if ( !osal_queue_receive(_usbd_q, &event, 1) ) return; + if ( !osal_queue_receive(_usbd_q, &event, timeout_ms) ) return; #if CFG_TUSB_DEBUG >= 2 if (event.event_id == DCD_EVENT_SETUP_RECEIVED) TU_LOG2("\r\n"); // extra line for setup @@ -592,6 +594,11 @@ void tud_task (void) TU_BREAKPOINT(); break; } + +#if CFG_TUSB_OS != OPT_OS_NONE && CFG_TUSB_OS != OPT_OS_PICO + // return if there is no more events, for application to run other background + if (osal_queue_empty(_usbd_q)) return; +#endif } } diff --git a/src/device/usbd.h b/src/device/usbd.h index b2bf8ba9d..30373abb9 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -43,8 +43,17 @@ bool tud_init (uint8_t rhport); // Check if device stack is already initialized bool tud_inited(void); +// Task function should be called in main/rtos loop, extended version of tud_task() +// - timeout_ms: millisecond to wait, zero = no wait, 0xFFFFFFFF = wait forever +// - in_isr: if function is called in ISR +void tud_task_ext(uint32_t timeout_ms, bool in_isr); + // Task function should be called in main/rtos loop -void tud_task (void); +TU_ATTR_ALWAYS_INLINE static inline +void tud_task (void) +{ + tud_task_ext(OSAL_TIMEOUT_WAIT_FOREVER, false); +} // Check if there is pending events need proccessing by tud_task() bool tud_task_event_ready(void); diff --git a/src/host/usbh.c b/src/host/usbh.c index ad90a1b1b..80d176142 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -392,8 +392,10 @@ bool tuh_init(uint8_t rhport) } @endcode */ -void tuh_task(void) +void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { + (void) in_isr; // not implemented yet + // Skip if stack is not initialized if ( !tusb_inited() ) return; @@ -401,7 +403,7 @@ void tuh_task(void) while (1) { hcd_event_t event; - if ( !osal_queue_receive(_usbh_q, &event, 1) ) return; + if ( !osal_queue_receive(_usbh_q, &event, timeout_ms) ) return; switch (event.event_id) { @@ -497,6 +499,11 @@ void tuh_task(void) default: break; } + +#if CFG_TUSB_OS != OPT_OS_NONE && CFG_TUSB_OS != OPT_OS_PICO + // return if there is no more events, for application to run other background + if (osal_queue_empty(_usbh_q)) return; +#endif } } diff --git a/src/host/usbh.h b/src/host/usbh.h index e883ac90b..1580717fd 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -91,8 +91,17 @@ bool tuh_init(uint8_t rhport); // Check if host stack is already initialized bool tuh_inited(void); +// Task function should be called in main/rtos loop, extended version of tuh_task() +// - timeout_ms: millisecond to wait, zero = no wait, 0xFFFFFFFF = wait forever +// - in_isr: if function is called in ISR +void tuh_task_ext(uint32_t timeout_ms, bool in_isr); + // Task function should be called in main/rtos loop -void tuh_task(void); +TU_ATTR_ALWAYS_INLINE static inline +void tuh_task(void) +{ + tuh_task_ext(OSAL_TIMEOUT_WAIT_FOREVER, false); +} // Interrupt handler, name alias to HCD extern void hcd_int_handler(uint8_t rhport); @@ -106,8 +115,8 @@ tusb_speed_t tuh_speed_get(uint8_t daddr); bool tuh_mounted(uint8_t daddr); // Check if device is suspended -TU_ATTR_ALWAYS_INLINE -static inline bool tuh_suspended(uint8_t daddr) +TU_ATTR_ALWAYS_INLINE static inline +bool tuh_suspended(uint8_t daddr) { // TODO implement suspend & resume on host (void) daddr; @@ -115,8 +124,8 @@ static inline bool tuh_suspended(uint8_t daddr) } // Check if device is ready to communicate with -TU_ATTR_ALWAYS_INLINE -static inline bool tuh_ready(uint8_t daddr) +TU_ATTR_ALWAYS_INLINE static inline +bool tuh_ready(uint8_t daddr) { return tuh_mounted(daddr) && !tuh_suspended(daddr); } From 6a022c73dbf1551a441fafbea3a27c1a9951816f Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 20 Apr 2022 18:35:38 +0700 Subject: [PATCH 80/81] add note for tud_task() behavior in freertos example --- examples/device/cdc_msc_freertos/src/main.c | 5 +++-- examples/device/hid_composite_freertos/src/main.c | 4 +++- src/device/usbd.h | 2 +- src/host/usbh.h | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/examples/device/cdc_msc_freertos/src/main.c b/examples/device/cdc_msc_freertos/src/main.c index 0d40782ef..0492f2724 100644 --- a/examples/device/cdc_msc_freertos/src/main.c +++ b/examples/device/cdc_msc_freertos/src/main.c @@ -130,10 +130,10 @@ void usb_device_task(void* param) // RTOS forever loop while (1) { - // tinyusb device task + // put this thread to waiting state until there is new events tud_task(); - tud_cdc_write_flush(); + // following code only run if tud_task() process at least 1 event } } @@ -196,6 +196,7 @@ void cdc_task(void* params) // for throughput test e.g // $ dd if=/dev/zero of=/dev/ttyACM0 count=10000 tud_cdc_write(buf, count); + tud_cdc_write_flush(); } } diff --git a/examples/device/hid_composite_freertos/src/main.c b/examples/device/hid_composite_freertos/src/main.c index 1695f968c..317b64611 100644 --- a/examples/device/hid_composite_freertos/src/main.c +++ b/examples/device/hid_composite_freertos/src/main.c @@ -132,8 +132,10 @@ void usb_device_task(void* param) // RTOS forever loop while (1) { - // tinyusb device task + // put this thread to waiting state until there is new events tud_task(); + + // following code only run if tud_task() process at least 1 event } } diff --git a/src/device/usbd.h b/src/device/usbd.h index 30373abb9..583962611 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -52,7 +52,7 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr); TU_ATTR_ALWAYS_INLINE static inline void tud_task (void) { - tud_task_ext(OSAL_TIMEOUT_WAIT_FOREVER, false); + tud_task_ext(UINT32_MAX, false); } // Check if there is pending events need proccessing by tud_task() diff --git a/src/host/usbh.h b/src/host/usbh.h index 1580717fd..c6d36fb7f 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -100,7 +100,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr); TU_ATTR_ALWAYS_INLINE static inline void tuh_task(void) { - tuh_task_ext(OSAL_TIMEOUT_WAIT_FOREVER, false); + tuh_task_ext(UINT32_MAX, false); } // Interrupt handler, name alias to HCD From 87572871d586856242c1fa44b1532a09e624162d Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 20 Apr 2022 18:52:15 +0700 Subject: [PATCH 81/81] update example for better cdc echo --- examples/device/cdc_msc_freertos/src/main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/device/cdc_msc_freertos/src/main.c b/examples/device/cdc_msc_freertos/src/main.c index 0492f2724..a5e907199 100644 --- a/examples/device/cdc_msc_freertos/src/main.c +++ b/examples/device/cdc_msc_freertos/src/main.c @@ -134,6 +134,7 @@ void usb_device_task(void* param) tud_task(); // following code only run if tud_task() process at least 1 event + tud_cdc_write_flush(); } } @@ -183,7 +184,7 @@ void cdc_task(void* params) // if ( tud_cdc_connected() ) { // There are data available - if ( tud_cdc_available() ) + while ( tud_cdc_available() ) { uint8_t buf[64]; @@ -196,8 +197,9 @@ void cdc_task(void* params) // for throughput test e.g // $ dd if=/dev/zero of=/dev/ttyACM0 count=10000 tud_cdc_write(buf, count); - tud_cdc_write_flush(); } + + tud_cdc_write_flush(); } // For ESP32-Sx this delay is essential to allow idle how to run and reset watchdog