From 1cef2b6a42d93704847c1a6ab82617e5baf04f4a Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Aug 2021 18:01:10 +0700 Subject: extra common edpt helper for device and host stack tu_edpt_validate() and tu_edpt_bind_driver() --- src/host/usbh.c | 338 ++++++++++++++++++++++++-------------------- src/host/usbh_classdriver.h | 2 + 2 files changed, 186 insertions(+), 154 deletions(-) (limited to 'src/host') diff --git a/src/host/usbh.c b/src/host/usbh.c index 93621c42a..36c2ea7c8 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -28,16 +28,23 @@ #if TUSB_OPT_HOST_ENABLED -#ifndef CFG_TUH_TASK_QUEUE_SZ -#define CFG_TUH_TASK_QUEUE_SZ 16 -#endif - #include "tusb.h" #include "host/usbh.h" #include "host/usbh_classdriver.h" #include "hub.h" #include "usbh_hcd.h" +//--------------------------------------------------------------------+ +// USBH Configuration +//--------------------------------------------------------------------+ + +#ifndef CFG_TUH_TASK_QUEUE_SZ +#define CFG_TUH_TASK_QUEUE_SZ 16 +#endif + +// Debug level of USBD +#define USBH_DBG_LVL 2 + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -135,6 +142,7 @@ CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbh_ctrl_buf[CFG_TUH_EN //------------- Helper Function Prototypes -------------// static bool enum_new_device(hcd_event_t* event); static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port); +static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size); // from usbh_control.c extern bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); @@ -314,151 +322,6 @@ uint8_t* usbh_get_enum_buf(void) return _usbh_ctrl_buf; } -//--------------------------------------------------------------------+ -// Endpoint API -//--------------------------------------------------------------------+ - -// TODO has some duplication code with device, refactor later -bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - usbh_device_t* dev = &_usbh_devices[dev_addr]; - -#if CFG_TUSB_OS != OPT_OS_NONE - // pre-check to help reducing mutex lock - TU_VERIFY((dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0)); - osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER); -#endif - - // can only claim the endpoint if it is not busy and not claimed yet. - bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0); - if (ret) - { - dev->ep_status[epnum][dir].claimed = 1; - } - -#if CFG_TUSB_OS != OPT_OS_NONE - osal_mutex_unlock(dev->mutex); -#endif - - return ret; -} - -// TODO has some duplication code with device, refactor later -bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - usbh_device_t* dev = &_usbh_devices[dev_addr]; - -#if CFG_TUSB_OS != OPT_OS_NONE - osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER); -#endif - - // can only release the endpoint if it is claimed and not busy - bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 1); - if (ret) - { - dev->ep_status[epnum][dir].claimed = 0; - } - -#if CFG_TUSB_OS != OPT_OS_NONE - osal_mutex_unlock(dev->mutex); -#endif - - return ret; -} - -// TODO has some duplication code with device, refactor later -bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - usbh_device_t* dev = &_usbh_devices[dev_addr]; - - TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); - - // Attempt to transfer on a busy endpoint, sound like an race condition ! - TU_ASSERT(dev->ep_status[epnum][dir].busy == 0); - - // Set busy first since the actual transfer can be complete before hcd_edpt_xfer() - // could return and USBH task can preempt and clear the busy - dev->ep_status[epnum][dir].busy = true; - - if ( hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes) ) - { - TU_LOG2("OK\r\n"); - return true; - }else - { - // HCD error, mark endpoint as ready to allow next transfer - dev->ep_status[epnum][dir].busy = false; - dev->ep_status[epnum][dir].claimed = 0; - TU_LOG2("failed\r\n"); - TU_BREAKPOINT(); - return false; - } -} - -bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) -{ - TU_LOG2("Open EP Control with Size = %u\r\n", max_packet_size); - - tusb_desc_endpoint_t ep0_desc = - { - .bLength = sizeof(tusb_desc_endpoint_t), - .bDescriptorType = TUSB_DESC_ENDPOINT, - .bEndpointAddress = 0, - .bmAttributes = { .xfer = TUSB_XFER_CONTROL }, - .wMaxPacketSize = { .size = max_packet_size }, - .bInterval = 0 - }; - - return hcd_edpt_open(_usbh_devices[dev_addr].rhport, dev_addr, &ep0_desc); -} - -bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep) -{ - TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, desc_ep->wMaxPacketSize.size); - - bool ret = hcd_edpt_open(rhport, dev_addr, desc_ep); - - if (ret) - { - usbh_device_t* dev = &_usbh_devices[dev_addr]; - - // new endpoints belongs to latest interface (last valid value) - // TODO FIXME not true with ISO - uint8_t drvid = 0xff; - for(uint8_t i=0; i < sizeof(dev->itf2drv); i++) - { - if ( dev->itf2drv[i] == 0xff ) break; - drvid = dev->itf2drv[i]; - } - TU_ASSERT(drvid < USBH_CLASS_DRIVER_COUNT); - - uint8_t const ep_addr = desc_ep->bEndpointAddress; - dev->ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = drvid; - } - - return ret; -} - -bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - usbh_device_t* dev = &_usbh_devices[dev_addr]; - - return dev->ep_status[epnum][dir].busy; -} - - //--------------------------------------------------------------------+ // HCD Event Handler //--------------------------------------------------------------------+ @@ -841,7 +704,7 @@ static bool enum_set_address_complete(uint8_t dev_addr, tusb_control_request_t c dev0->state = TUSB_DEVICE_STATE_UNPLUG; // open control pipe for new address - TU_ASSERT ( usbh_edpt_control_open(new_addr, new_dev->ep0_packet_size) ); + TU_ASSERT( usbh_edpt_control_open(new_addr, new_dev->ep0_packet_size) ); // Get full device descriptor TU_LOG2("Get Device Descriptor\r\n"); @@ -981,6 +844,34 @@ static bool enum_set_config_complete(uint8_t dev_addr, tusb_control_request_t co return true; } +// Get total length of n interface (depending on IAD) +static uint16_t get_interface_length(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len) +{ + uint8_t const* p_desc = (uint8_t const*) desc_itf; + uint16_t len = 0; + + while (itf_count--) + { + // Next on interface desc + len += tu_desc_len(desc_itf); + p_desc = tu_desc_next(p_desc); + + while (len < max_len) + { + // return on IAD regardless of itf count + if ( tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION ) return len; + + if ( (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) && + ((tusb_desc_interface_t const*) p_desc)->bAlternateSetting == 0 ) break; + + len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + } + + return len; +} + static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg) { usbh_device_t* dev = &_usbh_devices[dev_addr]; @@ -992,20 +883,25 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura while( p_desc < desc_end ) { // TODO Do we need to use IAD - // tusb_desc_interface_assoc_t const * desc_itf_assoc = NULL; + tusb_desc_interface_assoc_t const * desc_iad = NULL; // Class will always starts with Interface Association (if any) and then Interface descriptor if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) ) { - // desc_itf_assoc = (tusb_desc_interface_assoc_t const *) p_desc; + desc_iad = (tusb_desc_interface_assoc_t const *) p_desc; p_desc = tu_desc_next(p_desc); } + TU_LOG_INT(2, p_desc - (uint8_t*) desc_cfg); + TU_LOG_INT(2, tu_desc_type(p_desc)); TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; uint16_t const remaining_len = desc_end-p_desc; + uint16_t const drv_len = get_interface_length(desc_itf, desc_iad ? desc_iad->bInterfaceCount : 1, remaining_len); + TU_ASSERT(drv_len); + // Check if class is supported TODO drop class_code uint8_t drv_id; for (drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) @@ -1015,8 +911,11 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura if( drv_id >= USBH_CLASS_DRIVER_COUNT ) { - // skip unsupported class - p_desc = tu_desc_next(p_desc); + TU_LOG(USBH_DBG_LVL, "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); + + // skip unsupported class until next Interface or IAD descriptor + p_desc += drv_len; } else { @@ -1038,6 +937,10 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura uint16_t const itf_len = driver->open(dev->rhport, dev_addr, desc_itf, remaining_len); TU_ASSERT( sizeof(tusb_desc_interface_t) <= itf_len && itf_len <= remaining_len); + + // bind all endpoints for this driver + tu_edpt_bind_driver(dev->ep2drv, desc_itf, drv_len, drv_id); + p_desc += itf_len; } } @@ -1046,4 +949,131 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura return true; } +//--------------------------------------------------------------------+ +// Endpoint API +//--------------------------------------------------------------------+ + +// TODO has some duplication code with device, refactor later +bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + usbh_device_t* dev = &_usbh_devices[dev_addr]; + +#if CFG_TUSB_OS != OPT_OS_NONE + // pre-check to help reducing mutex lock + TU_VERIFY((dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0)); + osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER); +#endif + + // can only claim the endpoint if it is not busy and not claimed yet. + bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0); + if (ret) + { + dev->ep_status[epnum][dir].claimed = 1; + } + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_unlock(dev->mutex); +#endif + + return ret; +} + +// TODO has some duplication code with device, refactor later +bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + usbh_device_t* dev = &_usbh_devices[dev_addr]; + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER); +#endif + + // can only release the endpoint if it is claimed and not busy + bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 1); + if (ret) + { + dev->ep_status[epnum][dir].claimed = 0; + } + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_unlock(dev->mutex); +#endif + + return ret; +} + +// TODO has some duplication code with device, refactor later +bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + usbh_device_t* dev = &_usbh_devices[dev_addr]; + + TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); + + // Attempt to transfer on a busy endpoint, sound like an race condition ! + TU_ASSERT(dev->ep_status[epnum][dir].busy == 0); + + // Set busy first since the actual transfer can be complete before hcd_edpt_xfer() + // could return and USBH task can preempt and clear the busy + dev->ep_status[epnum][dir].busy = true; + + if ( hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes) ) + { + TU_LOG2("OK\r\n"); + return true; + }else + { + // HCD error, mark endpoint as ready to allow next transfer + dev->ep_status[epnum][dir].busy = false; + dev->ep_status[epnum][dir].claimed = 0; + TU_LOG2("failed\r\n"); + TU_BREAKPOINT(); + return false; + } +} + +static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) +{ + TU_LOG2("Open EP Control with Size = %u\r\n", max_packet_size); + + tusb_desc_endpoint_t ep0_desc = + { + .bLength = sizeof(tusb_desc_endpoint_t), + .bDescriptorType = TUSB_DESC_ENDPOINT, + .bEndpointAddress = 0, + .bmAttributes = { .xfer = TUSB_XFER_CONTROL }, + .wMaxPacketSize = { .size = max_packet_size }, + .bInterval = 0 + }; + + return hcd_edpt_open(_usbh_devices[dev_addr].rhport, dev_addr, &ep0_desc); +} + +bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep) +{ + usbh_device_t* dev = &_usbh_devices[dev_addr]; + TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) dev->speed)); + + return hcd_edpt_open(rhport, dev_addr, desc_ep); +} + +bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + usbh_device_t* dev = &_usbh_devices[dev_addr]; + + return dev->ep_status[epnum][dir].busy; +} + + + #endif diff --git a/src/host/usbh_classdriver.h b/src/host/usbh_classdriver.h index 0736fefa1..b05a33580 100644 --- a/src/host/usbh_classdriver.h +++ b/src/host/usbh_classdriver.h @@ -73,6 +73,8 @@ bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_ // If caller does not make any transfer, it must release endpoint for others. bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr); +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); -- cgit v1.3.1 From 62f2efbe8cf1e61f70660abac28f4226bca93daf Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Aug 2021 18:26:56 +0700 Subject: hid host skip get report descriptor if too large instead of assert --- examples/host/cdc_msc_hid/src/hid_app.c | 2 ++ src/class/hid/hid_host.c | 58 +++++++++++++++++++++------------ src/class/hid/hid_host.h | 2 ++ src/host/usbh.c | 2 -- 4 files changed, 41 insertions(+), 23 deletions(-) (limited to 'src/host') diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index 420600f9a..5e3ac6a72 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -61,6 +61,8 @@ void hid_app_task(void) // Invoked when device with hid interface is mounted // Report descriptor is also available for use. tuh_hid_parse_report_descriptor() // can be used to parse common/simple enough descriptor. +// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped +// therefore report_desc = NULL, desc_len = 0 void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) { printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance); diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 40b6f5631..a39ac8bec 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -247,6 +247,8 @@ static bool config_set_protocol (uint8_t dev_addr, tusb_control_requ static bool config_get_report_desc (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool config_get_report_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len); + uint16_t hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) { (void) max_len; @@ -367,26 +369,34 @@ static bool config_get_report_desc(uint8_t dev_addr, tusb_control_request_t cons uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - // Get Report Descriptor + // Get Report Descriptor if possible // using usbh enumeration buffer since report descriptor can be very long - TU_ASSERT( hid_itf->report_desc_len <= CFG_TUH_ENUMERATION_BUFSIZE ); + if( hid_itf->report_desc_len > CFG_TUH_ENUMERATION_BUFSIZE ) + { + TU_LOG2("HID Skip Report Descriptor since it is too large %u bytes\r\n", hid_itf->report_desc_len); - TU_LOG2("HID Get Report Descriptor\r\n"); - tusb_control_request_t const new_request = + // Driver is mounted without report descriptor + config_driver_mount_complete(dev_addr, instance, NULL, 0); + }else { - .bmRequestType_bit = + TU_LOG2("HID Get Report Descriptor\r\n"); + tusb_control_request_t const new_request = { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_IN - }, - .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = tu_u16(hid_itf->report_desc_type, 0), - .wIndex = itf_num, - .wLength = hid_itf->report_desc_len - }; + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_IN + }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = tu_u16(hid_itf->report_desc_type, 0), + .wIndex = itf_num, + .wLength = hid_itf->report_desc_len + }; + + TU_ASSERT(tuh_control_xfer(dev_addr, &new_request, usbh_get_enum_buf(), config_get_report_desc_complete)); + } - TU_ASSERT(tuh_control_xfer(dev_addr, &new_request, usbh_get_enum_buf(), config_get_report_desc_complete)); return true; } @@ -394,13 +404,21 @@ static bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_reque { TU_ASSERT(XFER_RESULT_SUCCESS == result); - uint8_t const itf_num = (uint8_t) request->wIndex; - uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + uint8_t const itf_num = (uint8_t) request->wIndex; + uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); uint8_t const* desc_report = usbh_get_enum_buf(); uint16_t const desc_len = request->wLength; + config_driver_mount_complete(dev_addr, instance, desc_report, desc_len); + + return true; +} + +static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) +{ + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + // enumeration is complete tuh_hid_mount_cb(dev_addr, instance, desc_report, desc_len); @@ -408,9 +426,7 @@ static bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_reque hidh_get_report(dev_addr, hid_itf); // notify usbh that driver enumeration is complete - usbh_driver_set_config_complete(dev_addr, itf_num); - - return true; + usbh_driver_set_config_complete(dev_addr, hid_itf->itf_num); } //--------------------------------------------------------------------+ diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index ef203123d..bbef05e25 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -97,6 +97,8 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, // Invoked when device with hid interface is mounted // Report descriptor is also available for use. tuh_hid_parse_report_descriptor() // can be used to parse common/simple enough descriptor. +// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped +// therefore report_desc = NULL, desc_len = 0 void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len); // Invoked when device with hid interface is un-mounted diff --git a/src/host/usbh.c b/src/host/usbh.c index 36c2ea7c8..979fc5065 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -892,8 +892,6 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura p_desc = tu_desc_next(p_desc); } - TU_LOG_INT(2, p_desc - (uint8_t*) desc_cfg); - TU_LOG_INT(2, tu_desc_type(p_desc)); TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; -- cgit v1.3.1 From 97703587d9f306f01a9435c1515a585f1b8d0975 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Aug 2021 19:08:38 +0700 Subject: improve host configuration parsing - remove driver class code binding - fully support IAD - auto calculate total length for interface descriptor for driver --- src/common/tusb_common.h | 3 + src/host/usbh.c | 131 +++++++++++++++++++------------------------- src/host/usbh_classdriver.h | 2 - src/host/usbh_hcd.h | 4 +- src/tusb.c | 30 ++++++++++ 5 files changed, 91 insertions(+), 79 deletions(-) (limited to 'src/host') diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 302e75277..c2356ffee 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -83,6 +83,9 @@ bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed); // Bind all endpoint of a interface descriptor to class driver void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* p_desc, uint16_t desc_len, uint8_t driver_id); +// Calculate total length of n interfaces (depending on IAD) +uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len); + //--------------------------------------------------------------------+ // Internal Inline Functions //--------------------------------------------------------------------+ diff --git a/src/host/usbh.c b/src/host/usbh.c index 979fc5065..662ce2673 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -48,6 +48,10 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ + +// Invalid driver ID in itf2drv[] ep2drv[][] mapping +enum { DRVID_INVALID = 0xFFu }; + #if CFG_TUSB_DEBUG >= 2 #define DRIVER_NAME(_name) .name = _name, #else @@ -59,7 +63,6 @@ static usbh_class_driver_t const usbh_class_drivers[] = #if CFG_TUH_CDC { DRIVER_NAME("CDC") - .class_code = TUSB_CLASS_CDC, .init = cdch_init, .open = cdch_open, .set_config = cdch_set_config, @@ -71,7 +74,6 @@ static usbh_class_driver_t const usbh_class_drivers[] = #if CFG_TUH_MSC { DRIVER_NAME("MSC") - .class_code = TUSB_CLASS_MSC, .init = msch_init, .open = msch_open, .set_config = msch_set_config, @@ -83,7 +85,6 @@ static usbh_class_driver_t const usbh_class_drivers[] = #if CFG_TUH_HID { DRIVER_NAME("HID") - .class_code = TUSB_CLASS_HID, .init = hidh_init, .open = hidh_open, .set_config = hidh_set_config, @@ -95,7 +96,6 @@ static usbh_class_driver_t const usbh_class_drivers[] = #if CFG_TUH_HUB { DRIVER_NAME("HUB") - .class_code = TUSB_CLASS_HUB, .init = hub_init, .open = hub_open, .set_config = hub_set_config, @@ -107,7 +107,6 @@ static usbh_class_driver_t const usbh_class_drivers[] = #if CFG_TUH_VENDOR { DRIVER_NAME("VENDOR") - .class_code = TUSB_CLASS_VENDOR_SPECIFIC, .init = cush_init, .open = cush_open_subtask, .xfer_cb = cush_isr, @@ -203,8 +202,8 @@ bool tuh_init(uint8_t rhport) TU_ASSERT(dev->mutex); #endif - memset(dev->itf2drv, 0xff, sizeof(dev->itf2drv)); // invalid mapping - memset(dev->ep2drv , 0xff, sizeof(dev->ep2drv )); // invalid mapping + memset(dev->itf2drv, DRVID_INVALID, sizeof(dev->itf2drv)); // invalid mapping + memset(dev->ep2drv , DRVID_INVALID, sizeof(dev->ep2drv )); // invalid mapping } // Class drivers init @@ -336,7 +335,6 @@ void hcd_event_handler(hcd_event_t const* event, bool in_isr) } } -// interrupt caused by a TD (with IOC=1) in pipe of class class_code void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred_bytes, xfer_result_t result, bool in_isr) { hcd_event_t event = @@ -409,8 +407,8 @@ void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port usbh_class_drivers[drv_id].close(dev_addr); } - memset(dev->itf2drv, 0xff, sizeof(dev->itf2drv)); // invalid mapping - memset(dev->ep2drv , 0xff, sizeof(dev->ep2drv )); // invalid mapping + memset(dev->itf2drv, DRVID_INVALID, sizeof(dev->itf2drv)); // invalid mapping + memset(dev->ep2drv , DRVID_INVALID, sizeof(dev->ep2drv )); // invalid mapping hcd_device_close(rhport, dev_addr); @@ -439,7 +437,7 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) { // continue with next valid interface uint8_t const drv_id = dev->itf2drv[itf_num]; - if (drv_id != 0xff) + if (drv_id != DRVID_INVALID) { usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id]; TU_LOG2("%s set config: itf = %u\r\n", driver->name, itf_num); @@ -835,43 +833,15 @@ static bool enum_set_config_complete(uint8_t dev_addr, tusb_control_request_t co dev->configured = 1; dev->state = TUSB_DEVICE_STATE_CONFIGURED; - // Start the Set Configuration process for interfaces (itf = 0xff) + // Start the Set Configuration process for interfaces (itf = DRVID_INVALID) // Since driver can perform control transfer within its set_config, this is done asynchronously. // The process continue with next interface when class driver complete its sequence with usbh_driver_set_config_complete() - // TODO use separated API instead of usig 0xff - usbh_driver_set_config_complete(dev_addr, 0xff); + // TODO use separated API instead of using DRVID_INVALID + usbh_driver_set_config_complete(dev_addr, DRVID_INVALID); return true; } -// Get total length of n interface (depending on IAD) -static uint16_t get_interface_length(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len) -{ - uint8_t const* p_desc = (uint8_t const*) desc_itf; - uint16_t len = 0; - - while (itf_count--) - { - // Next on interface desc - len += tu_desc_len(desc_itf); - p_desc = tu_desc_next(p_desc); - - while (len < max_len) - { - // return on IAD regardless of itf count - if ( tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION ) return len; - - if ( (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) && - ((tusb_desc_interface_t const*) p_desc)->bAlternateSetting == 0 ) break; - - len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - } - - return len; -} - static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg) { usbh_device_t* dev = &_usbh_devices[dev_addr]; @@ -895,53 +865,64 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; - uint16_t const remaining_len = desc_end-p_desc; - uint16_t const drv_len = get_interface_length(desc_itf, desc_iad ? desc_iad->bInterfaceCount : 1, remaining_len); - TU_ASSERT(drv_len); + // Interface number must not be used already + TU_ASSERT( dev->itf2drv[desc_itf->bInterfaceNumber] == DRVID_INVALID ); - // Check if class is supported TODO drop class_code - uint8_t drv_id; - for (drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) - { - if ( usbh_class_drivers[drv_id].class_code == desc_itf->bInterfaceClass ) break; - } + uint16_t const drv_len = tu_desc_get_interface_total_len(desc_itf, desc_iad ? desc_iad->bInterfaceCount : 1, desc_end-p_desc); + TU_ASSERT(drv_len); - if( drv_id >= USBH_CLASS_DRIVER_COUNT ) + if (desc_itf->bInterfaceClass == TUSB_CLASS_HUB && dev->hub_addr != 0) { - TU_LOG(USBH_DBG_LVL, "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); - - // skip unsupported class until next Interface or IAD descriptor - p_desc += drv_len; + // TODO Attach hub to Hub is not currently supported + // skip this interface + TU_LOG(USBH_DBG_LVL, "Only 1 level of HUB is supported\r\n"); } else { - usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id]; + // Find driver for this interface + uint8_t drv_id; + for (drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) + { + usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id]; - // Interface number must not be used already TODO alternate interface - TU_ASSERT( dev->itf2drv[desc_itf->bInterfaceNumber] == 0xff ); - dev->itf2drv[desc_itf->bInterfaceNumber] = drv_id; + if ( driver->open(dev->rhport, dev_addr, desc_itf, drv_len) ) + { + // open successfully + TU_LOG2("%s opened\r\n", driver->name); - if (desc_itf->bInterfaceClass == TUSB_CLASS_HUB && dev->hub_addr != 0) - { - // TODO Attach hub to Hub is not currently supported - // skip this interface - p_desc = tu_desc_next(p_desc); - } - else - { - TU_LOG2("%s open\r\n", driver->name); + // bind interface to found driver + dev->itf2drv[desc_itf->bInterfaceNumber] = drv_id; + + // If using IAD, bind all interfaces to the same driver + if (desc_iad) + { + // IAD's first interface number and class should match with opened interface + TU_ASSERT(desc_iad->bFirstInterface == desc_itf->bInterfaceNumber && + desc_iad->bFunctionClass == desc_itf->bInterfaceClass); + + for(uint8_t i=1; ibInterfaceCount; i++) + { + dev->itf2drv[desc_itf->bInterfaceNumber+i] = drv_id; + } + } - uint16_t const itf_len = driver->open(dev->rhport, dev_addr, desc_itf, remaining_len); - TU_ASSERT( sizeof(tusb_desc_interface_t) <= itf_len && itf_len <= remaining_len); + // bind all endpoints to found driver + tu_edpt_bind_driver(dev->ep2drv, desc_itf, drv_len, drv_id); - // bind all endpoints for this driver - tu_edpt_bind_driver(dev->ep2drv, desc_itf, drv_len, drv_id); + break; // exit driver find loop + } + } - p_desc += itf_len; + if( drv_id >= USBH_CLASS_DRIVER_COUNT ) + { + TU_LOG(USBH_DBG_LVL, "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); } } + + // next Interface or IAD descriptor + p_desc += drv_len; } return true; diff --git a/src/host/usbh_classdriver.h b/src/host/usbh_classdriver.h index b05a33580..fccb30253 100644 --- a/src/host/usbh_classdriver.h +++ b/src/host/usbh_classdriver.h @@ -43,8 +43,6 @@ typedef struct { char const* name; #endif - uint8_t class_code; - void (* const init )(void); uint16_t (* 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); diff --git a/src/host/usbh_hcd.h b/src/host/usbh_hcd.h index b3856d6b7..450b3e447 100644 --- a/src/host/usbh_hcd.h +++ b/src/host/usbh_hcd.h @@ -73,9 +73,9 @@ typedef struct { uint8_t suspended : 1; }; - volatile uint8_t state; // device state, value from enum tusbh_device_state_t + volatile uint8_t state; // device state, value from enum tusbh_device_state_t - uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) + uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) uint8_t ep2drv[CFG_TUH_EP_MAX][2]; // map endpoint to driver ( 0xff is invalid ) struct TU_ATTR_PACKED diff --git a/src/tusb.c b/src/tusb.c index 260a6506f..1fc775399 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -125,6 +125,36 @@ void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* desc_ } } +uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len) +{ + uint8_t const* p_desc = (uint8_t const*) desc_itf; + uint16_t len = 0; + + while (itf_count--) + { + // Next on interface desc + len += tu_desc_len(desc_itf); + p_desc = tu_desc_next(p_desc); + + while (len < max_len) + { + // return on IAD regardless of itf count + if ( tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION ) return len; + + if ( (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) && + ((tusb_desc_interface_t const*) p_desc)->bAlternateSetting == 0 ) + { + break; + } + + len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + } + + return len; +} + /*------------------------------------------------------------------*/ /* Debug *------------------------------------------------------------------*/ -- cgit v1.3.1 From 22a5b1608c0949d46f8e346878bff730712858e4 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Aug 2021 19:31:38 +0700 Subject: change host driver open return type to bool the descriptor len used by driver will be calculated by usbh --- src/class/cdc/cdc_host.c | 12 ++++++------ src/class/cdc/cdc_host.h | 10 +++++----- src/class/hid/hid_host.c | 20 ++++++++++---------- src/class/hid/hid_host.h | 10 +++++----- src/class/msc/msc_host.c | 10 +++++----- src/class/msc/msc_host.h | 10 +++++----- src/host/hub.c | 13 +++++++------ src/host/hub.h | 10 +++++----- src/host/usbh_classdriver.h | 10 +++++----- 9 files changed, 53 insertions(+), 52 deletions(-) (limited to 'src/host') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index fc7100e81..35b8de3b1 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -149,7 +149,7 @@ void cdch_init(void) tu_memclr(cdch_data, sizeof(cdch_data_t)*CFG_TUSB_HOST_DEVICE_MAX); } -uint16_t cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) +bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { (void) max_len; @@ -157,7 +157,7 @@ uint16_t cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const // Protocol 0xFF can be RNDIS device for windows XP TU_VERIFY( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass && - 0xFF != itf_desc->bInterfaceProtocol, 0); + 0xFF != itf_desc->bInterfaceProtocol); cdch_data_t * p_cdc = get_itf(dev_addr); @@ -186,7 +186,7 @@ uint16_t cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const // notification endpoint tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep), 0 ); + TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); p_cdc->ep_notif = desc_ep->bEndpointAddress; drv_len += tu_desc_len(p_desc); @@ -205,9 +205,9 @@ uint16_t cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const for(uint32_t i=0; i<2; i++) { tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_BULK == desc_ep->bmAttributes.xfer, 0); + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_BULK == desc_ep->bmAttributes.xfer); - TU_ASSERT(usbh_edpt_open(rhport, dev_addr, desc_ep), 0); + TU_ASSERT(usbh_edpt_open(rhport, dev_addr, desc_ep)); if ( tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN ) { @@ -222,7 +222,7 @@ uint16_t cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const } } - return drv_len; + return true; } bool cdch_set_config(uint8_t dev_addr, uint8_t itf_num) diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index edcd258a8..0d435138b 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -121,11 +121,11 @@ void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_i //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void cdch_init (void); -uint16_t 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); -void cdch_close (uint8_t dev_addr); +void cdch_init (void); +bool cdch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); +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); +void cdch_close (uint8_t dev_addr); #ifdef __cplusplus } diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index a39ac8bec..4dd198369 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -249,19 +249,22 @@ static bool config_get_report_desc_complete (uint8_t dev_addr, tusb_control_requ static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len); -uint16_t hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) +bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) { (void) max_len; - TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass, 0); + TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); + + // len = interface + hid + n*endpoints + uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); + TU_ASSERT(max_len >= drv_len); - uint16_t drv_len = sizeof(tusb_desc_interface_t); uint8_t const *p_desc = (uint8_t const *) desc_itf; //------------- HID descriptor -------------// p_desc = tu_desc_next(p_desc); tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; - TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType, 0); + TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType); // not enough interface, try to increase CFG_TUH_HID // TODO multiple devices @@ -269,13 +272,12 @@ uint16_t hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const TU_ASSERT(hid_dev->inst_count < CFG_TUH_HID, 0); //------------- Endpoint Descriptor -------------// - drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType, 0); + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); // TODO also open endpoint OUT - TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep), 0 ); + TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->inst_count); hid_dev->inst_count++; @@ -292,9 +294,7 @@ uint16_t hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const hid_itf->protocol_mode = HID_PROTOCOL_BOOT; if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) hid_itf->itf_protocol = desc_itf->bInterfaceProtocol; - drv_len += desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); - - return drv_len; + return true; } bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index bbef05e25..9a498afec 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -121,11 +121,11 @@ TU_ATTR_WEAK void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t ins //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void hidh_init (void); -uint16_t 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); -void hidh_close (uint8_t dev_addr); +void hidh_init (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); +void hidh_close (uint8_t dev_addr); #ifdef __cplusplus } diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 2c027deff..f02f4550a 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -360,22 +360,22 @@ static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* c static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); -uint16_t msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) +bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) { TU_VERIFY (MSC_SUBCLASS_SCSI == desc_itf->bInterfaceSubClass && MSC_PROTOCOL_BOT == desc_itf->bInterfaceProtocol); // msc driver length is fixed uint16_t const drv_len = sizeof(tusb_desc_interface_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); - TU_ASSERT(drv_len <= max_len, 0); + TU_ASSERT(drv_len <= max_len); msch_interface_t* p_msc = get_itf(dev_addr); tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(desc_itf); for(uint32_t i=0; i<2; i++) { - TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && TUSB_XFER_BULK == ep_desc->bmAttributes.xfer, 0); - TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc), 0); + TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); + TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc)); if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) { @@ -390,7 +390,7 @@ uint16_t msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const p_msc->itf_num = desc_itf->bInterfaceNumber; - return drv_len; + return true; } bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 9e4217ba5..7718ad4fe 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -106,11 +106,11 @@ TU_ATTR_WEAK void tuh_msc_umount_cb(uint8_t dev_addr); // Internal Class Driver API //--------------------------------------------------------------------+ -void msch_init (void); -uint16_t 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); -bool msch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); -void msch_close (uint8_t dev_addr); +void msch_init (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); +bool msch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); #ifdef __cplusplus } diff --git a/src/host/hub.c b/src/host/hub.c index 2ead5bed1..00dce4e65 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -147,16 +147,17 @@ void hub_init(void) tu_memclr(hub_data, CFG_TUSB_HOST_DEVICE_MAX*sizeof(hub_interface_t)); } -uint16_t hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) +bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { - // hub driver does not support multiple TT yet TU_VERIFY(TUSB_CLASS_HUB == itf_desc->bInterfaceClass && - 0 == itf_desc->bInterfaceSubClass && - 1 <= itf_desc->bInterfaceProtocol, 0); + 0 == itf_desc->bInterfaceSubClass); + + // hub driver does not support multiple TT yet + TU_VERIFY(itf_desc->bInterfaceProtocol <= 1); // msc driver length is fixed uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_endpoint_t); - TU_ASSERT(drv_len <= max_len, 0); + TU_ASSERT(drv_len <= max_len); //------------- Interrupt Status endpoint -------------// tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); @@ -169,7 +170,7 @@ uint16_t hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const hub_data[dev_addr-1].itf_num = itf_desc->bInterfaceNumber; hub_data[dev_addr-1].ep_in = desc_ep->bEndpointAddress; - return drv_len; + return true; } void hub_close(uint8_t dev_addr) diff --git a/src/host/hub.h b/src/host/hub.h index c9ffe4985..c4d544193 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -181,11 +181,11 @@ bool hub_status_pipe_queue(uint8_t dev_addr); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void hub_init (void); -uint16_t 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); -void hub_close (uint8_t dev_addr); +void hub_init (void); +bool hub_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); +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); +void hub_close (uint8_t dev_addr); #ifdef __cplusplus } diff --git a/src/host/usbh_classdriver.h b/src/host/usbh_classdriver.h index fccb30253..8bc2622aa 100644 --- a/src/host/usbh_classdriver.h +++ b/src/host/usbh_classdriver.h @@ -43,11 +43,11 @@ typedef struct { char const* name; #endif - void (* const init )(void); - uint16_t (* 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); + 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 -- cgit v1.3.1 From 800f85329ea21bdefc778c246c8098dea12fb402 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 23 Aug 2021 11:00:21 +0700 Subject: add tuh_hid_receive_report() for applicaiton to explicitly request report --- examples/host/cdc_msc_hid/src/hid_app.c | 13 ++++++++++ examples/host/cdc_msc_hid/src/main.c | 29 ++------------------- examples/host/cdc_msc_hid/src/tusb_config.h | 6 ++--- src/class/hid/hid_host.c | 39 ++++++++++++++++++----------- src/class/hid/hid_host.h | 30 +++++++++++++++++----- src/host/usbh.c | 8 +++--- src/tusb.c | 3 ++- 7 files changed, 73 insertions(+), 55 deletions(-) (limited to 'src/host') diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index 5e3ac6a72..11437c2b4 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -80,6 +80,13 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_re hid_info[instance].report_count = tuh_hid_parse_report_descriptor(hid_info[instance].report_info, MAX_REPORT, desc_report, desc_len); printf("HID has %u reports \r\n", hid_info[instance].report_count); } + + // request to receive report + // tuh_hid_report_received_cb() will be invoked when report is available + if ( !tuh_hid_receive_report(dev_addr, instance) ) + { + printf("Error: cannot request to receive report\r\n"); + } } // Invoked when device with hid interface is un-mounted @@ -110,6 +117,12 @@ void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t cons process_generic_report(dev_addr, instance, report, len); break; } + + // continue to request to receive report + if ( !tuh_hid_receive_report(dev_addr, instance) ) + { + printf("Error: cannot request to receive report\r\n"); + } } //--------------------------------------------------------------------+ diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 7ae814e38..a14be05ea 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -33,7 +33,6 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ -void print_greeting(void); void led_blinking_task(void); extern void cdc_task(void); @@ -43,7 +42,8 @@ extern void hid_app_task(void); int main(void) { board_init(); - print_greeting(); + + printf("TinyUSB Host CDC MSC HID Example\r\n"); tusb_init(); @@ -126,28 +126,3 @@ void led_blinking_task(void) board_led_write(led_state); led_state = 1 - led_state; // toggle } - -//--------------------------------------------------------------------+ -// HELPER FUNCTION -//--------------------------------------------------------------------+ -void print_greeting(void) -{ - char const * const rtos_name[] = - { - [OPT_OS_NONE] = "None", - [OPT_OS_FREERTOS] = "FreeRTOS", - [OPT_OS_MYNEWT] = "Mynewt OS", - [OPT_OS_CUSTOM] = "Custom OS implemnted by application", - [OPT_OS_PICO] = "Raspberry Pi Pico SDK", - [OPT_OS_RTTHREAD] = "RT-Thread" - }; - - printf("----------------------------------------------------\r\n"); - printf("TinyUSB Host Example\r\n"); - printf("If you find any bugs or problems, feel free to open\r\n"); - printf("an issue at https://github.com/hathach/tinyusb\r\n"); - printf("----------------------------------------------------\r\n\r\n"); - - printf("This Host demo is configured to support:\r\n"); - printf(" - RTOS = %s\r\n", rtos_name[CFG_TUSB_OS]); -} diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index b574acf9b..80f07f446 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -76,15 +76,15 @@ #define CFG_TUH_HUB 1 #define CFG_TUH_CDC 1 -#define CFG_TUH_HID 4 +#define CFG_TUH_HID 4 // typical keyboard + mouse device can have 3-4 HID interfaces #define CFG_TUH_MSC 1 #define CFG_TUH_VENDOR 0 #define CFG_TUSB_HOST_DEVICE_MAX (CFG_TUH_HUB ? 5 : 1) // normal hub has 4 ports //------------- HID -------------// - -#define CFG_TUH_HID_EP_BUFSIZE 64 +#define CFG_TUH_HID_EPIN_BUFSIZE 64 +#define CFG_TUH_HID_EPOUT_BUFSIZE 64 #ifdef __cplusplus } diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 4dd198369..2d76df588 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -52,8 +52,8 @@ typedef struct uint16_t epin_size; uint16_t epout_size; - uint8_t epin_buf[CFG_TUH_HID_EP_BUFSIZE]; - uint8_t epout_buf[CFG_TUH_HID_EP_BUFSIZE]; + uint8_t epin_buf[CFG_TUH_HID_EPIN_BUFSIZE]; + uint8_t epout_buf[CFG_TUH_HID_EPOUT_BUFSIZE]; } hidh_interface_t; typedef struct @@ -72,13 +72,8 @@ TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_a static uint8_t get_instance_id_by_itfnum(uint8_t dev_addr, uint8_t itf); static uint8_t get_instance_id_by_epaddr(uint8_t dev_addr, uint8_t ep_addr); -TU_ATTR_ALWAYS_INLINE static inline bool hidh_get_report(uint8_t dev_addr, hidh_interface_t* hid_itf) -{ - return usbh_edpt_xfer(dev_addr, hid_itf->ep_in, hid_itf->epin_buf, hid_itf->epin_size); -} - //--------------------------------------------------------------------+ -// Application API +// Interface API //--------------------------------------------------------------------+ uint8_t tuh_hid_instance_count(uint8_t dev_addr) @@ -98,6 +93,10 @@ uint8_t tuh_hid_interface_protocol(uint8_t dev_addr, uint8_t instance) return hid_itf->itf_protocol; } +//--------------------------------------------------------------------+ +// Control Endpoint API +//--------------------------------------------------------------------+ + uint8_t tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); @@ -186,6 +185,20 @@ bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, u return true; } +//--------------------------------------------------------------------+ +// Interrupt Endpoint API +//--------------------------------------------------------------------+ + +bool tuh_hid_receive_report(uint8_t dev_addr, uint8_t instance) +{ + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + + // claim endpoint + TU_VERIFY( usbh_edpt_claim(dev_addr, hid_itf->ep_in) ); + + return usbh_edpt_xfer(dev_addr, hid_itf->ep_in, hid_itf->epin_buf, hid_itf->epin_size); +} + //bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance) //{ // TU_VERIFY(tuh_n_hid_n_mounted(dev_addr, instance)); @@ -217,9 +230,6 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint3 TU_LOG2(" Get Report callback (%u, %u)\r\n", dev_addr, instance); TU_LOG1_MEM(hid_itf->epin_buf, 8, 2); tuh_hid_report_received_cb(dev_addr, instance, hid_itf->epin_buf, xferred_bytes); - - // queue next report - hidh_get_report(dev_addr, hid_itf); }else { if (tuh_hid_report_sent_cb) tuh_hid_report_sent_cb(dev_addr, instance, hid_itf->epout_buf, xferred_bytes); @@ -255,6 +265,8 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); + TU_LOG2("HID opening Interface %u (addr = %u)\r\n", desc_itf->bInterfaceNumber, dev_addr); + // len = interface + hid + n*endpoints uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); TU_ASSERT(max_len >= drv_len); @@ -336,7 +348,7 @@ static bool config_set_protocol(uint8_t dev_addr, tusb_control_request_t const * uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - TU_LOG2("HID Set Protocol\r\n"); + TU_LOG2("HID Set Protocol to Boot Mode\r\n"); hid_itf->protocol_mode = HID_PROTOCOL_BOOT; tusb_control_request_t const new_request = { @@ -422,9 +434,6 @@ static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uin // enumeration is complete tuh_hid_mount_cb(dev_addr, instance, desc_report, desc_len); - // queue transfer for IN endpoint - hidh_get_report(dev_addr, hid_itf); - // notify usbh that driver enumeration is complete usbh_driver_set_config_complete(dev_addr, hid_itf->itf_num); } diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 9a498afec..fe09b03b2 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -38,10 +38,15 @@ //--------------------------------------------------------------------+ // TODO Highspeed interrupt can be up to 512 bytes -#ifndef CFG_TUH_HID_EP_BUFSIZE -#define CFG_TUH_HID_EP_BUFSIZE 64 +#ifndef CFG_TUH_HID_EPIN_BUFSIZE +#define CFG_TUH_HID_EPIN_BUFSIZE 64 #endif +#ifndef CFG_TUH_HID_EPOUT_BUFSIZE +#define CFG_TUH_HID_EPOUT_BUFSIZE 64 +#endif + + typedef struct { uint8_t report_id; @@ -54,7 +59,7 @@ typedef struct } tuh_hid_report_info_t; //--------------------------------------------------------------------+ -// Application API +// Interface API //--------------------------------------------------------------------+ // Get the number of HID instances @@ -66,6 +71,14 @@ bool tuh_hid_mounted(uint8_t dev_addr, uint8_t instance); // Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible values uint8_t tuh_hid_interface_protocol(uint8_t dev_addr, uint8_t instance); +// Parse report descriptor into array of report_info struct and return number of reports. +// For complicated report, application should write its own parser. +uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) TU_ATTR_UNUSED; + +//--------------------------------------------------------------------+ +// Control Endpoint API +//--------------------------------------------------------------------+ + // Get current protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) // Note: Device will be initialized in Boot protocol for simplicity. // Application can use set_protocol() to switch back to Report protocol. @@ -79,13 +92,18 @@ bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol); // report_type is either Intput, Output or Feature, (value from hid_report_type_t) bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, void* report, uint16_t len); -// Parse report descriptor into array of report_info struct and return number of reports. -// For complicated report, application should write its own parser. -uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) TU_ATTR_UNUSED; +//--------------------------------------------------------------------+ +// Interrupt Endpoint API +//--------------------------------------------------------------------+ // Check if the interface is ready to use //bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance); +// Try to receive next report on Interrupt Endpoint. Immediately return +// - true If succeeded, tuh_hid_report_received_cb() callback will be invoked when report is available +// - false if failed to queue the transfer e.g endpoint is busy +bool tuh_hid_receive_report(uint8_t dev_addr, uint8_t instance); + // Send report using interrupt endpoint // If report_id > 0 (composite), it will be sent as 1st byte, then report contents. Otherwise only report content is sent. //void tuh_hid_send_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t const* report, uint16_t len); diff --git a/src/host/usbh.c b/src/host/usbh.c index 662ce2673..40c23a69d 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -186,7 +186,7 @@ bool tuh_init(uint8_t rhport) TU_LOG2("USBH init\r\n"); - tu_memclr(_usbh_devices, sizeof(usbh_device_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); + tu_memclr(_usbh_devices, sizeof(_usbh_devices)); //------------- Enumeration & Reporter Task init -------------// _usbh_q = osal_queue_create( &_usbh_qdef ); @@ -436,6 +436,7 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) for(itf_num++; itf_num < sizeof(dev->itf2drv); itf_num++) { // continue with next valid interface + // TODO skip IAD binding interface such as CDCs uint8_t const drv_id = dev->itf2drv[itf_num]; if (drv_id != DRVID_INVALID) { @@ -474,6 +475,7 @@ static bool enum_get_config_desc_complete (uint8_t dev_addr, tusb_control_ static bool enum_set_config_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool parse_configuration_descriptor (uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg); +#if CFG_TUH_HUB static bool enum_hub_clear_reset0_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { (void) dev_addr; (void) request; @@ -540,7 +542,7 @@ static bool enum_hub_get_status0_complete(uint8_t dev_addr, tusb_control_request return true; } - +#endif static bool enum_request_set_addr(void) { @@ -889,7 +891,7 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura if ( driver->open(dev->rhport, dev_addr, desc_itf, drv_len) ) { // open successfully - TU_LOG2("%s opened\r\n", driver->name); + TU_LOG2(" Opened successfully\r\n"); // bind interface to found driver dev->itf2drv[desc_itf->bInterfaceNumber] = drv_id; diff --git a/src/tusb.c b/src/tusb.c index 1fc775399..6494287d2 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -117,10 +117,11 @@ void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* desc_ { uint8_t const ep_addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress; + TU_LOG(2, " Bind EP %02x to driver id %u\r\n", ep_addr, driver_id); ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = driver_id; } - len = (uint16_t)(len + tu_desc_len(p_desc)); + len = (uint16_t)(len + tu_desc_len(p_desc)); p_desc = tu_desc_next(p_desc); } } -- cgit v1.3.1 From 6a16f6ccddf77e1b0232aec0c89d2105e391b297 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 23 Aug 2021 11:01:40 +0700 Subject: rename CFG_TUSB_HOST_DEVICE_MAX to CFG_TUH_DEVICE_MAX --- examples/host/cdc_msc_hid/src/msc_app.c | 2 +- examples/host/cdc_msc_hid/src/tusb_config.h | 2 +- lib/fatfs/diskio.c | 4 ++-- lib/fatfs/diskio.h | 2 +- lib/fatfs/ffconf.h | 2 +- src/class/cdc/cdc_host.c | 4 ++-- src/class/cdc/cdc_rndis_host.c | 10 +++++----- src/class/hid/hid_host.c | 2 +- src/class/msc/msc_host.c | 4 ++-- src/class/vendor/vendor_host.c | 4 ++-- src/host/hcd.h | 2 +- src/host/hub.c | 4 ++-- src/host/usbh.c | 14 +++++++------- src/host/usbh_hcd.h | 2 +- src/portable/ehci/ehci.c | 4 ++-- src/portable/ohci/ohci.h | 2 +- src/tusb_option.h | 10 +++++----- 17 files changed, 37 insertions(+), 37 deletions(-) (limited to 'src/host') diff --git a/examples/host/cdc_msc_hid/src/msc_app.c b/examples/host/cdc_msc_hid/src/msc_app.c index 3657a3d35..77a72052d 100644 --- a/examples/host/cdc_msc_hid/src/msc_app.c +++ b/examples/host/cdc_msc_hid/src/msc_app.c @@ -92,7 +92,7 @@ void tuh_msc_umount_cb(uint8_t dev_addr) // // if ( phy_disk == f_get_current_drive() ) // { // active drive is unplugged --> change to other drive -// for(uint8_t i=0; i 1 && period_1ms_addr == tu_align32(next_item.address)) && - max_loop < (HCD_MAX_ENDPOINT + EHCI_MAX_ITD + EHCI_MAX_SITD)*CFG_TUSB_HOST_DEVICE_MAX) + max_loop < (HCD_MAX_ENDPOINT + EHCI_MAX_ITD + EHCI_MAX_SITD)*CFG_TUH_DEVICE_MAX) { switch ( next_item.type ) { diff --git a/src/portable/ohci/ohci.h b/src/portable/ohci/ohci.h index 6a634592a..cd90aa45a 100644 --- a/src/portable/ohci/ohci.h +++ b/src/portable/ohci/ohci.h @@ -159,7 +159,7 @@ typedef struct TU_ATTR_ALIGNED(256) struct { ohci_ed_t ed; ohci_gtd_t gtd; - }control[CFG_TUSB_HOST_DEVICE_MAX+1]; + }control[CFG_TUH_DEVICE_MAX+1]; // ochi_itd_t itd[OHCI_MAX_ITD]; // itd requires alignment of 32 ohci_ed_t ed_pool[HCD_MAX_ENDPOINT]; diff --git a/src/tusb_option.h b/src/tusb_option.h index e189c65bb..bbbf10a84 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -266,14 +266,14 @@ // HOST OPTIONS //-------------------------------------------------------------------- #if TUSB_OPT_HOST_ENABLED - #ifndef CFG_TUSB_HOST_DEVICE_MAX - #define CFG_TUSB_HOST_DEVICE_MAX 1 - #warning CFG_TUSB_HOST_DEVICE_MAX is not defined, default value is 1 + #ifndef CFG_TUH_DEVICE_MAX + #define CFG_TUH_DEVICE_MAX 1 + #warning CFG_TUH_DEVICE_MAX is not defined, default value is 1 #endif //------------- HUB CLASS -------------// - #if CFG_TUH_HUB && (CFG_TUSB_HOST_DEVICE_MAX == 1) - #error There is no benefit enable hub with max device is 1. Please disable hub or increase CFG_TUSB_HOST_DEVICE_MAX + #if CFG_TUH_HUB && (CFG_TUH_DEVICE_MAX == 1) + #error There is no benefit enable hub with max device is 1. Please disable hub or increase CFG_TUH_DEVICE_MAX #endif #ifndef CFG_TUH_ENUMERATION_BUFSIZE -- cgit v1.3.1 From a490a3fe616205115ed351ddbc0bd202bcbdc3db Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 23 Aug 2021 15:40:57 +0700 Subject: add hcd attr, add note for ehci framelist on NXP derivative --- src/host/hcd.h | 4 +- src/host/hcd_attr.h | 104 +++++++++++++++++++++++++++++++++++++++++++++++ src/host/hub.c | 6 +-- src/host/usbh.c | 3 +- src/portable/ehci/ehci.c | 72 ++++++++++++++++---------------- src/portable/ehci/ehci.h | 2 +- 6 files changed, 151 insertions(+), 40 deletions(-) create mode 100644 src/host/hcd_attr.h (limited to 'src/host') diff --git a/src/host/hcd.h b/src/host/hcd.h index 62ff8b3f2..e1d21bf45 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -30,6 +30,7 @@ #include "common/tusb_common.h" #include "osal/osal.h" #include "common/tusb_fifo.h" +#include "hcd_attr.h" #ifdef __cplusplus extern "C" { @@ -62,6 +63,7 @@ typedef struct struct { uint8_t hub_addr; uint8_t hub_port; + uint8_t speed; } connection; // XFER_COMPLETE @@ -140,7 +142,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr); //--------------------------------------------------------------------+ -// Event API (implemented by stack) +// USBH implemented API //--------------------------------------------------------------------+ // Called by HCD to notify stack diff --git a/src/host/hcd_attr.h b/src/host/hcd_attr.h new file mode 100644 index 000000000..d18686587 --- /dev/null +++ b/src/host/hcd_attr.h @@ -0,0 +1,104 @@ +/* + * 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_HCD_ATTR_H_ +#define TUSB_HCD_ATTR_H_ + +#include "tusb_option.h" + +// Attribute includes +// - ENDPOINT_MAX: max (logical) number of endpoint +// - PORT_HIGHSPEED: mask to indicate which port support highspeed mode, bit0 for port0 and so on. + +//------------- NXP -------------// +#if TU_CHECK_MCU(LPC175X_6X) || TU_CHECK_MCU(LPC177X_8X) || TU_CHECK_MCU(LPC40XX) + +#elif TU_CHECK_MCU(LPC18XX) || TU_CHECK_MCU(LPC43XX) + #define HCD_ATTR_EHCI_TRANSDIMENSION + +#elif TU_CHECK_MCU(LPC54XXX) + // #define HCD_ATTR_EHCI_NXP_PTD + +#elif TU_CHECK_MCU(LPC55XX) + // #define HCD_ATTR_EHCI_NXP_PTD + +#elif TU_CHECK_MCU(MIMXRT10XX) + #define HCD_ATTR_EHCI_TRANSDIMENSION + +#elif TU_CHECK_MCU(MKL25ZXX) + +//------------- Microchip -------------// +#elif TU_CHECK_MCU(SAMD21) || TU_CHECK_MCU(SAMD51) || TU_CHECK_MCU(SAME5X) || \ + TU_CHECK_MCU(SAMD11) || TU_CHECK_MCU(SAML21) || TU_CHECK_MCU(SAML22) + +#elif TU_CHECK_MCU(SAMG) + +#elif TU_CHECK_MCU(SAMX7X) + +//------------- ST -------------// +#elif TU_CHECK_MCU(STM32F0) || TU_CHECK_MCU(STM32F1) || TU_CHECK_MCU(STM32F3) || \ + TU_CHECK_MCU(STM32L0) || TU_CHECK_MCU(STM32L1) || TU_CHECK_MCU(STM32L4) + +#elif TU_CHECK_MCU(STM32F2) || TU_CHECK_MCU(STM32F4) || TU_CHECK_MCU(STM32F3) + +#elif TU_CHECK_MCU(STM32F7) + +#elif TU_CHECK_MCU(STM32H7) + +//------------- Sony -------------// +#elif TU_CHECK_MCU(CXD56) + +//------------- Nuvoton -------------// +#elif TU_CHECK_MCU(NUC505) + +//------------- Espressif -------------// +#elif TU_CHECK_MCU(ESP32S2) || TU_CHECK_MCU(ESP32S3) + +//------------- Raspberry Pi -------------// +#elif TU_CHECK_MCU(RP2040) + +//------------- Silabs -------------// +#elif TU_CHECK_MCU(EFM32GG) || TU_CHECK_MCU(EFM32GG11) || TU_CHECK_MCU(EFM32GG12) + +//------------- Renesas -------------// +#elif TU_CHECK_MCU(RX63X) || TU_CHECK_MCU(RX65X) || TU_CHECK_MCU(RX72N) + +//#elif TU_CHECK_MCU(MM32F327X) +// #define DCD_ATTR_ENDPOINT_MAX not known yet + +//------------- GigaDevice -------------// +#elif TU_CHECK_MCU(GD32VF103) + +#else +// #warning "DCD_ATTR_ENDPOINT_MAX is not defined for this MCU, default to 8" +#endif + +// Default to fullspeed if not defined +//#ifndef PORT_HIGHSPEED +// #define DCD_ATTR_PORT_HIGHSPEED 0x00 +//#endif + +#endif diff --git a/src/host/hub.c b/src/host/hub.c index d685c6529..65e747e41 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -45,8 +45,8 @@ typedef struct hub_port_status_response_t port_status; } hub_interface_t; -CFG_TUSB_MEM_SECTION static hub_interface_t hub_data[CFG_TUH_DEVICE_MAX]; -TU_ATTR_ALIGNED(4) CFG_TUSB_MEM_SECTION static uint8_t _hub_buffer[sizeof(descriptor_hub_desc_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)]; #if CFG_TUSB_DEBUG static char const* const _hub_feature_str[] = @@ -144,7 +144,7 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_con //--------------------------------------------------------------------+ void hub_init(void) { - tu_memclr(hub_data, CFG_TUH_DEVICE_MAX*sizeof(hub_interface_t)); + tu_memclr(hub_data, sizeof(hub_data)); } bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) diff --git a/src/host/usbh.c b/src/host/usbh.c index 98132a8c0..76c1ba078 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -128,7 +128,8 @@ enum { CONFIG_NUM = 1 }; // default to use configuration 1 static bool _usbh_initialized = false; -// including zero-address +// all devices including hub and zero-address TODO exclude device0 to save space +// hub address start from CFG_TUH_DEVICE_MAX CFG_TUSB_MEM_SECTION usbh_device_t _usbh_devices[CFG_TUH_DEVICE_MAX+1]; // Event queue diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index bc83f5b8b..4d240cc50 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -24,11 +24,9 @@ * This file is part of the TinyUSB stack. */ -#include "common/tusb_common.h" +#include "host/hcd_attr.h" -#if TUSB_OPT_HOST_ENABLED && \ - (CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || \ - CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX ) +#if TUSB_OPT_HOST_ENABLED && defined(HCD_ATTR_EHCI_TRANSDIMENSION) //--------------------------------------------------------------------+ // INCLUDE @@ -47,21 +45,27 @@ // Debug level of EHCI #define EHCI_DBG 2 -// Framelist size as small as possible -// - Standard EHCI : 256 elements -// - NXP Transdimension: 8 elements -#define EHCI_CFG_FRAMELIST_SIZE_BITS 7 -#define EHCI_FRAMELIST_SIZE (1024 >> EHCI_CFG_FRAMELIST_SIZE_BITS) - -TU_VERIFY_STATIC(EHCI_CFG_FRAMELIST_SIZE_BITS <= 7, "incorrect value"); +// Framelist size as small as possible to save SRAM +#ifdef HCD_ATTR_EHCI_TRANSDIMENSION + // NXP Transdimension: 8 elements + #define FRAMELIST_SIZE_BIT_VALUE 7u + #define FRAMELIST_SIZE_USBCMD_VALUE (((FRAMELIST_SIZE_BIT_VALUE & 3) << EHCI_USBCMD_POS_FRAMELIST_SIZE) | \ + ((FRAMELIST_SIZE_BIT_VALUE >> 2) << EHCI_USBCMD_POS_NXP_FRAMELIST_SIZE_MSB)) +#else + // STD EHCI: 256 elements + #define FRAMELIST_SIZE_BIT_VALUE 2u + #define FRAMELIST_SIZE_USBCMD_VALUE ((FRAMELIST_SIZE_BIT_VALUE & 3) << EHCI_USBCMD_POS_FRAMELIST_SIZE) +#endif +#define FRAMELIST_SIZE (1024 >> FRAMELIST_SIZE_BIT_VALUE) typedef struct { - ehci_link_t period_framelist[EHCI_FRAMELIST_SIZE]; + ehci_link_t period_framelist[FRAMELIST_SIZE]; - // for NXP ECHI, only implement 1 ms & 2 ms & 4 ms, 8 ms (framelist) + // TODO only implement 1 ms & 2 ms & 4 ms, 8 ms (framelist) // [0] : 1ms, [1] : 2ms, [2] : 4ms, [3] : 8 ms + // TODO better implementation without dummy head to save SRAM ehci_qhd_t period_head_arr[4]; // Note control qhd of dev0 is used as head of async list @@ -84,10 +88,10 @@ CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4096) static ehci_data_t ehci_data; //--------------------------------------------------------------------+ // PROTOTYPE //--------------------------------------------------------------------+ -static inline ehci_link_t* get_period_head(uint8_t rhport, uint8_t interval_ms) +static inline ehci_link_t* get_period_head(uint8_t rhport, uint32_t interval_ms) { (void) rhport; - return (ehci_link_t*) &ehci_data.period_head_arr[ tu_log2( tu_min8(EHCI_FRAMELIST_SIZE, interval_ms) ) ]; + return (ehci_link_t*) &ehci_data.period_head_arr[ tu_log2( tu_min32(FRAMELIST_SIZE, interval_ms) ) ]; } static inline ehci_qhd_t* qhd_control(uint8_t dev_addr) @@ -260,37 +264,38 @@ bool ehci_init(uint8_t rhport, uint32_t capability_reg, uint32_t operatial_reg) //------------- Periodic List -------------// // Build the polling interval tree with 1 ms, 2 ms, 4 ms and 8 ms (framesize) only - for(uint32_t i=0; i<4; i++) + for ( uint32_t i = 0; i < TU_ARRAY_SIZE(ehci_data.period_head_arr); i++ ) { - ehci_data.period_head_arr[i].int_smask = 1; // queue head in period list must have smask non-zero + ehci_data.period_head_arr[i].int_smask = 1; // queue head in period list must have smask non-zero ehci_data.period_head_arr[i].qtd_overlay.halted = 1; // dummy node, always inactive } ehci_link_t * const framelist = ehci_data.period_framelist; - ehci_link_t * const period_1ms = get_period_head(rhport, 1); + ehci_link_t * const period_1ms = get_period_head(rhport, 1u); + // all links --> period_head_arr[0] (1ms) // 0, 2, 4, 6 etc --> period_head_arr[1] (2ms) // 1, 5 --> period_head_arr[2] (4ms) // 3 --> period_head_arr[3] (8ms) // TODO EHCI_FRAMELIST_SIZE with other size than 8 - for(uint32_t i=0; iterminate = 1; @@ -300,10 +305,9 @@ bool ehci_init(uint8_t rhport, uint32_t capability_reg, uint32_t operatial_reg) regs->nxp_tt_control = 0; //------------- USB CMD Register -------------// - regs->command |= TU_BIT(EHCI_USBCMD_POS_RUN_STOP) | TU_BIT(EHCI_USBCMD_POS_ASYNC_ENABLE) - | TU_BIT(EHCI_USBCMD_POS_PERIOD_ENABLE) // TODO enable period list only there is int/iso endpoint - | ((EHCI_CFG_FRAMELIST_SIZE_BITS & TU_BIN8(011)) << EHCI_USBCMD_POS_FRAMELIST_SZIE) - | ((EHCI_CFG_FRAMELIST_SIZE_BITS >> 2) << EHCI_USBCMD_POS_NXP_FRAMELIST_SIZE_MSB); + regs->command |= TU_BIT(EHCI_USBCMD_POS_RUN_STOP) | TU_BIT(EHCI_USBCMD_POS_ASYNC_ENABLE) | + TU_BIT(EHCI_USBCMD_POS_PERIOD_ENABLE) | // TODO enable period list only there is int/iso endpoint + FRAMELIST_SIZE_USBCMD_VALUE; //------------- ConfigFlag Register (skip) -------------// regs->portsc_bm.port_power = 1; // enable port power @@ -530,10 +534,10 @@ static void async_list_xfer_complete_isr(ehci_qhd_t * const async_head) }while(p_qhd != async_head); // async list traversal, stop if loop around } -static void period_list_xfer_complete_isr(uint8_t hostid, uint8_t interval_ms) +static void period_list_xfer_complete_isr(uint8_t hostid, uint32_t interval_ms) { uint16_t max_loop = 0; - uint32_t const period_1ms_addr = (uint32_t) get_period_head(hostid, 1); + uint32_t const period_1ms_addr = (uint32_t) get_period_head(hostid, 1u); ehci_link_t next_item = * get_period_head(hostid, interval_ms); // TODO abstract max loop guard for period @@ -616,8 +620,8 @@ static void xfer_error_isr(uint8_t hostid) }while(p_qhd != async_head); // async list traversal, stop if loop around //------------- TODO refractor period list -------------// - uint32_t const period_1ms_addr = (uint32_t) get_period_head(hostid, 1); - for (uint8_t interval_ms=1; interval_ms <= EHCI_FRAMELIST_SIZE; interval_ms *= 2) + uint32_t const period_1ms_addr = (uint32_t) get_period_head(hostid, 1u); + for (uint32_t interval_ms=1; interval_ms <= FRAMELIST_SIZE; interval_ms *= 2) { ehci_link_t next_item = * get_period_head(hostid, interval_ms); @@ -660,7 +664,7 @@ void hcd_int_handler(uint8_t rhport) if (int_status & EHCI_INT_MASK_FRAMELIST_ROLLOVER) { - ehci_data.uframe_number += (EHCI_FRAMELIST_SIZE << 3); + ehci_data.uframe_number += (FRAMELIST_SIZE << 3); } if (int_status & EHCI_INT_MASK_PORT_CHANGE) @@ -690,7 +694,7 @@ void hcd_int_handler(uint8_t rhport) if (int_status & EHCI_INT_MASK_NXP_PERIODIC) { - for (uint8_t i=1; i <= EHCI_FRAMELIST_SIZE; i *= 2) + for (uint32_t i=1; i <= FRAMELIST_SIZE; i *= 2) { period_list_xfer_complete_isr( rhport, i ); } diff --git a/src/portable/ehci/ehci.h b/src/portable/ehci/ehci.h index cbcf1712a..c2bee67a5 100644 --- a/src/portable/ehci/ehci.h +++ b/src/portable/ehci/ehci.h @@ -289,7 +289,7 @@ enum ehci_interrupt_mask_{ enum ehci_usbcmd_pos_ { EHCI_USBCMD_POS_RUN_STOP = 0, - EHCI_USBCMD_POS_FRAMELIST_SZIE = 2, + EHCI_USBCMD_POS_FRAMELIST_SIZE = 2, EHCI_USBCMD_POS_PERIOD_ENABLE = 4, EHCI_USBCMD_POS_ASYNC_ENABLE = 5, EHCI_USBCMD_POS_NXP_FRAMELIST_SIZE_MSB = 15, -- cgit v1.3.1 From 75cd593b609340b3101d0b002ac765c5595fa2eb Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 23 Aug 2021 17:00:41 +0700 Subject: add hcd_devtree_get_info() remove usbh_hcd.h --- src/host/hcd.h | 15 +++++++ src/host/hcd_attr.h | 1 + src/host/usbh.c | 78 ++++++++++++++++++++++++++++++++-- src/host/usbh_control.c | 9 ++-- src/host/usbh_hcd.h | 106 ----------------------------------------------- src/portable/ehci/ehci.c | 10 +++-- src/portable/ohci/ohci.c | 11 ++--- src/tusb_option.h | 6 --- 8 files changed, 106 insertions(+), 130 deletions(-) delete mode 100644 src/host/usbh_hcd.h (limited to 'src/host') diff --git a/src/host/hcd.h b/src/host/hcd.h index e1d21bf45..eb53d2e80 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -92,6 +92,14 @@ enum { //#define HCD_MAX_ENDPOINT 16 //#define HCD_MAX_XFER 16 + +typedef struct { + uint8_t rhport; + uint8_t hub_addr; + uint8_t hub_port; + uint8_t speed; +} hcd_devtree_info_t; + #endif //--------------------------------------------------------------------+ @@ -145,6 +153,13 @@ bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr); // USBH implemented API //--------------------------------------------------------------------+ +// Get device tree information of a device +// USB device tree can be complicated and manged by USBH, this help HCD to retrieve +// needed topology info to carry out its work +extern void hcd_devtree_get_info(uint8_t dev_addr, hcd_devtree_info_t* devtree_info); + +//------------- Event API -------------// + // Called by HCD to notify stack extern void hcd_event_handler(hcd_event_t const* event, bool in_isr); diff --git a/src/host/hcd_attr.h b/src/host/hcd_attr.h index d18686587..729fc407b 100644 --- a/src/host/hcd_attr.h +++ b/src/host/hcd_attr.h @@ -35,6 +35,7 @@ //------------- NXP -------------// #if TU_CHECK_MCU(LPC175X_6X) || TU_CHECK_MCU(LPC177X_8X) || TU_CHECK_MCU(LPC40XX) + #define HCD_ATTR_OHCI #elif TU_CHECK_MCU(LPC18XX) || TU_CHECK_MCU(LPC43XX) #define HCD_ATTR_EHCI_TRANSDIMENSION diff --git a/src/host/usbh.c b/src/host/usbh.c index 76c1ba078..8e9628cb2 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -32,12 +32,16 @@ #include "host/usbh.h" #include "host/usbh_classdriver.h" #include "hub.h" -#include "usbh_hcd.h" //--------------------------------------------------------------------+ // USBH Configuration //--------------------------------------------------------------------+ +// TODO remove,update +#ifndef CFG_TUH_EP_MAX +#define CFG_TUH_EP_MAX 9 +#endif + #ifndef CFG_TUH_TASK_QUEUE_SZ #define CFG_TUH_TASK_QUEUE_SZ 16 #endif @@ -45,6 +49,57 @@ // Debug level of USBD #define USBH_DBG_LVL 2 +//--------------------------------------------------------------------+ +// USBH-HCD common data structure +//--------------------------------------------------------------------+ + +typedef struct { + //------------- port -------------// + uint8_t rhport; + uint8_t hub_addr; + uint8_t hub_port; + uint8_t speed; + + //------------- device descriptor -------------// + uint16_t vendor_id; + uint16_t product_id; + uint8_t ep0_packet_size; + + //------------- configuration descriptor -------------// + // uint8_t interface_count; // bNumInterfaces alias + + //------------- device -------------// + struct TU_ATTR_PACKED + { + uint8_t connected : 1; + uint8_t addressed : 1; + uint8_t configured : 1; + uint8_t suspended : 1; + }; + + volatile uint8_t state; // device state, value from enum tusbh_device_state_t + + uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) + uint8_t ep2drv[CFG_TUH_EP_MAX][2]; // map endpoint to driver ( 0xff is invalid ) + + struct TU_ATTR_PACKED + { + volatile bool busy : 1; + volatile bool stalled : 1; + volatile bool claimed : 1; + + // TODO merge ep2drv here, 4-bit should be sufficient + }ep_status[CFG_TUH_EP_MAX][2]; + + // Mutex for claiming endpoint, only needed when using with preempted RTOS +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_def_t mutexdef; + osal_mutex_t mutex; +#endif + +} usbh_device_t; + + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -130,7 +185,7 @@ static bool _usbh_initialized = false; // all devices including hub and zero-address TODO exclude device0 to save space // hub address start from CFG_TUH_DEVICE_MAX -CFG_TUSB_MEM_SECTION usbh_device_t _usbh_devices[CFG_TUH_DEVICE_MAX+1]; +CFG_TUSB_MEM_SECTION usbh_device_t _usbh_devices[1+CFG_TUH_DEVICE_MAX+CFG_TUH_HUB]; // Event queue // role device/host is used by OS NONE for mutex (disable usb isr) @@ -139,7 +194,14 @@ static osal_queue_t _usbh_q; CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSIZE]; -//------------- Helper Function Prototypes -------------// +//------------- Helper Function -------------// + +TU_ATTR_ALWAYS_INLINE +static inline usbh_device_t* get_device(uint8_t dev_addr) +{ + return &_usbh_devices[dev_addr]; +} + static bool enum_new_device(hcd_event_t* event); static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port); static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size); @@ -326,6 +388,16 @@ uint8_t* usbh_get_enum_buf(void) // HCD Event Handler //--------------------------------------------------------------------+ +void hcd_devtree_get_info(uint8_t dev_addr, hcd_devtree_info_t* devtree_info) +{ + usbh_device_t const* dev = get_device(dev_addr); + + devtree_info->rhport = dev->rhport; + devtree_info->hub_addr = dev->hub_addr; + devtree_info->hub_port = dev->hub_port; + devtree_info->speed = dev->speed; +} + void hcd_event_handler(hcd_event_t const* event, bool in_isr) { switch (event->event_id) diff --git a/src/host/usbh_control.c b/src/host/usbh_control.c index 0bdb66fb5..9204576ac 100644 --- a/src/host/usbh_control.c +++ b/src/host/usbh_control.c @@ -29,7 +29,7 @@ #if TUSB_OPT_HOST_ENABLED #include "tusb.h" -#include "usbh_hcd.h" +#include "usbh_classdriver.h" enum { @@ -59,9 +59,7 @@ static usbh_control_xfer_t _ctrl_xfer; bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb) { // TODO need to claim the endpoint first - - usbh_device_t* dev = &_usbh_devices[dev_addr]; - const uint8_t rhport = dev->rhport; + const uint8_t rhport = usbh_get_rhport(dev_addr); _ctrl_xfer.request = (*request); _ctrl_xfer.buffer = buffer; @@ -89,8 +87,7 @@ bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t resu (void) ep_addr; (void) xferred_bytes; - usbh_device_t* dev = &_usbh_devices[dev_addr]; - const uint8_t rhport = dev->rhport; + const uint8_t rhport = usbh_get_rhport(dev_addr); tusb_control_request_t const * request = &_ctrl_xfer.request; diff --git a/src/host/usbh_hcd.h b/src/host/usbh_hcd.h deleted file mode 100644 index 9f8d3407d..000000000 --- a/src/host/usbh_hcd.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup Group_HCD - * @{ */ - -#ifndef _TUSB_USBH_HCD_H_ -#define _TUSB_USBH_HCD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "common/tusb_common.h" -#include "osal/osal.h" - -#ifndef CFG_TUH_EP_MAX -#define CFG_TUH_EP_MAX 9 -#endif - -//--------------------------------------------------------------------+ -// USBH-HCD common data structure -//--------------------------------------------------------------------+ - -// TODO move to usbh.c -typedef struct { - //------------- port -------------// - uint8_t rhport; - uint8_t hub_addr; - uint8_t hub_port; - uint8_t speed; - - //------------- device descriptor -------------// - uint16_t vendor_id; - uint16_t product_id; - uint8_t ep0_packet_size; - - //------------- configuration descriptor -------------// - // uint8_t interface_count; // bNumInterfaces alias - - //------------- device -------------// - struct TU_ATTR_PACKED - { - uint8_t connected : 1; - uint8_t addressed : 1; - uint8_t configured : 1; - uint8_t suspended : 1; - }; - - volatile uint8_t state; // device state, value from enum tusbh_device_state_t - - uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) - uint8_t ep2drv[CFG_TUH_EP_MAX][2]; // map endpoint to driver ( 0xff is invalid ) - - struct TU_ATTR_PACKED - { - volatile bool busy : 1; - volatile bool stalled : 1; - volatile bool claimed : 1; - - // TODO merge ep2drv here, 4-bit should be sufficient - }ep_status[CFG_TUH_EP_MAX][2]; - - // Mutex for claiming endpoint, only needed when using with preempted RTOS -#if CFG_TUSB_OS != OPT_OS_NONE - osal_mutex_def_t mutexdef; - osal_mutex_t mutex; -#endif - -} usbh_device_t; - -extern usbh_device_t _usbh_devices[CFG_TUH_DEVICE_MAX+1]; // including zero-address - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_USBH_HCD_H_ */ - -/** @} */ diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 4d240cc50..124d88ff3 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -34,7 +34,6 @@ #include "osal/osal.h" #include "host/hcd.h" -#include "host/usbh_hcd.h" #include "ehci_api.h" #include "ehci.h" @@ -791,13 +790,16 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c tu_memclr(p_qhd, sizeof(ehci_qhd_t)); } + hcd_devtree_info_t devtree_info; + hcd_devtree_get_info(dev_addr, &devtree_info); + uint8_t const xfer_type = ep_desc->bmAttributes.xfer; uint8_t const interval = ep_desc->bInterval; p_qhd->dev_addr = dev_addr; p_qhd->fl_inactive_next_xact = 0; p_qhd->ep_number = tu_edpt_number(ep_desc->bEndpointAddress); - p_qhd->ep_speed = _usbh_devices[dev_addr].speed; + p_qhd->ep_speed = devtree_info.speed; p_qhd->data_toggle_control= (xfer_type == TUSB_XFER_CONTROL) ? 1 : 0; p_qhd->head_list_flag = (dev_addr == 0) ? 1 : 0; // addr0's endpoint is the static asyn list head p_qhd->max_packet_size = ep_desc->wMaxPacketSize.size; @@ -834,8 +836,8 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c p_qhd->int_smask = p_qhd->fl_int_cmask = 0; } - p_qhd->fl_hub_addr = _usbh_devices[dev_addr].hub_addr; - p_qhd->fl_hub_port = _usbh_devices[dev_addr].hub_port; + p_qhd->fl_hub_addr = devtree_info.hub_addr; + p_qhd->fl_hub_port = devtree_info.hub_port; p_qhd->mult = 1; // TODO not use high bandwidth/park mode yet //------------- HCD Management Data -------------// diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c index 73489c764..bcee34938 100644 --- a/src/portable/ohci/ohci.c +++ b/src/portable/ohci/ohci.c @@ -24,10 +24,9 @@ * This file is part of the TinyUSB stack. */ -#include +#include "host/hcd_attr.h" -#if TUSB_OPT_HOST_ENABLED && \ - (CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX) +#if TUSB_OPT_HOST_ENABLED && defined(HCD_ATTR_OHCI) //--------------------------------------------------------------------+ // INCLUDE @@ -35,7 +34,6 @@ #include "osal/osal.h" #include "host/hcd.h" -#include "host/usbh_hcd.h" #include "ohci.h" // TODO remove @@ -280,10 +278,13 @@ static void ed_init(ohci_ed_t *p_ed, uint8_t dev_addr, uint16_t ep_size, uint8_t tu_memclr(p_ed, sizeof(ohci_ed_t)); } + hcd_devtree_info_t devtree_info; + hcd_devtree_get_info(dev_addr, &devtree_info); + p_ed->dev_addr = dev_addr; p_ed->ep_number = ep_addr & 0x0F; p_ed->pid = (xfer_type == TUSB_XFER_CONTROL) ? PID_FROM_TD : (tu_edpt_dir(ep_addr) ? PID_IN : PID_OUT); - p_ed->speed = _usbh_devices[dev_addr].speed; + p_ed->speed = devtree_info.speed; p_ed->is_iso = (xfer_type == TUSB_XFER_ISOCHRONOUS) ? 1 : 0; p_ed->max_packet_size = ep_size; diff --git a/src/tusb_option.h b/src/tusb_option.h index bbbf10a84..925f395e7 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -268,12 +268,6 @@ #if TUSB_OPT_HOST_ENABLED #ifndef CFG_TUH_DEVICE_MAX #define CFG_TUH_DEVICE_MAX 1 - #warning CFG_TUH_DEVICE_MAX is not defined, default value is 1 - #endif - - //------------- HUB CLASS -------------// - #if CFG_TUH_HUB && (CFG_TUH_DEVICE_MAX == 1) - #error There is no benefit enable hub with max device is 1. Please disable hub or increase CFG_TUH_DEVICE_MAX #endif #ifndef CFG_TUH_ENUMERATION_BUFSIZE -- cgit v1.3.1 From 3309425211639121ce72784405106ab22c4a426e Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 23 Aug 2021 19:56:53 +0700 Subject: sepearate CFG_TUH_DEVICE_MAX and CFG_TUH_HUB separate dev0 from _usbh_devices pool to save sram --- examples/host/cdc_msc_hid/src/tusb_config.h | 3 +- src/class/cdc/cdc_host.c | 2 + src/class/hid/hid_host.c | 4 +- src/class/msc/msc_host.c | 5 +- src/host/hub.c | 36 ++++++---- src/host/usbh.c | 104 +++++++++++++++------------- src/portable/ehci/ehci.c | 2 +- 7 files changed, 93 insertions(+), 63 deletions(-) (limited to 'src/host') diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index e2eb566bd..bc6c68e5b 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -80,7 +80,8 @@ #define CFG_TUH_MSC 1 #define CFG_TUH_VENDOR 0 -#define CFG_TUH_DEVICE_MAX (CFG_TUH_HUB ? 5 : 1) // normal hub has 4 ports +// max device support (excluding hub device) +#define CFG_TUH_DEVICE_MAX (CFG_TUH_HUB ? 4 : 1) // hub typically has 4 ports //------------- HID -------------// #define CFG_TUH_HID_EPIN_BUFSIZE 64 diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index e14cb0bab..08b9bab99 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -240,6 +240,8 @@ bool cdch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 void cdch_close(uint8_t dev_addr) { + TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX, ); + cdch_data_t * p_cdc = get_itf(dev_addr); tu_memclr(p_cdc, sizeof(cdch_data_t)); } diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 915f0b21a..a9ea03de6 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -62,7 +62,7 @@ typedef struct hidh_interface_t instances[CFG_TUH_HID]; } hidh_device_t; -static hidh_device_t _hidh_dev[CFG_TUH_DEVICE_MAX-1]; +static hidh_device_t _hidh_dev[CFG_TUH_DEVICE_MAX]; //------------- Internal prototypes -------------// @@ -240,6 +240,8 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint3 void hidh_close(uint8_t dev_addr) { + TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX, ); + hidh_device_t* hid_dev = get_dev(dev_addr); if (tuh_hid_umount_cb) { diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index c7669aa21..8069353cd 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -76,6 +76,7 @@ CFG_TUSB_MEM_SECTION static msch_interface_t _msch_itf[CFG_TUH_DEVICE_MAX]; CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t _msch_buffer[sizeof(scsi_inquiry_resp_t)]; +TU_ATTR_ALWAYS_INLINE static inline msch_interface_t* get_itf(uint8_t dev_addr) { return &_msch_itf[dev_addr-1]; @@ -291,11 +292,13 @@ bool tuh_msc_reset(uint8_t dev_addr) //--------------------------------------------------------------------+ void msch_init(void) { - tu_memclr(_msch_itf, sizeof(msch_interface_t)*CFG_TUH_DEVICE_MAX); + tu_memclr(_msch_itf, sizeof(_msch_itf)); } void msch_close(uint8_t dev_addr) { + TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX, ); + msch_interface_t* p_msc = get_itf(dev_addr); // invoke Application Callback diff --git a/src/host/hub.c b/src/host/hub.c index 65e747e41..fd4dbd04a 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -48,6 +48,12 @@ typedef struct 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)]; +TU_ATTR_ALWAYS_INLINE +static inline hub_interface_t* get_itf(uint8_t dev_addr) +{ + return &hub_data[dev_addr-1-CFG_TUH_DEVICE_MAX]; +} + #if CFG_TUSB_DEBUG static char const* const _hub_feature_str[] = { @@ -167,21 +173,26 @@ bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf TU_ASSERT(usbh_edpt_open(rhport, dev_addr, desc_ep)); - hub_data[dev_addr-1].itf_num = itf_desc->bInterfaceNumber; - hub_data[dev_addr-1].ep_in = desc_ep->bEndpointAddress; + hub_interface_t* p_hub = get_itf(dev_addr); + + p_hub->itf_num = itf_desc->bInterfaceNumber; + p_hub->ep_in = desc_ep->bEndpointAddress; return true; } void hub_close(uint8_t dev_addr) { - tu_memclr(&hub_data[dev_addr-1], sizeof( hub_interface_t)); + 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)); } bool hub_status_pipe_queue(uint8_t dev_addr) { - hub_interface_t * p_hub = &hub_data[dev_addr-1]; - return usbh_edpt_xfer(dev_addr, p_hub->ep_in, &p_hub->status_change, 1); + hub_interface_t* hub_itf = get_itf(dev_addr); + return usbh_edpt_xfer(dev_addr, hub_itf->ep_in, &hub_itf->status_change, 1); } @@ -194,7 +205,7 @@ static bool config_port_power_complete (uint8_t dev_addr, tusb_control_request_t bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) { - hub_interface_t* p_hub = &hub_data[dev_addr-1]; + hub_interface_t* p_hub = get_itf(dev_addr); TU_ASSERT(itf_num == p_hub->itf_num); // Get Hub Descriptor @@ -222,7 +233,7 @@ static bool config_set_port_power (uint8_t dev_addr, tusb_control_request_t cons (void) request; TU_ASSERT(XFER_RESULT_SUCCESS == result); - hub_interface_t* p_hub = &hub_data[dev_addr-1]; + hub_interface_t* p_hub = get_itf(dev_addr); // only use number of ports in hub descriptor descriptor_hub_desc_t const* desc_hub = (descriptor_hub_desc_t const*) _hub_buffer; @@ -238,7 +249,7 @@ static bool config_set_port_power (uint8_t dev_addr, tusb_control_request_t cons static bool config_port_power_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { TU_ASSERT(XFER_RESULT_SUCCESS == result); - hub_interface_t* p_hub = &hub_data[dev_addr-1]; + hub_interface_t* p_hub = get_itf(dev_addr); if (request->wIndex == p_hub->port_count) { @@ -272,7 +283,7 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32 (void) ep_addr; TU_ASSERT(result == XFER_RESULT_SUCCESS); - hub_interface_t * p_hub = &hub_data[dev_addr-1]; + hub_interface_t* p_hub = get_itf(dev_addr); TU_LOG2(" Port Status Change = 0x%02X\r\n", p_hub->status_change); @@ -294,7 +305,8 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32 static bool connection_get_status_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { TU_ASSERT(result == XFER_RESULT_SUCCESS); - hub_interface_t * p_hub = &hub_data[dev_addr-1]; + + hub_interface_t* p_hub = get_itf(dev_addr); uint8_t const port_num = (uint8_t) request->wIndex; // Connection change @@ -322,7 +334,7 @@ static bool connection_clear_conn_change_complete (uint8_t dev_addr, tusb_contro { TU_ASSERT(result == XFER_RESULT_SUCCESS); - hub_interface_t * p_hub = &hub_data[dev_addr-1]; + hub_interface_t* p_hub = get_itf(dev_addr); uint8_t const port_num = (uint8_t) request->wIndex; if ( p_hub->port_status.status.connection ) @@ -353,7 +365,7 @@ static bool connection_port_reset_complete (uint8_t dev_addr, tusb_control_reque { TU_ASSERT(result == XFER_RESULT_SUCCESS); - // usbh_hub_t * p_hub = &hub_data[dev_addr-1]; + // hub_interface_t* p_hub = get_itf(dev_addr); uint8_t const port_num = (uint8_t) request->wIndex; // submit attach event diff --git a/src/host/usbh.c b/src/host/usbh.c index 8e9628cb2..52c552408 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -99,6 +99,14 @@ typedef struct { } usbh_device_t; +typedef struct +{ + uint8_t rhport; + uint8_t hub_addr; + uint8_t hub_port; + uint8_t speed; +} usbh_dev0_t; + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF @@ -106,6 +114,7 @@ typedef struct { // Invalid driver ID in itf2drv[] ep2drv[][] mapping enum { DRVID_INVALID = 0xFFu }; +enum { ADDR_INVALID = 0xFFu }; #if CFG_TUSB_DEBUG >= 2 #define DRIVER_NAME(_name) .name = _name, @@ -183,9 +192,12 @@ enum { CONFIG_NUM = 1 }; // default to use configuration 1 static bool _usbh_initialized = false; +// Device with address = 0 for enumeration +static usbh_dev0_t _dev0; + // all devices including hub and zero-address TODO exclude device0 to save space -// hub address start from CFG_TUH_DEVICE_MAX -CFG_TUSB_MEM_SECTION usbh_device_t _usbh_devices[1+CFG_TUH_DEVICE_MAX+CFG_TUH_HUB]; +// hub address start from CFG_TUH_DEVICE_MAX+1 +CFG_TUSB_MEM_SECTION usbh_device_t _usbh_devices[1 + CFG_TUH_DEVICE_MAX + CFG_TUH_HUB]; // Event queue // role device/host is used by OS NONE for mutex (disable usb isr) @@ -214,13 +226,13 @@ extern bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result //--------------------------------------------------------------------+ bool tuh_device_configured(uint8_t dev_addr) { - return _usbh_devices[dev_addr].configured; + return get_device(dev_addr)->configured; } tusb_speed_t tuh_device_get_speed (uint8_t const dev_addr) { - TU_ASSERT( dev_addr <= CFG_TUH_DEVICE_MAX, TUSB_SPEED_INVALID); - return (tusb_speed_t) _usbh_devices[dev_addr].speed; + TU_ASSERT( dev_addr <= CFG_TUH_DEVICE_MAX + CFG_TUH_HUB, TUSB_SPEED_INVALID); + return (tusb_speed_t) get_device(dev_addr)->speed; } #if CFG_TUSB_OS == OPT_OS_NONE @@ -250,15 +262,16 @@ bool tuh_init(uint8_t rhport) TU_LOG2("USBH init\r\n"); tu_memclr(_usbh_devices, sizeof(_usbh_devices)); + tu_memclr(&_dev0, sizeof(_dev0)); //------------- Enumeration & Reporter Task init -------------// _usbh_q = osal_queue_create( &_usbh_qdef ); TU_ASSERT(_usbh_q != NULL); //------------- Semaphore, Mutex for Control Pipe -------------// - for(uint8_t i=0; imutex = osal_mutex_create(&dev->mutexdef); @@ -460,7 +473,7 @@ void hcd_event_device_remove(uint8_t hostid, bool in_isr) void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) { //------------- find the all devices (star-network) under port that is unplugged -------------// - for (uint8_t dev_addr = 0; dev_addr <= CFG_TUH_DEVICE_MAX; dev_addr ++) + for (uint8_t dev_addr = 0; dev_addr < TU_ARRAY_SIZE(_usbh_devices); dev_addr ++) { usbh_device_t* dev = &_usbh_devices[dev_addr]; @@ -493,13 +506,17 @@ void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port //--------------------------------------------------------------------+ // INTERNAL HELPER //--------------------------------------------------------------------+ -static uint8_t get_new_address(void) +static uint8_t get_new_address(bool is_hub) { - for (uint8_t addr=1; addr <= CFG_TUH_DEVICE_MAX; addr++) + uint8_t const start = (is_hub ? CFG_TUH_DEVICE_MAX : 0) + 1; + uint8_t const count = (is_hub ? CFG_TUH_HUB : CFG_TUH_DEVICE_MAX); + + for (uint8_t i=0; i < count; i++) { + uint8_t const addr = start + i; if (_usbh_devices[addr].state == TUSB_DEVICE_STATE_UNPLUG) return addr; } - return CFG_TUH_DEVICE_MAX+1; + return ADDR_INVALID; } void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) @@ -561,12 +578,11 @@ static bool enum_hub_clear_reset1_complete(uint8_t dev_addr, tusb_control_reques { (void) dev_addr; (void) request; TU_ASSERT(XFER_RESULT_SUCCESS == result); - usbh_device_t* dev0 = &_usbh_devices[0]; enum_request_set_addr(); // done with hub, waiting for next data on status pipe - (void) hub_status_pipe_queue( dev0->hub_addr ); + (void) hub_status_pipe_queue( _dev0.hub_addr ); return true; } @@ -575,7 +591,6 @@ static bool enum_hub_get_status1_complete(uint8_t dev_addr, tusb_control_request { (void) dev_addr; (void) request; TU_ASSERT(XFER_RESULT_SUCCESS == result); - usbh_device_t* dev0 = &_usbh_devices[0]; hub_port_status_response_t port_status; memcpy(&port_status, _usbh_ctrl_buf, sizeof(hub_port_status_response_t)); @@ -583,7 +598,7 @@ static bool enum_hub_get_status1_complete(uint8_t dev_addr, tusb_control_request // Acknowledge Port Reset Change if Reset Successful if (port_status.change.reset) { - TU_ASSERT( hub_port_clear_feature(dev0->hub_addr, dev0->hub_port, HUB_FEATURE_PORT_RESET_CHANGE, enum_hub_clear_reset1_complete) ); + TU_ASSERT( hub_port_clear_feature(_dev0.hub_addr, _dev0.hub_port, HUB_FEATURE_PORT_RESET_CHANGE, enum_hub_clear_reset1_complete) ); } return true; @@ -593,7 +608,6 @@ static bool enum_hub_get_status0_complete(uint8_t dev_addr, tusb_control_request { (void) dev_addr; (void) request; TU_ASSERT(XFER_RESULT_SUCCESS == result); - usbh_device_t* dev0 = &_usbh_devices[0]; hub_port_status_response_t port_status; memcpy(&port_status, _usbh_ctrl_buf, sizeof(hub_port_status_response_t)); @@ -604,13 +618,13 @@ static bool enum_hub_get_status0_complete(uint8_t dev_addr, tusb_control_request return hub_status_pipe_queue(dev_addr); } - dev0->speed = (port_status.status.high_speed) ? TUSB_SPEED_HIGH : + _dev0.speed = (port_status.status.high_speed) ? TUSB_SPEED_HIGH : (port_status.status.low_speed ) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; // Acknowledge Port Reset Change if (port_status.change.reset) { - hub_port_clear_feature(dev0->hub_addr, dev0->hub_port, HUB_FEATURE_PORT_RESET_CHANGE, enum_hub_clear_reset0_complete); + hub_port_clear_feature(_dev0.hub_addr, _dev0.hub_port, HUB_FEATURE_PORT_RESET_CHANGE, enum_hub_clear_reset0_complete); } return true; @@ -619,21 +633,22 @@ static bool enum_hub_get_status0_complete(uint8_t dev_addr, tusb_control_request static bool enum_request_set_addr(void) { - // Set Address - uint8_t const new_addr = get_new_address(); - TU_ASSERT(new_addr <= CFG_TUH_DEVICE_MAX); // TODO notify application we reach max devices + tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf; + + // Get new address + uint8_t const new_addr = get_new_address(desc_device->bDeviceClass == TUSB_CLASS_HUB); + TU_ASSERT(new_addr != ADDR_INVALID); TU_LOG2("Set Address = %d\r\n", new_addr); - usbh_device_t* dev0 = &_usbh_devices[0]; usbh_device_t* new_dev = &_usbh_devices[new_addr]; - new_dev->rhport = dev0->rhport; - new_dev->hub_addr = dev0->hub_addr; - new_dev->hub_port = dev0->hub_port; - new_dev->speed = dev0->speed; + new_dev->rhport = _dev0.rhport; + new_dev->hub_addr = _dev0.hub_addr; + new_dev->hub_port = _dev0.hub_port; + new_dev->speed = _dev0.speed; new_dev->connected = 1; - new_dev->ep0_packet_size = ((tusb_desc_device_t*) _usbh_ctrl_buf)->bMaxPacketSize0; + new_dev->ep0_packet_size = desc_device->bMaxPacketSize0; tusb_control_request_t const new_request = { @@ -656,22 +671,20 @@ static bool enum_request_set_addr(void) static bool enum_new_device(hcd_event_t* event) { - usbh_device_t* dev0 = &_usbh_devices[0]; - dev0->rhport = event->rhport; // TODO refractor integrate to device_pool - dev0->hub_addr = event->connection.hub_addr; - dev0->hub_port = event->connection.hub_port; - dev0->state = TUSB_DEVICE_STATE_UNPLUG; + _dev0.rhport = event->rhport; // TODO refractor integrate to device_pool + _dev0.hub_addr = event->connection.hub_addr; + _dev0.hub_port = event->connection.hub_port; //------------- connected/disconnected directly with roothub -------------// - if (dev0->hub_addr == 0) + if (_dev0.hub_addr == 0) { // wait until device is stable TODO non blocking osal_task_delay(RESET_DELAY); // device unplugged while delaying - if ( !hcd_port_connect_status(dev0->rhport) ) return true; + if ( !hcd_port_connect_status(_dev0.rhport) ) return true; - dev0->speed = hcd_port_speed_get( dev0->rhport ); + _dev0.speed = hcd_port_speed_get(_dev0.rhport ); enum_request_addr0_device_desc(); } @@ -681,7 +694,7 @@ static bool enum_new_device(hcd_event_t* event) { // wait until device is stable osal_task_delay(RESET_DELAY); - TU_ASSERT( hub_port_get_status(dev0->hub_addr, dev0->hub_port, _usbh_ctrl_buf, enum_hub_get_status0_complete) ); + TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, enum_hub_get_status0_complete) ); } #endif // CFG_TUH_HUB @@ -719,27 +732,26 @@ static bool enum_get_addr0_device_desc_complete(uint8_t dev_addr, tusb_control_r (void) request; TU_ASSERT(0 == dev_addr); - usbh_device_t* dev0 = &_usbh_devices[0]; - if (XFER_RESULT_SUCCESS != result) { #if CFG_TUH_HUB // TODO remove, waiting for next data on status pipe - if (dev0->hub_addr != 0) hub_status_pipe_queue(dev0->hub_addr); + if (_dev0.hub_addr != 0) hub_status_pipe_queue(_dev0.hub_addr); #endif return false; } - TU_ASSERT(tu_desc_type(_usbh_ctrl_buf) == TUSB_DESC_DEVICE); + tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf; + TU_ASSERT( tu_desc_type(desc_device) == TUSB_DESC_DEVICE ); // Reset device again before Set Address TU_LOG2("Port reset \r\n"); - if (dev0->hub_addr == 0) + if (_dev0.hub_addr == 0) { // connected directly to roothub - hcd_port_reset( dev0->rhport ); // reset port after 8 byte descriptor + hcd_port_reset( _dev0.rhport ); // reset port after 8 byte descriptor osal_task_delay(RESET_DELAY); enum_request_set_addr(); @@ -748,12 +760,12 @@ static bool enum_get_addr0_device_desc_complete(uint8_t dev_addr, tusb_control_r else { // after RESET_DELAY the hub_port_reset() already complete - TU_ASSERT( hub_port_reset(dev0->hub_addr, dev0->hub_port, NULL) ); + TU_ASSERT( hub_port_reset(_dev0.hub_addr, _dev0.hub_port, NULL) ); osal_task_delay(RESET_DELAY); tuh_task(); // FIXME temporarily to clean up port_reset control transfer - TU_ASSERT( hub_port_get_status(dev0->hub_addr, dev0->hub_port, _usbh_ctrl_buf, enum_hub_get_status1_complete) ); + TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, enum_hub_get_status1_complete) ); } #endif @@ -772,9 +784,7 @@ static bool enum_set_address_complete(uint8_t dev_addr, tusb_control_request_t c new_dev->addressed = 1; // TODO close device 0, may not be needed - usbh_device_t* dev0 = &_usbh_devices[0]; - hcd_device_close(dev0->rhport, 0); - dev0->state = TUSB_DEVICE_STATE_UNPLUG; + hcd_device_close(_dev0.rhport, 0); // open control pipe for new address TU_ASSERT( usbh_edpt_control_open(new_addr, new_dev->ep0_packet_size) ); diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 124d88ff3..e3b7499cc 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -71,7 +71,7 @@ typedef struct struct { ehci_qhd_t qhd; ehci_qtd_t qtd; - }control[CFG_TUH_DEVICE_MAX+1]; + }control[CFG_TUH_DEVICE_MAX+CFG_TUH_HUB+1]; ehci_qhd_t qhd_pool[HCD_MAX_ENDPOINT]; ehci_qtd_t qtd_pool[HCD_MAX_XFER] TU_ATTR_ALIGNED(32); -- cgit v1.3.1 From 353c070d00a31ef9eed1e701d4048414fe704738 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 24 Aug 2021 01:06:05 +0700 Subject: exclude dev0 from usbh devices pool --- src/class/cdc/cdc_host.c | 2 +- src/class/hid/hid_host.c | 3 ++- src/host/usbh.c | 41 +++++++++++++++++++++-------------------- 3 files changed, 24 insertions(+), 22 deletions(-) (limited to 'src/host') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 08b9bab99..e7eaf4d05 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -146,7 +146,7 @@ bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_co //--------------------------------------------------------------------+ void cdch_init(void) { - tu_memclr(cdch_data, sizeof(cdch_data_t)*CFG_TUH_DEVICE_MAX); + tu_memclr(cdch_data, sizeof(cdch_data)); } bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index a9ea03de6..3a832a247 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -243,9 +243,10 @@ void hidh_close(uint8_t dev_addr) TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX, ); hidh_device_t* hid_dev = get_dev(dev_addr); + if (tuh_hid_umount_cb) { - for ( uint8_t inst = 0; inst < hid_dev->inst_count; inst++ ) tuh_hid_umount_cb(dev_addr, inst); + for (uint8_t inst = 0; inst < hid_dev->inst_count; inst++ ) tuh_hid_umount_cb(dev_addr, inst); } tu_memclr(hid_dev, sizeof(hidh_device_t)); diff --git a/src/host/usbh.c b/src/host/usbh.c index 52c552408..fde51f5c9 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -195,9 +195,9 @@ static bool _usbh_initialized = false; // Device with address = 0 for enumeration static usbh_dev0_t _dev0; -// all devices including hub and zero-address TODO exclude device0 to save space +// all devices excluding zero-address // hub address start from CFG_TUH_DEVICE_MAX+1 -CFG_TUSB_MEM_SECTION usbh_device_t _usbh_devices[1 + CFG_TUH_DEVICE_MAX + CFG_TUH_HUB]; +CFG_TUSB_MEM_SECTION usbh_device_t _usbh_devices[CFG_TUH_DEVICE_MAX + CFG_TUH_HUB]; // Event queue // role device/host is used by OS NONE for mutex (disable usb isr) @@ -211,7 +211,7 @@ CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbh_ctrl_buf[CFG_TUH_EN TU_ATTR_ALWAYS_INLINE static inline usbh_device_t* get_device(uint8_t dev_addr) { - return &_usbh_devices[dev_addr]; + return &_usbh_devices[dev_addr-1]; } static bool enum_new_device(hcd_event_t* event); @@ -350,7 +350,7 @@ void tuh_task(void) case HCD_EVENT_XFER_COMPLETE: { - usbh_device_t* dev = &_usbh_devices[event.dev_addr]; + usbh_device_t* dev = get_device(event.dev_addr); uint8_t const ep_addr = event.xfer_complete.ep_addr; uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const ep_dir = tu_edpt_dir(ep_addr); @@ -389,7 +389,7 @@ void tuh_task(void) uint8_t usbh_get_rhport(uint8_t dev_addr) { - return _usbh_devices[dev_addr].rhport; + return get_device(dev_addr)->rhport; } uint8_t* usbh_get_enum_buf(void) @@ -473,9 +473,10 @@ void hcd_event_device_remove(uint8_t hostid, bool in_isr) void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) { //------------- find the all devices (star-network) under port that is unplugged -------------// - for (uint8_t dev_addr = 0; dev_addr < TU_ARRAY_SIZE(_usbh_devices); dev_addr ++) + for ( uint8_t dev_id = 0; dev_id < TU_ARRAY_SIZE(_usbh_devices); dev_id++ ) { - usbh_device_t* dev = &_usbh_devices[dev_addr]; + usbh_device_t* dev = &_usbh_devices[dev_id]; + uint8_t const dev_addr = dev_id+1; // TODO Hub multiple level if (dev->rhport == rhport && @@ -514,14 +515,14 @@ static uint8_t get_new_address(bool is_hub) for (uint8_t i=0; i < count; i++) { uint8_t const addr = start + i; - if (_usbh_devices[addr].state == TUSB_DEVICE_STATE_UNPLUG) return addr; + if (get_device(addr)->state == TUSB_DEVICE_STATE_UNPLUG) return addr; } return ADDR_INVALID; } void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) { - usbh_device_t* dev = &_usbh_devices[dev_addr]; + usbh_device_t* dev = get_device(dev_addr); for(itf_num++; itf_num < sizeof(dev->itf2drv); itf_num++) { @@ -641,7 +642,7 @@ static bool enum_request_set_addr(void) TU_LOG2("Set Address = %d\r\n", new_addr); - usbh_device_t* new_dev = &_usbh_devices[new_addr]; + usbh_device_t* new_dev = get_device(new_addr); new_dev->rhport = _dev0.rhport; new_dev->hub_addr = _dev0.hub_addr; @@ -780,7 +781,7 @@ static bool enum_set_address_complete(uint8_t dev_addr, tusb_control_request_t c uint8_t const new_addr = (uint8_t const) request->wValue; - usbh_device_t* new_dev = &_usbh_devices[new_addr]; + usbh_device_t* new_dev = get_device(new_addr); new_dev->addressed = 1; // TODO close device 0, may not be needed @@ -816,7 +817,7 @@ static bool enum_get_device_desc_complete(uint8_t dev_addr, tusb_control_request TU_ASSERT(XFER_RESULT_SUCCESS == result); tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf; - usbh_device_t* dev = &_usbh_devices[dev_addr]; + usbh_device_t* dev = get_device(dev_addr); dev->vendor_id = desc_device->idVendor; dev->product_id = desc_device->idProduct; @@ -914,7 +915,7 @@ static bool enum_set_config_complete(uint8_t dev_addr, tusb_control_request_t co TU_ASSERT(XFER_RESULT_SUCCESS == result); TU_LOG2("Device configured\r\n"); - usbh_device_t* dev = &_usbh_devices[dev_addr]; + usbh_device_t* dev = get_device(dev_addr); dev->configured = 1; dev->state = TUSB_DEVICE_STATE_CONFIGURED; @@ -929,7 +930,7 @@ static bool enum_set_config_complete(uint8_t dev_addr, tusb_control_request_t co static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg) { - usbh_device_t* dev = &_usbh_devices[dev_addr]; + usbh_device_t* dev = get_device(dev_addr); uint8_t const* desc_end = ((uint8_t const*) desc_cfg) + tu_le16toh(desc_cfg->wTotalLength); uint8_t const* p_desc = tu_desc_next(desc_cfg); @@ -1023,7 +1024,7 @@ bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - usbh_device_t* dev = &_usbh_devices[dev_addr]; + usbh_device_t* dev = get_device(dev_addr); #if CFG_TUSB_OS != OPT_OS_NONE // pre-check to help reducing mutex lock @@ -1051,7 +1052,7 @@ bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - usbh_device_t* dev = &_usbh_devices[dev_addr]; + usbh_device_t* dev = get_device(dev_addr); #if CFG_TUSB_OS != OPT_OS_NONE osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER); @@ -1077,7 +1078,7 @@ bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_ uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - usbh_device_t* dev = &_usbh_devices[dev_addr]; + usbh_device_t* dev = get_device(dev_addr); TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); @@ -1117,12 +1118,12 @@ static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) .bInterval = 0 }; - return hcd_edpt_open(_usbh_devices[dev_addr].rhport, dev_addr, &ep0_desc); + return hcd_edpt_open(get_device(dev_addr)->rhport, dev_addr, &ep0_desc); } bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep) { - usbh_device_t* dev = &_usbh_devices[dev_addr]; + usbh_device_t* dev = get_device(dev_addr); TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) dev->speed)); return hcd_edpt_open(rhport, dev_addr, desc_ep); @@ -1133,7 +1134,7 @@ bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - usbh_device_t* dev = &_usbh_devices[dev_addr]; + usbh_device_t* dev = get_device(dev_addr); return dev->ep_status[epnum][dir].busy; } -- cgit v1.3.1 From 5d152503ee6c31c7cf3ad2dfeb9ac38c70c42bd4 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 24 Aug 2021 12:16:23 +0700 Subject: fix dev0 out of bound array due to leftover --- src/host/usbh.c | 64 ++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 21 deletions(-) (limited to 'src/host') diff --git a/src/host/usbh.c b/src/host/usbh.c index fde51f5c9..75ed13e87 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -211,6 +211,7 @@ CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbh_ctrl_buf[CFG_TUH_EN TU_ATTR_ALWAYS_INLINE static inline usbh_device_t* get_device(uint8_t dev_addr) { + TU_ASSERT(dev_addr, NULL); return &_usbh_devices[dev_addr-1]; } @@ -350,26 +351,35 @@ void tuh_task(void) case HCD_EVENT_XFER_COMPLETE: { - usbh_device_t* dev = get_device(event.dev_addr); uint8_t const ep_addr = event.xfer_complete.ep_addr; uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const ep_dir = tu_edpt_dir(ep_addr); TU_LOG2("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); - dev->ep_status[epnum][ep_dir].busy = false; - dev->ep_status[epnum][ep_dir].claimed = 0; - - if ( 0 == epnum ) + if (event.dev_addr == 0) { + // device 0 only has control endpoint + TU_ASSERT(epnum == 0, ); usbh_control_xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); - }else + } + else { - uint8_t drv_id = dev->ep2drv[epnum][ep_dir]; - TU_ASSERT(drv_id < USBH_CLASS_DRIVER_COUNT, ); + usbh_device_t* dev = get_device(event.dev_addr); + dev->ep_status[epnum][ep_dir].busy = false; + dev->ep_status[epnum][ep_dir].claimed = 0; + + if ( 0 == epnum ) + { + usbh_control_xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + }else + { + uint8_t drv_id = dev->ep2drv[epnum][ep_dir]; + TU_ASSERT(drv_id < USBH_CLASS_DRIVER_COUNT, ); - TU_LOG2("%s xfer callback\r\n", usbh_class_drivers[drv_id].name); - usbh_class_drivers[drv_id].xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + TU_LOG2("%s xfer callback\r\n", usbh_class_drivers[drv_id].name); + usbh_class_drivers[drv_id].xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + } } } break; @@ -389,7 +399,7 @@ void tuh_task(void) uint8_t usbh_get_rhport(uint8_t dev_addr) { - return get_device(dev_addr)->rhport; + return (dev_addr == 0) ? _dev0.rhport : get_device(dev_addr)->rhport; } uint8_t* usbh_get_enum_buf(void) @@ -403,12 +413,21 @@ uint8_t* usbh_get_enum_buf(void) void hcd_devtree_get_info(uint8_t dev_addr, hcd_devtree_info_t* devtree_info) { - usbh_device_t const* dev = get_device(dev_addr); + if (dev_addr) + { + usbh_device_t const* dev = get_device(dev_addr); - devtree_info->rhport = dev->rhport; - devtree_info->hub_addr = dev->hub_addr; - devtree_info->hub_port = dev->hub_port; - devtree_info->speed = dev->speed; + devtree_info->rhport = dev->rhport; + devtree_info->hub_addr = dev->hub_addr; + devtree_info->hub_port = dev->hub_port; + devtree_info->speed = dev->speed; + }else + { + devtree_info->rhport = _dev0.rhport; + devtree_info->hub_addr = _dev0.hub_addr; + devtree_info->hub_port = _dev0.hub_port; + devtree_info->speed = _dev0.speed; + } } void hcd_event_handler(hcd_event_t const* event, bool in_isr) @@ -473,6 +492,7 @@ void hcd_event_device_remove(uint8_t hostid, bool in_isr) void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) { //------------- find the all devices (star-network) under port that is unplugged -------------// + // TODO mark as disconnected in ISR, also handle dev0 for ( uint8_t dev_id = 0; dev_id < TU_ARRAY_SIZE(_usbh_devices); dev_id++ ) { usbh_device_t* dev = &_usbh_devices[dev_id]; @@ -634,6 +654,7 @@ static bool enum_hub_get_status0_complete(uint8_t dev_addr, tusb_control_request static bool enum_request_set_addr(void) { + uint8_t const addr0 = 0; tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf; // Get new address @@ -665,7 +686,7 @@ static bool enum_request_set_addr(void) .wLength = 0 }; - TU_ASSERT( tuh_control_xfer(0, &new_request, NULL, enum_set_address_complete) ); + TU_ASSERT( tuh_control_xfer(addr0, &new_request, NULL, enum_set_address_complete) ); return true; } @@ -705,7 +726,8 @@ static bool enum_new_device(hcd_event_t* event) static bool enum_request_addr0_device_desc(void) { // TODO probably doesn't need to open/close each enumeration - TU_ASSERT( usbh_edpt_control_open(0, 8) ); + uint8_t const addr0 = 0; + TU_ASSERT( usbh_edpt_control_open(addr0, 8) ); //------------- Get first 8 bytes of device descriptor to get Control Endpoint Size -------------// TU_LOG2("Get 8 byte of Device Descriptor\r\n"); @@ -722,7 +744,7 @@ static bool enum_request_addr0_device_desc(void) .wIndex = 0, .wLength = 8 }; - TU_ASSERT( tuh_control_xfer(0, &request, _usbh_ctrl_buf, enum_get_addr0_device_desc_complete) ); + TU_ASSERT( tuh_control_xfer(addr0, &request, _usbh_ctrl_buf, enum_get_addr0_device_desc_complete) ); return true; } @@ -1106,7 +1128,7 @@ bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_ static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) { - TU_LOG2("Open EP Control with Size = %u\r\n", max_packet_size); + TU_LOG2("Open EP0 with Size = %u (addr = %u)\r\n", max_packet_size, dev_addr); tusb_desc_endpoint_t ep0_desc = { @@ -1118,7 +1140,7 @@ static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) .bInterval = 0 }; - return hcd_edpt_open(get_device(dev_addr)->rhport, dev_addr, &ep0_desc); + return hcd_edpt_open(usbh_get_rhport(dev_addr), dev_addr, &ep0_desc); } bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep) -- cgit v1.3.1 From 88bb8fac3d555e390f59770200c73a13eb61504b Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 24 Aug 2021 12:30:57 +0700 Subject: rename host API to be consistent with naming on device stack - tuh_device_get_speed() to tuh_speed_get() - tuh_device_configured() to tuh_mounted() - tuh_device_ready() to tuh_ready() --- src/host/usbh.c | 4 ++-- src/host/usbh.h | 17 ++++++++++++----- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 2 +- 3 files changed, 15 insertions(+), 8 deletions(-) (limited to 'src/host') diff --git a/src/host/usbh.c b/src/host/usbh.c index 75ed13e87..1b5a422f4 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -225,12 +225,12 @@ extern bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result //--------------------------------------------------------------------+ // PUBLIC API (Parameter Verification is required) //--------------------------------------------------------------------+ -bool tuh_device_configured(uint8_t dev_addr) +bool tuh_mounted(uint8_t dev_addr) { return get_device(dev_addr)->configured; } -tusb_speed_t tuh_device_get_speed (uint8_t const dev_addr) +tusb_speed_t tuh_speed_get (uint8_t const dev_addr) { TU_ASSERT( dev_addr <= CFG_TUH_DEVICE_MAX + CFG_TUH_HUB, TUSB_SPEED_INVALID); return (tusb_speed_t) get_device(dev_addr)->speed; diff --git a/src/host/usbh.h b/src/host/usbh.h index 4de6e7ba6..5f7229f27 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -57,16 +57,23 @@ void tuh_task(void); extern void hcd_int_handler(uint8_t rhport); #define tuh_int_handler hcd_int_handler -tusb_speed_t tuh_device_get_speed (uint8_t dev_addr); +tusb_speed_t tuh_speed_get (uint8_t dev_addr); -// Check if device is configured -bool tuh_device_configured(uint8_t dev_addr); +// Check if device is connected and configured +bool tuh_mounted(uint8_t dev_addr); + +// Check if device is suspended +static inline bool tuh_suspended(uint8_t dev_addr) +{ + // TODO implement suspend & resume on host + return false; +} // Check if device is ready to communicate with TU_ATTR_ALWAYS_INLINE -static inline bool tuh_device_ready(uint8_t dev_addr) +static inline bool tuh_ready(uint8_t dev_addr) { - return tuh_device_configured(dev_addr); + return tuh_mounted(dev_addr) && !tuh_suspended(dev_addr); } // Carry out control transfer diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 34803c674..e51dfac2b 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -87,7 +87,7 @@ static bool need_pre(uint8_t dev_addr) { // If this device is different to the speed of the root device // (i.e. is a low speed device on a full speed hub) then need pre - return hcd_port_speed_get(0) != tuh_device_get_speed(dev_addr); + return hcd_port_speed_get(0) != tuh_speed_get(dev_addr); } static void hw_xfer_complete(struct hw_endpoint *ep, xfer_result_t xfer_result) -- cgit v1.3.1 From 3c0c051df182cb7261e0f5eb6c52e84f860d0ae1 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 24 Aug 2021 19:10:23 +0700 Subject: add tuh_vid_pid_get() complete Sony PS4 dualshock controller example --- examples/host/hid_controller/.only.MCU_LPC175X_6X | 0 examples/host/hid_controller/.only.MCU_LPC177X_8X | 0 examples/host/hid_controller/.only.MCU_LPC18XX | 0 examples/host/hid_controller/.only.MCU_LPC40XX | 0 examples/host/hid_controller/.only.MCU_LPC43XX | 0 examples/host/hid_controller/.only.MCU_MIMXRT10XX | 0 examples/host/hid_controller/.only.MCU_RP2040 | 0 examples/host/hid_controller/CMakeLists.txt | 29 +++ examples/host/hid_controller/Makefile | 30 +++ examples/host/hid_controller/src/hid_app.c | 249 ++++++++++++++++++++++ examples/host/hid_controller/src/main.c | 93 ++++++++ examples/host/hid_controller/src/tusb_config.h | 95 +++++++++ src/class/hid/hid_host.c | 2 +- src/host/usbh.c | 116 ++++++---- src/host/usbh.h | 4 +- 15 files changed, 569 insertions(+), 49 deletions(-) create mode 100644 examples/host/hid_controller/.only.MCU_LPC175X_6X create mode 100644 examples/host/hid_controller/.only.MCU_LPC177X_8X create mode 100644 examples/host/hid_controller/.only.MCU_LPC18XX create mode 100644 examples/host/hid_controller/.only.MCU_LPC40XX create mode 100644 examples/host/hid_controller/.only.MCU_LPC43XX create mode 100644 examples/host/hid_controller/.only.MCU_MIMXRT10XX create mode 100644 examples/host/hid_controller/.only.MCU_RP2040 create mode 100644 examples/host/hid_controller/CMakeLists.txt create mode 100644 examples/host/hid_controller/Makefile create mode 100644 examples/host/hid_controller/src/hid_app.c create mode 100644 examples/host/hid_controller/src/main.c create mode 100644 examples/host/hid_controller/src/tusb_config.h (limited to 'src/host') diff --git a/examples/host/hid_controller/.only.MCU_LPC175X_6X b/examples/host/hid_controller/.only.MCU_LPC175X_6X new file mode 100644 index 000000000..e69de29bb diff --git a/examples/host/hid_controller/.only.MCU_LPC177X_8X b/examples/host/hid_controller/.only.MCU_LPC177X_8X new file mode 100644 index 000000000..e69de29bb diff --git a/examples/host/hid_controller/.only.MCU_LPC18XX b/examples/host/hid_controller/.only.MCU_LPC18XX new file mode 100644 index 000000000..e69de29bb diff --git a/examples/host/hid_controller/.only.MCU_LPC40XX b/examples/host/hid_controller/.only.MCU_LPC40XX new file mode 100644 index 000000000..e69de29bb diff --git a/examples/host/hid_controller/.only.MCU_LPC43XX b/examples/host/hid_controller/.only.MCU_LPC43XX new file mode 100644 index 000000000..e69de29bb diff --git a/examples/host/hid_controller/.only.MCU_MIMXRT10XX b/examples/host/hid_controller/.only.MCU_MIMXRT10XX new file mode 100644 index 000000000..e69de29bb diff --git a/examples/host/hid_controller/.only.MCU_RP2040 b/examples/host/hid_controller/.only.MCU_RP2040 new file mode 100644 index 000000000..e69de29bb diff --git a/examples/host/hid_controller/CMakeLists.txt b/examples/host/hid_controller/CMakeLists.txt new file mode 100644 index 000000000..0a99bc3a9 --- /dev/null +++ b/examples/host/hid_controller/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 3.5) + +include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) + +# gets PROJECT name for the example (e.g. -) +family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR}) + +project(${PROJECT}) + +# Checks this example is valid for the family and initializes the project +family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) + +add_executable(${PROJECT}) + +# Example source +target_sources(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src/hid_app.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_app.c + ) + +# Example include +target_include_directories(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src + ) + +# Configure compilation flags and libraries for the example... see the corresponding function +# in hw/bsp/FAMILY/family.cmake for details. +family_configure_host_example(${PROJECT}) \ No newline at end of file diff --git a/examples/host/hid_controller/Makefile b/examples/host/hid_controller/Makefile new file mode 100644 index 000000000..6f59faeee --- /dev/null +++ b/examples/host/hid_controller/Makefile @@ -0,0 +1,30 @@ +include ../../../tools/top.mk +include ../../make.mk + +INC += \ + src \ + $(TOP)/hw \ + +# Example source +EXAMPLE_SOURCE += \ + src/hid_app.c \ + src/main.c + +SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) + +CFLAGS += -Wno-error=cast-align + +# TinyUSB Host Stack source +SRC_C += \ + src/class/cdc/cdc_host.c \ + src/class/hid/hid_host.c \ + src/class/msc/msc_host.c \ + src/host/hub.c \ + src/host/usbh.c \ + src/host/usbh_control.c \ + src/portable/ehci/ehci.c \ + src/portable/ohci/ohci.c \ + src/portable/nxp/transdimension/hcd_transdimension.c \ + src/portable/nxp/lpc17_40/hcd_lpc17_40.c + +include ../../rules.mk diff --git a/examples/host/hid_controller/src/hid_app.c b/examples/host/hid_controller/src/hid_app.c new file mode 100644 index 000000000..37ae94abd --- /dev/null +++ b/examples/host/hid_controller/src/hid_app.c @@ -0,0 +1,249 @@ +/* + * 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. + * + */ + +#include "bsp/board.h" +#include "tusb.h" + +/* From https://www.kernel.org/doc/html/latest/input/gamepad.html + ____________________________ __ + / [__ZL__] [__ZR__] \ | + / [__ TL __] [__ TR __] \ | Front Triggers + __/________________________________\__ __| + / _ \ | + / /\ __ (N) \ | + / || __ |MO| __ _ _ \ | Main Pad + | <===DP===> |SE| |ST| (W) -|- (E) | | + \ || ___ ___ _ / | + /\ \/ / \ / \ (S) /\ __| + / \________ | LS | ____ | RS | ________/ \ | +| / \ \___/ / \ \___/ / \ | | Control Sticks +| / \_____/ \_____/ \ | __| +| / \ | + \_____/ \_____/ + + |________|______| |______|___________| + D-Pad Left Right Action Pad + Stick Stick + + |_____________| + Menu Pad + + Most gamepads have the following features: + - Action-Pad 4 buttons in diamonds-shape (on the right side) NORTH, SOUTH, WEST and EAST. + - D-Pad (Direction-pad) 4 buttons (on the left side) that point up, down, left and right. + - Menu-Pad Different constellations, but most-times 2 buttons: SELECT - START. + - Analog-Sticks provide freely moveable sticks to control directions, Analog-sticks may also + provide a digital button if you press them. + - Triggers are located on the upper-side of the pad in vertical direction. The upper buttons + are normally named Left- and Right-Triggers, the lower buttons Z-Left and Z-Right. + - Rumble Many devices provide force-feedback features. But are mostly just simple rumble motors. + */ + +// Sony DS4 report layout detail https://www.psdevwiki.com/ps4/DS4-USB +typedef struct TU_ATTR_PACKED +{ + int8_t x, y, z, rz; // joystick + + struct { + uint8_t dpad : 4; // (hat format, 0x08 is released, 0=N, 1=NE, 2=E, 3=SE, 4=S, 5=SW, 6=W, 7=NW) + uint8_t square : 1; // west + uint8_t cross : 1; // south + uint8_t circle : 1; // east + uint8_t triangle : 1; // north + }; + + struct { + uint8_t l1 : 1; + uint8_t r1 : 1; + uint8_t l2 : 1; + uint8_t r2 : 1; + uint8_t share : 1; + uint8_t option : 1; + uint8_t l3 : 1; + uint8_t r3 : 1; + }; + + struct { + uint8_t ps : 1; // playstation button + uint8_t tpad : 1; // track pad click + uint8_t counter : 6; // +1 each report + }; + + // comment out since not used by this example + // uint8_t l2_trigger; // 0 released, 0xff fully pressed + // uint8_t r2_trigger; // as above + + // uint16_t timestamp; + // uint8_t battery; + // + // int16_t gyro[3]; // x, y, z; + // int16_t accel[3]; // x, y, z + + // there is still lots more info + +} sony_ds4_report_t; + +// check if device is Sony DualShock 4 +static inline bool is_sony_ds4(uint8_t dev_addr) +{ + uint16_t vid, pid; + tuh_vid_pid_get(dev_addr, &vid, &pid); + + return (vid == 0x054c && pid == 0x09cc); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ + +void hid_app_task(void) +{ + // nothing to do +} + +//--------------------------------------------------------------------+ +// TinyUSB Callbacks +//--------------------------------------------------------------------+ + +// Invoked when device with hid interface is mounted +// Report descriptor is also available for use. tuh_hid_parse_report_descriptor() +// can be used to parse common/simple enough descriptor. +// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped +// therefore report_desc = NULL, desc_len = 0 +void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) +{ + uint16_t vid, pid; + tuh_vid_pid_get(dev_addr, &vid, &pid); + + printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance); + printf("VID = %04x, PID = %04x\r\n", vid, pid); + + // Sony DualShock 4 [CUH-ZCT2x] + if ( is_sony_ds4(dev_addr) ) + { + // request to receive report + // tuh_hid_report_received_cb() will be invoked when report is available + if ( !tuh_hid_receive_report(dev_addr, instance) ) + { + printf("Error: cannot request to receive report\r\n"); + } + } +} + +// Invoked when device with hid interface is un-mounted +void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) +{ + printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); + +} + +// check if different than 2 +bool diff_than_2(int8_t x, int8_t y) +{ + return (x - y > 2) || (y - x > 2); +} + +// check if 2 reports are different enough +bool diff_report(sony_ds4_report_t const* rpt1, sony_ds4_report_t const* rpt2) +{ + bool result; + + // x, y, z, rz must different than 2 to be counted + result = diff_than_2(rpt1->x, rpt2->x) || diff_than_2(rpt1->y , rpt2->y ) || + diff_than_2(rpt1->z, rpt2->z) || diff_than_2(rpt1->rz, rpt2->rz); + + // check the reset with mem compare + result |= memcmp(&rpt1->rz + 1, &rpt2->rz + 1, sizeof(sony_ds4_report_t)-4); + + return result; +} + +void process_sony_ds4(uint8_t const* report, uint16_t len) +{ + const char* dpad_str[] = { "N", "NE", "E", "SE", "S", "SW", "W", "NW", "none" }; + + // previous report used to compare for changes + static sony_ds4_report_t prev_report = { 0 }; + + uint8_t const report_id = report[0]; + report++; + len--; + + // all buttons state is stored in ID 1 + if (report_id == 1) + { + sony_ds4_report_t ds4_report; + memcpy(&ds4_report, report, sizeof(ds4_report)); + + // counter is +1, assign to make it easier to compare 2 report + prev_report.counter = ds4_report.counter; + + // only print if changes since it is polled ~ 5ms + // Since count+1 after each report and x, y, z, rz fluctuate within 1 or 2 + // We need more than memcmp to check if report is different enough + if ( diff_report(&prev_report, &ds4_report) ) + { + printf("(x, y, z, rz) = (%d, %d, %d, %d)\r\n", ds4_report.x, ds4_report.y, ds4_report.z, ds4_report.rz); + printf("DPad = %s ", dpad_str[ds4_report.dpad]); + + if (ds4_report.square ) printf("Square "); + if (ds4_report.cross ) printf("Cross "); + if (ds4_report.circle ) printf("Circle "); + if (ds4_report.triangle ) printf("Triangle "); + + if (ds4_report.l1) printf("L1 "); + if (ds4_report.r1) printf("R1 "); + if (ds4_report.l2) printf("L2 "); + if (ds4_report.r2) printf("R2 "); + + if (ds4_report.share) printf("Share "); + if (ds4_report.option) printf("Option "); + if (ds4_report.l3) printf("L3 "); + if (ds4_report.r3) printf("R3 "); + + if (ds4_report.ps ) printf("PS "); + if (ds4_report.tpad ) printf("TPad "); + + printf("\r\n"); + } + + prev_report = ds4_report; + } +} + +// Invoked when received report from device via interrupt endpoint +void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) +{ + if ( is_sony_ds4(dev_addr) ) + { + process_sony_ds4(report, len); + } + + // continue to request to receive report + if ( !tuh_hid_receive_report(dev_addr, instance) ) + { + printf("Error: cannot request to receive report\r\n"); + } +} diff --git a/examples/host/hid_controller/src/main.c b/examples/host/hid_controller/src/main.c new file mode 100644 index 000000000..e13fa818a --- /dev/null +++ b/examples/host/hid_controller/src/main.c @@ -0,0 +1,93 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +/* This example current worked and tested with following controller + * - Sony DualShock 4 [CUH-ZCT2x] VID = 0x054c, PID = 0x09cc + */ + + +#include +#include +#include + +#include "bsp/board.h" +#include "tusb.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF PROTYPES +//--------------------------------------------------------------------+ +void led_blinking_task(void); + +extern void cdc_task(void); +extern void hid_app_task(void); + +/*------------- MAIN -------------*/ +int main(void) +{ + board_init(); + + printf("TinyUSB Host HID Controller Example\r\n"); + + tusb_init(); + + while (1) + { + // tinyusb host task + tuh_task(); + led_blinking_task(); + +#if CFG_TUH_CDC + cdc_task(); +#endif + +#if CFG_TUH_HID + hid_app_task(); +#endif + } + + return 0; +} + +//--------------------------------------------------------------------+ +// TinyUSB Callbacks +//--------------------------------------------------------------------+ + +//--------------------------------------------------------------------+ +// Blinking Task +//--------------------------------------------------------------------+ +void led_blinking_task(void) +{ + const uint32_t interval_ms = 1000; + static uint32_t start_ms = 0; + + static bool led_state = false; + + // Blink every interval ms + if ( board_millis() - start_ms < interval_ms) return; // not enough time + start_ms += interval_ms; + + board_led_write(led_state); + led_state = 1 - led_state; // toggle +} diff --git a/examples/host/hid_controller/src/tusb_config.h b/examples/host/hid_controller/src/tusb_config.h new file mode 100644 index 000000000..74b471ae4 --- /dev/null +++ b/examples/host/hid_controller/src/tusb_config.h @@ -0,0 +1,95 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#ifndef _TUSB_CONFIG_H_ +#define _TUSB_CONFIG_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +//-------------------------------------------------------------------- +// COMMON CONFIGURATION +//-------------------------------------------------------------------- + +// defined by compiler flags for flexibility +#ifndef CFG_TUSB_MCU + #error CFG_TUSB_MCU must be defined +#endif + +#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX + #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_HOST | OPT_MODE_HIGH_SPEED) +#else + #define CFG_TUSB_RHPORT0_MODE OPT_MODE_HOST +#endif + +#ifndef CFG_TUSB_OS +#define CFG_TUSB_OS OPT_OS_NONE +#endif + +// CFG_TUSB_DEBUG is defined by compiler in DEBUG build +// #define CFG_TUSB_DEBUG 0 + +/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. + * Tinyusb use follows macros to declare transferring memory so that they can be put + * into those specific section. + * e.g + * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) + * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) + */ +#ifndef CFG_TUSB_MEM_SECTION +#define CFG_TUSB_MEM_SECTION +#endif + +#ifndef CFG_TUSB_MEM_ALIGN +#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) +#endif + +//-------------------------------------------------------------------- +// CONFIGURATION +//-------------------------------------------------------------------- + +// Size of buffer to hold descriptors and other data used for enumeration +#define CFG_TUH_ENUMERATION_BUFSIZE 256 + +#define CFG_TUH_HUB 0 +#define CFG_TUH_CDC 0 +#define CFG_TUH_HID 4 // typical keyboard + mouse device can have 3-4 HID interfaces +#define CFG_TUH_MSC 0 +#define CFG_TUH_VENDOR 0 + +// max device support (excluding hub device) +// 1 hub typically has 4 ports +#define CFG_TUH_DEVICE_MAX (CFG_TUH_HUB ? 4 : 1) + +//------------- HID -------------// + +#define CFG_TUH_HID_EP_BUFSIZE 64 + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_CONFIG_H_ */ diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 3a832a247..8c66477b3 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -228,7 +228,7 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint3 if ( dir == TUSB_DIR_IN ) { TU_LOG2(" Get Report callback (%u, %u)\r\n", dev_addr, instance); - TU_LOG1_MEM(hid_itf->epin_buf, 8, 2); + TU_LOG3_MEM(hid_itf->epin_buf, xferred_bytes, 2); tuh_hid_report_received_cb(dev_addr, instance, hid_itf->epin_buf, xferred_bytes); }else { diff --git a/src/host/usbh.c b/src/host/usbh.c index 1b5a422f4..548456a40 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -61,9 +61,13 @@ typedef struct { uint8_t speed; //------------- device descriptor -------------// - uint16_t vendor_id; - uint16_t product_id; - uint8_t ep0_packet_size; + uint16_t vid; + uint16_t pid; + + uint8_t ep0_size; + uint8_t i_manufacturer; + uint8_t i_product; + uint8_t i_serial; //------------- configuration descriptor -------------// // uint8_t interface_count; // bNumInterfaces alias @@ -105,6 +109,8 @@ typedef struct uint8_t hub_addr; uint8_t hub_port; uint8_t speed; + + volatile uint8_t connected; } usbh_dev0_t; @@ -230,9 +236,22 @@ bool tuh_mounted(uint8_t dev_addr) return get_device(dev_addr)->configured; } -tusb_speed_t tuh_speed_get (uint8_t const dev_addr) +bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t* vid, uint16_t* pid) +{ + *vid = *pid = 0; + + TU_VERIFY(tuh_mounted(dev_addr)); + + usbh_device_t const* dev = get_device(dev_addr); + + *vid = dev->vid; + *pid = dev->pid; + + return true; +} + +tusb_speed_t tuh_speed_get (uint8_t dev_addr) { - TU_ASSERT( dev_addr <= CFG_TUH_DEVICE_MAX + CFG_TUH_HUB, TUSB_SPEED_INVALID); return (tusb_speed_t) get_device(dev_addr)->speed; } @@ -652,45 +671,6 @@ static bool enum_hub_get_status0_complete(uint8_t dev_addr, tusb_control_request } #endif -static bool enum_request_set_addr(void) -{ - uint8_t const addr0 = 0; - tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf; - - // Get new address - uint8_t const new_addr = get_new_address(desc_device->bDeviceClass == TUSB_CLASS_HUB); - TU_ASSERT(new_addr != ADDR_INVALID); - - TU_LOG2("Set Address = %d\r\n", new_addr); - - usbh_device_t* new_dev = get_device(new_addr); - - new_dev->rhport = _dev0.rhport; - new_dev->hub_addr = _dev0.hub_addr; - new_dev->hub_port = _dev0.hub_port; - new_dev->speed = _dev0.speed; - new_dev->connected = 1; - new_dev->ep0_packet_size = desc_device->bMaxPacketSize0; - - tusb_control_request_t const new_request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_OUT - }, - .bRequest = TUSB_REQ_SET_ADDRESS, - .wValue = new_addr, - .wIndex = 0, - .wLength = 0 - }; - - TU_ASSERT( tuh_control_xfer(addr0, &new_request, NULL, enum_set_address_complete) ); - - return true; -} - static bool enum_new_device(hcd_event_t* event) { _dev0.rhport = event->rhport; // TODO refractor integrate to device_pool @@ -795,6 +775,45 @@ static bool enum_get_addr0_device_desc_complete(uint8_t dev_addr, tusb_control_r return true; } +static bool enum_request_set_addr(void) +{ + uint8_t const addr0 = 0; + tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf; + + // Get new address + uint8_t const new_addr = get_new_address(desc_device->bDeviceClass == TUSB_CLASS_HUB); + TU_ASSERT(new_addr != ADDR_INVALID); + + TU_LOG2("Set Address = %d\r\n", new_addr); + + usbh_device_t* new_dev = get_device(new_addr); + + new_dev->rhport = _dev0.rhport; + new_dev->hub_addr = _dev0.hub_addr; + new_dev->hub_port = _dev0.hub_port; + new_dev->speed = _dev0.speed; + new_dev->connected = 1; + new_dev->ep0_size = desc_device->bMaxPacketSize0; + + tusb_control_request_t const new_request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_OUT + }, + .bRequest = TUSB_REQ_SET_ADDRESS, + .wValue = new_addr, + .wIndex = 0, + .wLength = 0 + }; + + TU_ASSERT( tuh_control_xfer(addr0, &new_request, NULL, enum_set_address_complete) ); + + return true; +} + // After SET_ADDRESS is complete static bool enum_set_address_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { @@ -810,7 +829,7 @@ static bool enum_set_address_complete(uint8_t dev_addr, tusb_control_request_t c hcd_device_close(_dev0.rhport, 0); // open control pipe for new address - TU_ASSERT( usbh_edpt_control_open(new_addr, new_dev->ep0_packet_size) ); + TU_ASSERT( usbh_edpt_control_open(new_addr, new_dev->ep0_size) ); // Get full device descriptor TU_LOG2("Get Device Descriptor\r\n"); @@ -841,8 +860,11 @@ static bool enum_get_device_desc_complete(uint8_t dev_addr, tusb_control_request tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf; usbh_device_t* dev = get_device(dev_addr); - dev->vendor_id = desc_device->idVendor; - dev->product_id = desc_device->idProduct; + dev->vid = desc_device->idVendor; + dev->pid = desc_device->idProduct; + dev->i_manufacturer = desc_device->iManufacturer; + dev->i_product = desc_device->iProduct; + dev->i_serial = desc_device->iSerialNumber; // if (tuh_attach_cb) tuh_attach_cb((tusb_desc_device_t*) _usbh_ctrl_buf); diff --git a/src/host/usbh.h b/src/host/usbh.h index 5f7229f27..8411cad28 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -57,7 +57,8 @@ void tuh_task(void); extern void hcd_int_handler(uint8_t rhport); #define tuh_int_handler hcd_int_handler -tusb_speed_t tuh_speed_get (uint8_t dev_addr); +bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t* vid, uint16_t* pid); +tusb_speed_t tuh_speed_get(uint8_t dev_addr); // Check if device is connected and configured bool tuh_mounted(uint8_t dev_addr); @@ -66,6 +67,7 @@ bool tuh_mounted(uint8_t dev_addr); static inline bool tuh_suspended(uint8_t dev_addr) { // TODO implement suspend & resume on host + (void) dev_addr; return false; } -- cgit v1.3.1 From 3debeb637acb49222f36fa08f904adc4f5d9e1b7 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 24 Aug 2021 21:34:51 +0700 Subject: test hid controller with rp2040 --- examples/host/hid_controller/CMakeLists.txt | 1 - examples/host/hid_controller/src/hid_app.c | 22 +++++++++++----------- src/host/usbh.c | 2 +- 3 files changed, 12 insertions(+), 13 deletions(-) (limited to 'src/host') diff --git a/examples/host/hid_controller/CMakeLists.txt b/examples/host/hid_controller/CMakeLists.txt index 0a99bc3a9..aaf8bc34f 100644 --- a/examples/host/hid_controller/CMakeLists.txt +++ b/examples/host/hid_controller/CMakeLists.txt @@ -16,7 +16,6 @@ add_executable(${PROJECT}) target_sources(${PROJECT} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/hid_app.c ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_app.c ) # Example include diff --git a/examples/host/hid_controller/src/hid_app.c b/examples/host/hid_controller/src/hid_app.c index 37ae94abd..c61ce70f3 100644 --- a/examples/host/hid_controller/src/hid_app.c +++ b/examples/host/hid_controller/src/hid_app.c @@ -64,7 +64,7 @@ // Sony DS4 report layout detail https://www.psdevwiki.com/ps4/DS4-USB typedef struct TU_ATTR_PACKED { - int8_t x, y, z, rz; // joystick + uint8_t x, y, z, rz; // joystick struct { uint8_t dpad : 4; // (hat format, 0x08 is released, 0=N, 1=NE, 2=E, 3=SE, 4=S, 5=SW, 6=W, 7=NW) @@ -160,7 +160,7 @@ void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) } // check if different than 2 -bool diff_than_2(int8_t x, int8_t y) +bool diff_than_2(uint8_t x, uint8_t y) { return (x - y > 2) || (y - x > 2); } @@ -205,7 +205,7 @@ void process_sony_ds4(uint8_t const* report, uint16_t len) // We need more than memcmp to check if report is different enough if ( diff_report(&prev_report, &ds4_report) ) { - printf("(x, y, z, rz) = (%d, %d, %d, %d)\r\n", ds4_report.x, ds4_report.y, ds4_report.z, ds4_report.rz); + printf("(x, y, z, rz) = (%u, %u, %u, %u)\r\n", ds4_report.x, ds4_report.y, ds4_report.z, ds4_report.rz); printf("DPad = %s ", dpad_str[ds4_report.dpad]); if (ds4_report.square ) printf("Square "); @@ -213,15 +213,15 @@ void process_sony_ds4(uint8_t const* report, uint16_t len) if (ds4_report.circle ) printf("Circle "); if (ds4_report.triangle ) printf("Triangle "); - if (ds4_report.l1) printf("L1 "); - if (ds4_report.r1) printf("R1 "); - if (ds4_report.l2) printf("L2 "); - if (ds4_report.r2) printf("R2 "); + if (ds4_report.l1 ) printf("L1 "); + if (ds4_report.r1 ) printf("R1 "); + if (ds4_report.l2 ) printf("L2 "); + if (ds4_report.r2 ) printf("R2 "); - if (ds4_report.share) printf("Share "); - if (ds4_report.option) printf("Option "); - if (ds4_report.l3) printf("L3 "); - if (ds4_report.r3) printf("R3 "); + if (ds4_report.share ) printf("Share "); + if (ds4_report.option ) printf("Option "); + if (ds4_report.l3 ) printf("L3 "); + if (ds4_report.r3 ) printf("R3 "); if (ds4_report.ps ) printf("PS "); if (ds4_report.tpad ) printf("TPad "); diff --git a/src/host/usbh.c b/src/host/usbh.c index 548456a40..51b8f85b6 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -252,7 +252,7 @@ bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t* vid, uint16_t* pid) tusb_speed_t tuh_speed_get (uint8_t dev_addr) { - return (tusb_speed_t) get_device(dev_addr)->speed; + return (tusb_speed_t) (dev_addr ? get_device(dev_addr)->speed : _dev0.speed); } #if CFG_TUSB_OS == OPT_OS_NONE -- cgit v1.3.1