From 3623ba1884ddff23e9b64766cb6dd032f1425846 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 17 Mar 2023 16:12:49 +0700 Subject: fix trailing space and new line temporarily disable codespell --- src/host/hub.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/host/hub.c') diff --git a/src/host/hub.c b/src/host/hub.c index 3da5358b2..b84042fb6 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -202,7 +202,7 @@ bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0); - + TU_ASSERT(tuh_edpt_open(dev_addr, desc_ep)); hub_interface_t* p_hub = get_itf(dev_addr); -- cgit v1.3.1 From 71fb6469d4997347f2014daa41839391cc070a74 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 24 Mar 2023 14:02:09 +0700 Subject: separate CFG_TUSB_MEM_SECTION and CFG_TUSB_MEM_ALIGN to - CFG_TUD_MEM_SECTION and CFG_TUD_MEM_ALIGN - CFG_TUH_MEM_SECTION and CFG_TUH_MEM_ALIGN - fix missing mem section and align for host --- hw/bsp/ea4088qs/board.mk | 3 ++- src/class/cdc/cdc_host.c | 6 +++--- src/class/cdc/cdc_rndis_host.c | 4 ++-- src/class/hid/hid_host.c | 6 +++--- src/class/msc/msc_host.c | 8 ++++---- src/host/hub.c | 8 ++++---- src/host/usbh.c | 8 ++++---- src/portable/ehci/ehci.c | 2 +- src/portable/nxp/khci/hcd_khci.c | 4 ++-- src/portable/ohci/ohci.c | 2 +- src/tusb_option.h | 40 +++++++++++++++++++++++++++++++++++++++- tools/build_utils.py | 2 +- tools/gen_doc.py | 2 ++ 13 files changed, 68 insertions(+), 27 deletions(-) (limited to 'src/host/hub.c') diff --git a/hw/bsp/ea4088qs/board.mk b/hw/bsp/ea4088qs/board.mk index 376840fb1..e1e14b717 100644 --- a/hw/bsp/ea4088qs/board.mk +++ b/hw/bsp/ea4088qs/board.mk @@ -10,7 +10,8 @@ CFLAGS += \ -nostdlib \ -DCORE_M4 \ -D__USE_LPCOPEN \ - -DCFG_TUSB_MEM_SECTION='__attribute__((section(".data.$$RAM2")))' \ + -DCFG_TUD_MEM_SECTION='__attribute__((section(".data.$$RAM2")))' \ + -DCFG_TUH_MEM_SECTION='__attribute__((section(".data.$$RAM2")))' \ -DCFG_TUSB_MCU=OPT_MCU_LPC40XX # mcu driver cause following warnings diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index fee314823..734ddd1b8 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -62,10 +62,10 @@ typedef struct { tu_edpt_stream_t rx; uint8_t tx_ff_buf[CFG_TUH_CDC_TX_BUFSIZE]; - CFG_TUSB_MEM_ALIGN uint8_t tx_ep_buf[CFG_TUH_CDC_TX_EPSIZE]; + CFG_TUH_MEM_ALIGN uint8_t tx_ep_buf[CFG_TUH_CDC_TX_EPSIZE]; uint8_t rx_ff_buf[CFG_TUH_CDC_TX_BUFSIZE]; - CFG_TUSB_MEM_ALIGN uint8_t rx_ep_buf[CFG_TUH_CDC_TX_EPSIZE]; + CFG_TUH_MEM_ALIGN uint8_t rx_ep_buf[CFG_TUH_CDC_TX_EPSIZE]; } stream; } cdch_interface_t; @@ -74,7 +74,7 @@ typedef struct { // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION +CFG_TUH_MEM_SECTION static cdch_interface_t cdch_data[CFG_TUH_CDC]; static inline cdch_interface_t* get_itf(uint8_t idx) diff --git a/src/class/cdc/cdc_rndis_host.c b/src/class/cdc/cdc_rndis_host.c index 41d21bbad..11a5355aa 100644 --- a/src/class/cdc/cdc_rndis_host.c +++ b/src/class/cdc/cdc_rndis_host.c @@ -50,8 +50,8 @@ //--------------------------------------------------------------------+ #define RNDIS_MSG_PAYLOAD_MAX (1024*4) -CFG_TUSB_MEM_SECTION static uint8_t msg_notification[CFG_TUH_DEVICE_MAX][8]; -CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t msg_payload[RNDIS_MSG_PAYLOAD_MAX]; +CFG_TUH_MEM_SECTION static uint8_t msg_notification[CFG_TUH_DEVICE_MAX][8]; +CFG_TUH_MEM_SECTION CFG_TUH_MEM_ALIGN static uint8_t msg_payload[RNDIS_MSG_PAYLOAD_MAX]; static rndish_data_t rndish_data[CFG_TUH_DEVICE_MAX]; diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 20373f541..a0032aeba 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -54,11 +54,11 @@ typedef struct uint16_t epin_size; uint16_t epout_size; - uint8_t epin_buf[CFG_TUH_HID_EPIN_BUFSIZE]; - uint8_t epout_buf[CFG_TUH_HID_EPOUT_BUFSIZE]; + CFG_TUH_MEM_ALIGN uint8_t epin_buf[CFG_TUH_HID_EPIN_BUFSIZE]; + CFG_TUH_MEM_ALIGN uint8_t epout_buf[CFG_TUH_HID_EPOUT_BUFSIZE]; } hidh_interface_t; -CFG_TUSB_MEM_SECTION +CFG_TUH_MEM_SECTION tu_static hidh_interface_t _hidh_itf[CFG_TUH_HID]; //--------------------------------------------------------------------+ diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 2fddeb818..1b48813ec 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -71,15 +71,15 @@ typedef struct tuh_msc_complete_cb_t complete_cb; uintptr_t complete_arg; - msc_cbw_t cbw; - msc_csw_t csw; + CFG_TUH_MEM_ALIGN msc_cbw_t cbw; + CFG_TUH_MEM_ALIGN msc_csw_t csw; }msch_interface_t; -CFG_TUSB_MEM_SECTION static msch_interface_t _msch_itf[CFG_TUH_DEVICE_MAX]; +CFG_TUH_MEM_SECTION static msch_interface_t _msch_itf[CFG_TUH_DEVICE_MAX]; // buffer used to read scsi information when mounted // largest response data currently is inquiry TODO Inquiry is not part of enum anymore -CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) +CFG_TUH_MEM_SECTION CFG_TUH_MEM_ALIGN static uint8_t _msch_buffer[sizeof(scsi_inquiry_resp_t)]; TU_ATTR_ALWAYS_INLINE diff --git a/src/host/hub.c b/src/host/hub.c index b84042fb6..386ad6aae 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -43,12 +43,12 @@ typedef struct uint8_t port_count; uint8_t status_change; // data from status change interrupt endpoint - hub_port_status_response_t port_status; - hub_status_response_t hub_status; + CFG_TUH_MEM_ALIGN hub_port_status_response_t port_status; + CFG_TUH_MEM_ALIGN hub_status_response_t hub_status; } hub_interface_t; -CFG_TUSB_MEM_SECTION static hub_interface_t hub_data[CFG_TUH_HUB]; -CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t _hub_buffer[sizeof(descriptor_hub_desc_t)]; +CFG_TUH_MEM_SECTION static hub_interface_t hub_data[CFG_TUH_HUB]; +CFG_TUH_MEM_SECTION CFG_TUH_MEM_ALIGN static uint8_t _hub_buffer[sizeof(descriptor_hub_desc_t)]; TU_ATTR_ALWAYS_INLINE static inline hub_interface_t* get_itf(uint8_t dev_addr) diff --git a/src/host/usbh.c b/src/host/usbh.c index 3eff0830a..3be662c63 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -203,7 +203,7 @@ static usbh_dev0_t _dev0; // 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 -CFG_TUSB_MEM_SECTION usbh_device_t _usbh_devices[TOTAL_DEVICES]; +static usbh_device_t _usbh_devices[TOTAL_DEVICES]; // Mutex for claiming endpoint #if OSAL_MUTEX_REQUIRED @@ -218,15 +218,15 @@ CFG_TUSB_MEM_SECTION usbh_device_t _usbh_devices[TOTAL_DEVICES]; OSAL_QUEUE_DEF(usbh_int_set, _usbh_qdef, CFG_TUH_TASK_QUEUE_SZ, hcd_event_t); static osal_queue_t _usbh_q; -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN +CFG_TUH_MEM_SECTION CFG_TUH_MEM_ALIGN static uint8_t _usbh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSIZE]; // Control transfers: since most controllers do not support multiple control transfers // on multiple devices concurrently and control transfers are not used much except for // enumeration, we will only execute control transfers one at a time. -CFG_TUSB_MEM_SECTION struct +CFG_TUH_MEM_SECTION struct { - tusb_control_request_t request TU_ATTR_ALIGNED(4); + CFG_TUH_MEM_ALIGN tusb_control_request_t request; uint8_t* buffer; tuh_xfer_cb_t complete_cb; uintptr_t user_data; diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index ee9dfb11f..9951aa5da 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -85,7 +85,7 @@ typedef struct }ehci_data_t; // Periodic frame list must be 4K alignment -CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4096) static ehci_data_t ehci_data; +CFG_TUH_MEM_SECTION TU_ATTR_ALIGNED(4096) static ehci_data_t ehci_data; //--------------------------------------------------------------------+ // PROTOTYPE diff --git a/src/portable/nxp/khci/hcd_khci.c b/src/portable/nxp/khci/hcd_khci.c index 6d25cd862..f6029ee0d 100644 --- a/src/portable/nxp/khci/hcd_khci.c +++ b/src/portable/nxp/khci/hcd_khci.c @@ -137,8 +137,8 @@ typedef struct // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ // BDT(Buffer Descriptor Table) must be 256-byte aligned -CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(512) static hcd_data_t _hcd; -//CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t _rx_buf[1024]; +CFG_TUH_MEM_SECTION TU_ATTR_ALIGNED(512) static hcd_data_t _hcd; +//CFG_TUH_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t _rx_buf[1024]; int find_pipe(uint8_t dev_addr, uint8_t ep_addr) { diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c index 260804d3d..3f702d22c 100644 --- a/src/portable/ohci/ohci.c +++ b/src/portable/ohci/ohci.c @@ -145,7 +145,7 @@ enum { //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(256) static ohci_data_t ohci_data; +CFG_TUH_MEM_SECTION TU_ATTR_ALIGNED(256) static ohci_data_t ohci_data; static ohci_ed_t * const p_ed_head[] = { diff --git a/src/tusb_option.h b/src/tusb_option.h index c679f2f12..f8ac722f4 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -289,12 +289,15 @@ #define CFG_TUSB_DEBUG 0 #endif -// place data in accessible RAM for usb controller +// TODO MEM_SECTION can be different for host and device controller +// should use CFG_TUD_MEM_SECTION, CFG_TUH_MEM_SECTION #ifndef CFG_TUSB_MEM_SECTION #define CFG_TUSB_MEM_SECTION #endif // alignment requirement of buffer used for endpoint transferring +// TODO MEM_ALIGN can be different for host and device controller +// should use CFG_TUD_MEM_ALIGN, CFG_TUH_MEM_ALIGN #ifndef CFG_TUSB_MEM_ALIGN #define CFG_TUSB_MEM_ALIGN TU_ATTR_ALIGNED(4) #endif @@ -312,6 +315,26 @@ // Device Options (Default) //-------------------------------------------------------------------- +// Attribute to place data in accessible RAM for device controller +// default to CFG_TUSB_MEM_SECTION for backward-compatible +#ifndef CFG_TUD_MEM_SECTION + #ifdef CFG_TUSB_MEM_SECTION + #define CFG_TUD_MEM_SECTION CFG_TUSB_MEM_SECTION + #else + #define CFG_TUD_MEM_SECTION + #endif +#endif + +// Attribute to align memory for device controller +// default to CFG_TUSB_MEM_ALIGN for backward-compatible +#ifndef CFG_TUD_MEM_ALIGN + #ifdef CFG_TUSB_MEM_ALIGN + #define CFG_TUD_MEM_ALIGN CFG_TUSB_MEM_ALIGN + #else + #define CFG_TUD_MEM_ALIGN TU_ATTR_ALIGNED(4) + #endif +#endif + #ifndef CFG_TUD_ENDPOINT0_SIZE #define CFG_TUD_ENDPOINT0_SIZE 64 #endif @@ -390,6 +413,21 @@ #endif #endif // CFG_TUH_ENABLED +// Attribute to place data in accessible RAM for host controller +// default to CFG_TUSB_MEM_SECTION for backward-compatible +#ifndef CFG_TUH_MEM_SECTION + #ifdef CFG_TUSB_MEM_SECTION + #define CFG_TUH_MEM_SECTION CFG_TUSB_MEM_SECTION + #else + #define CFG_TUH_MEM_SECTION + #endif +#endif + +// Attribute to align memory for host controller +#ifndef CFG_TUH_MEM_ALIGN + #define CFG_TUH_MEM_ALIGN TU_ATTR_ALIGNED(4) +#endif + //------------- CLASS -------------// #ifndef CFG_TUH_HUB diff --git a/tools/build_utils.py b/tools/build_utils.py index d0ef52717..905d06a86 100644 --- a/tools/build_utils.py +++ b/tools/build_utils.py @@ -93,7 +93,7 @@ def build_example(example, board, make_option): ret[2] = 1 print(build_format.format(example, board, status, '-', flash_size, sram_size)) else: - subprocess.run(make_cmd + " clean", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + #subprocess.run(make_cmd + " clean", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) build_result = subprocess.run(make_cmd + " all", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) if build_result.returncode == 0: diff --git a/tools/gen_doc.py b/tools/gen_doc.py index db11e2cfb..9078299cc 100644 --- a/tools/gen_doc.py +++ b/tools/gen_doc.py @@ -6,9 +6,11 @@ from get_deps import deps_all # TOP is tinyusb root dir TOP = Path(__file__).parent.parent.resolve() + ########################################### # Dependencies ########################################### + def gen_deps_doc(): deps_rst = Path(TOP) / "docs/reference/dependencies.rst" df = pd.DataFrame.from_dict(deps_all, orient='index', columns=['Commit', 'Project']) -- cgit v1.3.1 From 206d63e038744b228cfa6051d701cab50b520fe6 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 11 May 2023 14:26:12 +0700 Subject: correct EHCI reporting failed xfer (instead of stalled) when device is unplugged --- src/class/cdc/cdc_host.c | 21 +++++++++++---------- src/class/hid/hid_host.c | 27 ++++++++++++++++----------- src/class/msc/msc_host.c | 10 +++++++--- src/common/tusb_debug.h | 1 + src/device/usbd_control.c | 9 ++++++--- src/host/hub.c | 9 ++++++++- src/host/usbh.c | 20 +++++++++++++------- src/portable/ehci/ehci.c | 11 ++++++++--- src/tusb.c | 4 ++++ 9 files changed, 74 insertions(+), 38 deletions(-) (limited to 'src/host/hub.c') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index fe3691bf4..9ff666ed4 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -35,8 +35,7 @@ // Debug level, TUSB_CFG_DEBUG must be at least this level for debug message #define CDCH_DEBUG 2 - -#define TU_LOG_CDCH(...) TU_LOG(CDCH_DEBUG, __VA_ARGS__) +#define TU_LOG_DRV(...) TU_LOG(CDCH_DEBUG, __VA_ARGS__) //--------------------------------------------------------------------+ // Host CDC Interface @@ -537,6 +536,8 @@ void cdch_close(uint8_t daddr) cdch_interface_t* p_cdc = &cdch_data[idx]; if (p_cdc->daddr == daddr) { + TU_LOG_DRV(" CDCh close addr = %u index = %u\r\n", daddr, idx); + // Invoke application callback if (tuh_cdc_umount_cb) tuh_cdc_umount_cb(idx); @@ -804,7 +805,7 @@ static void acm_process_config(tuh_xfer_t* xfer) static bool acm_set_control_line_state(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_VERIFY(p_cdc->acm_capability.support_line_request); - TU_LOG_CDCH("CDC ACM Set Control Line State\r\n"); + TU_LOG_DRV("CDC ACM Set Control Line State\r\n"); tusb_control_request_t const request = { .bmRequestType_bit = { @@ -834,7 +835,7 @@ static bool acm_set_control_line_state(cdch_interface_t* p_cdc, uint16_t line_st } static bool acm_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_LOG_CDCH("CDC ACM Set Line Conding\r\n"); + TU_LOG_DRV("CDC ACM Set Line Conding\r\n"); tusb_control_request_t const request = { .bmRequestType_bit = { @@ -894,7 +895,7 @@ static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc); TU_VERIFY(p_cdc); - TU_LOG_CDCH("FTDI opened\r\n"); + TU_LOG_DRV("FTDI opened\r\n"); p_cdc->serial_drid = SERIAL_DRIVER_FTDI; @@ -938,7 +939,7 @@ static bool ftdi_sio_reset(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, u static bool ftdi_sio_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_LOG_CDCH("CDC FTDI Set Control Line State\r\n"); + TU_LOG_DRV("CDC FTDI Set Control Line State\r\n"); p_cdc->user_control_cb = complete_cb; TU_ASSERT(ftdi_sio_set_request(p_cdc, FTDI_SIO_MODEM_CTRL, 0x0300 | line_state, complete_cb ? cdch_internal_control_complete : NULL, user_data)); @@ -974,7 +975,7 @@ static uint32_t ftdi_232bm_baud_to_divisor(uint32_t baud) static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { uint16_t const divisor = (uint16_t) ftdi_232bm_baud_to_divisor(baudrate); - TU_LOG_CDCH("CDC FTDI Set BaudRate = %lu, divisor = 0x%04x\n", baudrate, divisor); + TU_LOG_DRV("CDC FTDI Set BaudRate = %lu, divisor = 0x%04x\n", baudrate, divisor); p_cdc->user_control_cb = complete_cb; _ftdi_requested_baud = baudrate; @@ -1061,7 +1062,7 @@ static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, ui cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc); TU_VERIFY(p_cdc); - TU_LOG_CDCH("CP210x opened\r\n"); + TU_LOG_DRV("CP210x opened\r\n"); p_cdc->serial_drid = SERIAL_DRIVER_CP210X; // endpoint pair @@ -1109,7 +1110,7 @@ static bool cp210x_ifc_enable(cdch_interface_t* p_cdc, uint16_t enabled, tuh_xfe } static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_LOG_CDCH("CDC CP210x Set BaudRate = %lu\n", baudrate); + TU_LOG_DRV("CDC CP210x Set BaudRate = %lu\n", baudrate); uint32_t baud_le = tu_htole32(baudrate); p_cdc->user_control_cb = complete_cb; return cp210x_set_request(p_cdc, CP210X_SET_BAUDRATE, 0, (uint8_t *) &baud_le, 4, @@ -1118,7 +1119,7 @@ static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_ static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_LOG_CDCH("CDC CP210x Set Control Line State\r\n"); + TU_LOG_DRV("CDC CP210x Set Control Line State\r\n"); p_cdc->user_control_cb = complete_cb; return cp210x_set_request(p_cdc, CP210X_SET_MHS, 0x0300 | line_state, NULL, 0, complete_cb ? cdch_internal_control_complete : NULL, user_data); diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index d95d3ef35..3a491937a 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -33,6 +33,10 @@ #include "hid_host.h" +// Debug level, TUSB_CFG_DEBUG must be at least this level for debug message +#define HIDH_DEBUG 2 +#define TU_LOG_DRV(...) TU_LOG(HIDH_DEBUG, __VA_ARGS__) + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -207,7 +211,7 @@ static void set_protocol_complete(tuh_xfer_t* xfer) static bool _hidh_set_protocol(uint8_t daddr, uint8_t itf_num, uint8_t protocol, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_LOG2("HID Set Protocol = %d\r\n", protocol); + TU_LOG_DRV("HID Set Protocol = %d\r\n", protocol); tusb_control_request_t const request = { @@ -246,7 +250,7 @@ bool tuh_hid_set_protocol(uint8_t daddr, uint8_t idx, uint8_t protocol) static void set_report_complete(tuh_xfer_t* xfer) { - TU_LOG2("HID Set Report complete\r\n"); + TU_LOG_DRV("HID Set Report complete\r\n"); if (tuh_hid_set_report_complete_cb) { @@ -266,7 +270,7 @@ bool tuh_hid_set_report(uint8_t daddr, uint8_t idx, uint8_t report_id, uint8_t r hidh_interface_t* p_hid = get_hid_itf(daddr, idx); TU_VERIFY(p_hid); - TU_LOG2("HID Set Report: id = %u, type = %u, len = %u\r\n", report_id, report_type, len); + TU_LOG_DRV("HID Set Report: id = %u, type = %u, len = %u\r\n", report_id, report_type, len); tusb_control_request_t const request = { @@ -298,7 +302,7 @@ bool tuh_hid_set_report(uint8_t daddr, uint8_t idx, uint8_t report_id, uint8_t r static bool _hidh_set_idle(uint8_t daddr, uint8_t itf_num, uint16_t idle_rate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { // SET IDLE request, device can stall if not support this request - TU_LOG2("HID Set Idle \r\n"); + TU_LOG_DRV("HID Set Idle \r\n"); tusb_control_request_t const request = { @@ -367,7 +371,7 @@ bool tuh_hid_send_ready(uint8_t dev_addr, uint8_t idx) bool tuh_hid_send_report(uint8_t daddr, uint8_t idx, uint8_t report_id, const void* report, uint16_t len) { - TU_LOG2("HID Send Report %d\r\n", report_id); + TU_LOG_DRV("HID Send Report %d\r\n", report_id); hidh_interface_t* p_hid = get_hid_itf(daddr, idx); TU_VERIFY(p_hid); @@ -430,7 +434,7 @@ bool hidh_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t result, uint32_t if ( dir == TUSB_DIR_IN ) { - TU_LOG2(" Get Report callback (%u, %u)\r\n", daddr, idx); + TU_LOG_DRV(" Get Report callback (%u, %u)\r\n", daddr, idx); TU_LOG3_MEM(p_hid->epin_buf, xferred_bytes, 2); tuh_hid_report_received_cb(daddr, idx, p_hid->epin_buf, (uint16_t) xferred_bytes); }else @@ -448,8 +452,9 @@ void hidh_close(uint8_t daddr) hidh_interface_t* p_hid = &_hidh_itf[i]; if (p_hid->daddr == daddr) { - if(tuh_hid_umount_cb) tuh_hid_umount_cb(daddr, i); - p_hid->daddr = 0; + TU_LOG_DRV(" HIDh close addr = %u index = %u\r\n", daddr, i); + if(tuh_hid_umount_cb) tuh_hid_umount_cb(daddr, i); + p_hid->daddr = 0; } } } @@ -465,7 +470,7 @@ bool hidh_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *desc_ TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); - TU_LOG2("[%u] HID opening Interface %u\r\n", daddr, desc_itf->bInterfaceNumber); + TU_LOG_DRV("[%u] HID opening Interface %u\r\n", daddr, desc_itf->bInterfaceNumber); // len = interface + hid + n*endpoints uint16_t const drv_len = (uint16_t) (sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + @@ -592,7 +597,7 @@ static void process_set_config(tuh_xfer_t* xfer) // using usbh enumeration buffer since report descriptor can be very long if( p_hid->report_desc_len > CFG_TUH_ENUMERATION_BUFSIZE ) { - TU_LOG2("HID Skip Report Descriptor since it is too large %u bytes\r\n", p_hid->report_desc_len); + TU_LOG_DRV("HID Skip Report Descriptor since it is too large %u bytes\r\n", p_hid->report_desc_len); // Driver is mounted without report descriptor config_driver_mount_complete(daddr, idx, NULL, 0); @@ -763,7 +768,7 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info_arr, for ( uint8_t i = 0; i < report_num; i++ ) { info = report_info_arr+i; - TU_LOG2("%u: id = %u, usage_page = %u, usage = %u\r\n", i, info->report_id, info->usage_page, info->usage); + TU_LOG_DRV("%u: id = %u, usage_page = %u, usage = %u\r\n", i, info->report_id, info->usage_page, info->usage); } return report_num; diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 1b48813ec..138443de4 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -35,7 +35,6 @@ // Debug level, TUSB_CFG_DEBUG must be at least this level for debug message #define MSCH_DEBUG 2 - #define TU_LOG_MSCH(...) TU_LOG(MSCH_DEBUG, __VA_ARGS__) //--------------------------------------------------------------------+ @@ -82,6 +81,7 @@ CFG_TUH_MEM_SECTION static msch_interface_t _msch_itf[CFG_TUH_DEVICE_MAX]; CFG_TUH_MEM_SECTION CFG_TUH_MEM_ALIGN static uint8_t _msch_buffer[sizeof(scsi_inquiry_resp_t)]; +// FIXME potential nul reference TU_ATTR_ALWAYS_INLINE static inline msch_interface_t* get_itf(uint8_t dev_addr) { @@ -305,11 +305,15 @@ void msch_init(void) void msch_close(uint8_t dev_addr) { TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX, ); - msch_interface_t* p_msc = get_itf(dev_addr); + TU_VERIFY(p_msc->configured, ); + + TU_LOG_MSCH(" MSCh close addr = %d\r\n", dev_addr); // invoke Application Callback - if (p_msc->mounted && tuh_msc_umount_cb) tuh_msc_umount_cb(dev_addr); + if (p_msc->mounted) { + if(tuh_msc_umount_cb) tuh_msc_umount_cb(dev_addr); + } tu_memclr(p_msc, sizeof(msch_interface_t)); } diff --git a/src/common/tusb_debug.h b/src/common/tusb_debug.h index 82f682043..36507041f 100644 --- a/src/common/tusb_debug.h +++ b/src/common/tusb_debug.h @@ -46,6 +46,7 @@ #if CFG_TUSB_DEBUG >= 2 extern char const* const tu_str_speed[]; extern char const* const tu_str_std_request[]; +extern char const* const tu_str_xfer_result[]; #endif void tu_print_mem(void const *buf, uint32_t count, uint8_t indent); diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index ea8eef285..2afe967b5 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -32,7 +32,10 @@ #include "tusb.h" #include "device/usbd_pvt.h" -#if CFG_TUSB_DEBUG >= 2 +// Debug level of USBD Control +#define USBD_CONTROL_DEBUG 2 + +#if CFG_TUSB_DEBUG >= USBD_CONTROL_DEBUG extern void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback); #endif @@ -188,7 +191,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result { TU_VERIFY(_ctrl_xfer.buffer); memcpy(_ctrl_xfer.buffer, _usbd_ctrl_buf, xferred_bytes); - TU_LOG_MEM(2, _usbd_ctrl_buf, xferred_bytes, 2); + TU_LOG_MEM(USBD_CONTROL_DEBUG, _usbd_ctrl_buf, xferred_bytes, 2); } _ctrl_xfer.total_xferred += (uint16_t) xferred_bytes; @@ -205,7 +208,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result // callback can still stall control in status phase e.g out data does not make sense if ( _ctrl_xfer.complete_cb ) { - #if CFG_TUSB_DEBUG >= 2 + #if CFG_TUSB_DEBUG >= USBD_CONTROL_DEBUG usbd_driver_print_control_complete_name(_ctrl_xfer.complete_cb); #endif diff --git a/src/host/hub.c b/src/host/hub.c index 386ad6aae..85bf22b3e 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -33,6 +33,10 @@ #include "usbh_classdriver.h" #include "hub.h" +// Debug level, TUSB_CFG_DEBUG must be at least this level for debug message +#define HUB_DEBUG 2 +#define TU_LOG_DRV(...) TU_LOG(HUB_DEBUG, __VA_ARGS__) + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -218,7 +222,10 @@ void hub_close(uint8_t dev_addr) TU_VERIFY(dev_addr > CFG_TUH_DEVICE_MAX, ); hub_interface_t* p_hub = get_itf(dev_addr); - if (p_hub->ep_in) tu_memclr(p_hub, sizeof( hub_interface_t)); + if (p_hub->ep_in) { + TU_LOG_DRV(" HUB close addr = %d\r\n", dev_addr); + tu_memclr(p_hub, sizeof( hub_interface_t)); + } } bool hub_edpt_status_xfer(uint8_t dev_addr) diff --git a/src/host/usbh.c b/src/host/usbh.c index 24ce47a7f..4cfc7c5c2 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -61,6 +61,8 @@ typedef struct uint8_t hub_addr; uint8_t hub_port; uint8_t speed; + + // enumeration is in progress, done when all interfaces are configured volatile uint8_t enumerating; // struct TU_ATTR_PACKED { @@ -436,7 +438,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 = tu_edpt_dir(ep_addr); - TU_LOG_USBH("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); + TU_LOG_USBH("on EP %02X with %u bytes %s\r\n", ep_addr, (unsigned int) event.xfer_complete.len, + tu_str_xfer_result[event.xfer_complete.result]); if (event.dev_addr == 0) { @@ -866,6 +869,10 @@ TU_ATTR_FAST_FUNC void hcd_event_handler(hcd_event_t const* event, bool in_isr) { switch (event->event_id) { +// case HCD_EVENT_DEVICE_REMOVE: +// +// break; + default: osal_queue_send(_usbh_q, event, in_isr); break; @@ -1128,30 +1135,28 @@ static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t h usbh_device_t* dev = &_usbh_devices[dev_id]; uint8_t const dev_addr = dev_id+1; - // TODO Hub multiple level if (dev->rhport == rhport && (hub_addr == 0 || dev->hub_addr == hub_addr) && // hub_addr = 0 means roothub (hub_port == 0 || dev->hub_port == hub_port) && // hub_port = 0 means all devices of downstream hub dev->connected) { - TU_LOG_USBH(" Address = %u\r\n", dev_addr); + TU_LOG_USBH("Device unplugged address = %u\r\n", dev_addr); if (is_hub_addr(dev_addr)) { - TU_LOG(USBH_DEBUG, "HUB address = %u is unmounted\r\n", dev_addr); + TU_LOG(USBH_DEBUG, " is a HUB device\r\n", dev_addr); // If the device itself is a usb hub, unplug downstream devices. // FIXME un-roll recursive calls to prevent potential stack overflow process_device_unplugged(rhport, dev_addr, 0); }else { - // Invoke callback before closing driver + // Invoke callback before closing driver (maybe call it later ?) if (tuh_umount_cb) tuh_umount_cb(dev_addr); } // Close class driver for (uint8_t drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) { - TU_LOG_USBH("%s close\r\n", usbh_class_drivers[drv_id].name); usbh_class_drivers[drv_id].close(dev_addr); } @@ -1449,6 +1454,7 @@ static uint8_t get_new_address(bool is_hub) { uint8_t start; uint8_t end; + if ( is_hub ) { start = CFG_TUH_DEVICE_MAX; @@ -1459,7 +1465,7 @@ static uint8_t get_new_address(bool is_hub) end = start + CFG_TUH_DEVICE_MAX; } - for ( uint8_t idx = start; idx < end; idx++) + for (uint8_t idx = start; idx < end; idx++) { if (!_usbh_devices[idx].connected) return (idx+1); } diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 494e2e50f..69e59ce65 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -142,8 +142,11 @@ static inline ehci_qhd_t* qhd_get_from_addr (uint8_t dev_addr, uint8_t ep_addr); // determine if a queue head has bus-related error static inline bool qhd_has_xact_error (ehci_qhd_t * p_qhd) { - return (p_qhd->qtd_overlay.buffer_err || p_qhd->qtd_overlay.babble_err || p_qhd->qtd_overlay.xact_err); - //p_qhd->qtd_overlay.non_hs_period_missed_uframe || p_qhd->qtd_overlay.pingstate_err TODO split transaction error + volatile ehci_qtd_t *qtd_overlay = &p_qhd->qtd_overlay; + + // Error count = 0 often occurs when device disconnected + return (qtd_overlay->err_count == 0 || qtd_overlay->buffer_err || qtd_overlay->babble_err || qtd_overlay->xact_err); + //qtd_overlay->non_hs_period_missed_uframe || qtd_overlay->pingstate_err TODO split transaction error } static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); @@ -630,7 +633,9 @@ static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd) p_qhd->total_xferred_bytes += p_qhd->p_qtd_list_head->expected_bytes - p_qhd->p_qtd_list_head->total_bytes; -// if ( XFER_RESULT_FAILED == error_event ) TU_BREAKPOINT(); // TODO skip unplugged device +// if ( XFER_RESULT_FAILED == error_event ) { +// TU_BREAKPOINT(); // TODO skip unplugged device +// } p_qhd->p_qtd_list_head->used = 0; // free QTD qtd_remove_1st_from_qhd(p_qhd); diff --git a/src/tusb.c b/src/tusb.c index 85fe5a3cc..7327db685 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -439,6 +439,10 @@ char const* const tu_str_std_request[] = "Synch Frame" }; +char const* const tu_str_xfer_result[] = { + "OK", "Failed", "Stalled", "Timeout" +}; + #endif static void dump_str_line(uint8_t const* buf, uint16_t count) -- cgit v1.3.1 From 8ad024e51bbc663678d8a357f91021bd39222246 Mon Sep 17 00:00:00 2001 From: Ivo Popov Date: Sun, 9 Apr 2023 19:10:01 -0400 Subject: Even when we get an empty "status change" interrupt from the hub, schedule another interrupt poll. During enumeration, when there are multiple devices attached to the hub as it's plugged into the Pi Pico, enumeration hangs, because we get a "status change" callback with value zero. With this patch, we retry several times on "zero" status change callbacks, until eventually we succeed. This is the cheapo hub that exhibits this behavior, but I assume it's not the only one: https://www.amazon.com/gp/product/B083RQMC7S. While debugging this, I consulted the implementation in the Linux kernel. There, hub setup explicitly checks each port individually, before starting to depend on "status change" interrupts: https://elixir.bootlin.com/linux/latest/source/drivers/usb/core/hub.c#L1133. We probably should do something like that here, but it's a much bigger change. --- src/host/hub.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/host/hub.c') diff --git a/src/host/hub.c b/src/host/hub.c index 85bf22b3e..5b2db547d 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -361,6 +361,13 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32 break; } } + + // The status change event was neither for the hub, nor for any of + // its ports. (For example `p_hub->status_change == 0`.) This + // shouldn't happen, but it does with some devices. Initiate the + // next interrupt poll here, because we've scheduled no other work + // whose completion can initiate it. + hub_edpt_status_xfer(dev_addr); } // NOTE: next status transfer is queued by usbh.c after handling this request -- cgit v1.3.1 From 5c428d35a61f7d877cba19d9e094bd519ae91997 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 29 May 2023 13:27:20 +0700 Subject: check status_change is not zero first --- src/host/hub.c | 42 ++++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 24 deletions(-) (limited to 'src/host/hub.c') diff --git a/src/host/hub.c b/src/host/hub.c index 5b2db547d..0807c2023 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -327,51 +327,45 @@ static void connection_clear_conn_change_complete (tuh_xfer_t* xfer); static void connection_port_reset_complete (tuh_xfer_t* xfer); // callback as response of interrupt endpoint polling -bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ +bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { (void) xferred_bytes; // TODO can be more than 1 for hub with lots of ports (void) ep_addr; TU_ASSERT(result == XFER_RESULT_SUCCESS); hub_interface_t* p_hub = get_itf(dev_addr); - TU_LOG2(" Hub Status Change = 0x%02X\r\n", p_hub->status_change); + uint8_t const status_change = p_hub->status_change; + TU_LOG2(" Hub Status Change = 0x%02X\r\n", status_change); - // Hub bit 0 is for the hub device events - if (tu_bit_test(p_hub->status_change, 0)) - { - if (hub_port_get_status(dev_addr, 0, &p_hub->hub_status, hub_get_status_complete, 0) == false) - { + if ( status_change == 0 ) { + // The status change event was neither for the hub, nor for any of its ports. + // This shouldn't happen, but it does with some devices. + // Initiate the next interrupt poll here. + hub_edpt_status_xfer(dev_addr); + return true; + } + + if (tu_bit_test(status_change, 0)) { + // Hub bit 0 is for the hub device events + if (hub_port_get_status(dev_addr, 0, &p_hub->hub_status, hub_get_status_complete, 0) == false) { //Hub status control transfer failed, retry hub_edpt_status_xfer(dev_addr); } } - else - { + else { // Hub bits 1 to n are hub port events - for (uint8_t port=1; port <= p_hub->port_count; port++) - { - if ( tu_bit_test(p_hub->status_change, port) ) - { - if (hub_port_get_status(dev_addr, port, &p_hub->port_status, hub_port_get_status_complete, 0) == false) - { + for (uint8_t port=1; port <= p_hub->port_count; port++) { + if ( tu_bit_test(status_change, port) ) { + if (hub_port_get_status(dev_addr, port, &p_hub->port_status, hub_port_get_status_complete, 0) == false) { //Hub status control transfer failed, retry hub_edpt_status_xfer(dev_addr); } break; } } - - // The status change event was neither for the hub, nor for any of - // its ports. (For example `p_hub->status_change == 0`.) This - // shouldn't happen, but it does with some devices. Initiate the - // next interrupt poll here, because we've scheduled no other work - // whose completion can initiate it. - hub_edpt_status_xfer(dev_addr); } // NOTE: next status transfer is queued by usbh.c after handling this request - return true; } -- cgit v1.3.1 From 20ef6c4ef7f7fa7130352ae0c0984692a9719b35 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 29 May 2023 13:29:11 +0700 Subject: slightly clean up --- src/host/hub.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/host/hub.c') diff --git a/src/host/hub.c b/src/host/hub.c index 0807c2023..182bd6ce8 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -341,8 +341,7 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32 // The status change event was neither for the hub, nor for any of its ports. // This shouldn't happen, but it does with some devices. // Initiate the next interrupt poll here. - hub_edpt_status_xfer(dev_addr); - return true; + return hub_edpt_status_xfer(dev_addr); } if (tu_bit_test(status_change, 0)) { -- cgit v1.3.1 From dc74e634f93962512229ba7d4e14467c16125c0d Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 25 Jul 2023 12:35:40 +0700 Subject: fix unaligned hub status_change --- src/host/hub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/host/hub.c') diff --git a/src/host/hub.c b/src/host/hub.c index 182bd6ce8..16dd534d2 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -45,8 +45,8 @@ typedef struct uint8_t itf_num; uint8_t ep_in; uint8_t port_count; - uint8_t status_change; // data from status change interrupt endpoint + CFG_TUH_MEM_ALIGN uint8_t status_change; CFG_TUH_MEM_ALIGN hub_port_status_response_t port_status; CFG_TUH_MEM_ALIGN hub_status_response_t hub_status; } hub_interface_t; -- cgit v1.3.1 From 1f95a417f271e627ec981be3d211eed8c37cb052 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 7 Aug 2023 18:22:28 +0700 Subject: Add tuh_rhport_is_active() and tuh_rhport_reset_bus() - also improve ehci bus reset - seperate bus reset delay and contact debouncing delay in enumeration --- src/host/hcd.h | 5 +- src/host/hub.c | 2 +- src/host/usbh.c | 118 +++++++++++++++++--------------- src/host/usbh.h | 39 ++++++----- src/portable/chipidea/ci_hs/hcd_ci_hs.c | 43 ++++++------ src/portable/ehci/ehci.c | 24 +++++-- 6 files changed, 128 insertions(+), 103 deletions(-) (limited to 'src/host/hub.c') diff --git a/src/host/hcd.h b/src/host/hcd.h index d77dd6e2f..9bcc1c6df 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -149,10 +149,11 @@ uint32_t hcd_frame_number(uint8_t rhport); // Get the current connect status of roothub port bool hcd_port_connect_status(uint8_t rhport); -// Reset USB bus on the port +// Reset USB bus on the port. Return immediately, bus reset sequence may not be complete. +// Some port would require hcd_port_reset_end() to be invoked after 10ms to complete the reset sequence. void hcd_port_reset(uint8_t rhport); -// TODO implement later +// Complete bus reset sequence, may be required by some controllers void hcd_port_reset_end(uint8_t rhport); // Get port link speed diff --git a/src/host/hub.c b/src/host/hub.c index 16dd534d2..ec30eb96a 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -330,7 +330,7 @@ static void connection_port_reset_complete (tuh_xfer_t* xfer); bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { (void) xferred_bytes; // TODO can be more than 1 for hub with lots of ports (void) ep_addr; - TU_ASSERT(result == XFER_RESULT_SUCCESS); + TU_VERIFY(result == XFER_RESULT_SUCCESS); hub_interface_t* p_hub = get_itf(dev_addr); diff --git a/src/host/usbh.c b/src/host/usbh.c index 49f8c78f1..cc7e38b45 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -181,9 +181,6 @@ static usbh_class_driver_t const usbh_class_drivers[] = }; enum { USBH_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(usbh_class_drivers) }; - -enum { RESET_DELAY = 500 }; // 200 USB specs say only 50ms but many devices require much longer - enum { CONFIG_NUM = 1 }; // default to use configuration 1 @@ -251,40 +248,27 @@ static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t #if CFG_TUSB_OS == OPT_OS_NONE // TODO rework time-related function later -TU_ATTR_WEAK void osal_task_delay(uint32_t msec) -{ +// weak and overridable +TU_ATTR_WEAK void osal_task_delay(uint32_t msec) { const uint32_t start = hcd_frame_number(_usbh_controller); while ( ( hcd_frame_number(_usbh_controller) - start ) < msec ) {} } #endif //--------------------------------------------------------------------+ -// PUBLIC API (Parameter Verification is required) +// Device API //--------------------------------------------------------------------+ -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; - } -} - -bool tuh_mounted(uint8_t dev_addr) -{ - usbh_device_t* dev = get_device(dev_addr); +bool tuh_mounted(uint8_t dev_addr) { + usbh_device_t *dev = get_device(dev_addr); TU_VERIFY(dev); return dev->configured; } -bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t* vid, uint16_t* pid) -{ +bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t *vid, uint16_t *pid) { *vid = *pid = 0; - usbh_device_t const* dev = get_device(dev_addr); + usbh_device_t const *dev = get_device(dev_addr); TU_VERIFY(dev && dev->addressed && dev->vid != 0); *vid = dev->vid; @@ -293,26 +277,48 @@ bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t* vid, uint16_t* pid) return true; } -tusb_speed_t tuh_speed_get (uint8_t dev_addr) -{ - usbh_device_t* dev = get_device(dev_addr); +tusb_speed_t tuh_speed_get(uint8_t dev_addr) { + usbh_device_t *dev = get_device(dev_addr); return (tusb_speed_t) (dev ? get_device(dev_addr)->speed : _dev0.speed); } -static void clear_device(usbh_device_t* dev) -{ +bool tuh_rhport_is_active(uint8_t rhport) { + return _usbh_controller == rhport; +} + +bool tuh_rhport_reset_bus(uint8_t rhport, bool active) { + TU_VERIFY(tuh_rhport_is_active(rhport)); + if ( active ) { + hcd_port_reset(rhport); + } else { + hcd_port_reset_end(rhport); + } + return true; +} + +//--------------------------------------------------------------------+ +// PUBLIC API (Parameter Verification is required) +//--------------------------------------------------------------------+ + +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; + } +} + +static void clear_device(usbh_device_t* dev) { tu_memclr(dev, sizeof(usbh_device_t)); memset(dev->itf2drv, TUSB_INDEX_INVALID_8, sizeof(dev->itf2drv)); // invalid mapping memset(dev->ep2drv , TUSB_INDEX_INVALID_8, sizeof(dev->ep2drv )); // invalid mapping } -bool tuh_inited(void) -{ +bool tuh_inited(void) { return _usbh_controller != TUSB_INDEX_INVALID_8; } -bool tuh_init(uint8_t controller_id) -{ +bool tuh_init(uint8_t controller_id) { // skip if already initialized if ( tuh_inited() ) return true; @@ -359,8 +365,7 @@ bool tuh_init(uint8_t controller_id) return true; } -bool tuh_task_event_ready(void) -{ +bool tuh_task_event_ready(void) { // Skip if stack is not initialized if ( !tuh_inited() ) return false; @@ -385,8 +390,7 @@ bool tuh_task_event_ready(void) } @endcode */ -void tuh_task_ext(uint32_t timeout_ms, bool in_isr) -{ +void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { (void) in_isr; // not implemented yet // Skip if stack is not initialized @@ -403,8 +407,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) case HCD_EVENT_DEVICE_ATTACH: // due to the shared _usbh_ctrl_buf, we must complete enumerating // one device before enumerating another one. - if ( _dev0.enumerating ) - { + if ( _dev0.enumerating ) { TU_LOG_USBH("[%u:] USBH Defer Attach until current enumeration complete\r\n", event.rhport); bool is_empty = osal_queue_empty(_usbh_q); @@ -414,8 +417,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) // Exit if this is the only event in the queue, otherwise we may loop forever return; } - }else - { + }else { TU_LOG_USBH("[%u:] USBH DEVICE ATTACH\r\n", event.rhport); _dev0.enumerating = 1; enum_new_device(&event); @@ -428,8 +430,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) #if CFG_TUH_HUB // TODO remove - if ( event.connection.hub_addr != 0) - { + if ( event.connection.hub_addr != 0) { // done with hub, waiting for next data on status pipe (void) hub_edpt_status_xfer( event.connection.hub_addr ); } @@ -1230,6 +1231,12 @@ static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hu // one device before enumerating another one. //--------------------------------------------------------------------+ +enum { + ENUM_RESET_DELAY = 50, // USB specs: 10 to 50ms + ENUM_CONTACT_DEBOUNCING_DELAY = 450, // when plug/unplug a device, physical connection can be bouncing and may + // generate a series of attach/detach event. This delay wait for stable connection +}; + enum { ENUM_IDLE, ENUM_RESET_1, // 1st reset when attached @@ -1311,7 +1318,7 @@ static void process_enumeration(tuh_xfer_t* xfer) break; case ENUM_HUB_GET_STATUS_2: - osal_task_delay(RESET_DELAY); + osal_task_delay(ENUM_RESET_DELAY); TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, process_enumeration, ENUM_HUB_CLEAR_RESET_2), ); break; @@ -1468,12 +1475,14 @@ static bool enum_new_device(hcd_event_t* event) if (_dev0.hub_addr == 0) { // connected/disconnected directly with roothub - // wait until device is stable TODO non blocking hcd_port_reset(_dev0.rhport); - osal_task_delay(RESET_DELAY); // TODO may not work for no-OS on MCU that require reset_end() since - // sof of controller may not running while resetting + osal_task_delay(ENUM_RESET_DELAY); // TODO may not work for no-OS on MCU that require reset_end() since + // sof of controller may not running while resetting hcd_port_reset_end( _dev0.rhport); + // wait until device connection is stable TODO non blocking + osal_task_delay(ENUM_CONTACT_DEBOUNCING_DELAY); + // device unplugged while delaying if ( !hcd_port_connect_status(_dev0.rhport) ) { enum_full_complete(); @@ -1489,6 +1498,7 @@ static bool enum_new_device(hcd_event_t* event) xfer.result = XFER_RESULT_SUCCESS; xfer.user_data = ENUM_ADDR0_DEVICE_DESC; + process_enumeration(&xfer); } @@ -1496,8 +1506,8 @@ static bool enum_new_device(hcd_event_t* event) else { // connected/disconnected via external hub - // wait until device is stable - osal_task_delay(RESET_DELAY); + // wait until device connection is stable TODO non blocking + osal_task_delay(ENUM_CONTACT_DEBOUNCING_DELAY); // ENUM_HUB_GET_STATUS //TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, enum_hub_get_status0_complete, 0) ); @@ -1508,23 +1518,19 @@ static bool enum_new_device(hcd_event_t* event) return true; } -static uint8_t get_new_address(bool is_hub) -{ +static uint8_t get_new_address(bool is_hub) { uint8_t start; uint8_t end; - if ( is_hub ) - { + if ( is_hub ) { start = CFG_TUH_DEVICE_MAX; end = start + CFG_TUH_HUB; - }else - { + }else { start = 0; end = start + CFG_TUH_DEVICE_MAX; } - for (uint8_t idx = start; idx < end; idx++) - { + for (uint8_t idx = start; idx < end; idx++) { if (!_usbh_devices[idx].connected) return (idx+1); } diff --git a/src/host/usbh.h b/src/host/usbh.h index 0d56f40c9..684e8240e 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -47,8 +47,7 @@ typedef void (*tuh_xfer_cb_t)(tuh_xfer_t* xfer); // it is advised to initialize it using member name // Note2: not all field is available/meaningful in callback, // some info is not saved by usbh to save SRAM -struct tuh_xfer_s -{ +struct tuh_xfer_s { uint8_t daddr; uint8_t ep_addr; uint8_t TU_RESERVED; // reserved @@ -56,8 +55,7 @@ struct tuh_xfer_s uint32_t actual_len; // excluding setup packet - union - { + union { tusb_control_request_t const* setup; // setup packet pointer if control transfer uint32_t buflen; // expected length if not control transfer (not available in callback) }; @@ -70,15 +68,13 @@ struct tuh_xfer_s }; // Subject to change -typedef struct -{ +typedef struct { uint8_t daddr; tusb_desc_interface_t desc; } tuh_itf_info_t; // ConfigID for tuh_config() -enum -{ +enum { TUH_CFGID_RPI_PIO_USB_CONFIGURATION = OPT_MCU_RP2040 << 8 // cfg_param: pio_usb_configuration_t }; @@ -105,12 +101,12 @@ TU_ATTR_WEAK void tuh_umount_cb(uint8_t daddr); // Should be called before tuh_init() // - cfg_id : configure ID (TBD) // - cfg_param: configure data, structure depends on the ID -bool tuh_configure(uint8_t controller_id, uint32_t cfg_id, const void* cfg_param); +bool tuh_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param); // Init host stack -bool tuh_init(uint8_t controller_id); +bool tuh_init(uint8_t rhport); -// Check if host stack is already initialized +// Check if host stack is already initialized with any roothub ports bool tuh_inited(void); // Task function should be called in main/rtos loop, extended version of tuh_task() @@ -120,8 +116,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr); // Task function should be called in main/rtos loop TU_ATTR_ALWAYS_INLINE static inline -void tuh_task(void) -{ +void tuh_task(void) { tuh_task_ext(UINT32_MAX, false); } @@ -135,8 +130,20 @@ extern void hcd_int_handler(uint8_t rhport); // Interrupt handler, name alias to HCD #define tuh_int_handler hcd_int_handler +// Check if roothub port is initialized and active as a host +bool tuh_rhport_is_active(uint8_t rhport); + +// Assert/de-assert Bus Reset signal to roothub port. USB specs: it should last 10-50ms +bool tuh_rhport_reset_bus(uint8_t rhport, bool active); + +//--------------------------------------------------------------------+ +// Device API +//--------------------------------------------------------------------+ + +// Get VID/PID of device bool tuh_vid_pid_get(uint8_t daddr, uint16_t* vid, uint16_t* pid); +// Get speed of device tusb_speed_t tuh_speed_get(uint8_t daddr); // Check if device is connected and configured @@ -144,8 +151,7 @@ bool tuh_mounted(uint8_t daddr); // Check if device is suspended TU_ATTR_ALWAYS_INLINE static inline -bool tuh_suspended(uint8_t daddr) -{ +bool tuh_suspended(uint8_t daddr) { // TODO implement suspend & resume on host (void) daddr; return false; @@ -153,8 +159,7 @@ bool tuh_suspended(uint8_t daddr) // Check if device is ready to communicate with TU_ATTR_ALWAYS_INLINE static inline -bool tuh_ready(uint8_t daddr) -{ +bool tuh_ready(uint8_t daddr) { return tuh_mounted(daddr) && !tuh_suspended(daddr); } diff --git a/src/portable/chipidea/ci_hs/hcd_ci_hs.c b/src/portable/chipidea/ci_hs/hcd_ci_hs.c index 6ee91e18e..462cbd301 100644 --- a/src/portable/chipidea/ci_hs/hcd_ci_hs.c +++ b/src/portable/chipidea/ci_hs/hcd_ci_hs.c @@ -39,24 +39,27 @@ #include "ci_hs_type.h" #if CFG_TUSB_MCU == OPT_MCU_MIMXRT1XXX - #include "ci_hs_imxrt.h" - bool hcd_dcache_clean(void const* addr, uint32_t data_size) { - return imxrt_dcache_clean(addr, data_size); - } +#include "ci_hs_imxrt.h" - bool hcd_dcache_invalidate(void const* addr, uint32_t data_size) { - return imxrt_dcache_invalidate(addr, data_size); - } +bool hcd_dcache_clean(void const* addr, uint32_t data_size) { + return imxrt_dcache_clean(addr, data_size); +} + +bool hcd_dcache_invalidate(void const* addr, uint32_t data_size) { + return imxrt_dcache_invalidate(addr, data_size); +} - bool hcd_dcache_clean_invalidate(void const* addr, uint32_t data_size) { - return imxrt_dcache_clean_invalidate(addr, data_size); - } +bool hcd_dcache_clean_invalidate(void const* addr, uint32_t data_size) { + return imxrt_dcache_clean_invalidate(addr, data_size); +} #elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX) - #include "ci_hs_lpc18_43.h" + +#include "ci_hs_lpc18_43.h" + #else - #error "Unsupported MCUs" +#error "Unsupported MCUs" #endif //--------------------------------------------------------------------+ @@ -67,25 +70,25 @@ // Controller API //--------------------------------------------------------------------+ -bool hcd_init(uint8_t rhport) -{ - ci_hs_regs_t* hcd_reg = CI_HS_REG(rhport); +bool hcd_init(uint8_t rhport) { + ci_hs_regs_t *hcd_reg = CI_HS_REG(rhport); // Reset controller hcd_reg->USBCMD |= USBCMD_RESET; - while( hcd_reg->USBCMD & USBCMD_RESET ) {} + while ( hcd_reg->USBCMD & USBCMD_RESET ) {} // Set mode to device, must be set immediately after reset #if CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX // LPC18XX/43XX need to set VBUS Power Select to HIGH // RHPORT1 is fullspeed only (need external PHY for Highspeed) hcd_reg->USBMODE = USBMODE_CM_HOST | USBMODE_VBUS_POWER_SELECT; - if (rhport == 1) hcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED; + if ( rhport == 1 ) hcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED; #else hcd_reg->USBMODE = USBMODE_CM_HOST; #endif // FIXME force full speed, still have issue with Highspeed enumeration + // probably due to physical connection bouncing when plug/unplug // 1. Have issue when plug/unplug devices, maybe the port is not reset properly // 2. Also does not seems to detect disconnection hcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED; @@ -93,13 +96,11 @@ bool hcd_init(uint8_t rhport) return ehci_init(rhport, (uint32_t) &hcd_reg->CAPLENGTH, (uint32_t) &hcd_reg->USBCMD); } -void hcd_int_enable(uint8_t rhport) -{ +void hcd_int_enable(uint8_t rhport) { CI_HCD_INT_ENABLE(rhport); } -void hcd_int_disable(uint8_t rhport) -{ +void hcd_int_disable(uint8_t rhport) { CI_HCD_INT_DISABLE(rhport); } diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 9be24c888..79811985c 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -188,6 +188,11 @@ void hcd_port_reset(uint8_t rhport) ehci_registers_t* regs = ehci_data.regs; + // skip if already in reset + if (regs->portsc_bm.port_reset) { + return; + } + // mask out Write-1-to-Clear bits uint32_t portsc = regs->portsc & ~EHCI_PORTSC_MASK_W1C; @@ -202,16 +207,18 @@ void hcd_port_reset(uint8_t rhport) void hcd_port_reset_end(uint8_t rhport) { (void) rhport; - -#if 0 // TODO check if this is necessary ehci_registers_t* regs = ehci_data.regs; + // skip if reset is already complete + if (!regs->portsc_bm.port_reset) { + return; + } + // mask out all change bits since they are Write 1 to clear - uint32_t portsc = regs->portsc & ~EHCI_PORTSC_MASK_CHANGE_ALL; - portsc &= ~(EHCI_PORTSC_MASK_PORT_RESET); + uint32_t portsc = regs->portsc & ~EHCI_PORTSC_MASK_W1C; + portsc &= ~EHCI_PORTSC_MASK_PORT_RESET; regs->portsc = portsc; -#endif } bool hcd_port_connect_status(uint8_t rhport) @@ -426,6 +433,11 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet hcd_dcache_clean(setup_packet, 8); + // Control endpoint never be stalled. Skip reset Data Toggle since it is fixed per stage + if (qhd->qtd_overlay.halted) { + qhd->qtd_overlay.halted = false; + } + // attach TD to QHD -> start transferring qhd_attach_qtd(qhd, td); @@ -662,7 +674,7 @@ void hcd_int_handler(uint8_t rhport) if (int_status & EHCI_INT_MASK_PORT_CHANGE) { // Including: Force port resume, over-current change, enable/disable change and connect status change. uint32_t const port_status = regs->portsc & EHCI_PORTSC_MASK_W1C; - print_portsc(regs); + // print_portsc(regs); if (regs->portsc_bm.connect_status_change) { port_connect_status_change_isr(rhport); -- cgit v1.3.1 From 1b33a315365184a74a8b5bbce5fdbdfc4dfe6f69 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 15 Aug 2023 22:51:21 +0700 Subject: more minor clean up - also rename usbh_classdriver.h to usbh_pvt.h to consitent with usbd --- src/class/cdc/cdc_host.c | 2 +- src/class/hid/hid_host.c | 2 +- src/class/msc/msc_host.c | 2 +- src/device/usbd.c | 31 +++++-------- src/device/usbd_pvt.h | 2 +- src/host/hub.c | 2 +- src/host/usbh.c | 84 ++++++++++++++++----------------- src/host/usbh_classdriver.h | 111 -------------------------------------------- src/host/usbh_pvt.h | 108 ++++++++++++++++++++++++++++++++++++++++++ src/tusb.c | 2 +- 10 files changed, 164 insertions(+), 182 deletions(-) delete mode 100644 src/host/usbh_classdriver.h create mode 100644 src/host/usbh_pvt.h (limited to 'src/host/hub.c') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 40ebd331d..53e15710e 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -29,7 +29,7 @@ #if (CFG_TUH_ENABLED && CFG_TUH_CDC) #include "host/usbh.h" -#include "host/usbh_classdriver.h" +#include "host/usbh_pvt.h" #include "cdc_host.h" diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 4253170d4..a3551c85a 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -29,7 +29,7 @@ #if (CFG_TUH_ENABLED && CFG_TUH_HID) #include "host/usbh.h" -#include "host/usbh_classdriver.h" +#include "host/usbh_pvt.h" #include "hid_host.h" diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 90a58d3d0..da264142c 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -29,7 +29,7 @@ #if CFG_TUH_ENABLED && CFG_TUH_MSC #include "host/usbh.h" -#include "host/usbh_classdriver.h" +#include "host/usbh_pvt.h" #include "msc_host.h" diff --git a/src/device/usbd.c b/src/device/usbd.c index 156b92ce1..f0d9fba52 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -238,34 +238,25 @@ enum { BUILTIN_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; tu_static usbd_class_driver_t const * _app_driver = NULL; tu_static uint8_t _app_driver_count = 0; +#define TOTAL_DRIVER_COUNT (_app_driver_count + BUILTIN_DRIVER_COUNT) + // virtually joins built-in and application drivers together. // Application is positioned first to allow overwriting built-in ones. static inline usbd_class_driver_t const * get_driver(uint8_t drvid) { - // Application drivers - if ( usbd_app_driver_get_cb ) - { - if ( drvid < _app_driver_count ) return &_app_driver[drvid]; - drvid -= _app_driver_count; - } - - // when there is no built-in drivers BUILTIN_DRIVER_COUNT = 0 will cause -Wtype-limits warning -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wtype-limits" -#endif - - // Built-in drivers - if (drvid < BUILTIN_DRIVER_COUNT) return &_usbd_driver[drvid]; + usbd_class_driver_t const * driver = NULL; -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif + if ( drvid < _app_driver_count ) { + // Application drivers + driver = &_app_driver[drvid]; + } else if ( drvid < TOTAL_DRIVER_COUNT && BUILTIN_DRIVER_COUNT > 0 ){ + driver = &_usbd_driver[drvid - _app_driver_count]; + } - return NULL; + return driver; } -#define TOTAL_DRIVER_COUNT (_app_driver_count + BUILTIN_DRIVER_COUNT) + //--------------------------------------------------------------------+ // DCD Event diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 940b2858b..16585167f 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -59,7 +59,7 @@ typedef struct } usbd_class_driver_t; // Invoked when initializing device stack to get additional class drivers. -// Can optionally implemented by application to extend/overwrite class driver support. +// Can be implemented by application to extend/overwrite class driver support. // Note: The drivers array must be accessible at all time when stack is active usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) TU_ATTR_WEAK; diff --git a/src/host/hub.c b/src/host/hub.c index ec30eb96a..32f5e0ac7 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -30,7 +30,7 @@ #include "hcd.h" #include "usbh.h" -#include "usbh_classdriver.h" +#include "usbh_pvt.h" #include "hub.h" // Debug level, TUSB_CFG_DEBUG must be at least this level for debug message diff --git a/src/host/usbh.c b/src/host/usbh.c index af8142be3..739157b56 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -30,7 +30,7 @@ #include "host/hcd.h" #include "tusb.h" -#include "host/usbh_classdriver.h" +#include "host/usbh_pvt.h" #include "hub.h" //--------------------------------------------------------------------+ @@ -183,6 +183,23 @@ static usbh_class_driver_t const usbh_class_drivers[] = enum { USBH_BUILTIN_DRIVER_COUNT = TU_ARRAY_SIZE(usbh_class_drivers) }; enum { CONFIG_NUM = 1 }; // default to use configuration 1 +// Additional class drivers implemented by application +tu_static usbh_class_driver_t const * _app_driver = NULL; +tu_static uint8_t _app_driver_count = 0; + +#define TOTAL_DRIVER_COUNT (_app_driver_count + USBH_BUILTIN_DRIVER_COUNT) + +static inline usbh_class_driver_t const *get_driver(uint8_t drv_id) { + usbh_class_driver_t const *driver = NULL; + + if ( drv_id < _app_driver_count ) { + driver = &_app_driver[drv_id]; + } else if ( drv_id < TOTAL_DRIVER_COUNT && USBH_BUILTIN_DRIVER_COUNT > 0) { + driver = &usbh_class_drivers[drv_id - _app_driver_count]; + } + + return driver; +} //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION @@ -246,21 +263,6 @@ static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hu 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); -// Additional class drivers implemented by application -tu_static usbh_class_driver_t const * _app_driver = NULL; -tu_static uint8_t _app_driver_count = 0; -tu_static uint8_t _total_driver_count = USBH_BUILTIN_DRIVER_COUNT; - -static usbh_class_driver_t const * usbh_get_driver(uint8_t drv_id) -{ - usbh_class_driver_t const * driver = NULL; - if ( drv_id < _app_driver_count ) - driver = &_app_driver[drv_id]; - else if ( drv_id < _total_driver_count ) - driver = &usbh_class_drivers[drv_id - _app_driver_count]; - return driver; -} - #if CFG_TUSB_OS == OPT_OS_NONE // TODO rework time-related function later // weak and overridable @@ -354,11 +356,10 @@ bool tuh_init(uint8_t controller_id) { _usbh_mutex = osal_mutex_create(&_usbh_mutexdef); TU_ASSERT(_usbh_mutex); #endif + // Get application driver if available - if ( usbh_app_driver_get_cb ) - { + if ( usbh_app_driver_get_cb ) { _app_driver = usbh_app_driver_get_cb(&_app_driver_count); - _total_driver_count = USBH_BUILTIN_DRIVER_COUNT + _app_driver_count; } // Device @@ -372,9 +373,9 @@ bool tuh_init(uint8_t controller_id) { } // Class drivers - for (uint8_t drv_id = 0; drv_id < _total_driver_count; drv_id++) + for (uint8_t drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) { - usbh_class_driver_t const * driver = usbh_get_driver(drv_id); + usbh_class_driver_t const * driver = get_driver(drv_id); if ( driver ) { TU_LOG_USBH("%s init\r\n", driver->name); @@ -508,12 +509,12 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { #endif { uint8_t drv_id = dev->ep2drv[epnum][ep_dir]; - usbh_class_driver_t const * driver = usbh_get_driver(drv_id); + usbh_class_driver_t const * driver = get_driver(drv_id); if ( driver ) { 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); + event.xfer_complete.len); } else { @@ -1220,12 +1221,10 @@ static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hu // 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)) - { + (hub_port == 0 || dev->hub_port == hub_port)) { TU_LOG_USBH("Device unplugged address = %u\r\n", daddr); - if (is_hub_addr(daddr)) - { + if (is_hub_addr(daddr)) { TU_LOG(CFG_TUH_LOG_LEVEL, " is a HUB device %u\r\n", daddr); // Submit removed event If the device itself is a hub (un-rolled recursive) @@ -1243,14 +1242,11 @@ static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hu } // Close class driver - for (uint8_t drv_id = 0; drv_id < _total_driver_count; drv_id++) - { - usbh_class_driver_t const * driver = usbh_get_driver(drv_id); - if ( driver ) - { - driver->close(daddr); - } + 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); } + hcd_device_close(rhport, daddr); clear_device(dev); // abort on-going control xfer if any @@ -1679,10 +1675,9 @@ static bool _parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configur TU_ASSERT(drv_len >= sizeof(tusb_desc_interface_t)); // Find driver for this interface - uint8_t drv_id = 0; - for (; drv_id < _total_driver_count; drv_id++) + for (uint8_t drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) { - usbh_class_driver_t const * driver = usbh_get_driver(drv_id); + usbh_class_driver_t const * driver = get_driver(drv_id); if (driver && driver->open(dev->rhport, dev_addr, desc_itf, drv_len) ) { @@ -1705,12 +1700,11 @@ static bool _parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configur break; // exit driver find loop } - } - - if( drv_id >= _total_driver_count ) - { - TU_LOG(CFG_TUH_LOG_LEVEL, "Interface %u: class = %u subclass = %u protocol = %u is not supported\r\n", - desc_itf->bInterfaceNumber, desc_itf->bInterfaceClass, desc_itf->bInterfaceSubClass, desc_itf->bInterfaceProtocol); + if ( drv_id == TOTAL_DRIVER_COUNT - 1 ) + { + TU_LOG(CFG_TUH_LOG_LEVEL, "[%u:%u] Interface %u: class = %u subclass = %u protocol = %u is not supported\r\n", + dev->rhport, dev_addr, desc_itf->bInterfaceNumber, desc_itf->bInterfaceClass, desc_itf->bInterfaceSubClass, desc_itf->bInterfaceProtocol); + } } // next Interface or IAD descriptor @@ -1730,9 +1724,9 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) // IAD binding interface such as CDCs should return itf_num + 1 when complete // with usbh_driver_set_config_complete() uint8_t const drv_id = dev->itf2drv[itf_num]; - if (drv_id != TUSB_INDEX_INVALID_8) + usbh_class_driver_t const * driver = get_driver(drv_id); + if (driver) { - usbh_class_driver_t const * driver = usbh_get_driver(drv_id); TU_LOG_USBH("%s set config: itf = %u\r\n", driver->name, itf_num); driver->set_config(dev_addr, itf_num); break; diff --git a/src/host/usbh_classdriver.h b/src/host/usbh_classdriver.h deleted file mode 100644 index 7443b2d90..000000000 --- a/src/host/usbh_classdriver.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_USBH_CLASSDRIVER_H_ -#define _TUSB_USBH_CLASSDRIVER_H_ - -#include "osal/osal.h" -#include "common/tusb_fifo.h" -#include "common/tusb_private.h" - -#ifdef __cplusplus - extern "C" { -#endif - -// Level where CFG_TUSB_DEBUG must be at least for USBH is logged -#ifndef CFG_TUH_LOG_LEVEL - #define CFG_TUH_LOG_LEVEL 2 -#endif - -#define TU_LOG_USBH(...) TU_LOG(CFG_TUH_LOG_LEVEL, __VA_ARGS__) - -enum { - USBH_EPSIZE_BULK_MAX = (TUH_OPT_HIGH_SPEED ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS) -}; - -//--------------------------------------------------------------------+ -// Class Driver API -//--------------------------------------------------------------------+ - -typedef struct { - #if CFG_TUSB_DEBUG >= 2 - char const* name; - #endif - - void (* const init )(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); - void (* const close )(uint8_t dev_addr); -} usbh_class_driver_t; - -// Call by class driver to tell USBH that it has complete the enumeration -void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num); - -uint8_t usbh_get_rhport(uint8_t dev_addr); - -uint8_t* usbh_get_enum_buf(void); - -void usbh_int_set(bool enabled); - -//--------------------------------------------------------------------+ -// USBH Endpoint API -//--------------------------------------------------------------------+ - -// Submit a usb transfer with callback support, require CFG_TUH_API_EDPT_XFER -bool usbh_edpt_xfer_with_callback(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, - tuh_xfer_cb_t complete_cb, uintptr_t user_data); - -TU_ATTR_ALWAYS_INLINE -static inline bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) -{ - return usbh_edpt_xfer_with_callback(dev_addr, ep_addr, buffer, total_bytes, NULL, 0); -} - - -// Claim an endpoint before submitting a transfer. -// If caller does not make any transfer, it must release endpoint for others. -bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr); - -// Release claimed endpoint without submitting a transfer -bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr); - -// Check if endpoint transferring is complete -bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr); - -//--------------------------------------------------------------------+ -// USBH application additional driver API -//--------------------------------------------------------------------+ -// Invoked when initializing host stack to get additional class drivers. -// Can optionally implemented by application to extend/overwrite class driver support. -// Note: The drivers array must be accessible at all time when stack is active -usbh_class_driver_t const* usbh_app_driver_get_cb(uint8_t* driver_count) TU_ATTR_WEAK; - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/src/host/usbh_pvt.h b/src/host/usbh_pvt.h new file mode 100644 index 000000000..0b58a91bc --- /dev/null +++ b/src/host/usbh_pvt.h @@ -0,0 +1,108 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_USBH_CLASSDRIVER_H_ +#define _TUSB_USBH_CLASSDRIVER_H_ + +#include "osal/osal.h" +#include "common/tusb_fifo.h" +#include "common/tusb_private.h" + +#ifdef __cplusplus + extern "C" { +#endif + +// Level where CFG_TUSB_DEBUG must be at least for USBH is logged +#ifndef CFG_TUH_LOG_LEVEL + #define CFG_TUH_LOG_LEVEL 2 +#endif + +#define TU_LOG_USBH(...) TU_LOG(CFG_TUH_LOG_LEVEL, __VA_ARGS__) + +enum { + USBH_EPSIZE_BULK_MAX = (TUH_OPT_HIGH_SPEED ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS) +}; + +//--------------------------------------------------------------------+ +// Class Driver API +//--------------------------------------------------------------------+ + +typedef struct { + #if CFG_TUSB_DEBUG >= 2 + char const* name; + #endif + + void (* const init )(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); + void (* const close )(uint8_t dev_addr); +} usbh_class_driver_t; + +// Invoked when initializing host stack to get additional class drivers. +// Can be implemented by application to extend/overwrite class driver support. +// Note: The drivers array must be accessible at all time when stack is active +usbh_class_driver_t const* usbh_app_driver_get_cb(uint8_t* driver_count) TU_ATTR_WEAK; + +// Call by class driver to tell USBH that it has complete the enumeration +void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num); + +uint8_t usbh_get_rhport(uint8_t dev_addr); + +uint8_t* usbh_get_enum_buf(void); + +void usbh_int_set(bool enabled); + +//--------------------------------------------------------------------+ +// USBH Endpoint API +//--------------------------------------------------------------------+ + +// Submit a usb transfer with callback support, require CFG_TUH_API_EDPT_XFER +bool usbh_edpt_xfer_with_callback(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, + tuh_xfer_cb_t complete_cb, uintptr_t user_data); + +TU_ATTR_ALWAYS_INLINE +static inline bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +{ + return usbh_edpt_xfer_with_callback(dev_addr, ep_addr, buffer, total_bytes, NULL, 0); +} + + +// Claim an endpoint before submitting a transfer. +// If caller does not make any transfer, it must release endpoint for others. +bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr); + +// Release claimed endpoint without submitting a transfer +bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr); + +// Check if endpoint transferring is complete +bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr); + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/src/tusb.c b/src/tusb.c index 465b608b0..7b0a669a0 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -36,7 +36,7 @@ #endif #if CFG_TUH_ENABLED -#include "host/usbh_classdriver.h" +#include "host/usbh_pvt.h" #endif //--------------------------------------------------------------------+ -- cgit v1.3.1 From a4aa454a7a21c022569eccfea493b8a96d182d9c Mon Sep 17 00:00:00 2001 From: Ryzee119 Date: Sun, 7 Jan 2024 08:25:31 +1030 Subject: [HUB] Fix double status xfer --- src/host/hub.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src/host/hub.c') diff --git a/src/host/hub.c b/src/host/hub.c index 32f5e0ac7..3bac18698 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -435,9 +435,12 @@ static void hub_port_get_status_complete (tuh_xfer_t* xfer) // Other changes are: L1 state // TODO clear change - // prepare for next hub status - // TODO continue with status_change, or maybe we can do it again with status - hub_edpt_status_xfer(daddr); + else + { + // prepare for next hub status + // TODO continue with status_change, or maybe we can do it again with status + hub_edpt_status_xfer(daddr); + } } } -- cgit v1.3.1 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/class/cdc/cdc_host.c | 4 ++++ src/class/cdc/cdc_host.h | 1 + src/class/hid/hid_host.c | 4 ++++ src/class/hid/hid_host.h | 1 + src/class/msc/msc_host.c | 5 +++++ src/class/msc/msc_host.h | 1 + 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 +--- src/tusb_option.h | 5 +++++ 13 files changed, 76 insertions(+), 19 deletions(-) (limited to 'src/host/hub.c') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 2fb37d835..14f380b40 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -637,6 +637,10 @@ void cdch_init(void) { } } +bool cdch_deinit(void) { + return true; +} + void cdch_close(uint8_t daddr) { for (uint8_t idx = 0; idx < CFG_TUH_CDC; idx++) { cdch_interface_t* p_cdc = &cdch_data[idx]; diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index d512a23a5..7530b1e9d 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -193,6 +193,7 @@ TU_ATTR_WEAK extern void tuh_cdc_tx_complete_cb(uint8_t idx); // Internal Class Driver API //--------------------------------------------------------------------+ void 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); bool cdch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 7330fa237..16e2d3c2c 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -376,6 +376,10 @@ void hidh_init(void) { tu_memclr(_hidh_itf, sizeof(_hidh_itf)); } +bool hidh_deinit(void) { + return true; +} + bool hidh_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { (void) result; diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 17f4e27c0..9ea222b3d 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -164,6 +164,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_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); bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 39f2d9f1c..61ecb8e4e 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -288,6 +288,11 @@ void msch_init(void) { tu_memclr(_msch_itf, sizeof(_msch_itf)); } +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 9ca1b4703..5bf2e62e3 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -114,6 +114,7 @@ TU_ATTR_WEAK void tuh_msc_umount_cb(uint8_t dev_addr); //--------------------------------------------------------------------+ void 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); void msch_close (uint8_t dev_addr); 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); diff --git a/src/tusb_option.h b/src/tusb_option.h index 96378cb80..22f27e9e1 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -29,9 +29,14 @@ #include "common/tusb_compiler.h" +// Version is release as major.minor.revision eg 1.0.0. though there could be notable APIs before a new release. +// For notable API changes within a release, we increase the build number. #define TUSB_VERSION_MAJOR 0 #define TUSB_VERSION_MINOR 16 #define TUSB_VERSION_REVISION 0 +#define TUSB_VERSION_BUILD 1 + +#define TUSB_VERSION_NUMBER (TUSB_VERSION_MAJOR << 24 | TUSB_VERSION_MINOR << 16 | TUSB_VERSION_REVISION << 8 | TUSB_VERSION_BUILD) #define TUSB_VERSION_STRING TU_STRING(TUSB_VERSION_MAJOR) "." TU_STRING(TUSB_VERSION_MINOR) "." TU_STRING(TUSB_VERSION_REVISION) //--------------------------------------------------------------------+ -- 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/hub.c') 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