From 74bd2647589790b3bee49146774133c2061a34fe Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 22 Mar 2024 11:42:33 +0700 Subject: adding deinit() stub for usbh/hcd class driver add TUSB_VERSION_BUILD, also add TUSB_VERSION_NUMBER --- src/host/hcd.h | 3 +++ src/host/hub.c | 7 +++++-- src/host/hub.h | 1 + src/host/usbh.c | 55 +++++++++++++++++++++++++++++++++++++++-------------- src/host/usbh.h | 4 ++++ src/host/usbh_pvt.h | 4 +--- 6 files changed, 55 insertions(+), 19 deletions(-) (limited to 'src/host') diff --git a/src/host/hcd.h b/src/host/hcd.h index 2bde289df..d5804c608 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -130,6 +130,9 @@ bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) TU_AT // Initialize controller to host mode bool hcd_init(uint8_t rhport); +// De-initialize controller +bool hcd_deinit(uint8_t rhport); + // Interrupt Handler void hcd_int_handler(uint8_t rhport, bool in_isr); diff --git a/src/host/hub.c b/src/host/hub.c index 3bac18698..0853ff27a 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -182,11 +182,14 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, //--------------------------------------------------------------------+ // CLASS-USBH API (don't require to verify parameters) //--------------------------------------------------------------------+ -void hub_init(void) -{ +void hub_init(void) { tu_memclr(hub_data, sizeof(hub_data)); } +bool hub_deinit(void) { + return true; +} + bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { (void) rhport; diff --git a/src/host/hub.h b/src/host/hub.h index 390740e1f..c3f4a3612 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -205,6 +205,7 @@ static inline bool hub_port_clear_reset_change(uint8_t hub_addr, uint8_t hub_por // Internal Class Driver API //--------------------------------------------------------------------+ void hub_init (void); +bool hub_deinit (void); bool hub_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); bool hub_set_config (uint8_t dev_addr, uint8_t itf_num); bool hub_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); diff --git a/src/host/usbh.c b/src/host/usbh.c index 625857683..cf348bbb2 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -45,8 +45,13 @@ #endif //--------------------------------------------------------------------+ -// Callback weak stubs (called if application does not provide) +// Weak stubs: invoked if no strong implementation is available //--------------------------------------------------------------------+ +TU_ATTR_WEAK bool hcd_deinit(uint8_t rhport) { + (void) rhport; + return false; +} + TU_ATTR_WEAK void tuh_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr) { (void) rhport; (void) eventid; @@ -119,16 +124,17 @@ typedef struct { // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ #if CFG_TUSB_DEBUG >= CFG_TUH_LOG_LEVEL - #define DRIVER_NAME(_name) .name = _name, + #define DRIVER_NAME(_name) _name #else - #define DRIVER_NAME(_name) + #define DRIVER_NAME(_name) NULL #endif static usbh_class_driver_t const usbh_class_drivers[] = { #if CFG_TUH_CDC { - DRIVER_NAME("CDC") + .name = DRIVER_NAME("CDC"), .init = cdch_init, + .deinit = cdch_deinit, .open = cdch_open, .set_config = cdch_set_config, .xfer_cb = cdch_xfer_cb, @@ -138,8 +144,9 @@ static usbh_class_driver_t const usbh_class_drivers[] = { #if CFG_TUH_MSC { - DRIVER_NAME("MSC") + .name = DRIVER_NAME("MSC"), .init = msch_init, + .deinit = msch_deinit, .open = msch_open, .set_config = msch_set_config, .xfer_cb = msch_xfer_cb, @@ -149,8 +156,9 @@ static usbh_class_driver_t const usbh_class_drivers[] = { #if CFG_TUH_HID { - DRIVER_NAME("HID") + .name = DRIVER_NAME("HID"), .init = hidh_init, + .deinit = hidh_deinit, .open = hidh_open, .set_config = hidh_set_config, .xfer_cb = hidh_xfer_cb, @@ -160,8 +168,9 @@ static usbh_class_driver_t const usbh_class_drivers[] = { #if CFG_TUH_HUB { - DRIVER_NAME("HUB") + .name = DRIVER_NAME("HUB"), .init = hub_init, + .deinit = hub_deinit, .open = hub_open, .set_config = hub_set_config, .xfer_cb = hub_xfer_cb, @@ -171,9 +180,11 @@ static usbh_class_driver_t const usbh_class_drivers[] = { #if CFG_TUH_VENDOR { - DRIVER_NAME("VENDOR") + .name = DRIVER_NAME("VENDOR"), .init = cush_init, - .open = cush_open_subtask, + .deinit = cush_deinit, + .open = cush_open, + .set_config = cush_set_config, .xfer_cb = cush_isr, .close = cush_close } @@ -338,11 +349,11 @@ bool tuh_inited(void) { return _usbh_controller != TUSB_INDEX_INVALID_8; } -bool tuh_init(uint8_t controller_id) { +bool tuh_init(uint8_t rhport) { // skip if already initialized if ( tuh_inited() ) return true; - TU_LOG_USBH("USBH init on controller %u\r\n", controller_id); + TU_LOG_USBH("USBH init on controller %u\r\n", rhport); TU_LOG_INT_USBH(sizeof(usbh_device_t)); TU_LOG_INT_USBH(sizeof(hcd_event_t)); TU_LOG_INT_USBH(sizeof(_ctrl_xfer)); @@ -383,10 +394,26 @@ bool tuh_init(uint8_t controller_id) { } } - _usbh_controller = controller_id;; + _usbh_controller = rhport;; + + TU_ASSERT(hcd_init(rhport)); + hcd_int_enable(rhport); + + return true; +} + +bool tuh_deinit(uint8_t rhport) { + if (!tuh_rhport_is_active(rhport)) return true; + + hcd_int_disable(rhport); + hcd_deinit(rhport); - TU_ASSERT(hcd_init(controller_id)); - hcd_int_enable(controller_id); + _usbh_controller = TUSB_INDEX_INVALID_8; + + // no other controller is active, deinit the stack + if (!tuh_inited()) { + + } return true; } diff --git a/src/host/usbh.h b/src/host/usbh.h index 9ff118543..0e31e80a7 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -109,7 +109,11 @@ bool tuh_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param); // Init host stack bool tuh_init(uint8_t rhport); +// Deinit host stack on rhport +bool tuh_deinit(uint8_t rhport); + // Check if host stack is already initialized with any roothub ports +// To check if an rhport is initialized, use tuh_rhport_is_active() bool tuh_inited(void); // Task function should be called in main/rtos loop, extended version of tuh_task() diff --git a/src/host/usbh_pvt.h b/src/host/usbh_pvt.h index 4ed2a72b5..204315175 100644 --- a/src/host/usbh_pvt.h +++ b/src/host/usbh_pvt.h @@ -50,11 +50,9 @@ enum { //--------------------------------------------------------------------+ typedef struct { - #if CFG_TUSB_DEBUG >= CFG_TUH_LOG_LEVEL char const* name; - #endif - void (* const init )(void); + bool (* const deinit )(void); bool (* const open )(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); bool (* const set_config )(uint8_t dev_addr, uint8_t itf_num); bool (* const xfer_cb )(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -- cgit v1.3.1 From e84c9f3e221092687808f175e1e19732a10fea72 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 22 Mar 2024 16:12:57 +0700 Subject: implement tuh_init() change usbh driver init() return type from void to bool --- src/class/cdc/cdc_host.c | 12 +++++-- src/class/cdc/cdc_host.h | 2 +- src/class/hid/hid_host.c | 4 ++- src/class/hid/hid_host.h | 2 +- src/class/msc/msc_host.c | 5 +-- src/class/msc/msc_host.h | 2 +- src/host/hub.c | 3 +- src/host/hub.h | 12 +++---- src/host/usbh.c | 85 ++++++++++++++++++++++++++++++------------------ src/host/usbh_pvt.h | 2 +- 10 files changed, 79 insertions(+), 50 deletions(-) (limited to 'src/host') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 14f380b40..5bdd41f1f 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -621,12 +621,11 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, // CLASS-USBH API //--------------------------------------------------------------------+ -void cdch_init(void) { +bool cdch_init(void) { + TU_LOG_DRV("sizeof(cdch_interface_t) = %u\r\n", sizeof(cdch_interface_t)); tu_memclr(cdch_data, sizeof(cdch_data)); - for (size_t i = 0; i < CFG_TUH_CDC; i++) { cdch_interface_t* p_cdc = &cdch_data[i]; - tu_edpt_stream_init(&p_cdc->stream.tx, true, true, false, p_cdc->stream.tx_ff_buf, CFG_TUH_CDC_TX_BUFSIZE, p_cdc->stream.tx_ep_buf, CFG_TUH_CDC_TX_EPSIZE); @@ -635,9 +634,16 @@ void cdch_init(void) { p_cdc->stream.rx_ff_buf, CFG_TUH_CDC_RX_BUFSIZE, p_cdc->stream.rx_ep_buf, CFG_TUH_CDC_RX_EPSIZE); } + + return true; } bool cdch_deinit(void) { + for (size_t i = 0; i < CFG_TUH_CDC; i++) { + cdch_interface_t* p_cdc = &cdch_data[i]; + tu_edpt_stream_deinit(&p_cdc->stream.tx); + tu_edpt_stream_deinit(&p_cdc->stream.rx); + } return true; } diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index 7530b1e9d..b63dd1530 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -192,7 +192,7 @@ TU_ATTR_WEAK extern void tuh_cdc_tx_complete_cb(uint8_t idx); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void cdch_init (void); +bool cdch_init (void); bool cdch_deinit (void); bool cdch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); bool cdch_set_config (uint8_t dev_addr, uint8_t itf_num); diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 16e2d3c2c..efc54656e 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -372,8 +372,10 @@ bool tuh_hid_send_report(uint8_t daddr, uint8_t idx, uint8_t report_id, const vo //--------------------------------------------------------------------+ // USBH API //--------------------------------------------------------------------+ -void hidh_init(void) { +bool hidh_init(void) { + TU_LOG_DRV("sizeof(hidh_interface_t) = %u\r\n", sizeof(hidh_interface_t)); tu_memclr(_hidh_itf, sizeof(_hidh_itf)); + return true; } bool hidh_deinit(void) { diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 9ea222b3d..0902bf1af 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -163,7 +163,7 @@ TU_ATTR_WEAK void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t idx //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void hidh_init(void); +bool hidh_init(void); bool hidh_deinit(void); bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const* desc_itf, uint16_t max_len); bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num); diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 61ecb8e4e..ce6e7fb2d 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -284,15 +284,16 @@ bool tuh_msc_reset(uint8_t dev_addr) { //--------------------------------------------------------------------+ // CLASS-USBH API //--------------------------------------------------------------------+ -void msch_init(void) { +bool msch_init(void) { + TU_LOG_DRV("sizeof(msch_interface_t) = %u\r\n", sizeof(msch_interface_t)); tu_memclr(_msch_itf, sizeof(_msch_itf)); + return true; } bool msch_deinit(void) { return true; } - void msch_close(uint8_t dev_addr) { TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX,); msch_interface_t* p_msc = get_itf(dev_addr); diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 5bf2e62e3..9fda566d8 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -113,7 +113,7 @@ TU_ATTR_WEAK void tuh_msc_umount_cb(uint8_t dev_addr); // Internal Class Driver API //--------------------------------------------------------------------+ -void msch_init (void); +bool msch_init (void); bool msch_deinit (void); bool msch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); bool msch_set_config (uint8_t dev_addr, uint8_t itf_num); diff --git a/src/host/hub.c b/src/host/hub.c index 0853ff27a..e97014443 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -182,8 +182,9 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, //--------------------------------------------------------------------+ // CLASS-USBH API (don't require to verify parameters) //--------------------------------------------------------------------+ -void hub_init(void) { +bool hub_init(void) { tu_memclr(hub_data, sizeof(hub_data)); + return true; } bool hub_deinit(void) { diff --git a/src/host/hub.h b/src/host/hub.h index c3f4a3612..385efe6b2 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -187,16 +187,14 @@ bool hub_port_get_status (uint8_t hub_addr, uint8_t hub_port, void* resp, 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_data) -{ +TU_ATTR_ALWAYS_INLINE static inline +bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, 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_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_data) -{ +TU_ATTR_ALWAYS_INLINE 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_data) { return hub_port_clear_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET_CHANGE, complete_cb, user_data); } @@ -204,7 +202,7 @@ static inline bool hub_port_clear_reset_change(uint8_t hub_addr, uint8_t hub_por //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void hub_init (void); +bool hub_init (void); bool hub_deinit (void); bool hub_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); bool hub_set_config (uint8_t dev_addr, uint8_t itf_num); diff --git a/src/host/usbh.c b/src/host/usbh.c index cf348bbb2..1edc43fd6 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -351,51 +351,55 @@ bool tuh_inited(void) { bool tuh_init(uint8_t rhport) { // skip if already initialized - if ( tuh_inited() ) return true; + if (tuh_rhport_is_active(rhport)) return true; TU_LOG_USBH("USBH init on controller %u\r\n", rhport); - TU_LOG_INT_USBH(sizeof(usbh_device_t)); - TU_LOG_INT_USBH(sizeof(hcd_event_t)); - TU_LOG_INT_USBH(sizeof(_ctrl_xfer)); - TU_LOG_INT_USBH(sizeof(tuh_xfer_t)); - TU_LOG_INT_USBH(sizeof(tu_fifo_t)); - TU_LOG_INT_USBH(sizeof(tu_edpt_stream_t)); - // Event queue - _usbh_q = osal_queue_create( &_usbh_qdef ); - TU_ASSERT(_usbh_q != NULL); + // Init host stack if not already + if (!tuh_inited()) { + TU_LOG_INT_USBH(sizeof(usbh_device_t)); + TU_LOG_INT_USBH(sizeof(hcd_event_t)); + TU_LOG_INT_USBH(sizeof(_ctrl_xfer)); + TU_LOG_INT_USBH(sizeof(tuh_xfer_t)); + TU_LOG_INT_USBH(sizeof(tu_fifo_t)); + TU_LOG_INT_USBH(sizeof(tu_edpt_stream_t)); + + // Event queue + _usbh_q = osal_queue_create(&_usbh_qdef); + TU_ASSERT(_usbh_q != NULL); #if OSAL_MUTEX_REQUIRED - // Init mutex - _usbh_mutex = osal_mutex_create(&_usbh_mutexdef); - TU_ASSERT(_usbh_mutex); + // Init mutex + _usbh_mutex = osal_mutex_create(&_usbh_mutexdef); + TU_ASSERT(_usbh_mutex); #endif - // Get application driver if available - if ( usbh_app_driver_get_cb ) { - _app_driver = usbh_app_driver_get_cb(&_app_driver_count); - } + // Get application driver if available + if (usbh_app_driver_get_cb) { + _app_driver = usbh_app_driver_get_cb(&_app_driver_count); + } - // Device - tu_memclr(&_dev0, sizeof(_dev0)); - tu_memclr(_usbh_devices, sizeof(_usbh_devices)); - tu_memclr(&_ctrl_xfer, sizeof(_ctrl_xfer)); + // 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; iname); - driver->init(); + // Class drivers + for (uint8_t drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) { + usbh_class_driver_t const* driver = get_driver(drv_id); + if (driver) { + TU_LOG_USBH("%s init\r\n", driver->name); + driver->init(); + } } } + // Init host controller _usbh_controller = rhport;; - TU_ASSERT(hcd_init(rhport)); hcd_int_enable(rhport); @@ -405,14 +409,31 @@ bool tuh_init(uint8_t rhport) { bool tuh_deinit(uint8_t rhport) { if (!tuh_rhport_is_active(rhport)) return true; + // deinit host controller hcd_int_disable(rhport); hcd_deinit(rhport); _usbh_controller = TUSB_INDEX_INVALID_8; - // no other controller is active, deinit the stack + // deinit host stack if no controller is active if (!tuh_inited()) { + // Class drivers + for (uint8_t drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) { + usbh_class_driver_t const* driver = get_driver(drv_id); + if (driver) { + TU_LOG_USBH("%s deinit\r\n", driver->name); + driver->deinit(); + } + } + + osal_queue_delete(_usbh_q); + _usbh_q = NULL; + #if OSAL_MUTEX_REQUIRED + // TODO make sure there is no task waiting on this mutex + osal_mutex_delete(_usbh_mutex); + _usbh_mutex = NULL; + #endif } return true; diff --git a/src/host/usbh_pvt.h b/src/host/usbh_pvt.h index 204315175..95de915e9 100644 --- a/src/host/usbh_pvt.h +++ b/src/host/usbh_pvt.h @@ -51,7 +51,7 @@ enum { typedef struct { char const* name; - void (* const init )(void); + bool (* const init )(void); bool (* const deinit )(void); bool (* const open )(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); bool (* const set_config )(uint8_t dev_addr, uint8_t itf_num); -- cgit v1.3.1 From 0da1da942a735bcac7b48786a511a38b02519e88 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 Mar 2024 16:32:02 +0700 Subject: enhance hub removal using while loop to unroll recursive instead of event queue. --- src/host/usbh.c | 117 +++++++++++++++++++++++++++----------------------------- 1 file changed, 57 insertions(+), 60 deletions(-) (limited to 'src/host') diff --git a/src/host/usbh.c b/src/host/usbh.c index 1edc43fd6..71691fad6 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1138,43 +1138,42 @@ bool tuh_interface_set(uint8_t daddr, uint8_t itf_num, uint8_t itf_alt, 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 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) -{ +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) -{ +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) -{ +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) -{ +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) -{ +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) -{ +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) -{ +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); } @@ -1210,57 +1209,55 @@ TU_ATTR_ALWAYS_INLINE static inline bool is_hub_addr(uint8_t daddr) { static void process_removing_device(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 + uint32_t removing_hubs = 0; + do { + for (uint8_t dev_id = 0; dev_id < TOTAL_DEVICES; dev_id++) { + usbh_device_t* dev = &_usbh_devices[dev_id]; + uint8_t const daddr = dev_id + 1; + + // hub_addr = 0 means roothub, hub_port = 0 means all devices of downstream hub + if (dev->rhport == rhport && dev->connected && + (hub_addr == 0 || dev->hub_addr == hub_addr) && + (hub_port == 0 || dev->hub_port == hub_port)) { + TU_LOG_USBH("Device unplugged address = %u\r\n", daddr); + + if (is_hub_addr(daddr)) { + TU_LOG_USBH(" is a HUB device %u\r\n", daddr); + // marking this hub to run the loop on its children next (unroll recursive) + removing_hubs |= TU_BIT(dev_id - CFG_TUH_DEVICE_MAX); + } else { + // Invoke callback before closing driver (maybe call it later ?) + if (tuh_umount_cb) tuh_umount_cb(daddr); + } -#if 0 - // index as hub addr, value is hub port (0xFF for invalid) - uint8_t removing_hubs[CFG_TUH_HUB]; - memset(removing_hubs, TUSB_INDEX_INVALID_8, sizeof(removing_hubs)); - - removing_hubs[hub_addr-CFG_TUH_DEVICE_MAX] = hub_port; + // Close class driver + for (uint8_t drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) { + usbh_class_driver_t const* driver = get_driver(drv_id); + if (driver) driver->close(daddr); + } - // consecutive non-removing hub - uint8_t nop_count = 0; -#endif + hcd_device_close(rhport, daddr); + clear_device(dev); - for (uint8_t dev_id = 0; dev_id < TOTAL_DEVICES; dev_id++) { - usbh_device_t *dev = &_usbh_devices[dev_id]; - uint8_t const daddr = dev_id + 1; - - // hub_addr = 0 means roothub, hub_port = 0 means all devices of downstream hub - if (dev->rhport == rhport && dev->connected && - (hub_addr == 0 || dev->hub_addr == hub_addr) && - (hub_port == 0 || dev->hub_port == hub_port)) { - TU_LOG_USBH("Device unplugged address = %u\r\n", daddr); - - if (is_hub_addr(daddr)) { - TU_LOG_USBH(" is a HUB device %u\r\n", daddr); - - // Submit removed event If the device itself is a hub (un-rolled recursive) - // TODO a better to unroll recursrive is using array of removing_hubs and mark it here - hcd_event_t event; - event.rhport = rhport; - event.event_id = HCD_EVENT_DEVICE_REMOVE; - event.connection.hub_addr = daddr; - event.connection.hub_port = 0; - - hcd_event_handler(&event, false); - } else { - // Invoke callback before closing driver (maybe call it later ?) - if (tuh_umount_cb) tuh_umount_cb(daddr); + // abort on-going control xfer on this device if any + if (_ctrl_xfer.daddr == daddr) _set_control_xfer_stage(CONTROL_STAGE_IDLE); } + } - // Close class driver - for (uint8_t drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) { - usbh_class_driver_t const * driver = get_driver(drv_id); - if ( driver ) driver->close(daddr); - } + if (removing_hubs == 0) break; + + // find the next 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); - hcd_device_close(rhport, daddr); - clear_device(dev); - // abort on-going control xfer if any - if (_ctrl_xfer.daddr == daddr) _set_control_xfer_stage(CONTROL_STAGE_IDLE); + // update hub_addr and hub_port for next loop + hub_addr = h_id + 1 + CFG_TUH_DEVICE_MAX; + hub_port = 0; + break; + } } - } + } while(1); } //--------------------------------------------------------------------+ -- cgit v1.3.1 From 3dcb7362aa8f0e710157da4b28be44abb2c26230 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 Mar 2024 19:18:20 +0700 Subject: fix build when CFG_TUH_HUB == 0 --- src/host/usbh.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src/host') diff --git a/src/host/usbh.c b/src/host/usbh.c index 71691fad6..f2dc2f7c1 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1219,11 +1219,10 @@ static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hu if (dev->rhport == rhport && dev->connected && (hub_addr == 0 || dev->hub_addr == hub_addr) && (hub_port == 0 || dev->hub_port == hub_port)) { - TU_LOG_USBH("Device unplugged address = %u\r\n", daddr); + TU_LOG_USBH("[%u:%u:%u] unplugged address = %u\r\n", rhport, hub_addr, hub_port, daddr); if (is_hub_addr(daddr)) { TU_LOG_USBH(" is a HUB device %u\r\n", daddr); - // marking this hub to run the loop on its children next (unroll recursive) removing_hubs |= TU_BIT(dev_id - CFG_TUH_DEVICE_MAX); } else { // Invoke callback before closing driver (maybe call it later ?) @@ -1244,9 +1243,11 @@ static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hu } } + // if removing a hub, we need to remove its downstream devices + #if CFG_TUH_HUB if (removing_hubs == 0) break; - // find the next hub to process + // 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); @@ -1257,6 +1258,10 @@ static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hu break; } } + #else + (void) removing_hubs; + break; + #endif } while(1); } -- cgit v1.3.1 From d50003e33d89740c0993ae236629392df82453c2 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Wed, 27 Mar 2024 11:21:13 -0700 Subject: Fake unplug devices when a root hub is deinit --- src/host/usbh.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/host') diff --git a/src/host/usbh.c b/src/host/usbh.c index f2dc2f7c1..29c6eb1e9 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -415,6 +415,15 @@ bool tuh_deinit(uint8_t rhport) { _usbh_controller = TUSB_INDEX_INVALID_8; + // "unplug" all devices on this rhport + for (uint8_t idx = 0; idx < CFG_TUH_DEVICE_MAX + CFG_TUH_HUB; idx++) { + usbh_device_t *dev = &_usbh_devices[idx]; + if (!dev->connected || dev->rhport != rhport) { + continue; + } + process_removing_device(rhport, dev->hub_addr, dev->hub_port); + } + // deinit host stack if no controller is active if (!tuh_inited()) { // Class drivers -- cgit v1.3.1 From ddb1034a9c77d8ef4efccf3df76013f86efe5e09 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 Mar 2024 21:45:52 +0700 Subject: use hub_addr=0, hub_port=0 for removing root hub port --- src/host/usbh.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'src/host') diff --git a/src/host/usbh.c b/src/host/usbh.c index 29c6eb1e9..05091736e 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -412,17 +412,10 @@ bool tuh_deinit(uint8_t rhport) { // deinit host controller hcd_int_disable(rhport); hcd_deinit(rhport); - _usbh_controller = TUSB_INDEX_INVALID_8; - // "unplug" all devices on this rhport - for (uint8_t idx = 0; idx < CFG_TUH_DEVICE_MAX + CFG_TUH_HUB; idx++) { - usbh_device_t *dev = &_usbh_devices[idx]; - if (!dev->connected || dev->rhport != rhport) { - continue; - } - process_removing_device(rhport, dev->hub_addr, dev->hub_port); - } + // "unplug" all devices on this rhport (hub_addr = 0, hub_port = 0) + process_removing_device(rhport, 0, 0); // deinit host stack if no controller is active if (!tuh_inited()) { -- cgit v1.3.1 From 7d3d60f96de3f6e15291c9302463c294e2dc98de Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 2 Apr 2024 16:38:40 +0700 Subject: add hcd_configure() to change max NAK dynamically --- src/host/hcd.h | 2 +- src/host/usbh.c | 13 ++++++++----- src/host/usbh.h | 14 ++++++++++++-- src/portable/analog/max3421/hcd_max3421.c | 17 +++++++++++------ src/tusb_option.h | 1 - 5 files changed, 32 insertions(+), 15 deletions(-) (limited to 'src/host') diff --git a/src/host/hcd.h b/src/host/hcd.h index d5804c608..5547c7cc5 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -125,7 +125,7 @@ bool hcd_dcache_clean_invalidate(void const* addr, uint32_t data_size) TU_ATTR_W //--------------------------------------------------------------------+ // optional hcd configuration, called by tuh_configure() -bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) TU_ATTR_WEAK; +bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param); // Initialize controller to host mode bool hcd_init(uint8_t rhport); diff --git a/src/host/usbh.c b/src/host/usbh.c index 05091736e..aa0603d47 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -52,6 +52,13 @@ TU_ATTR_WEAK bool hcd_deinit(uint8_t rhport) { return false; } +TU_ATTR_WEAK bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) { + (void) rhport; + (void) cfg_id; + (void) cfg_param; + return false; +} + TU_ATTR_WEAK void tuh_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr) { (void) rhport; (void) eventid; @@ -332,11 +339,7 @@ bool tuh_rhport_reset_bus(uint8_t rhport, bool active) { //--------------------------------------------------------------------+ bool tuh_configure(uint8_t rhport, uint32_t cfg_id, const void *cfg_param) { - if ( hcd_configure ) { - return hcd_configure(rhport, cfg_id, cfg_param); - } else { - return false; - } + return hcd_configure(rhport, cfg_id, cfg_param); } static void clear_device(usbh_device_t* dev) { diff --git a/src/host/usbh.h b/src/host/usbh.h index 0e31e80a7..57362c778 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -73,11 +73,21 @@ typedef struct { tusb_desc_interface_t desc; } tuh_itf_info_t; -// ConfigID for tuh_config() +// ConfigID for tuh_configure() enum { - TUH_CFGID_RPI_PIO_USB_CONFIGURATION = OPT_MCU_RP2040 << 8 // cfg_param: pio_usb_configuration_t + TUH_CFGID_INVALID = 0, + TUH_CFGID_RPI_PIO_USB_CONFIGURATION = 100, // cfg_param: pio_usb_configuration_t + TUH_CFGID_MAX3421 = 200, }; +typedef union { + // For TUH_CFGID_RPI_PIO_USB_CONFIGURATION use pio_usb_configuration_t + + struct { + uint8_t max_nak; + } max3421; +} tuh_configure_param_t; + //--------------------------------------------------------------------+ // APPLICATION CALLBACK //--------------------------------------------------------------------+ diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index 1b182e551..12d80e0b5 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -30,6 +30,7 @@ #include #include "host/hcd.h" +#include "host/usbh.h" //--------------------------------------------------------------------+ // @@ -230,7 +231,9 @@ typedef struct { } max3421_data_t; static max3421_data_t _hcd_data; -static uint8_t _max_nak = MAX_NAK_DEFAULT; // max NAK before giving up in a usb frame + +// max NAK before giving up in a frame. 0 means infinite NAKs +static uint8_t _max_nak = MAX_NAK_DEFAULT; //--------------------------------------------------------------------+ // API: SPI transfer with MAX3421E @@ -409,10 +412,11 @@ static void free_ep(uint8_t daddr) { } } -// Check if endpoint has an queued transfer +// Check if endpoint has an queued transfer and not reach max NAK TU_ATTR_ALWAYS_INLINE static inline bool is_ep_pending(max3421_ep_t const * ep) { uint8_t const state = ep->state; - return ep->packet_size && state >= EP_STATE_ATTEMPT_1 && state < EP_STATE_ATTEMPT_1 + _max_nak; + return ep->packet_size && (state >= EP_STATE_ATTEMPT_1) && + (_max_nak == 0 || state < EP_STATE_ATTEMPT_1 + _max_nak); } // Find the next pending endpoint using round-robin scheduling, starting from next endpoint. @@ -447,10 +451,11 @@ static max3421_ep_t * find_next_pending_ep(max3421_ep_t * cur_ep) { // optional hcd configuration, called by tuh_configure() bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) { (void) rhport; - (void) cfg_id; - (void) cfg_param; + TU_VERIFY(cfg_id == TUH_CFGID_MAX3421); - return false; + tuh_configure_param_t const* cfg = (tuh_configure_param_t const*) cfg_param; + _max_nak = cfg->max3421.max_nak; + return true; } // Initialize controller to host mode diff --git a/src/tusb_option.h b/src/tusb_option.h index f90fb7026..812074c44 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -144,7 +144,6 @@ #define OPT_MCU_RX72N 1402 ///< Renesas RX72N #define OPT_MCU_RAXXX 1403 ///< Renesas RAxxx families - // Mind Motion #define OPT_MCU_MM32F327X 1500 ///< Mind Motion MM32F327 -- cgit v1.3.1