From d1ee2bf18fced22364537949c4a18e1c15c99b6d Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 29 Jan 2025 15:14:25 +0100 Subject: Fix Auto speed display. Signed-off-by: HiFiPhile --- src/host/usbh.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'src/host') diff --git a/src/host/usbh.c b/src/host/usbh.c index a2994cde7..f022d93f1 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -365,9 +365,26 @@ bool tuh_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { if (tuh_rhport_is_active(rhport)) { return true; // skip if already initialized } - - TU_LOG_USBH("USBH init on controller %u, speed = %s\r\n", rhport, - rh_init->speed == TUSB_SPEED_HIGH ? "High" : "Full"); +#if CFG_TUSB_DEBUG >= CFG_TUH_LOG_LEVEL + char const* speed_str = 0; + switch (rh_init->speed) { + case TUSB_SPEED_HIGH: + speed_str = "High"; + break; + case TUSB_SPEED_FULL: + speed_str = "Full"; + break; + case TUSB_SPEED_LOW: + speed_str = "Low"; + break; + case TUSB_SPEED_AUTO: + speed_str = "Auto"; + break; + default: + break; + } + TU_LOG_USBH("USBH init on controller %u, speed = %s\r\n", rhport, speed_str); +#endif // Init host stack if not already if (!tuh_inited()) { -- cgit v1.3.1 From bc37ed6e3e9158a811ed07479638d3db8437344e Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 6 May 2025 15:23:23 +0700 Subject: usbh: force removed device in the same bus info, before setting address. usbh: move code around hub: queue status endpoint for detach/remove event --- src/host/hub.c | 3 +- src/host/usbh.c | 231 +++++++++++++++++++++++++++----------------------------- 2 files changed, 114 insertions(+), 120 deletions(-) (limited to 'src/host') diff --git a/src/host/hub.c b/src/host/hub.c index c87289a14..0ed0e0c42 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -459,7 +459,8 @@ static void process_new_status(tuh_xfer_t* xfer) { } }; hcd_event_handler(&event, false); - processed = true; // usbh queue status after handled this in (de)enumeration + // skip status for attach event, usbh will do it after handled this enumeration + processed = (event.event_id == HCD_EVENT_DEVICE_ATTACH); break; } diff --git a/src/host/usbh.c b/src/host/usbh.c index fbb61e10e..92c254a9e 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -34,7 +34,7 @@ #include "hub.h" //--------------------------------------------------------------------+ -// USBH Configuration +// Configuration //--------------------------------------------------------------------+ #ifndef CFG_TUH_TASK_QUEUE_SZ #define CFG_TUH_TASK_QUEUE_SZ 16 @@ -89,7 +89,7 @@ TU_ATTR_WEAK bool hcd_dcache_clean_invalidate(const void* addr, uint32_t data_si } //--------------------------------------------------------------------+ -// USBH-HCD common data structure +// Data Structure //--------------------------------------------------------------------+ typedef struct { tuh_bus_info_t bus_info; @@ -131,8 +131,60 @@ typedef struct { } usbh_device_t; +// sum of end device + hub +#define TOTAL_DEVICES (CFG_TUH_DEVICE_MAX + CFG_TUH_HUB) + +// all devices excluding zero-address +// hub address start from CFG_TUH_DEVICE_MAX+1 +// TODO: hub can has its own simpler struct to save memory +static usbh_device_t _usbh_devices[TOTAL_DEVICES]; + +// Mutex for claiming endpoint +#if OSAL_MUTEX_REQUIRED +static osal_mutex_def_t _usbh_mutexdef; +static osal_mutex_t _usbh_mutex; +#else +#define _usbh_mutex NULL +#endif + +// Event queue: 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; + +// Control transfers: since most controllers do not support multiple control transfers +// on multiple devices concurrently and control transfers are not used much except for +// enumeration, we will only execute control transfers one at a time. +typedef struct { + uint8_t* buffer; + tuh_xfer_cb_t complete_cb; + uintptr_t user_data; + + volatile uint8_t stage; + uint8_t daddr; + volatile uint16_t actual_len; + uint8_t failed_count; +} usbh_ctrl_xfer_info_t; + +typedef struct { + uint8_t controller_id; // controller ID + uint8_t enumerating_daddr; // device address of the device being enumerated + uint8_t attach_debouncing_bm; // bitmask for roothub port attach debouncing + tuh_bus_info_t dev0_bus; // bus info for dev0 in enumeration + usbh_ctrl_xfer_info_t ctrl_xfer_info; // control transfer +} usbh_data_t; + +static usbh_data_t _usbh_data = { + .controller_id = TUSB_INDEX_INVALID_8, +}; + +typedef struct { + TUH_EPBUF_TYPE_DEF(tusb_control_request_t, request); + TUH_EPBUF_DEF(ctrl, CFG_TUH_ENUMERATION_BUFSIZE); +} usbh_epbuf_t; +CFG_TUH_MEM_SECTION static usbh_epbuf_t _usbh_epbuf; + //--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF +// Class Driver //--------------------------------------------------------------------+ #if CFG_TUSB_DEBUG >= CFG_TUH_LOG_LEVEL #define DRIVER_NAME(_name) _name @@ -235,82 +287,58 @@ static inline usbh_class_driver_t const *get_driver(uint8_t drv_id) { } //--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION +// Function Inline and Prototypes //--------------------------------------------------------------------+ +static bool enum_new_device(hcd_event_t* event); +static void process_removed_device(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); +static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -// sum of end device + hub -#define TOTAL_DEVICES (CFG_TUH_DEVICE_MAX + CFG_TUH_HUB) - -// all devices excluding zero-address -// hub address start from CFG_TUH_DEVICE_MAX+1 -// TODO: hub can has its own simpler struct to save memory -static usbh_device_t _usbh_devices[TOTAL_DEVICES]; - -// Mutex for claiming endpoint -#if OSAL_MUTEX_REQUIRED - static osal_mutex_def_t _usbh_mutexdef; - static osal_mutex_t _usbh_mutex; -#else - #define _usbh_mutex NULL -#endif - -// Event queue: 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; - -// Control transfers: since most controllers do not support multiple control transfers -// on multiple devices concurrently and control transfers are not used much except for -// enumeration, we will only execute control transfers one at a time. -typedef struct { - uint8_t* buffer; - tuh_xfer_cb_t complete_cb; - uintptr_t user_data; - - volatile uint8_t stage; - uint8_t daddr; - volatile uint16_t actual_len; - uint8_t failed_count; -} usbh_ctrl_xfer_info_t; - -typedef struct { - uint8_t controller_id; // controller ID - uint8_t enumerating_daddr; // device address of the device being enumerated - uint8_t attach_debouncing_bm; // bitmask for roothub port attach debouncing - tuh_bus_info_t dev0_bus; // bus info for dev0 in enumeration - usbh_ctrl_xfer_info_t ctrl_xfer_info; // control transfer -} usbh_data_t; - -static usbh_data_t _usbh_data = { - .controller_id = TUSB_INDEX_INVALID_8, -}; - -typedef struct { - TUH_EPBUF_TYPE_DEF(tusb_control_request_t, request); - TUH_EPBUF_DEF(ctrl, CFG_TUH_ENUMERATION_BUFSIZE); -} usbh_epbuf_t; -CFG_TUH_MEM_SECTION static usbh_epbuf_t _usbh_epbuf; - -//------------- Helper Function -------------// TU_ATTR_ALWAYS_INLINE static inline usbh_device_t* get_device(uint8_t dev_addr) { TU_VERIFY(dev_addr > 0 && dev_addr <= TOTAL_DEVICES, NULL); return &_usbh_devices[dev_addr-1]; } -static bool enum_new_device(hcd_event_t* event); -static void process_removed_device(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); -static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); - TU_ATTR_ALWAYS_INLINE static inline bool queue_event(hcd_event_t const * event, bool in_isr) { TU_ASSERT(osal_queue_send(_usbh_q, event, in_isr)); tuh_event_hook_cb(event->rhport, event->event_id, in_isr); return true; } +TU_ATTR_ALWAYS_INLINE static inline void _control_set_xfer_stage(uint8_t stage) { + if (_usbh_data.ctrl_xfer_info.stage != stage) { + (void) osal_mutex_lock(_usbh_mutex, OSAL_TIMEOUT_WAIT_FOREVER); + _usbh_data.ctrl_xfer_info.stage = stage; + (void) osal_mutex_unlock(_usbh_mutex); + } +} + +TU_ATTR_ALWAYS_INLINE static inline bool usbh_setup_send(uint8_t daddr, const uint8_t setup_packet[8]) { + const uint8_t rhport = usbh_get_rhport(daddr); + const bool ret = hcd_setup_send(rhport, daddr, setup_packet); + if (!ret) { + _control_set_xfer_stage(CONTROL_STAGE_IDLE); + } + return ret; +} + +TU_ATTR_ALWAYS_INLINE static inline void usbh_device_close(uint8_t rhport, uint8_t daddr) { + hcd_device_close(rhport, daddr); + + // abort any ongoing control transfer + if (daddr == _usbh_data.ctrl_xfer_info.daddr) { + _control_set_xfer_stage(CONTROL_STAGE_IDLE); + } + + // invalidate if enumerating + if (daddr == _usbh_data.enumerating_daddr) { + _usbh_data.enumerating_daddr = TUSB_INDEX_INVALID_8; + } +} + //--------------------------------------------------------------------+ // Device API //--------------------------------------------------------------------+ - bool tuh_mounted(uint8_t dev_addr) { usbh_device_t *dev = get_device(dev_addr); TU_VERIFY(dev); @@ -530,16 +558,16 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { break; case HCD_EVENT_DEVICE_REMOVE: - TU_LOG_USBH("[%u:%u:%u] USBH DEVICE REMOVED\r\n", event.rhport, event.connection.hub_addr, event.connection.hub_port); - process_removed_device(event.rhport, event.connection.hub_addr, event.connection.hub_port); - - #if CFG_TUH_HUB - // TODO remove - if (event.connection.hub_addr != 0 && event.connection.hub_port != 0) { - // done with hub, waiting for next data on status pipe - (void) hub_edpt_status_xfer(event.connection.hub_addr); + TU_LOG1("[%u:%u:%u] USBH DEVICE REMOVED\r\n", event.rhport, event.connection.hub_addr, event.connection.hub_port); + if (_usbh_data.enumerating_daddr == 0 && + event.rhport == _usbh_data.dev0_bus.rhport && + event.connection.hub_addr == _usbh_data.dev0_bus.hub_addr && + event.connection.hub_port == _usbh_data.dev0_bus.hub_port) { + // dev0 is unplugged while enumerating (not yet assigned an address) + usbh_device_close(_usbh_data.dev0_bus.rhport, 0); + } else { + process_removed_device(event.rhport, event.connection.hub_addr, event.connection.hub_port); } - #endif break; case HCD_EVENT_XFER_COMPLETE: { @@ -623,23 +651,6 @@ static void _control_blocking_complete_cb(tuh_xfer_t* xfer) { *((xfer_result_t*) xfer->user_data) = xfer->result; } -TU_ATTR_ALWAYS_INLINE static inline void _control_set_xfer_stage(uint8_t stage) { - if (_usbh_data.ctrl_xfer_info.stage != stage) { - (void) osal_mutex_lock(_usbh_mutex, OSAL_TIMEOUT_WAIT_FOREVER); - _usbh_data.ctrl_xfer_info.stage = stage; - (void) osal_mutex_unlock(_usbh_mutex); - } -} - -TU_ATTR_ALWAYS_INLINE static inline bool usbh_setup_send(uint8_t daddr, const uint8_t setup_packet[8]) { - const uint8_t rhport = usbh_get_rhport(daddr); - const bool ret = hcd_setup_send(rhport, daddr, setup_packet); - if (!ret) { - _control_set_xfer_stage(CONTROL_STAGE_IDLE); - } - return ret; -} - // TODO timeout_ms is not supported yet bool tuh_control_xfer (tuh_xfer_t* xfer) { TU_VERIFY(xfer->ep_addr == 0 && xfer->setup); // EP0 with setup packet @@ -1270,21 +1281,8 @@ TU_ATTR_ALWAYS_INLINE static inline bool is_hub_addr(uint8_t daddr) { // a device unplugged from rhport:hub_addr:hub_port static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) { - // if dev0 is unplugged while enumerating (not yet assigned an address) - if (_usbh_data.enumerating_daddr == 0) { - const tuh_bus_info_t* dev0_bus = &_usbh_data.dev0_bus; - if ((rhport == dev0_bus->rhport) && (hub_addr == dev0_bus->hub_addr) && (hub_port == dev0_bus->hub_port)) { - hcd_device_close(dev0_bus->rhport, 0); - if (_usbh_data.ctrl_xfer_info.daddr == 0) { - _control_set_xfer_stage(CONTROL_STAGE_IDLE); - } - _usbh_data.enumerating_daddr = TUSB_INDEX_INVALID_8; - return; - } - } - - //------------- find the all devices (star-network) under port that is unplugged -------------// - uint32_t removing_hubs = 0; + // Find the all devices (star-network) under port that is unplugged + uint32_t removing_hubs_bm = 0; do { for (uint8_t dev_id = 0; dev_id < TOTAL_DEVICES; dev_id++) { usbh_device_t* dev = &_usbh_devices[dev_id]; @@ -1298,7 +1296,7 @@ static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub if (is_hub_addr(daddr)) { TU_LOG_USBH(" is a HUB device %u\r\n", daddr); - removing_hubs |= TU_BIT(dev_id - CFG_TUH_DEVICE_MAX); + removing_hubs_bm |= TU_BIT(dev_id - CFG_TUH_DEVICE_MAX); } else { // Invoke callback before closing driver (maybe call it later ?) if (tuh_umount_cb) { @@ -1314,30 +1312,21 @@ static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub } } - hcd_device_close(rhport, daddr); + usbh_device_close(rhport, daddr); clear_device(dev); - - // abort ongoing control xfer on this device if any - if (daddr == _usbh_data.ctrl_xfer_info.daddr) { - _control_set_xfer_stage(CONTROL_STAGE_IDLE); - } - - if (daddr == _usbh_data.enumerating_daddr) { - _usbh_data.enumerating_daddr = TUSB_INDEX_INVALID_8; - } } } // if removing a hub, we need to remove all of its downstream devices #if CFG_TUH_HUB - if (removing_hubs == 0) { + if (removing_hubs_bm == 0) { break; } // find a marked hub to process for (uint8_t h_id = 0; h_id < CFG_TUH_HUB; h_id++) { - if (tu_bit_test(removing_hubs, h_id)) { - removing_hubs &= ~TU_BIT(h_id); + if (tu_bit_test(removing_hubs_bm, h_id)) { + removing_hubs_bm &= ~TU_BIT(h_id); // update hub_addr and hub_port for next loop hub_addr = h_id + 1 + CFG_TUH_DEVICE_MAX; @@ -1560,6 +1549,10 @@ static void process_enumeration(tuh_xfer_t* xfer) { } case ENUM_SET_ADDR: { + // Due to physical debouncing, some devices can cause multiple attaches (actually reset) without detach event + // Force remove currently mounted with the same bus info (rhport, hub addr, hub port) if exists + process_removed_device(dev0_bus->rhport, dev0_bus->hub_addr, dev0_bus->hub_port); + const tusb_desc_device_t *desc_device = (const tusb_desc_device_t *) _usbh_epbuf.ctrl; const uint8_t new_addr = enum_get_new_address(desc_device->bDeviceClass == TUSB_CLASS_HUB); TU_ASSERT(new_addr != 0,); @@ -1582,7 +1575,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { new_dev->addressed = 1; _usbh_data.enumerating_daddr = new_addr; - hcd_device_close(dev0_bus->rhport, 0); // close dev0 + usbh_device_close(dev0_bus->rhport, 0); // close dev0 TU_ASSERT(usbh_edpt_control_open(new_addr, new_dev->ep0_size),); // open new control endpoint -- cgit v1.3.1 From 809af3e74ca37495d6c385acd33a488c2984a093 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 6 May 2025 15:44:00 +0700 Subject: chore(usbh): change removing_hubs to array instead of bitmask --- .idea/debugServers/rt1064.xml | 2 +- src/host/usbh.c | 37 +++++++++++++++++++++---------------- 2 files changed, 22 insertions(+), 17 deletions(-) (limited to 'src/host') diff --git a/.idea/debugServers/rt1064.xml b/.idea/debugServers/rt1064.xml index b908b59e2..4fb2fdf6a 100644 --- a/.idea/debugServers/rt1064.xml +++ b/.idea/debugServers/rt1064.xml @@ -1,5 +1,5 @@ - + diff --git a/src/host/usbh.c b/src/host/usbh.c index 92c254a9e..a3d79a105 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -299,6 +299,10 @@ TU_ATTR_ALWAYS_INLINE static inline usbh_device_t* get_device(uint8_t dev_addr) return &_usbh_devices[dev_addr-1]; } +TU_ATTR_ALWAYS_INLINE static inline bool is_hub_addr(uint8_t daddr) { + return (CFG_TUH_HUB > 0) && (daddr > CFG_TUH_DEVICE_MAX); +} + TU_ATTR_ALWAYS_INLINE static inline bool queue_event(hcd_event_t const * event, bool in_isr) { TU_ASSERT(osal_queue_send(_usbh_q, event, in_isr)); tuh_event_hook_cb(event->rhport, event->event_id, in_isr); @@ -1274,15 +1278,13 @@ uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_i //--------------------------------------------------------------------+ // Detaching //--------------------------------------------------------------------+ - -TU_ATTR_ALWAYS_INLINE static inline bool is_hub_addr(uint8_t daddr) { - return (CFG_TUH_HUB > 0) && (daddr > CFG_TUH_DEVICE_MAX); -} - // a device unplugged from rhport:hub_addr:hub_port static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) { // Find the all devices (star-network) under port that is unplugged - uint32_t removing_hubs_bm = 0; + #if CFG_TUH_HUB + uint8_t removing_hubs[CFG_TUH_HUB] = { 0 }; + #endif + do { for (uint8_t dev_id = 0; dev_id < TOTAL_DEVICES; dev_id++) { usbh_device_t* dev = &_usbh_devices[dev_id]; @@ -1294,10 +1296,13 @@ static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub (hub_port == 0 || dev->bus_info.hub_port == hub_port)) { TU_LOG_USBH("[%u:%u:%u] unplugged address = %u\r\n", rhport, hub_addr, hub_port, daddr); + #if CFG_TUH_HUB if (is_hub_addr(daddr)) { TU_LOG_USBH(" is a HUB device %u\r\n", daddr); - removing_hubs_bm |= TU_BIT(dev_id - CFG_TUH_DEVICE_MAX); - } else { + removing_hubs[dev_id - CFG_TUH_DEVICE_MAX] = 1; + } else + #endif + { // Invoke callback before closing driver (maybe call it later ?) if (tuh_umount_cb) { tuh_umount_cb(daddr); @@ -1317,16 +1322,16 @@ static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub } } - // if removing a hub, we need to remove all of its downstream devices - #if CFG_TUH_HUB - if (removing_hubs_bm == 0) { +#if CFG_TUH_HUB + // if a hub is removed, we need to remove all of its downstream devices + if (tu_mem_is_zero(removing_hubs, CFG_TUH_HUB)) { break; } // find a marked hub to process for (uint8_t h_id = 0; h_id < CFG_TUH_HUB; h_id++) { - if (tu_bit_test(removing_hubs_bm, h_id)) { - removing_hubs_bm &= ~TU_BIT(h_id); + if (removing_hubs[h_id]) { + removing_hubs[h_id] = 0; // update hub_addr and hub_port for next loop hub_addr = h_id + 1 + CFG_TUH_DEVICE_MAX; @@ -1334,10 +1339,10 @@ static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub break; } } - #else - (void) removing_hubs; +#else break; - #endif +#endif + } while(1); } -- cgit v1.3.1 From baf67539fc2d328a6274c35c18c90da27c37bc60 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 13 May 2025 10:28:42 +0700 Subject: fix warnings, minor clean up --- .github/actions/setup_toolchain/toolchain.json | 2 +- examples/host/cdc_msc_hid/src/hid_app.c | 100 ++++++++----------------- src/class/cdc/cdc_host.c | 2 +- src/class/hid/hid_host.c | 6 +- src/host/hub.c | 1 - src/host/usbh.c | 5 +- 6 files changed, 41 insertions(+), 75 deletions(-) (limited to 'src/host') diff --git a/.github/actions/setup_toolchain/toolchain.json b/.github/actions/setup_toolchain/toolchain.json index ea07ca344..f7123ef11 100644 --- a/.github/actions/setup_toolchain/toolchain.json +++ b/.github/actions/setup_toolchain/toolchain.json @@ -1,7 +1,7 @@ { "aarch64-gcc": "https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz", "arm-clang": "https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm/releases/download/release-19.1.1/LLVM-ET-Arm-19.1.1-Linux-x86_64.tar.xz", - "arm-gcc": "https://github.com/xpack-dev-tools/gcc-xpack/releases/download/v14.2.0-1/xpack-gcc-14.2.0-1-linux-x64.tar.gz", + "arm-gcc": "https://github.com/xpack-dev-tools/arm-none-eabi-gcc-xpack/releases/download/v14.2.1-1.1/xpack-arm-none-eabi-gcc-14.2.1-1.1-linux-x64.tar.gz", "msp430-gcc": "http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSPGCC/9_2_0_0/export/msp430-gcc-9.2.0.50_linux64.tar.bz2", "riscv-gcc": "https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v13.2.0-2/xpack-riscv-none-elf-gcc-13.2.0-2-linux-x64.tar.gz", "rx-gcc": "https://github.com/hathach/rx_device/releases/download/0.0.1/gcc-8.3.0.202411-GNURX-ELF.run", diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index a751c9c80..6f01d6f45 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -29,14 +29,9 @@ //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ +#define MAX_REPORT 4 -// If your host terminal support ansi escape code such as TeraTerm -// it can be use to simulate mouse cursor movement within terminal -#define USE_ANSI_ESCAPE 0 - -#define MAX_REPORT 4 - -static uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII }; +static uint8_t const keycode2ascii[128][2] = {HID_KEYCODE_TO_ASCII}; // Each HID instance can has multiple reports static struct { @@ -45,8 +40,8 @@ static struct { } hid_info[CFG_TUH_HID]; static void process_kbd_report(hid_keyboard_report_t const *report); -static void process_mouse_report(hid_mouse_report_t const * report); -static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); +static void process_mouse_report(hid_mouse_report_t const *report); +static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len); void hid_app_task(void) { // nothing to do @@ -70,7 +65,7 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *desc_re printf("HID Interface Protocol = %s\r\n", protocol_str[itf_protocol]); - // By default host stack will use activate boot protocol on supported interface. + // By default, host stack will use boot protocol on supported interface. // Therefore for this simple example, we only need to parse generic report descriptor (with built-in parser) if (itf_protocol == HID_ITF_PROTOCOL_NONE) { hid_info[instance].report_count = tuh_hid_parse_report_descriptor(hid_info[instance].report_info, MAX_REPORT, desc_report, desc_len); @@ -121,7 +116,7 @@ void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t cons //--------------------------------------------------------------------+ // look up new key in previous keys -static inline bool find_key_in_report(hid_keyboard_report_t const* report, uint8_t keycode) { +static inline bool find_key_in_report(hid_keyboard_report_t const *report, uint8_t keycode) { for (uint8_t i = 0; i < 6; i++) { if (report->keycode[i] == keycode) { return true; @@ -130,28 +125,25 @@ static inline bool find_key_in_report(hid_keyboard_report_t const* report, uint8 return false; } -static void process_kbd_report(hid_keyboard_report_t const *report) -{ - static hid_keyboard_report_t prev_report = { 0, 0, {0} }; // previous report to check key released +static void process_kbd_report(hid_keyboard_report_t const *report) { + static hid_keyboard_report_t prev_report = {0, 0, {0}};// previous report to check key released //------------- example code ignore control (non-printable) key affects -------------// - for(uint8_t i=0; i<6; i++) - { - if ( report->keycode[i] ) - { - if ( find_key_in_report(&prev_report, report->keycode[i]) ) - { + for (uint8_t i = 0; i < 6; i++) { + if (report->keycode[i]) { + if (find_key_in_report(&prev_report, report->keycode[i])) { // exist in previous report means the current key is holding - }else - { + } else { // not existed in previous report means the current key is pressed bool const is_shift = report->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT); uint8_t ch = keycode2ascii[report->keycode[i]][is_shift ? 1 : 0]; putchar(ch); - if ( ch == '\r' ) putchar('\n'); // added new line for enter key + if (ch == '\r') { + putchar('\n'); + } - #ifndef __ICCARM__ // TODO IAR doesn't support stream control ? - fflush(stdout); // flush right away, else nanolib will wait for newline + #ifndef __ICCARM__ // TODO IAR doesn't support stream control ? + fflush(stdout);// flush right away, else nanolib will wait for newline #endif } } @@ -166,55 +158,22 @@ static void process_kbd_report(hid_keyboard_report_t const *report) //--------------------------------------------------------------------+ static void cursor_movement(int8_t x, int8_t y, int8_t wheel) { -#if USE_ANSI_ESCAPE - // Move X using ansi escape - if ( x < 0) - { - printf(ANSI_CURSOR_BACKWARD(%d), (-x)); // move left - }else if ( x > 0) - { - printf(ANSI_CURSOR_FORWARD(%d), x); // move right - } - - // Move Y using ansi escape - if ( y < 0) - { - printf(ANSI_CURSOR_UP(%d), (-y)); // move up - }else if ( y > 0) - { - printf(ANSI_CURSOR_DOWN(%d), y); // move down - } - - // Scroll using ansi escape - if (wheel < 0) - { - printf(ANSI_SCROLL_UP(%d), (-wheel)); // scroll up - }else if (wheel > 0) - { - printf(ANSI_SCROLL_DOWN(%d), wheel); // scroll down - } - - printf("\r\n"); -#else printf("(%d %d %d)\r\n", x, y, wheel); -#endif } -static void process_mouse_report(hid_mouse_report_t const * report) -{ - static hid_mouse_report_t prev_report = { 0 }; +static void process_mouse_report(hid_mouse_report_t const *report) { + static hid_mouse_report_t prev_report = {0}; - //------------- button state -------------// + // button state uint8_t button_changed_mask = report->buttons ^ prev_report.buttons; - if ( button_changed_mask & report->buttons) - { + if (button_changed_mask & report->buttons) { printf(" %c%c%c ", - report->buttons & MOUSE_BUTTON_LEFT ? 'L' : '-', - report->buttons & MOUSE_BUTTON_MIDDLE ? 'M' : '-', - report->buttons & MOUSE_BUTTON_RIGHT ? 'R' : '-'); + report->buttons & MOUSE_BUTTON_LEFT ? 'L' : '-', + report->buttons & MOUSE_BUTTON_MIDDLE ? 'M' : '-', + report->buttons & MOUSE_BUTTON_RIGHT ? 'R' : '-'); } - //------------- cursor movement -------------// + // cursor movement cursor_movement(report->x, report->y, report->wheel); } @@ -263,18 +222,23 @@ static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t c if (rpt_info->usage_page == HID_USAGE_PAGE_DESKTOP) { switch (rpt_info->usage) { case HID_USAGE_DESKTOP_KEYBOARD: - TU_LOG1("HID receive keyboard report\r\n"); + TU_LOG2("HID receive keyboard report\r\n"); // Assume keyboard follow boot report layout process_kbd_report((hid_keyboard_report_t const *) report); break; case HID_USAGE_DESKTOP_MOUSE: - TU_LOG1("HID receive mouse report\r\n"); + TU_LOG2("HID receive mouse report\r\n"); // Assume mouse follow boot report layout process_mouse_report((hid_mouse_report_t const *) report); break; default: + printf("report[%u] ", rpt_info->report_id); + for (uint8_t i = 0; i < len; i++) { + printf("%02X ", report[i]); + } + printf("\r\n"); break; } } diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 4058857c5..bf245db3f 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -672,7 +672,7 @@ void cdch_close(uint8_t daddr) { bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { // TODO handle stall response, retry failed transfer ... - TU_ASSERT(event == XFER_RESULT_SUCCESS); + TU_VERIFY(event == XFER_RESULT_SUCCESS); uint8_t const idx = get_idx_by_ep_addr(daddr, ep_addr); cdch_interface_t * p_cdc = get_itf(idx); diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index a3cc7d6d7..57e437196 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -444,7 +444,7 @@ bool hidh_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t result, uint32_t hidh_epbuf_t* epbuf = get_hid_epbuf(idx); if (dir == TUSB_DIR_IN) { - TU_LOG_DRV(" Get Report callback (%u, %u)\r\n", daddr, idx); + TU_LOG_DRV(" [idx=%u] Get Report callback\r\n", idx); TU_LOG3_MEM(epbuf->epin, xferred_bytes, 2); tuh_hid_report_received_cb(daddr, idx, epbuf->epin, (uint16_t) xferred_bytes); } else { @@ -461,7 +461,9 @@ void hidh_close(uint8_t daddr) { hidh_interface_t* p_hid = &_hidh_itf[i]; if (p_hid->daddr == daddr) { TU_LOG_DRV(" HIDh close addr = %u index = %u\r\n", daddr, i); - if (tuh_hid_umount_cb) tuh_hid_umount_cb(daddr, i); + if (tuh_hid_umount_cb) { + tuh_hid_umount_cb(daddr, i); + } tu_memclr(p_hid, sizeof(hidh_interface_t)); } } diff --git a/src/host/hub.c b/src/host/hub.c index 0ed0e0c42..0b172a596 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -201,7 +201,6 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, bool hub_port_get_status_local(uint8_t hub_addr, uint8_t hub_port, hub_port_status_response_t* resp) { (void) hub_port; - TU_VERIFY(hub_addr > CFG_TUH_DEVICE_MAX); hub_interface_t* p_hub = get_hub_itf(hub_addr); *resp = p_hub->port_status; return true; diff --git a/src/host/usbh.c b/src/host/usbh.c index a3d79a105..8ab1402dc 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -579,7 +579,8 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const ep_dir = (uint8_t) tu_edpt_dir(ep_addr); - TU_LOG_USBH("on EP %02X with %u bytes: %s\r\n", ep_addr, (unsigned int) event.xfer_complete.len, tu_str_xfer_result[event.xfer_complete.result]); + TU_LOG_USBH("[:%u] on EP %02X with %u bytes: %s\r\n", + event.dev_addr, ep_addr, (unsigned int) event.xfer_complete.len, tu_str_xfer_result[event.xfer_complete.result]); if (event.dev_addr == 0) { // device 0 only has control endpoint @@ -618,7 +619,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { uint8_t drv_id = dev->ep2drv[epnum][ep_dir]; usbh_class_driver_t const* driver = get_driver(drv_id); if (driver) { - TU_LOG_USBH("%s xfer callback\r\n", driver->name); + TU_LOG_USBH(" %s xfer callback\r\n", driver->name); driver->xfer_cb(event.dev_addr, ep_addr, (xfer_result_t) event.xfer_complete.result, event.xfer_complete.len); } else { -- cgit v1.3.1 From fe4446090e5ab872faa973cae55839cf6929bf7e Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 13 May 2025 16:27:26 +0700 Subject: fix dual example for rp2350 conflict printf and cdc_printf --- examples/dual/host_hid_to_device_cdc/src/main.c | 8 +++-- examples/dual/host_info_to_device_cdc/src/main.c | 44 +++++++++++++----------- src/host/usbh.c | 6 ++-- 3 files changed, 33 insertions(+), 25 deletions(-) (limited to 'src/host') diff --git a/examples/dual/host_hid_to_device_cdc/src/main.c b/examples/dual/host_hid_to_device_cdc/src/main.c index 633f7a6ac..6f30ca381 100644 --- a/examples/dual/host_hid_to_device_cdc/src/main.c +++ b/examples/dual/host_hid_to_device_cdc/src/main.c @@ -190,7 +190,9 @@ void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) { // look up new key in previous keys static inline bool find_key_in_report(hid_keyboard_report_t const* report, uint8_t keycode) { for (uint8_t i = 0; i < 6; i++) { - if (report->keycode[i] == keycode) return true; + if (report->keycode[i] == keycode) { + return true; + } } return false; @@ -230,7 +232,9 @@ static void process_kbd_report(uint8_t dev_addr, hid_keyboard_report_t const* re // TODO example skips key released } - if (flush) tud_cdc_write_flush(); + if (flush) { + tud_cdc_write_flush(); + } prev_report = *report; } diff --git a/examples/dual/host_info_to_device_cdc/src/main.c b/examples/dual/host_info_to_device_cdc/src/main.c index 7e593f234..82a48fc61 100644 --- a/examples/dual/host_info_to_device_cdc/src/main.c +++ b/examples/dual/host_info_to_device_cdc/src/main.c @@ -78,6 +78,22 @@ static void print_device_info(uint8_t daddr, const tusb_desc_device_t* desc_devi void led_blinking_task(void); void cdc_task(void); +#define cdc_printf(...) \ + do { \ + char _tempbuf[256]; \ + char* _bufptr = _tempbuf; \ + uint32_t count = (uint32_t) sprintf(_tempbuf, __VA_ARGS__); \ + while (count > 0) { \ + uint32_t wr_count = tud_cdc_write(_bufptr, count); \ + count -= wr_count; \ + _bufptr += wr_count; \ + if (count > 0){ \ + tud_task(); \ + tud_cdc_write_flush(); \ + } \ + } \ + } while(0) + /*------------- MAIN -------------*/ int main(void) { board_init(); @@ -160,22 +176,6 @@ void cdc_task(void) { //--------------------------------------------------------------------+ // Host Get device information //--------------------------------------------------------------------+ -#define cdc_printf(...) \ - do { \ - char _tempbuf[256]; \ - char* _bufptr = _tempbuf; \ - uint32_t count = (uint32_t) sprintf(_tempbuf, __VA_ARGS__); \ - while (count > 0) { \ - uint32_t wr_count = tud_cdc_write(_bufptr, count); \ - count -= wr_count; \ - _bufptr += wr_count; \ - if (count > 0){ \ - tud_task();\ - tud_cdc_write_flush(); \ - } \ - } \ - } while(0) - static void print_device_info(uint8_t daddr, const tusb_desc_device_t* desc_device) { // Get String descriptor using Sync API uint16_t serial[64]; @@ -232,12 +232,12 @@ void tuh_enum_descriptor_device_cb(uint8_t daddr, tusb_desc_device_t const* desc } void tuh_mount_cb(uint8_t daddr) { - printf("mounted device %u\r\n", daddr); + cdc_printf("mounted device %u\r\n", daddr); is_print[daddr] = true; } void tuh_umount_cb(uint8_t daddr) { - printf("unmounted device %u\r\n", daddr); + cdc_printf("unmounted device %u\r\n", daddr); is_print[daddr] = false; } @@ -249,7 +249,9 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) return; // not enough time + if (board_millis() - start_ms < blink_interval_ms) { + return;// not enough time + } start_ms += blink_interval_ms; board_led_write(led_state); @@ -300,7 +302,9 @@ static int _count_utf8_bytes(const uint16_t *buf, size_t len) { } static void print_utf16(uint16_t *temp_buf, size_t buf_len) { - if ((temp_buf[0] & 0xff) == 0) return; // empty + if ((temp_buf[0] & 0xff) == 0) { + return;// empty + } size_t utf16_len = ((temp_buf[0] & 0xff) - 2) / sizeof(uint16_t); size_t utf8_len = (size_t) _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); diff --git a/src/host/usbh.c b/src/host/usbh.c index 8ab1402dc..b7d5a05f2 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -547,7 +547,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { // TODO better to have an separated queue for newly attached devices if (_usbh_data.enumerating_daddr == TUSB_INDEX_INVALID_8) { // New device attached and we are ready - TU_LOG1("[%u:] USBH Device Attach\r\n", event.rhport); + TU_LOG_USBH("[%u:] USBH Device Attach\r\n", event.rhport); _usbh_data.enumerating_daddr = 0; // enumerate new device with address 0 enum_new_device(&event); } else { @@ -562,7 +562,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { break; case HCD_EVENT_DEVICE_REMOVE: - TU_LOG1("[%u:%u:%u] USBH DEVICE REMOVED\r\n", event.rhport, event.connection.hub_addr, event.connection.hub_port); + TU_LOG_USBH("[%u:%u:%u] USBH DEVICE REMOVED\r\n", event.rhport, event.connection.hub_addr, event.connection.hub_port); if (_usbh_data.enumerating_daddr == 0 && event.rhport == _usbh_data.dev0_bus.rhport && event.connection.hub_addr == _usbh_data.dev0_bus.hub_addr && @@ -1464,7 +1464,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { bool retry = (_usbh_data.enumerating_daddr != TUSB_INDEX_INVALID_8) && (failed_count < ATTEMPT_COUNT_MAX); if (retry) { tusb_time_delay_ms_api(ATTEMPT_DELAY_MS); // delay a bit - TU_LOG1("Enumeration attempt %u/%u\r\n", failed_count+1, ATTEMPT_COUNT_MAX); + TU_LOG_USBH("Enumeration attempt %u/%u\r\n", failed_count+1, ATTEMPT_COUNT_MAX); retry = tuh_control_xfer(xfer); } -- cgit v1.3.1 From e41a63c60dbebd9579698e6444bc62cfa518e15c Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 21 May 2025 15:27:18 +0700 Subject: add usbh_spin_lock/unlock() use spinlock instead of atomic flag for hcd max3421 --- .../boards/adafruit_feather_esp32c6/board.cmake | 3 + .../boards/adafruit_feather_esp32c6/board.h | 56 ++++++++++++++++++ hw/bsp/espressif/boards/family.c | 2 + src/host/usbh.c | 13 ++++ src/host/usbh_pvt.h | 3 + src/portable/analog/max3421/hcd_max3421.c | 69 ++++++++++++++++------ 6 files changed, 129 insertions(+), 17 deletions(-) create mode 100644 hw/bsp/espressif/boards/adafruit_feather_esp32c6/board.cmake create mode 100644 hw/bsp/espressif/boards/adafruit_feather_esp32c6/board.h (limited to 'src/host') diff --git a/hw/bsp/espressif/boards/adafruit_feather_esp32c6/board.cmake b/hw/bsp/espressif/boards/adafruit_feather_esp32c6/board.cmake new file mode 100644 index 000000000..9adaefb17 --- /dev/null +++ b/hw/bsp/espressif/boards/adafruit_feather_esp32c6/board.cmake @@ -0,0 +1,3 @@ +# Apply board specific content here +set(IDF_TARGET "esp32c6") +set(MAX3421_HOST 1) diff --git a/hw/bsp/espressif/boards/adafruit_feather_esp32c6/board.h b/hw/bsp/espressif/boards/adafruit_feather_esp32c6/board.h new file mode 100644 index 000000000..18b51410d --- /dev/null +++ b/hw/bsp/espressif/boards/adafruit_feather_esp32c6/board.h @@ -0,0 +1,56 @@ +/* + * 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. + */ + +/* metadata: + name: Adafruit Feather EPS32-C6 + url: https://www.adafruit.com/product/5933 +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#define NEOPIXEL_PIN 15 + +#define BUTTON_PIN 9 +#define BUTTON_STATE_ACTIVE 0 + +// SPI for USB host shield +#define MAX3421_SPI_HOST SPI2_HOST +#define MAX3421_SCK_PIN 21 +#define MAX3421_MOSI_PIN 22 +#define MAX3421_MISO_PIN 23 +#define MAX3421_CS_PIN 8 +#define MAX3421_INTR_PIN 7 + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/espressif/boards/family.c b/hw/bsp/espressif/boards/family.c index cf11e2441..8f6c4bee2 100644 --- a/hw/bsp/espressif/boards/family.c +++ b/hw/bsp/espressif/boards/family.c @@ -49,7 +49,9 @@ static led_strip_handle_t led_strip; static void max3421_init(void); #endif +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_ESP32P4) static bool usb_init(void); +#endif //--------------------------------------------------------------------+ // Implementation diff --git a/src/host/usbh.c b/src/host/usbh.c index b7d5a05f2..f2e5c1f0e 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -147,6 +147,9 @@ static osal_mutex_t _usbh_mutex; #define _usbh_mutex NULL #endif +// Spinlock for interrupt handler +static OSAL_SPINLOCK_DEF(_usbh_spin, usbh_int_set); + // Event queue: 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; @@ -424,6 +427,8 @@ bool tuh_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { TU_LOG_INT_USBH(sizeof(tu_fifo_t)); TU_LOG_INT_USBH(sizeof(tu_edpt_stream_t)); + osal_spin_init(&_usbh_spin); + // Event queue _usbh_q = osal_queue_create(&_usbh_qdef); TU_ASSERT(_usbh_q != NULL); @@ -895,6 +900,14 @@ void usbh_int_set(bool enabled) { } } +void usbh_spin_lock(bool in_isr) { + osal_spin_lock(&_usbh_spin, in_isr); +} + +void usbh_spin_unlock(bool in_isr) { + osal_spin_unlock(&_usbh_spin, in_isr); +} + void usbh_defer_func(osal_task_func_t func, void *param, bool in_isr) { hcd_event_t event = { 0 }; event.event_id = USBH_EVENT_FUNC_CALL; diff --git a/src/host/usbh_pvt.h b/src/host/usbh_pvt.h index 61b012493..cb092e5f3 100644 --- a/src/host/usbh_pvt.h +++ b/src/host/usbh_pvt.h @@ -71,6 +71,9 @@ void usbh_int_set(bool enabled); void usbh_defer_func(osal_task_func_t func, void *param, bool in_isr); +void usbh_spin_lock(bool in_isr); +void usbh_spin_unlock(bool in_isr); + //--------------------------------------------------------------------+ // USBH Endpoint API //--------------------------------------------------------------------+ diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index bb33200f2..971dbd62e 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -28,9 +28,9 @@ #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 -#include #include "host/hcd.h" #include "host/usbh.h" +#include "host/usbh_pvt.h" //--------------------------------------------------------------------+ // @@ -233,7 +233,7 @@ typedef struct { uint8_t hxfr; }sndfifo_owner; - atomic_flag busy; // busy transferring + bool busy_lock; // busy transferring #if OSAL_MUTEX_REQUIRED OSAL_MUTEX_DEF(spi_mutexdef); @@ -327,7 +327,9 @@ TU_ATTR_ALWAYS_INLINE static inline void mode_write(uint8_t rhport, uint8_t data } TU_ATTR_ALWAYS_INLINE static inline void peraddr_write(uint8_t rhport, uint8_t data, bool in_isr) { - if ( _hcd_data.peraddr == data ) return; // no need to change address + if (_hcd_data.peraddr == data) { + return; // no need to change address + } _hcd_data.peraddr = data; reg_write(rhport, PERADDR_ADDR, data, in_isr); @@ -373,7 +375,7 @@ TU_ATTR_ALWAYS_INLINE static inline void hwfifo_setup(uint8_t rhport, const uint static void hwfifo_receive(uint8_t rhport, uint8_t * buffer, uint16_t len, bool in_isr) { uint8_t hirq; - uint8_t const reg = RCVVFIFO_ADDR; + const uint8_t reg = RCVVFIFO_ADDR; max3421_spi_lock(rhport, in_isr); @@ -389,7 +391,7 @@ static void hwfifo_receive(uint8_t rhport, uint8_t * buffer, uint16_t len, bool //--------------------------------------------------------------------+ static max3421_ep_t* find_ep_not_addr0(uint8_t daddr, uint8_t ep_num, uint8_t ep_dir) { - uint8_t const is_out = 1-ep_dir; + const uint8_t is_out = 1-ep_dir; for(size_t i=1; ixferred_len = 0; ep->state = EP_STATE_ATTEMPT_1; + bool has_xfer = false; + + usbh_spin_lock(false); + if (!_hcd_data.busy_lock) { + _hcd_data.busy_lock = true; + has_xfer = true; + } + usbh_spin_unlock(false); + // carry out transfer if not busy - if (!atomic_flag_test_and_set(&_hcd_data.busy)) { + if (has_xfer) { xact_generic(rhport, ep, true, false); } @@ -781,8 +792,17 @@ bool hcd_setup_send(uint8_t rhport, uint8_t daddr, uint8_t const setup_packet[8] ep->xferred_len = 0; ep->state = EP_STATE_ATTEMPT_1; + bool has_xfer = false; + + usbh_spin_lock(false); + if (!_hcd_data.busy_lock) { + _hcd_data.busy_lock = true; + has_xfer = true; + } + usbh_spin_unlock(false); + // carry out transfer if not busy - if (!atomic_flag_test_and_set(&_hcd_data.busy)) { + if (has_xfer) { xact_setup(rhport, ep, false); } @@ -848,8 +868,8 @@ static void handle_connect_irq(uint8_t rhport, bool in_isr) { } static void xfer_complete_isr(uint8_t rhport, max3421_ep_t *ep, xfer_result_t result, uint8_t hrsl, bool in_isr) { - uint8_t const ep_dir = 1-ep->hxfr_bm.is_out; - uint8_t const ep_addr = tu_edpt_addr(ep->hxfr_bm.ep_num, ep_dir); + const uint8_t ep_dir = 1 - ep->hxfr_bm.is_out; + const uint8_t ep_addr = tu_edpt_addr(ep->hxfr_bm.ep_num, ep_dir); // save data toggle if (ep_dir) { @@ -867,7 +887,9 @@ static void xfer_complete_isr(uint8_t rhport, max3421_ep_t *ep, xfer_result_t re xact_generic(rhport, next_ep, true, in_isr); }else { // no more pending - atomic_flag_clear(&_hcd_data.busy); + usbh_spin_lock(in_isr); + _hcd_data.busy_lock = false; + usbh_spin_unlock(in_isr); } } @@ -906,7 +928,9 @@ static void handle_xfer_done(uint8_t rhport, bool in_isr) { xact_generic(rhport, next_ep, true, in_isr); } else { // no more pending in this frame -> clear busy - atomic_flag_clear(&_hcd_data.busy); + usbh_spin_lock(in_isr); + _hcd_data.busy_lock = false; + usbh_spin_unlock(in_isr); } return; @@ -997,8 +1021,8 @@ void print_hirq(uint8_t hirq) { // Interrupt handler void hcd_int_handler(uint8_t rhport, bool in_isr) { uint8_t hirq = reg_read(rhport, HIRQ_ADDR, in_isr) & _hcd_data.hien; - if (!hirq) return; -// print_hirq(hirq); + if (!hirq) { return; } + // print_hirq(hirq); if (hirq & HIRQ_FRAME_IRQ) { _hcd_data.frame_count++; @@ -1017,8 +1041,19 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { } // start usb transfer if not busy - if (ep_retry != NULL && !atomic_flag_test_and_set(&_hcd_data.busy)) { - xact_generic(rhport, ep_retry, true, in_isr); + if (ep_retry != NULL) { + bool has_xfer = false; + + usbh_spin_lock(in_isr); + if (!_hcd_data.busy_lock) { + _hcd_data.busy_lock = true; + has_xfer = true; + } + usbh_spin_unlock(in_isr); + + if (has_xfer) { + xact_generic(rhport, ep_retry, true, in_isr); + } } } -- cgit v1.3.1 From d533650105c3d41e77a063869175cc56f5ef0461 Mon Sep 17 00:00:00 2001 From: Cédric Berger Date: Mon, 9 Jun 2025 16:56:02 +0200 Subject: Fix TUH_EPSIZE_BULK_MPS macro TUH_EPSIZE_BULK_MPS should be set based on TUH_OPT_HIGH_SPEED, not TUD_OPT_HIGH_SPEED --- src/host/usbh.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/host') diff --git a/src/host/usbh.h b/src/host/usbh.h index 6f34d8bb3..13eede869 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -42,7 +42,7 @@ //--------------------------------------------------------------------+ // Endpoint Bulk size depending on host mx speed -#define TUH_EPSIZE_BULK_MPS (TUD_OPT_HIGH_SPEED ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS) +#define TUH_EPSIZE_BULK_MPS (TUH_OPT_HIGH_SPEED ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS) // forward declaration struct tuh_xfer_s; -- cgit v1.3.1 From 9503883ba7f99523a14082ce68a5f900585747b0 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 18 Jun 2025 23:35:44 +0700 Subject: usbh: add new API tuh_descriptor_get_device_local() cdc host: remove the local desc_dev and the get_device descriptor call for ftdi and pl2303 --- src/class/cdc/cdc_host.c | 141 +++++++++++++++-------------------------------- src/common/tusb_types.h | 1 - src/host/usbh.c | 58 ++++++++++++++----- src/host/usbh.h | 3 + 4 files changed, 91 insertions(+), 112 deletions(-) (limited to 'src/host') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 3be61e654..d704d82d7 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -123,10 +123,6 @@ typedef struct { static cdch_interface_t cdch_data[CFG_TUH_CDC]; CFG_TUH_MEM_SECTION static cdch_epbuf_t cdch_epbuf[CFG_TUH_CDC]; -#if CFG_TUH_CDC_FTDI || CFG_TUH_CDC_PL2303 - static tusb_desc_device_t desc_dev[CFG_TUH_ENUMERATION_BUFSIZE]; -#endif - //--------------------------------------------------------------------+ // Serial Driver //--------------------------------------------------------------------+ @@ -189,8 +185,6 @@ static bool ch34x_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complet static uint16_t const pl2303_vid_pid_list[][2] = {CFG_TUH_CDC_PL2303_VID_PID_LIST}; static const struct pl2303_type_data pl2303_type_data[TYPE_COUNT] = {PL2303_TYPE_DATA}; -CFG_TUH_MEM_SECTION CFG_TUH_MEM_ALIGN - static bool pl2303_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); static bool pl2303_process_set_config(tuh_xfer_t *xfer); @@ -331,7 +325,7 @@ TU_ATTR_ALWAYS_INLINE static inline cdch_interface_t * get_itf(uint8_t idx) { } TU_ATTR_ALWAYS_INLINE static inline uint8_t get_idx_by_ptr(cdch_interface_t* p_cdc) { - return p_cdc - cdch_data; + return (uint8_t) (p_cdc - cdch_data); } static inline uint8_t get_idx_by_ep_addr(uint8_t daddr, uint8_t ep_addr) { @@ -434,7 +428,7 @@ bool tuh_cdc_itf_get_info(uint8_t idx, tuh_itf_info_t * info) { info->daddr = p_cdc->daddr; - // re-construct descriptor + // re-construct interface descriptor tusb_desc_interface_t * desc = &info->desc; desc->bLength = sizeof(tusb_desc_interface_t); desc->bDescriptorType = TUSB_DESC_INTERFACE; @@ -975,8 +969,6 @@ bool cdch_set_config(uint8_t daddr, uint8_t itf_num) { // ACM //--------------------------------------------------------------------+ -//------------- Driver API -------------// - // internal control complete to update state such as line state, encoding static void acm_internal_control_complete(tuh_xfer_t *xfer) { uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); @@ -1089,7 +1081,6 @@ static bool acm_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, } //------------- Enumeration -------------// - enum { CONFIG_ACM_SET_CONTROL_LINE_STATE = 0, CONFIG_ACM_SET_LINE_CODING, @@ -1339,8 +1330,7 @@ static bool ftdi_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_ //------------- Enumeration -------------// enum { - CONFIG_FTDI_GET_DESC = 0, - CONFIG_FTDI_DETERMINE_TYPE, + CONFIG_FTDI_DETERMINE_TYPE = 0, CONFIG_FTDI_WRITE_LATENCY, CONFIG_FTDI_SIO_RESET, CONFIG_FTDI_SET_DATA, @@ -1383,15 +1373,6 @@ static bool ftdi_proccess_set_config(tuh_xfer_t *xfer) { switch (state) { // from here sequence overtaken from Linux Kernel function ftdi_port_probe() - case CONFIG_FTDI_GET_DESC: - // get device descriptor - if (itf_num == 0) { // only necessary for 1st interface. other interface overtake type from interface 0 - TU_ASSERT(tuh_descriptor_get_device(xfer->daddr, &desc_dev, sizeof(tusb_desc_device_t), - cdch_process_set_config, CONFIG_FTDI_DETERMINE_TYPE)); - break; - } - TU_ATTR_FALLTHROUGH; - case CONFIG_FTDI_DETERMINE_TYPE: // determine type if (itf_num == 0) { @@ -1472,7 +1453,9 @@ static bool ftdi_proccess_set_config(tuh_xfer_t *xfer) { //------------- Helper -------------// static bool ftdi_determine_type(cdch_interface_t *p_cdc) { - uint16_t const version = desc_dev->bcdDevice; + tusb_desc_device_t desc_dev; + TU_VERIFY(tuh_descriptor_get_device_local(p_cdc->daddr, &desc_dev)); + uint16_t const version = desc_dev.bcdDevice; uint8_t const itf_num = p_cdc->bInterfaceNumber; p_cdc->ftdi.chip_type = UNKNOWN; @@ -1482,8 +1465,7 @@ static bool ftdi_determine_type(cdch_interface_t *p_cdc) { switch (version) { case 0x200: - // FT232A not supported to keep it simple (no extra _read_latency_timer()) - // not testable + // FT232A not supported to keep it simple (no extra _read_latency_timer()) not testable // p_cdc->ftdi.chip_type = FT232A; // p_cdc->ftdi.baud_base = 48000000 / 2; // p_cdc->ftdi.channel = 0; @@ -1497,50 +1479,20 @@ static bool ftdi_determine_type(cdch_interface_t *p_cdc) { // p_cdc->ftdi.chip_type = FT232B; // } break; - case 0x400: - p_cdc->ftdi.chip_type = FT232B; - p_cdc->ftdi.channel = 0; - break; - case 0x500: - p_cdc->ftdi.chip_type = FT2232C; - break; - case 0x600: - p_cdc->ftdi.chip_type = FT232R; - p_cdc->ftdi.channel = 0; - break; - case 0x700: - p_cdc->ftdi.chip_type = FT2232H; - break; - case 0x800: - p_cdc->ftdi.chip_type = FT4232H; - break; - case 0x900: - p_cdc->ftdi.chip_type = FT232H; - break; - case 0x1000: - p_cdc->ftdi.chip_type = FTX; - break; - case 0x2800: - p_cdc->ftdi.chip_type = FT2233HP; - break; - case 0x2900: - p_cdc->ftdi.chip_type = FT4233HP; - break; - case 0x3000: - p_cdc->ftdi.chip_type = FT2232HP; - break; - case 0x3100: - p_cdc->ftdi.chip_type = FT4232HP; - break; - case 0x3200: - p_cdc->ftdi.chip_type = FT233HP; - break; - case 0x3300: - p_cdc->ftdi.chip_type = FT232HP; - break; - case 0x3600: - p_cdc->ftdi.chip_type = FT4232HA; - break; + case 0x400: p_cdc->ftdi.chip_type = FT232B; p_cdc->ftdi.channel = 0; break; + case 0x500: p_cdc->ftdi.chip_type = FT2232C; break; + case 0x600: p_cdc->ftdi.chip_type = FT232R; p_cdc->ftdi.channel = 0; break; + case 0x700: p_cdc->ftdi.chip_type = FT2232H; break; + case 0x800: p_cdc->ftdi.chip_type = FT4232H; break; + case 0x900: p_cdc->ftdi.chip_type = FT232H; break; + case 0x1000: p_cdc->ftdi.chip_type = FTX; break; + case 0x2800: p_cdc->ftdi.chip_type = FT2233HP; break; + case 0x2900: p_cdc->ftdi.chip_type = FT4233HP; break; + case 0x3000: p_cdc->ftdi.chip_type = FT2232HP; break; + case 0x3100: p_cdc->ftdi.chip_type = FT4232HP; break; + case 0x3200: p_cdc->ftdi.chip_type = FT233HP; break; + case 0x3300: p_cdc->ftdi.chip_type = FT232HP; break; + case 0x3600: p_cdc->ftdi.chip_type = FT4232HA; break; default: if (version < 0x200) { p_cdc->ftdi.chip_type = SIO; @@ -1550,7 +1502,7 @@ static bool ftdi_determine_type(cdch_interface_t *p_cdc) { } TU_LOG_P_CDC("%s detected (bcdDevice = 0x%04x)", - ftdi_chip_name[p_cdc->ftdi.chip_type], desc_dev->bcdDevice); + ftdi_chip_name[p_cdc->ftdi.chip_type], version); return (p_cdc->ftdi.chip_type != UNKNOWN); } @@ -2025,7 +1977,8 @@ static bool ch34x_write_reg_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t comp } static bool ch34x_modem_ctrl_request(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - uint8_t control = ~((p_cdc->requested_line_state.rts ? CH34X_BIT_RTS : 0) |// CH34x signals are inverted + // CH34x signals are inverted + uint8_t control = ~((p_cdc->requested_line_state.rts ? CH34X_BIT_RTS : 0) | (p_cdc->requested_line_state.dtr ? CH34X_BIT_DTR : 0)); return ch34x_control_out(p_cdc, CH34X_REQ_MODEM_CTRL, control, 0, complete_cb, user_data); } @@ -2506,8 +2459,7 @@ static bool pl2303_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complet //------------- Enumeration -------------// enum { - CONFIG_PL2303_GET_DESC = 0, - CONFIG_PL2303_DETECT_TYPE, + CONFIG_PL2303_DETECT_TYPE = 0, CONFIG_PL2303_READ1, CONFIG_PL2303_WRITE1, CONFIG_PL2303_READ2, @@ -2568,14 +2520,8 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { TU_ASSERT(p_cdc && (xfer->result == XFER_RESULT_SUCCESS || xfer->user_data == CONFIG_PL2303_READ1)); switch (state) { // from here sequence overtaken from Linux Kernel function pl2303_startup() - case CONFIG_PL2303_GET_DESC: - p_cdc->user_control_cb = cdch_process_set_config;// set once for whole process config - // get device descriptor - TU_ASSERT(tuh_descriptor_get_device(xfer->daddr, &desc_dev, sizeof(tusb_desc_device_t), - cdch_process_set_config, CONFIG_PL2303_DETECT_TYPE)); - break; - case CONFIG_PL2303_DETECT_TYPE: + p_cdc->user_control_cb = cdch_process_set_config;// set once for whole process config // get type and quirks (step 1) type = pl2303_detect_type(p_cdc, 1, cdch_process_set_config, CONFIG_PL2303_READ1); TU_ASSERT(type != PL2303_DETECT_TYPE_FAILED); @@ -2784,39 +2730,39 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { static int8_t pl2303_detect_type(cdch_interface_t *p_cdc, uint8_t step, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - /* - * Legacy PL2303H, variants 0 and 1 (difference unknown). - */ - if (desc_dev->bDeviceClass == 0x02) { + tusb_desc_device_t desc_dev; + TU_VERIFY(tuh_descriptor_get_device_local(p_cdc->daddr, &desc_dev), PL2303_DETECT_TYPE_FAILED); + + // Legacy PL2303H, variants 0 and 1 (difference unknown). + if (desc_dev.bDeviceClass == 0x02) { return TYPE_H; /* variant 0 */ } - if (desc_dev->bMaxPacketSize0 != 0x40) { - if (desc_dev->bDeviceClass == 0x00 || desc_dev->bDeviceClass == 0xff) { + if (desc_dev.bMaxPacketSize0 != 0x40) { + if (desc_dev.bDeviceClass == 0x00 || desc_dev.bDeviceClass == 0xff) { return TYPE_H; /* variant 1 */ } return TYPE_H; /* variant 0 */ } - switch (desc_dev->bcdUSB) { + switch (desc_dev.bcdUSB) { case 0x101: /* USB 1.0.1? Let's assume they meant 1.1... */ TU_ATTR_FALLTHROUGH; case 0x110: - switch (desc_dev->bcdDevice) { - case 0x300: - return TYPE_HX; - case 0x400: - return TYPE_HXD; - default: - return TYPE_HX; + switch (desc_dev.bcdDevice) { + case 0x300: return TYPE_HX; + case 0x400: return TYPE_HXD; + default: return TYPE_HX; } break; + case 0x200: - switch (desc_dev->bcdDevice) { + switch (desc_dev.bcdDevice) { case 0x100: /* GC */ case 0x105: return TYPE_HXN; + case 0x300: /* GT / TA */ if (step == 1) { // step 1 trigger pl2303_supports_hx_status() request @@ -2833,6 +2779,7 @@ static int8_t pl2303_detect_type(cdch_interface_t *p_cdc, uint8_t step, case 0x400: /* GL */ case 0x405: return TYPE_HXN; + case 0x500: /* GE / TB */ if (step == 1) { // step 1 trigger pl2303_supports_hx_status() request @@ -2851,6 +2798,7 @@ static int8_t pl2303_detect_type(cdch_interface_t *p_cdc, uint8_t step, case 0x700: /* GR */ case 0x705: return TYPE_HXN; + default: break; } @@ -2858,8 +2806,7 @@ static int8_t pl2303_detect_type(cdch_interface_t *p_cdc, uint8_t step, default: break; } - TU_LOG_P_CDC("unknown device type bcdUSB = 0x%04x", desc_dev->bcdUSB); - + TU_LOG_P_CDC("unknown device type bcdUSB = 0x%04x", desc_dev.bcdUSB); return PL2303_DETECT_TYPE_FAILED; } diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index fd7f01b67..ff5d8b66a 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -345,7 +345,6 @@ typedef struct TU_ATTR_PACKED { uint8_t iManufacturer ; ///< Index of string descriptor describing manufacturer. uint8_t iProduct ; ///< Index of string descriptor describing product. uint8_t iSerialNumber ; ///< Index of string descriptor describing the device's serial number. - uint8_t bNumConfigurations ; ///< Number of possible configurations. } tusb_desc_device_t; diff --git a/src/host/usbh.c b/src/host/usbh.c index f2e5c1f0e..08c362171 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -94,26 +94,28 @@ TU_ATTR_WEAK bool hcd_dcache_clean_invalidate(const void* addr, uint32_t data_si typedef struct { tuh_bus_info_t bus_info; - // Device State - struct TU_ATTR_PACKED { - volatile uint8_t connected : 1; // After 1st transfer - volatile uint8_t addressed : 1; // After SET_ADDR - volatile uint8_t configured : 1; // After SET_CONFIG and all drivers are configured - volatile uint8_t suspended : 1; // Bus suspended - // volatile uint8_t removing : 1; // Physically disconnected, waiting to be processed by usbh - }; - // Device Descriptor - uint8_t ep0_size; + uint16_t bcdUSB; + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bMaxPacketSize0; uint16_t idVendor; uint16_t idProduct; + uint16_t bcdDevice; uint8_t iManufacturer; uint8_t iProduct; uint8_t iSerialNumber; uint8_t bNumConfigurations; - // Configuration Descriptor - // uint8_t interface_count; // bNumInterfaces alias + // Device State + struct TU_ATTR_PACKED { + volatile uint8_t connected : 1; // After 1st transfer + volatile uint8_t addressed : 1; // After SET_ADDR + volatile uint8_t configured : 1; // After SET_CONFIG and all drivers are configured + volatile uint8_t suspended : 1; // Bus suspended + // volatile uint8_t removing : 1; // Physically disconnected, waiting to be processed by usbh + }; // Endpoint & Interface uint8_t itf2drv[CFG_TUH_INTERFACE_MAX]; // map interface number to driver (0xff is invalid) @@ -373,6 +375,28 @@ bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t *vid, uint16_t *pid) { return true; } +bool tuh_descriptor_get_device_local(uint8_t daddr, tusb_desc_device_t* desc_device) { + usbh_device_t *dev = get_device(daddr); + TU_VERIFY(dev && desc_device); + + desc_device->bLength = sizeof(tusb_desc_device_t); + desc_device->bDescriptorType = TUSB_DESC_DEVICE; + desc_device->bcdUSB = dev->bcdUSB; + desc_device->bDeviceClass = dev->bDeviceClass; + desc_device->bDeviceSubClass = dev->bDeviceSubClass; + desc_device->bDeviceProtocol = dev->bDeviceProtocol; + desc_device->bMaxPacketSize0 = dev->bMaxPacketSize0; + desc_device->idVendor = dev->idVendor; + desc_device->idProduct = dev->idProduct; + desc_device->bcdDevice = dev->bcdDevice; + desc_device->iManufacturer = dev->iManufacturer; + desc_device->iProduct = dev->iProduct; + desc_device->iSerialNumber = dev->iSerialNumber; + desc_device->bNumConfigurations = dev->bNumConfigurations; + + return true; +} + tusb_speed_t tuh_speed_get(uint8_t daddr) { tuh_bus_info_t bus_info; tuh_bus_info_get(daddr, &bus_info); @@ -1579,7 +1603,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { usbh_device_t* new_dev = get_device(new_addr); new_dev->bus_info = *dev0_bus; new_dev->connected = 1; - new_dev->ep0_size = desc_device->bMaxPacketSize0; + new_dev->bMaxPacketSize0 = desc_device->bMaxPacketSize0; TU_ASSERT(tuh_address_set(0, new_addr, process_enumeration, ENUM_GET_DEVICE_DESC),); break; @@ -1596,7 +1620,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { usbh_device_close(dev0_bus->rhport, 0); // close dev0 - TU_ASSERT(usbh_edpt_control_open(new_addr, new_dev->ep0_size),); // open new control endpoint + TU_ASSERT(usbh_edpt_control_open(new_addr, new_dev->bMaxPacketSize0),); // open new control endpoint TU_LOG_USBH("Get Device Descriptor\r\n"); TU_ASSERT(tuh_descriptor_get_device(new_addr, _usbh_epbuf.ctrl, sizeof(tusb_desc_device_t), @@ -1609,8 +1633,14 @@ static void process_enumeration(tuh_xfer_t* xfer) { case ENUM_GET_STRING_LANGUAGE_ID_LEN: { // save the received device descriptor tusb_desc_device_t const *desc_device = (tusb_desc_device_t const *) _usbh_epbuf.ctrl; + dev->bcdUSB = desc_device->bcdUSB; + dev->bDeviceClass = desc_device->bDeviceClass; + dev->bDeviceSubClass = desc_device->bDeviceSubClass; + dev->bDeviceProtocol = desc_device->bDeviceProtocol; + dev->bMaxPacketSize0 = desc_device->bMaxPacketSize0; dev->idVendor = desc_device->idVendor; dev->idProduct = desc_device->idProduct; + dev->bcdDevice = desc_device->bcdDevice; dev->iManufacturer = desc_device->iManufacturer; dev->iProduct = desc_device->iProduct; dev->iSerialNumber = desc_device->iSerialNumber; diff --git a/src/host/usbh.h b/src/host/usbh.h index 13eede869..1ee511722 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -204,6 +204,9 @@ bool tuh_rhport_reset_bus(uint8_t rhport, bool active); // Get VID/PID of device bool tuh_vid_pid_get(uint8_t daddr, uint16_t* vid, uint16_t* pid); +// Get local (cached) device descriptor once device is enumerated +bool tuh_descriptor_get_device_local(uint8_t daddr, tusb_desc_device_t* desc_device); + // Get speed of device tusb_speed_t tuh_speed_get(uint8_t daddr); -- cgit v1.3.1 From 5c974cee23e9ece208df43b60070740fc2eda0c3 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Jun 2025 12:51:29 +0700 Subject: usbh make TU_API_SYNC() public, to implement sync() API, change return of sync API from uint8_t to tusb_xfer_result_t --- src/common/tusb_types.h | 2 ++ src/host/usbh.c | 47 ++----------------------------- src/host/usbh.h | 73 +++++++++++++++++++++++++++++++------------------ 3 files changed, 51 insertions(+), 71 deletions(-) (limited to 'src/host') diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index ff5d8b66a..ec7aad796 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -278,6 +278,8 @@ typedef enum { XFER_RESULT_INVALID } xfer_result_t; +#define tusb_xfer_result_t xfer_result_t + // TODO remove enum { DESC_OFFSET_LEN = 0, diff --git a/src/host/usbh.c b/src/host/usbh.c index 08c362171..adaeef092 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1092,8 +1092,9 @@ TU_ATTR_FAST_FUNC void hcd_event_handler(hcd_event_t const* event, bool in_isr) // generic helper to get a descriptor // if blocking, user_data is 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) { +TU_ATTR_ALWAYS_INLINE static inline +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) { tusb_control_request_t const request = { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, @@ -1134,7 +1135,6 @@ 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_xfer_cb_t complete_cb, uintptr_t user_data) { return _get_descriptor(daddr, TUSB_DESC_STRING, index, language_id, buffer, len, complete_cb, user_data); @@ -1272,47 +1272,6 @@ bool tuh_interface_set(uint8_t daddr, uint8_t itf_num, uint8_t itf_alt, return tuh_control_xfer(&xfer); } -//--------------------------------------------------------------------+ -// Descriptor Sync -//--------------------------------------------------------------------+ - -#define _CONTROL_SYNC_API(_async_func, ...) \ - xfer_result_t result = XFER_RESULT_INVALID;\ - 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) { - _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) { - _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) { - _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) { - _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) { - _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) { - _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) { - _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) { - _CONTROL_SYNC_API(tuh_descriptor_get_serial_string, daddr, language_id, buffer, len); -} - //--------------------------------------------------------------------+ // Detaching //--------------------------------------------------------------------+ diff --git a/src/host/usbh.h b/src/host/usbh.h index 1ee511722..1e9bb26bc 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -234,8 +234,18 @@ bool tuh_bus_info_get(uint8_t daddr, tuh_bus_info_t* bus_info); //--------------------------------------------------------------------+ // Transfer API +// Each Function will make a USB transfer request to device. If +// - complete_cb != NULL, the function will return immediately and invoke the callback when request is complete. +// - complete_cb == NULL, the function will block until request is complete. +// In this case, user_data should be tusb_xfer_result_t* to hold the transfer result. //--------------------------------------------------------------------+ +// Helper to make Sync API from async one +#define TU_API_SYNC(_async_api, ...) \ + xfer_result_t result = XFER_RESULT_INVALID;\ + TU_VERIFY(_async_api(__VA_ARGS__, NULL, (uintptr_t) &result), XFER_RESULT_TIMEOUT); \ + return result + // Submit a control transfer // - async: complete callback invoked when finished. // - sync : blocking if complete callback is NULL. @@ -327,45 +337,54 @@ bool tuh_descriptor_get_serial_string(uint8_t daddr, uint16_t language_id, void* //--------------------------------------------------------------------+ // Descriptors Synchronous (blocking) +// Sync API which is blocking until transfer is complete. +// return transfer result //--------------------------------------------------------------------+ -// 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); +// Sync version of tuh_descriptor_get() +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_descriptor_get_sync(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len) { + TU_API_SYNC(tuh_descriptor_get, daddr, type, index, buffer, 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); +// Sync version of tuh_descriptor_get_device() +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_descriptor_get_device_sync(uint8_t daddr, void* buffer, uint16_t len) { + TU_API_SYNC(tuh_descriptor_get_device, daddr, buffer, 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); +// Sync version of tuh_descriptor_get_configuration() +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_descriptor_get_configuration_sync(uint8_t daddr, uint8_t index, void* buffer, uint16_t len) { + TU_API_SYNC(tuh_descriptor_get_configuration, daddr, index, buffer, 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); +// Sync version of tuh_descriptor_get_hid_report() +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_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) { + TU_API_SYNC(tuh_descriptor_get_hid_report, daddr, itf_num, desc_type, index, buffer, 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); +// Sync version of tuh_descriptor_get_string() +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_descriptor_get_string_sync(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len) { + TU_API_SYNC(tuh_descriptor_get_string, daddr, index, language_id, buffer, len); +} -// Sync (blocking) version of tuh_descriptor_get_string_langid() -TU_ATTR_ALWAYS_INLINE static inline -uint8_t tuh_descriptor_get_string_langid_sync(uint8_t daddr, void* buffer, uint16_t len) { +// Sync version of tuh_descriptor_get_string_langid() +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_descriptor_get_string_langid_sync(uint8_t daddr, void* buffer, uint16_t len) { return tuh_descriptor_get_string_sync(daddr, 0, 0, buffer, 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); +// Sync version of tuh_descriptor_get_manufacturer_string() +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_descriptor_get_manufacturer_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len) { + TU_API_SYNC(tuh_descriptor_get_manufacturer_string, daddr, language_id, buffer, 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); +// Sync version of tuh_descriptor_get_product_string() +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_descriptor_get_product_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len) { + TU_API_SYNC(tuh_descriptor_get_product_string, daddr, language_id, buffer, 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); +// Sync version of tuh_descriptor_get_serial_string() +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len) { + TU_API_SYNC(tuh_descriptor_get_serial_string, daddr, language_id, buffer, len); +} #ifdef __cplusplus } -- cgit v1.3.1