From a6d18c400ddc6b61f665baae5672ed46af17c99c Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 17 Aug 2021 13:29:26 +0700 Subject: fix keyboard report reserved is always 0 --- src/class/hid/hid_device.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index a10e3a5e3..2ee80750a 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -121,6 +121,7 @@ bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modi hid_keyboard_report_t report; report.modifier = modifier; + report.reserved = 0; if ( keycode ) { -- cgit v1.3.1 From 351581537f47a9cca84e1b4f13af704c0effaa78 Mon Sep 17 00:00:00 2001 From: kkitayam <45088311+kkitayam@users.noreply.github.com> Date: Tue, 17 Aug 2021 23:13:11 +0900 Subject: Removes redundant SOF processing from the Renesas RX family. The same logic regarding the resume signal was implemented by usbd. See also: #1023 --- src/portable/renesas/usba/dcd_usba.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'src') diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index 1db1fdb32..cdc66079a 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -139,7 +139,6 @@ typedef struct { pipe_state_t pipe[10]; uint8_t ep[2][16]; /* a lookup table for a pipe index from an endpoint address */ - uint8_t suspended; } dcd_data_t; //--------------------------------------------------------------------+ @@ -815,20 +814,9 @@ void dcd_int_handler(uint8_t rhport) } if (is0 & USB_IS0_RESM) { dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); - _dcd.suspended = 0; } if (is0 & USB_IS0_SOFR) { - if (_dcd.suspended) { - /* When USB host resumes caused by `dcd_remote_wakeup()`, - * RESM interrupt does not rise. - * Therefore we need to manually send resume event. - * Of course, when USB host resumes on its own, - * RESM interrupt rise properly, then this statements are ignored. */ - // TODO can be dropped since this logic is implemented by usbd - // USBD will exit suspended mode when SOF event is received - dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); - _dcd.suspended = 0; - } + // USBD will exit suspended mode when SOF event is received dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); } if (is0 & USB_IS0_DVST) { @@ -844,7 +832,6 @@ void dcd_int_handler(uint8_t rhport) case USB_IS0_DVSQ_SUSP2: case USB_IS0_DVSQ_SUSP3: dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); - _dcd.suspended = 1; default: break; } -- cgit v1.3.1 From ff59e98a6ab29c70cdf743db7412ddb609e32730 Mon Sep 17 00:00:00 2001 From: kkitayam <45088311+kkitayam@users.noreply.github.com> Date: Thu, 19 Aug 2021 23:57:34 +0900 Subject: Add compile switch to enable SOF during suspend only --- src/portable/renesas/usba/dcd_usba.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index cdc66079a..095dcc136 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -27,6 +27,10 @@ #include "tusb_option.h" +// Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) +// We disable SOF for now until needed later on +#define USE_SOF 0 + #if TUSB_OPT_DEVICE_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_RX63X || \ CFG_TUSB_MCU == OPT_MCU_RX65X || \ CFG_TUSB_MCU == OPT_MCU_RX72N ) @@ -626,7 +630,7 @@ void dcd_init(uint8_t rhport) /* Setup default control pipe */ USB0.DCPMAXP.BIT.MXPS = 64; USB0.INTENB0.WORD = USB_IS0_VBINT | USB_IS0_BRDY | USB_IS0_BEMP | - USB_IS0_DVST | USB_IS0_CTRT | USB_IS0_SOFR | USB_IS0_RESM; + USB_IS0_DVST | USB_IS0_CTRT | (USE_SOF ? USB_IS0_SOFR: 0) | USB_IS0_RESM; USB0.BEMPENB.WORD = 1; USB0.BRDYENB.WORD = 1; @@ -814,10 +818,16 @@ void dcd_int_handler(uint8_t rhport) } if (is0 & USB_IS0_RESM) { dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); +#if (0==USE_SOF) + USB0.INTENB0.BIT.SOFE = 0; +#endif } - if (is0 & USB_IS0_SOFR) { + if ((is0 & USB_IS0_SOFR) && USB0.INTENB0.BIT.SOFE) { // USBD will exit suspended mode when SOF event is received dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); +#if (0==USE_SOF) + USB0.INTENB0.BIT.SOFE = 0; +#endif } if (is0 & USB_IS0_DVST) { switch (is0 & USB_IS0_DVSQ) { @@ -832,6 +842,9 @@ void dcd_int_handler(uint8_t rhport) case USB_IS0_DVSQ_SUSP2: case USB_IS0_DVSQ_SUSP3: dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); +#if (0==USE_SOF) + USB0.INTENB0.BIT.SOFE = 1; +#endif default: break; } -- cgit v1.3.1 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/common/tusb_common.h | 14 ++ src/device/usbd.c | 58 +------- src/host/usbh.c | 338 ++++++++++++++++++++++++-------------------- src/host/usbh_classdriver.h | 2 + src/tusb.c | 62 ++++++++ 5 files changed, 265 insertions(+), 209 deletions(-) (limited to 'src') diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index c8a66a879..302e75277 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -73,6 +73,20 @@ #include "tusb_error.h" // TODO remove #include "tusb_timeout.h" // TODO remove +//--------------------------------------------------------------------+ +// Internal Helper used by Host and Device Stack +//--------------------------------------------------------------------+ + +// Check if endpoint descriptor is valid per USB specs +bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed); + +// Bind all endpoint of a interface descriptor to class driver +void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* p_desc, uint16_t desc_len, uint8_t driver_id); + +//--------------------------------------------------------------------+ +// Internal Inline Functions +//--------------------------------------------------------------------+ + //------------- Mem -------------// #define tu_memclr(buffer, size) memset((buffer), 0, (size)) #define tu_varclr(_var) tu_memclr(_var, sizeof(*(_var))) diff --git a/src/device/usbd.c b/src/device/usbd.c index 8b4f4e7e3..23f174dab 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -274,7 +274,6 @@ static osal_mutex_t _usbd_mutex; //--------------------------------------------------------------------+ // Prototypes //--------------------------------------------------------------------+ -static void mark_interface_endpoint(uint8_t ep2drv[][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id); static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request); static bool process_set_config(uint8_t rhport, uint8_t cfg_num); static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request); @@ -901,7 +900,8 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) } } - mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, drv_len, drv_id); // TODO refactor + // bind all endpoints for this driver + tu_edpt_bind_driver(_usbd_dev.ep2drv, desc_itf, drv_len, drv_id); p_desc += drv_len; // next interface @@ -919,25 +919,6 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) return true; } -// Helper marking endpoint of interface belongs to class driver -static void mark_interface_endpoint(uint8_t ep2drv[][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id) -{ - uint16_t len = 0; - - while( len < desc_len ) - { - if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) - { - uint8_t const ep_addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress; - - ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = driver_id; - } - - len = (uint16_t)(len + tu_desc_len(p_desc)); - p_desc = tu_desc_next(p_desc); - } -} - // return descriptor's buffer and update desc_len static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request) { @@ -1177,41 +1158,8 @@ void usbd_defer_func(osal_task_func_t func, void* param, bool in_isr) bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { - uint16_t const max_packet_size = tu_le16toh(desc_ep->wMaxPacketSize.size); - - TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, max_packet_size); TU_ASSERT(tu_edpt_number(desc_ep->bEndpointAddress) < CFG_TUD_ENDPPOINT_MAX); - - switch (desc_ep->bmAttributes.xfer) - { - case TUSB_XFER_ISOCHRONOUS: - { - uint16_t const spec_size = (_usbd_dev.speed == TUSB_SPEED_HIGH ? 1024 : 1023); - TU_ASSERT(max_packet_size <= spec_size); - } - break; - - case TUSB_XFER_BULK: - if (_usbd_dev.speed == TUSB_SPEED_HIGH) - { - // Bulk highspeed must be EXACTLY 512 - TU_ASSERT(max_packet_size == 512); - }else - { - // TODO Bulk fullspeed can only be 8, 16, 32, 64 - TU_ASSERT(max_packet_size <= 64); - } - break; - - case TUSB_XFER_INTERRUPT: - { - uint16_t const spec_size = (_usbd_dev.speed == TUSB_SPEED_HIGH ? 1024 : 64); - TU_ASSERT(max_packet_size <= spec_size); - } - break; - - default: return false; - } + TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) _usbd_dev.speed)); return dcd_edpt_open(rhport, desc_ep); } 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); diff --git a/src/tusb.c b/src/tusb.c index 0350fa1de..260a6506f 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -63,6 +63,68 @@ bool tusb_inited(void) return ret; } +//--------------------------------------------------------------------+ +// Internal Helper for both Host and Device stack +//--------------------------------------------------------------------+ + +bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed) +{ + uint16_t const max_packet_size = tu_le16toh(desc_ep->wMaxPacketSize.size); + TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, max_packet_size); + + switch (desc_ep->bmAttributes.xfer) + { + case TUSB_XFER_ISOCHRONOUS: + { + uint16_t const spec_size = (speed == TUSB_SPEED_HIGH ? 1024 : 1023); + TU_ASSERT(max_packet_size <= spec_size); + } + break; + + case TUSB_XFER_BULK: + if (speed == TUSB_SPEED_HIGH) + { + // Bulk highspeed must be EXACTLY 512 + TU_ASSERT(max_packet_size == 512); + }else + { + // TODO Bulk fullspeed can only be 8, 16, 32, 64 + TU_ASSERT(max_packet_size <= 64); + } + break; + + case TUSB_XFER_INTERRUPT: + { + uint16_t const spec_size = (speed == TUSB_SPEED_HIGH ? 1024 : 64); + TU_ASSERT(max_packet_size <= spec_size); + } + break; + + default: return false; + } + + return true; +} + +void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* desc_itf, uint16_t desc_len, uint8_t driver_id) +{ + uint8_t const* p_desc = (uint8_t const*) desc_itf; + uint16_t len = 0; + + while( len < desc_len ) + { + if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) + { + uint8_t const ep_addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress; + + ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = driver_id; + } + + len = (uint16_t)(len + tu_desc_len(p_desc)); + p_desc = tu_desc_next(p_desc); + } +} + /*------------------------------------------------------------------*/ /* Debug *------------------------------------------------------------------*/ -- 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') 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') 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') 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 beb1a5c678dd50c3142d2c74a29e92affa0b06c9 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Aug 2021 19:39:33 +0700 Subject: minor clean up --- src/device/usbd.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 23f174dab..e12dafcfd 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -856,12 +856,12 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) while( p_desc < desc_end ) { - 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); // next to Interface } @@ -870,6 +870,13 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) tusb_desc_interface_t const * desc_itf = (tusb_desc_interface_t const*) p_desc; uint16_t const remaining_len = desc_end-p_desc; + // Interface number must not be used already + TU_ASSERT(DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber]); + + // TODO usbd can calculate the total length used for driver --> driver open() does not need to calculate it + // uint16_t const drv_len = tu_desc_get_interface_total_len(desc_itf, desc_iad ? desc_iad->bInterfaceCount : 1, desc_end-p_desc); + + // Find driver for this interface uint8_t drv_id; for (drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) { @@ -881,31 +888,30 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) // Open successfully, check if length is correct TU_ASSERT( sizeof(tusb_desc_interface_t) <= drv_len && drv_len <= remaining_len); - // Interface number must not be used already - TU_ASSERT(DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber]); - TU_LOG2(" %s opened\r\n", driver->name); + + // bind interface to found driver _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; - // If IAD exist, assign all interfaces to the same driver - if (desc_itf_assoc) + // 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_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber && - desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass); + TU_ASSERT(desc_iad->bFirstInterface == desc_itf->bInterfaceNumber && + desc_iad->bFunctionClass == desc_itf->bInterfaceClass); - for(uint8_t i=1; ibInterfaceCount; i++) + for(uint8_t i=1; ibInterfaceCount; i++) { _usbd_dev.itf2drv[desc_itf->bInterfaceNumber+i] = drv_id; } } - // bind all endpoints for this driver + // bind all endpoints to found driver tu_edpt_bind_driver(_usbd_dev.ep2drv, desc_itf, drv_len, drv_id); p_desc += drv_len; // next interface - break; + break; // exit driver find loop } } -- cgit v1.3.1 From e20755442a3fe2141c9be8d54bee2aa4e092cdfc Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Sat, 21 Aug 2021 12:02:20 +0200 Subject: nuc126: fix set_address & disable sof --- src/portable/nuvoton/nuc121/dcd_nuc121.c | 37 ++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index 20519ec28..80a19eb17 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -40,6 +40,12 @@ #include "device/dcd.h" #include "NuMicro.h" +// Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) +// We disable SOF for now until needed later on +#ifndef USE_SOF +# define USE_SOF 0 +#endif + /* allocation of USBD RAM for Setup, EP0_IN, and and EP_OUT */ #define PERIPH_SETUP_BUF_BASE 0 #define PERIPH_SETUP_BUF_LEN 8 @@ -65,9 +71,6 @@ enum ep_enum PERIPH_MAX_EP, }; -/* set by dcd_set_address() */ -static volatile uint8_t assigned_address; - /* reset by dcd_init(), this is used by dcd_edpt_open() to assign USBD peripheral buffer addresses */ static uint32_t bufseg_addr; @@ -197,7 +200,11 @@ static void bus_reset(void) } /* centralized location for USBD interrupt enable bit mask */ +#if USE_SOF static const uint32_t enabled_irqs = USBD_INTSTS_VBDETIF_Msk | USBD_INTSTS_BUSIF_Msk | USBD_INTSTS_SETUP_Msk | USBD_INTSTS_USBIF_Msk | USBD_INTSTS_SOFIF_Msk; +#else +static const uint32_t enabled_irqs = USBD_INTSTS_VBDETIF_Msk | USBD_INTSTS_BUSIF_Msk | USBD_INTSTS_SETUP_Msk | USBD_INTSTS_USBIF_Msk; +#endif /* NUC121/NUC125/NUC126 TinyUSB API driver implementation @@ -239,7 +246,9 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { (void) rhport; usb_control_send_zlp(); /* SET_ADDRESS is the one exception where TinyUSB doesn't use dcd_edpt_xfer() to generate a ZLP */ - assigned_address = dev_addr; + + // DCD can only set address after status for this request is complete. + // do it at dcd_edpt0_status_complete() } void dcd_remote_wakeup(uint8_t rhport) @@ -420,9 +429,6 @@ void dcd_int_handler(uint8_t rhport) { if (status & USBD_INTSTS_EPEVT0_Msk) /* PERIPH_EP0 (EP0_IN) event: this is treated separately from the rest */ { - /* given ACK from host has happened, we can now set the address (if not already done) */ - if((USBD->FADDR != assigned_address) && (USBD->FADDR == 0)) USBD->FADDR = assigned_address; - uint16_t const available_bytes = USBD->EP[PERIPH_EP0].MXPLD; active_ep0_xfer = (available_bytes == xfer_table[PERIPH_EP0].max_packet_size); @@ -495,6 +501,23 @@ void dcd_int_handler(uint8_t rhport) USBD->INTSTS = status & enabled_irqs; } +// Invoked when a control transfer's status stage is complete. +// May help DCD to prepare for next control transfer, this API is optional. +void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) +{ + (void) rhport; + + if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && + request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && + request->bRequest == TUSB_REQ_SET_ADDRESS ) + { + uint8_t const dev_addr = (uint8_t) request->wValue; + + // Setting new address after the whole request is complete + USBD->FADDR = dev_addr; + } +} + void dcd_disconnect(uint8_t rhport) { (void) rhport; -- cgit v1.3.1 From 69e539fda4c72a2f3177b3944f83632ef6752c11 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Sat, 21 Aug 2021 12:11:35 +0200 Subject: Fix CI. --- src/portable/nuvoton/nuc121/dcd_nuc121.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index 80a19eb17..a776e46f5 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -245,6 +245,7 @@ void dcd_int_disable(uint8_t rhport) void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { (void) rhport; + (void) dev_addr; usb_control_send_zlp(); /* SET_ADDRESS is the one exception where TinyUSB doesn't use dcd_edpt_xfer() to generate a ZLP */ // DCD can only set address after status for this request is complete. -- cgit v1.3.1 From 4941cde175af2ef21bbe24d7d3271b46363c0759 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Sun, 22 Aug 2021 13:26:50 +0200 Subject: Fix vendor fifo deadlock, add tud_vendor_n_read_flush --- src/class/vendor/vendor_device.c | 9 +++++++++ src/class/vendor/vendor_device.h | 7 +++++++ 2 files changed, 16 insertions(+) (limited to 'src') diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 6718a97bf..8c59b4ea7 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -103,6 +103,13 @@ uint32_t tud_vendor_n_read (uint8_t itf, void* buffer, uint32_t bufsize) return num_read; } +void tud_vendor_n_read_flush (uint8_t itf) +{ + vendord_interface_t* p_itf = &_vendord_itf[itf]; + tu_fifo_clear(&p_itf->rx_ff); + _prep_out_transaction(p_itf); +} + //--------------------------------------------------------------------+ // Write API //--------------------------------------------------------------------+ @@ -199,6 +206,8 @@ uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, ui TU_BREAKPOINT(); } + maybe_transmit(p_vendor); + return drv_len; } diff --git a/src/class/vendor/vendor_device.h b/src/class/vendor/vendor_device.h index 6d9c784c0..844693c68 100644 --- a/src/class/vendor/vendor_device.h +++ b/src/class/vendor/vendor_device.h @@ -45,6 +45,7 @@ bool tud_vendor_n_mounted (uint8_t itf); uint32_t tud_vendor_n_available (uint8_t itf); uint32_t tud_vendor_n_read (uint8_t itf, void* buffer, uint32_t bufsize); bool tud_vendor_n_peek (uint8_t itf, uint8_t* u8); +void tud_vendor_n_read_flush (uint8_t itf); uint32_t tud_vendor_n_write (uint8_t itf, void const* buffer, uint32_t bufsize); uint32_t tud_vendor_n_write_available (uint8_t itf); @@ -59,6 +60,7 @@ static inline bool tud_vendor_mounted (void); static inline uint32_t tud_vendor_available (void); static inline uint32_t tud_vendor_read (void* buffer, uint32_t bufsize); static inline bool tud_vendor_peek (uint8_t* u8); +static inline void tud_vendor_read_flush (void); static inline uint32_t tud_vendor_write (void const* buffer, uint32_t bufsize); static inline uint32_t tud_vendor_write_str (char const* str); static inline uint32_t tud_vendor_write_available (void); @@ -99,6 +101,11 @@ static inline bool tud_vendor_peek (uint8_t* u8) return tud_vendor_n_peek(0, u8); } +static inline void tud_vendor_read_flush(void) +{ + tud_vendor_n_read_flush(0); +} + static inline uint32_t tud_vendor_write (void const* buffer, uint32_t bufsize) { return tud_vendor_n_write(0, buffer, bufsize); -- 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') 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') 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 4ca176c291a138f19ecf2426d636609d8c25da06 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 23 Aug 2021 12:37:54 +0700 Subject: refactor ehci init api --- src/portable/ehci/ehci.c | 37 ++++++++++----- src/portable/ehci/ehci.h | 7 +-- src/portable/ehci/ehci_api.h | 45 ++++++++++++++++++ src/portable/ehci/hcd_ehci.h | 53 ---------------------- .../nxp/transdimension/common_transdimension.h | 2 +- .../nxp/transdimension/hcd_transdimension.c | 26 ++++------- 6 files changed, 81 insertions(+), 89 deletions(-) create mode 100644 src/portable/ehci/ehci_api.h delete mode 100644 src/portable/ehci/hcd_ehci.h (limited to 'src') diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 62be83468..bc83f5b8b 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -37,13 +37,25 @@ #include "host/hcd.h" #include "host/usbh_hcd.h" -#include "hcd_ehci.h" +#include "ehci_api.h" #include "ehci.h" //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ +// 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"); + + typedef struct { ehci_link_t period_framelist[EHCI_FRAMELIST_SIZE]; @@ -65,9 +77,7 @@ typedef struct volatile uint32_t uframe_number; }ehci_data_t; -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ + // Periodic frame list must be 4K alignment CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4096) static ehci_data_t ehci_data; @@ -109,7 +119,7 @@ static inline bool qhd_has_xact_error (ehci_qhd_t * p_qhd) //p_qhd->qtd_overlay.non_hs_period_missed_uframe || p_qhd->qtd_overlay.pingstate_err TODO split transaction error } -static void qhd_init (ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); +static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); static inline ehci_qtd_t* qtd_find_free (void); static inline ehci_qtd_t* qtd_next (ehci_qtd_t const * p_qtd); @@ -218,12 +228,13 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) ehci_data.regs->command_bm.async_adv_doorbell = 1; } -// EHCI controller init -bool hcd_ehci_init(uint8_t rhport) +bool ehci_init(uint8_t rhport, uint32_t capability_reg, uint32_t operatial_reg) { + (void) capability_reg; // not used yet + tu_memclr(&ehci_data, sizeof(ehci_data_t)); - ehci_data.regs = (ehci_registers_t* ) hcd_ehci_register_addr(rhport); + ehci_data.regs = (ehci_registers_t* ) operatial_reg; ehci_registers_t* regs = ehci_data.regs; @@ -470,16 +481,16 @@ static void async_advance_isr(uint8_t rhport) } } -static void port_connect_status_change_isr(uint8_t hostid) +static void port_connect_status_change_isr(uint8_t rhport) { // NOTE There is an sequence plug->unplug->…..-> plug if device is powering with pre-plugged device if (ehci_data.regs->portsc_bm.current_connect_status) { - hcd_port_reset(hostid); - hcd_event_device_attach(hostid, true); + hcd_port_reset(rhport); + hcd_event_device_attach(rhport, true); }else // device unplugged { - hcd_event_device_remove(hostid, true); + hcd_event_device_remove(rhport, true); } } @@ -656,6 +667,8 @@ void hcd_int_handler(uint8_t rhport) { uint32_t port_status = regs->portsc & EHCI_PORTSC_MASK_ALL; + TU_LOG_HEX(EHCI_DBG, regs->portsc); + if (regs->portsc_bm.connect_status_change) { port_connect_status_change_isr(rhport); diff --git a/src/portable/ehci/ehci.h b/src/portable/ehci/ehci.h index 874195a0c..cbcf1712a 100644 --- a/src/portable/ehci/ehci.h +++ b/src/portable/ehci/ehci.h @@ -46,8 +46,6 @@ //--------------------------------------------------------------------+ // EHCI CONFIGURATION & CONSTANTS //--------------------------------------------------------------------+ -#define EHCI_CFG_FRAMELIST_SIZE_BITS 7 /// Framelist Size (NXP specific) (0:1024) - (1:512) - (2:256) - (3:128) - (4:64) - (5:32) - (6:16) - (7:8) -#define EHCI_FRAMELIST_SIZE (1024 >> EHCI_CFG_FRAMELIST_SIZE_BITS) // TODO merge OHCI with EHCI enum { @@ -55,9 +53,6 @@ enum { EHCI_MAX_SITD = 16 }; -//------------- Validation -------------// -TU_VERIFY_STATIC(EHCI_CFG_FRAMELIST_SIZE_BITS <= 7, "incorrect value"); - //--------------------------------------------------------------------+ // EHCI Data Structure //--------------------------------------------------------------------+ @@ -411,7 +406,7 @@ typedef volatile struct uint32_t wake_on_over_current_enable : 1; ///< Enables over-current conditions as wake-up events uint32_t nxp_phy_clock_disable : 1; ///< NXP customized: the PHY can be put into Low Power Suspend – Clock Disable when the downstream device has been put into suspend mode or when no downstream device is connected. Low power suspend is completely under the control of software. 0: enable PHY clock, 1: disable PHY clock uint32_t nxp_port_force_fullspeed : 1; ///< NXP customized: Writing this bit to a 1 will force the port to only connect at Full Speed. It disables the chirp sequence that allowsthe port to identify itself as High Speed. This is useful for testing FS configurations with a HS host, hub or device. - uint32_t : 1; + uint32_t TU_RESERVED : 1; uint32_t nxp_port_speed : 2; ///< NXP customized: This register field indicates the speed atwhich the port is operating. For HS mode operation in the host controllerand HS/FS operation in the device controller the port routing steers data to the Protocol engine. For FS and LS mode operation in the host controller, the port routing steers data to the Protocol Engine w/ Embedded Transaction Translator. 0x0: Fullspeed, 0x1: Lowspeed, 0x2: Highspeed uint32_t TU_RESERVED : 4; }portsc_bm; diff --git a/src/portable/ehci/ehci_api.h b/src/portable/ehci/ehci_api.h new file mode 100644 index 000000000..12e0a73d7 --- /dev/null +++ b/src/portable/ehci/ehci_api.h @@ -0,0 +1,45 @@ +/* + * 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_EHCI_API_H_ +#define _TUSB_EHCI_API_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// API Implemented by EHCI +//--------------------------------------------------------------------+ + +// Initialize EHCI driver +bool ehci_init(uint8_t rhport, uint32_t capability_reg, uint32_t operatial_reg); + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/src/portable/ehci/hcd_ehci.h b/src/portable/ehci/hcd_ehci.h deleted file mode 100644 index 480d11eda..000000000 --- a/src/portable/ehci/hcd_ehci.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_HCD_EHCI_H_ -#define _TUSB_HCD_EHCI_H_ - -#ifdef __cplusplus - extern "C" { -#endif - - -//--------------------------------------------------------------------+ -// API Implemented by HCD -//--------------------------------------------------------------------+ - -// Get operational address i.e EHCI Command register -uint32_t hcd_ehci_register_addr(uint8_t rhport); - -//--------------------------------------------------------------------+ -// API Implemented by EHCI -//--------------------------------------------------------------------+ - -// Initialize EHCI driver -extern bool hcd_ehci_init (uint8_t rhport); - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/src/portable/nxp/transdimension/common_transdimension.h b/src/portable/nxp/transdimension/common_transdimension.h index 7b94dac34..69074de41 100644 --- a/src/portable/nxp/transdimension/common_transdimension.h +++ b/src/portable/nxp/transdimension/common_transdimension.h @@ -127,7 +127,7 @@ typedef struct __I uint32_t ENDPTSTAT; ///< Endpoint Status __IO uint32_t ENDPTCOMPLETE; ///< Endpoint Complete __IO uint32_t ENDPTCTRL[8]; ///< Endpoint Control 0 - 7 -} dcd_registers_t; +} dcd_registers_t, hcd_registers_t; #ifdef __cplusplus } diff --git a/src/portable/nxp/transdimension/hcd_transdimension.c b/src/portable/nxp/transdimension/hcd_transdimension.c index db447ef23..d216f0728 100644 --- a/src/portable/nxp/transdimension/hcd_transdimension.c +++ b/src/portable/nxp/transdimension/hcd_transdimension.c @@ -43,7 +43,7 @@ #include "common/tusb_common.h" #include "common_transdimension.h" -#include "portable/ehci/hcd_ehci.h" +#include "portable/ehci/ehci_api.h" //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF @@ -82,26 +82,26 @@ typedef struct bool hcd_init(uint8_t rhport) { - dcd_registers_t* dcd_reg = (dcd_registers_t*) _hcd_controller[rhport].regs_base; + hcd_registers_t* hcd_reg = (hcd_registers_t*) _hcd_controller[rhport].regs_base; // Reset controller - dcd_reg->USBCMD |= USBCMD_RESET; - while( dcd_reg->USBCMD & USBCMD_RESET ) {} + hcd_reg->USBCMD |= USBCMD_RESET; + while( hcd_reg->USBCMD & USBCMD_RESET ) {} // Set mode to device, must be set immediately after reset #if CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX // LPC18XX/43XX need to set VBUS Power Select to HIGH // RHPORT1 is fullspeed only (need external PHY for Highspeed) - dcd_reg->USBMODE = USBMODE_CM_HOST | USBMODE_VBUS_POWER_SELECT; - if (rhport == 1) dcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED; + hcd_reg->USBMODE = USBMODE_CM_HOST | USBMODE_VBUS_POWER_SELECT; + if (rhport == 1) hcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED; #else - dcd_reg->USBMODE = USBMODE_CM_HOST; + hcd_reg->USBMODE = USBMODE_CM_HOST; #endif // FIXME force full speed, still have issue with Highspeed enumeration - dcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED; + hcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED; - return hcd_ehci_init(rhport); + return ehci_init(rhport, (uint32_t) &hcd_reg->CAPLENGTH, (uint32_t) &hcd_reg->USBCMD); } void hcd_int_enable(uint8_t rhport) @@ -114,12 +114,4 @@ void hcd_int_disable(uint8_t rhport) NVIC_DisableIRQ(_hcd_controller[rhport].irqnum); } -uint32_t hcd_ehci_register_addr(uint8_t rhport) -{ - dcd_registers_t* hcd_reg = (dcd_registers_t*) _hcd_controller[rhport].regs_base; - - // EHCI USBCMD has same address within dcd_register_t - return (uint32_t) &hcd_reg->USBCMD; -} - #endif -- 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') 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') 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') 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') 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 8dc16dd3a73dc2dd85dafd7460ba19cff2579fed Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 24 Aug 2021 01:19:06 +0700 Subject: fix rp2040 build --- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 2c007ddd3..34803c674 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -39,7 +39,6 @@ #include "host/hcd.h" #include "host/usbh.h" -#include "host/usbh_hcd.h" #define ROOT_PORT 0 -- cgit v1.3.1 From 86201f77be1c2fc058f7896b99d6069b4b0b12a5 Mon Sep 17 00:00:00 2001 From: Greg Steiert Date: Mon, 23 Aug 2021 16:17:57 -0700 Subject: initial commit of support for K32L2B --- hw/bsp/board_mcu.h | 3 +- hw/bsp/frdm_k32l2b/board.h | 58 +++++++++++++ hw/bsp/frdm_k32l2b/board.mk | 51 ++++++++++++ hw/bsp/frdm_k32l2b/frdm_k32l2b.c | 174 +++++++++++++++++++++++++++++++++++++++ src/device/dcd_attr.h | 2 +- src/portable/nxp/khci/dcd_khci.c | 4 +- src/tusb_option.h | 1 + 7 files changed, 290 insertions(+), 3 deletions(-) create mode 100644 hw/bsp/frdm_k32l2b/board.h create mode 100644 hw/bsp/frdm_k32l2b/board.mk create mode 100644 hw/bsp/frdm_k32l2b/frdm_k32l2b.c (limited to 'src') diff --git a/hw/bsp/board_mcu.h b/hw/bsp/board_mcu.h index acfd7348d..8cc50c808 100644 --- a/hw/bsp/board_mcu.h +++ b/hw/bsp/board_mcu.h @@ -46,7 +46,8 @@ #include "chip.h" #elif CFG_TUSB_MCU == OPT_MCU_LPC51UXX || CFG_TUSB_MCU == OPT_MCU_LPC54XXX || \ - CFG_TUSB_MCU == OPT_MCU_LPC55XX || CFG_TUSB_MCU == OPT_MCU_MKL25ZXX + CFG_TUSB_MCU == OPT_MCU_LPC55XX || CFG_TUSB_MCU == OPT_MCU_MKL25ZXX || \ + CFG_TUSB_MCU == OPT_MCU_K32L2BXX #include "fsl_device_registers.h" #elif CFG_TUSB_MCU == OPT_MCU_NRF5X diff --git a/hw/bsp/frdm_k32l2b/board.h b/hw/bsp/frdm_k32l2b/board.h new file mode 100644 index 000000000..60bc03fbd --- /dev/null +++ b/hw/bsp/frdm_k32l2b/board.h @@ -0,0 +1,58 @@ +/* + * 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. + */ + + +#ifndef BOARD_H_ +#define BOARD_H_ + +#include "fsl_device_registers.h" + +// LED +//#define LED_PINMUX IOMUXC_GPIO_11_GPIOMUX_IO11 +//#define LED_PIN_CLOCK kCLOCK_PortB +#define LED_GPIO GPIOD +#define LED_PORT PORTD +#define LED_PIN 5 +#define LED_STATE_ON 0 + +// SW3 button1 +//#define BUTTON_PINMUX IOMUXC_GPIO_SD_05_GPIO2_IO05 +//#define BUTTON_PIN_CLOCK kCLOCK_PortC +#define BUTTON_GPIO GPIOC +#define BUTTON_PORT PORTC +#define BUTTON_PIN 3 +#define BUTTON_STATE_ACTIVE 0 + +// UART +#define UART_PORT LPUART0 +//#define UART_PIN_CLOCK kCLOCK_PortA +#define UART_PIN_PORT PORTA +#define UART_PIN_RX 1u +#define UART_PIN_TX 2u +#define SOPT5_LPUART0RXSRC_LPUART_RX 0x00u /*!<@brief LPUART0 Receive Data Source Select: LPUART_RX pin */ +#define SOPT5_LPUART0TXSRC_LPUART_TX 0x00u /*!<@brief LPUART0 Transmit Data Source Select: LPUART0_TX pin */ + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/frdm_k32l2b/board.mk b/hw/bsp/frdm_k32l2b/board.mk new file mode 100644 index 000000000..56df553da --- /dev/null +++ b/hw/bsp/frdm_k32l2b/board.mk @@ -0,0 +1,51 @@ +SDK_DIR = hw/mcu/nxp/mcux-sdk +DEPS_SUBMODULES += $(SDK_DIR) + +CFLAGS += \ + -mthumb \ + -mabi=aapcs \ + -mcpu=cortex-m0plus \ + -DCPU_K32L2B31VLH0A \ + -DCFG_TUSB_MCU=OPT_MCU_K32L2BXX + +# mcu driver cause following warnings +CFLAGS += -Wno-error=unused-parameter + +MCU_DIR = $(SDK_DIR)/devices/K32L2B31A + +# All source paths should be relative to the top level. +LD_FILE = $(MCU_DIR)/gcc/K32L2B31xxxxA_flash.ld + +SRC_C += \ + src/portable/nxp/khci/dcd_khci.c \ + $(MCU_DIR)/system_K32L2B31A.c \ + $(MCU_DIR)/project_template/clock_config.c \ + $(MCU_DIR)/drivers/fsl_clock.c \ + $(SDK_DIR)/drivers/gpio/fsl_gpio.c \ + $(SDK_DIR)/drivers/lpuart/fsl_lpuart.c + +INC += \ + $(TOP)/hw/bsp/$(BOARD) \ + $(TOP)/$(SDK_DIR)/CMSIS/Include \ + $(TOP)/$(SDK_DIR)/drivers/smc \ + $(TOP)/$(SDK_DIR)/drivers/common \ + $(TOP)/$(SDK_DIR)/drivers/gpio \ + $(TOP)/$(SDK_DIR)/drivers/port \ + $(TOP)/$(SDK_DIR)/drivers/lpuart \ + $(TOP)/$(MCU_DIR) \ + $(TOP)/$(MCU_DIR)/drivers \ + $(TOP)/$(MCU_DIR)/project_template \ + +SRC_S += $(MCU_DIR)/gcc/startup_K32L2B31A.S + +# For freeRTOS port source +FREERTOS_PORT = ARM_CM0 + +# For flash-jlink target +JLINK_DEVICE = MKL25Z128xxx4 + +# For flash-pyocd target +PYOCD_TARGET = K32L2B + +# flash using pyocd +flash: flash-pyocd diff --git a/hw/bsp/frdm_k32l2b/frdm_k32l2b.c b/hw/bsp/frdm_k32l2b/frdm_k32l2b.c new file mode 100644 index 000000000..c5e92d37d --- /dev/null +++ b/hw/bsp/frdm_k32l2b/frdm_k32l2b.c @@ -0,0 +1,174 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2018, hathach (tinyusb.org) + * Copyright (c) 2020, Koji Kitayama + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "../board.h" +#include "board.h" +#include "fsl_gpio.h" +#include "fsl_port.h" +#include "fsl_clock.h" +#include "fsl_lpuart.h" + +#include "clock_config.h" + +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB0_IRQHandler(void) +{ + tud_int_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ +// LED +/* +//#define LED_PINMUX IOMUXC_GPIO_AD_B0_09_GPIO1_IO09 +#define LED_PORT GPIOB +#define LED_PIN_CLOCK kCLOCK_PortD +#define LED_PIN_PORT PORTD +#define LED_PIN 5U +#define LED_PIN_FUNCTION kPORT_MuxAsGpio +#define LED_STATE_ON 0 + +// UART +#define UART_PORT LPUART0 +#define UART_PIN_CLOCK kCLOCK_PortA +#define UART_PIN_PORT PORTA +#define UART_PIN_RX 1u +#define UART_PIN_TX 2u +#define UART_PIN_FUNCTION kPORT_MuxAlt2 +*/ +//#define SOPT5_UART0RXSRC_UART_RX 0x00u /*!< UART0 receive data source select: UART0_RX pin */ +//#define SOPT5_UART0TXSRC_UART_TX 0x00u /*!< UART0 transmit data source select: UART0_TX pin */ + +//const uint8_t dcd_data[] = { 0x00 }; + +void board_init(void) +{ + /* Port A Clock Gate Control: Clock enabled */ + CLOCK_EnableClock(kCLOCK_PortA); + /* Port B Clock Gate Control: Clock enabled */ + CLOCK_EnableClock(kCLOCK_PortB); + /* Port C Clock Gate Control: Clock enabled */ + CLOCK_EnableClock(kCLOCK_PortC); + /* Port D Clock Gate Control: Clock enabled */ + CLOCK_EnableClock(kCLOCK_PortD); + /* Port E Clock Gate Control: Clock enabled */ + CLOCK_EnableClock(kCLOCK_PortE); + + gpio_pin_config_t led_config = { kGPIO_DigitalOutput, 0 }; + GPIO_PinInit(LED_GPIO, LED_PIN, &led_config); + PORT_SetPinMux(LED_PORT, LED_PIN, kPORT_MuxAsGpio); + + gpio_pin_config_t button_config = { kGPIO_DigitalInput, 0 }; + GPIO_PinInit(BUTTON_GPIO, BUTTON_PIN, &button_config); + const port_pin_config_t BUTTON_CFG = { + kPORT_PullUp, + kPORT_FastSlewRate, + kPORT_PassiveFilterDisable, + kPORT_LowDriveStrength, + kPORT_MuxAsGpio + }; + PORT_SetPinConfig(BUTTON_PORT, BUTTON_PIN, &BUTTON_CFG); + + /* PORTA1 (pin 23) is configured as LPUART0_RX */ + PORT_SetPinMux(PORTA, 1U, kPORT_MuxAlt2); + /* PORTA2 (pin 24) is configured as LPUART0_TX */ + PORT_SetPinMux(PORTA, 2U, kPORT_MuxAlt2); + + SIM->SOPT5 = ((SIM->SOPT5 & + /* Mask bits to zero which are setting */ + (~(SIM_SOPT5_LPUART0TXSRC_MASK | SIM_SOPT5_LPUART0RXSRC_MASK))) + /* LPUART0 Transmit Data Source Select: LPUART0_TX pin. */ + | SIM_SOPT5_LPUART0TXSRC(SOPT5_LPUART0TXSRC_LPUART_TX) + /* LPUART0 Receive Data Source Select: LPUART_RX pin. */ + | SIM_SOPT5_LPUART0RXSRC(SOPT5_LPUART0RXSRC_LPUART_RX)); + + BOARD_BootClockRUN(); + SystemCoreClockUpdate(); + CLOCK_SetLpuart0Clock(1); + +#if CFG_TUSB_OS == OPT_OS_NONE + // 1ms tick timer + SysTick_Config(SystemCoreClock / 1000); +#elif CFG_TUSB_OS == OPT_OS_FREERTOS + // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) + NVIC_SetPriority(USB0_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); +#endif + + lpuart_config_t uart_config; + LPUART_GetDefaultConfig(&uart_config); + uart_config.baudRate_Bps = CFG_BOARD_UART_BAUDRATE; + uart_config.enableTx = true; + uart_config.enableRx = true; + LPUART_Init(UART_PORT, &uart_config, CLOCK_GetFreq(kCLOCK_McgIrc48MClk)); + + // USB +// SystemCoreClockUpdate(); + CLOCK_EnableUsbfs0Clock(kCLOCK_UsbSrcIrc48M, 48000000U); +// CLOCK_EnableUsbfs0Clock(kCLOCK_UsbSrcPll0, CLOCK_GetFreq(kCLOCK_PllFllSelClk)); +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) +{ + GPIO_PinWrite(LED_GPIO, LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON)); +} + +uint32_t board_button_read(void) +{ + return BUTTON_STATE_ACTIVE == GPIO_PinRead(BUTTON_GPIO, BUTTON_PIN); +} + +int board_uart_read(uint8_t* buf, int len) +{ + LPUART_ReadBlocking(UART_PORT, buf, len); + return len; +} + +int board_uart_write(void const * buf, int len) +{ + LPUART_WriteBlocking(UART_PORT, (uint8_t*)buf, len); + return len; +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; +void SysTick_Handler(void) +{ + system_ticks++; +} + +uint32_t board_millis(void) +{ + return system_ticks; +} +#endif diff --git a/src/device/dcd_attr.h b/src/device/dcd_attr.h index 7772a6d96..a35fc0ac5 100644 --- a/src/device/dcd_attr.h +++ b/src/device/dcd_attr.h @@ -60,7 +60,7 @@ #elif TU_CHECK_MCU(MIMXRT10XX) #define DCD_ATTR_ENDPOINT_MAX 8 -#elif TU_CHECK_MCU(MKL25ZXX) +#elif TU_CHECK_MCU(MKL25ZXX) || TU_CHECK_MCU(K32L2BXX) #define DCD_ATTR_ENDPOINT_MAX 16 //------------- Nordic -------------// diff --git a/src/portable/nxp/khci/dcd_khci.c b/src/portable/nxp/khci/dcd_khci.c index 519b8fb7b..dce464fd2 100644 --- a/src/portable/nxp/khci/dcd_khci.c +++ b/src/portable/nxp/khci/dcd_khci.c @@ -26,7 +26,9 @@ #include "tusb_option.h" -#if TUSB_OPT_DEVICE_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_MKL25ZXX ) +#if TUSB_OPT_DEVICE_ENABLED && ( \ + ( CFG_TUSB_MCU == OPT_MCU_MKL25ZXX ) || ( CFG_TUSB_MCU == OPT_MCU_K32L2BXX ) \ + ) #include "fsl_device_registers.h" #define KHCI USB0 diff --git a/src/tusb_option.h b/src/tusb_option.h index e189c65bb..d551765ae 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -108,6 +108,7 @@ // NXP Kinetis #define OPT_MCU_MKL25ZXX 1200 ///< NXP MKL25Zxx +#define OPT_MCU_K32L2BXX 1201 ///< NXP K32L2Bxx // Silabs #define OPT_MCU_EFM32GG 1300 ///< Silabs EFM32GG -- 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') 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') 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') 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') 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 From 22028455077eb1bb4e9c98735cb990305067ef36 Mon Sep 17 00:00:00 2001 From: Xu Chun Guang Date: Fri, 27 Aug 2021 10:50:25 +0800 Subject: fix: bth stridx error --- src/device/usbd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/device/usbd.h b/src/device/usbd.h index c85616c95..9becf2d0d 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -734,7 +734,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Primary Interface */ #define TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ - 9, TUSB_DESC_INTERFACE, _itfnum, _stridx, 3, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 3, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, _stridx, \ /* Endpoint In for events */ \ 7, TUSB_DESC_ENDPOINT, _ep_evt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_evt_size), _ep_evt_interval, \ /* Endpoint In for ACL data */ \ -- cgit v1.3.1