diff options
| author | Gordon McNab <[email protected]> | 2021-12-08 08:36:43 +0000 |
|---|---|---|
| committer | Gordon McNab <[email protected]> | 2021-12-08 08:36:43 +0000 |
| commit | 9a7db985931ae215e808d40e7bacd52535d45305 (patch) | |
| tree | a4d75e2c3823766da53a006280c0d805630d996e /src/device | |
| parent | edf3f3501656b010ad4a9e1d0a0d62573dd0b3fb (diff) | |
| parent | cde824f17f73b5ce4fcec8c176827297854a76c2 (diff) | |
Merge branch 'master' into port-ft90x
Diffstat (limited to 'src/device')
| -rw-r--r-- | src/device/dcd.h | 14 | ||||
| -rw-r--r-- | src/device/dcd_attr.h | 122 | ||||
| -rw-r--r-- | src/device/usbd.c | 274 | ||||
| -rw-r--r-- | src/device/usbd.h | 108 | ||||
| -rw-r--r-- | src/device/usbd_pvt.h | 3 |
5 files changed, 358 insertions, 163 deletions
diff --git a/src/device/dcd.h b/src/device/dcd.h index 66767c1fe..c042cc708 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -106,7 +106,14 @@ typedef struct TU_ATTR_ALIGNED(4) void dcd_init (uint8_t rhport); // Interrupt Handler +#if __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wredundant-decls" +#endif void dcd_int_handler(uint8_t rhport); +#if __GNUC__ +#pragma GCC diagnostic pop +#endif // Enable device interrupt void dcd_int_enable (uint8_t rhport); @@ -137,6 +144,11 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re // Configure endpoint's registers according to descriptor bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_ep); +// Close all non-control endpoints, cancel all pending transfers if any. +// Invoked when switching from a non-zero Configuration by SET_CONFIGURE therefore +// required for multiple configuration support. +void dcd_edpt_close_all (uint8_t rhport); + // Close an endpoint. // Since it is weak, caller must TU_ASSERT this function's existence before calling it. void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; @@ -148,7 +160,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer // This API is optional, may be useful for register-based for transferring data. bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) TU_ATTR_WEAK; -// Stall endpoint +// Stall endpoint, any queuing transfer should be removed from endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); // clear stall, data toggle is also reset to DATA0 diff --git a/src/device/dcd_attr.h b/src/device/dcd_attr.h index 638a17814..c51940573 100644 --- a/src/device/dcd_attr.h +++ b/src/device/dcd_attr.h @@ -36,121 +36,167 @@ // - PORT_HIGHSPEED: mask to indicate which port support highspeed mode, bit0 for port0 and so on. //------------- NXP -------------// -#if TU_CHECK_MCU(LPC11UXX) || TU_CHECK_MCU(LPC13XX) || TU_CHECK_MCU(LPC15XX) +#if TU_CHECK_MCU(OPT_MCU_LPC11UXX, OPT_MCU_LPC13XX, OPT_MCU_LPC15XX) #define DCD_ATTR_ENDPOINT_MAX 5 -#elif TU_CHECK_MCU(LPC175X_6X) || TU_CHECK_MCU(LPC177X_8X) || TU_CHECK_MCU(LPC40XX) +#elif TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC40XX) #define DCD_ATTR_ENDPOINT_MAX 16 -#elif TU_CHECK_MCU(LPC18XX) || TU_CHECK_MCU(LPC43XX) +#elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX) // TODO USB0 has 6, USB1 has 4 + #define DCD_ATTR_CONTROLLER_CHIPIDEA_HS #define DCD_ATTR_ENDPOINT_MAX 6 -#elif TU_CHECK_MCU(LPC51UXX) +#elif TU_CHECK_MCU(OPT_MCU_LPC51UXX) #define DCD_ATTR_ENDPOINT_MAX 5 -#elif TU_CHECK_MCU(LPC54XXX) +#elif TU_CHECK_MCU(OPT_MCU_LPC54XXX) // TODO USB0 has 5, USB1 has 6 #define DCD_ATTR_ENDPOINT_MAX 6 -#elif TU_CHECK_MCU(LPC55XX) +#elif TU_CHECK_MCU(OPT_MCU_LPC55XX) // TODO USB0 has 5, USB1 has 6 #define DCD_ATTR_ENDPOINT_MAX 6 -#elif TU_CHECK_MCU(MIMXRT10XX) +#elif TU_CHECK_MCU(OPT_MCU_MIMXRT10XX) + #define DCD_ATTR_CONTROLLER_CHIPIDEA_HS #define DCD_ATTR_ENDPOINT_MAX 8 -#elif TU_CHECK_MCU(MKL25ZXX) || TU_CHECK_MCU(K32L2BXX) +#elif TU_CHECK_MCU(OPT_MCU_MKL25ZXX, OPT_MCU_K32L2BXX) + #define DCD_ATTR_ENDPOINT_MAX 16 + +#elif TU_CHECK_MCU(OPT_MCU_MM32F327X) #define DCD_ATTR_ENDPOINT_MAX 16 //------------- Nordic -------------// -#elif TU_CHECK_MCU(NRF5X) +#elif TU_CHECK_MCU(OPT_MCU_NRF5X) // 8 CBI + 1 ISO #define DCD_ATTR_ENDPOINT_MAX 9 //------------- 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(OPT_MCU_SAMD21, OPT_MCU_SAMD51, OPT_MCU_SAME5X) || \ + TU_CHECK_MCU(OPT_MCU_SAMD11, OPT_MCU_SAML21, OPT_MCU_SAML22) #define DCD_ATTR_ENDPOINT_MAX 8 -#elif TU_CHECK_MCU(SAMG) +#elif TU_CHECK_MCU(OPT_MCU_SAMG) #define DCD_ATTR_ENDPOINT_MAX 6 #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER -#elif TU_CHECK_MCU(SAMX7X) +#elif TU_CHECK_MCU(OPT_MCU_SAMX7X) #define DCD_ATTR_ENDPOINT_MAX 10 #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER //------------- 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) - // F1: F102, F103 - // L4: L4x2, L4x3 +#elif TU_CHECK_MCU(OPT_MCU_STM32F0) + #define DCD_ATTR_ENDPOINT_MAX 8 + +#elif TU_CHECK_MCU(OPT_MCU_STM32F1) + #if defined (STM32F105x8) || defined (STM32F105xB) || defined (STM32F105xC) || \ + defined (STM32F107xB) || defined (STM32F107xC) + #define DCD_ATTR_ENDPOINT_MAX 4 + #define DCD_ATTR_DWC2_STM32 + #else + #define DCD_ATTR_ENDPOINT_MAX 8 + #endif + +#elif TU_CHECK_MCU(OPT_MCU_STM32F2) + // FS has 4 ep, HS has 5 ep + #define DCD_ATTR_ENDPOINT_MAX 6 + #define DCD_ATTR_DWC2_STM32 + +#elif TU_CHECK_MCU(OPT_MCU_STM32F3) #define DCD_ATTR_ENDPOINT_MAX 8 -#elif TU_CHECK_MCU(STM32F2) || TU_CHECK_MCU(STM32F4) || TU_CHECK_MCU(STM32F3) - // F1: F105, F107 only has 4 - // L4: L4x5, L4x6 has 6 - // For most mcu, FS has 4, HS has 6 +#elif TU_CHECK_MCU(OPT_MCU_STM32F4) + // For most mcu, FS has 4, HS has 6. TODO 446/469/479 HS has 9 #define DCD_ATTR_ENDPOINT_MAX 6 + #define DCD_ATTR_DWC2_STM32 -#elif TU_CHECK_MCU(STM32F7) +#elif TU_CHECK_MCU(OPT_MCU_STM32F7) // FS has 6, HS has 9 #define DCD_ATTR_ENDPOINT_MAX 9 + #define DCD_ATTR_DWC2_STM32 -#elif TU_CHECK_MCU(STM32H7) +#elif TU_CHECK_MCU(OPT_MCU_STM32H7) #define DCD_ATTR_ENDPOINT_MAX 9 + #define DCD_ATTR_DWC2_STM32 + +#elif TU_CHECK_MCU(OPT_MCU_STM32G4) + #define DCD_ATTR_ENDPOINT_MAX 8 + +#elif TU_CHECK_MCU(OPT_MCU_STM32L0, OPT_MCU_STM32L1) + #define DCD_ATTR_ENDPOINT_MAX 8 + +#elif TU_CHECK_MCU(OPT_MCU_STM32L4) + #if defined (STM32L475xx) || defined (STM32L476xx) || \ + defined (STM32L485xx) || defined (STM32L486xx) || defined (STM32L496xx) || \ + defined (STM32L4A6xx) || defined (STM32L4P5xx) || defined (STM32L4Q5xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || \ + defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + #define DCD_ATTR_ENDPOINT_MAX 6 + #define DCD_ATTR_DWC2_STM32 + #else + #define DCD_ATTR_ENDPOINT_MAX 8 + #endif //------------- Sony -------------// -#elif TU_CHECK_MCU(CXD56) +#elif TU_CHECK_MCU(OPT_MCU_CXD56) #define DCD_ATTR_ENDPOINT_MAX 7 #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER //------------- TI -------------// -#elif TU_CHECK_MCU(MSP430x5xx) +#elif TU_CHECK_MCU(OPT_MCU_MSP430x5xx) + #define DCD_ATTR_ENDPOINT_MAX 8 + +#elif TU_CHECK_MCU(OPT_MCU_MSP432E4, OPT_MCU_TM4C123, OPT_MCU_TM4C129) #define DCD_ATTR_ENDPOINT_MAX 8 //------------- ValentyUSB -------------// -#elif TU_CHECK_MCU(VALENTYUSB_EPTRI) +#elif TU_CHECK_MCU(OPT_MCU_VALENTYUSB_EPTRI) #define DCD_ATTR_ENDPOINT_MAX 16 //------------- Nuvoton -------------// -#elif TU_CHECK_MCU(NUC121) || TU_CHECK_MCU(NUC126) +#elif TU_CHECK_MCU(OPT_MCU_NUC121, OPT_MCU_NUC126) #define DCD_ATTR_ENDPOINT_MAX 8 -#elif TU_CHECK_MCU(NUC120) +#elif TU_CHECK_MCU(OPT_MCU_NUC120) #define DCD_ATTR_ENDPOINT_MAX 6 -#elif TU_CHECK_MCU(NUC505) +#elif TU_CHECK_MCU(OPT_MCU_NUC505) #define DCD_ATTR_ENDPOINT_MAX 12 //------------- Espressif -------------// -#elif TU_CHECK_MCU(ESP32S2) || TU_CHECK_MCU(ESP32S3) +#elif TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) #define DCD_ATTR_ENDPOINT_MAX 6 //------------- Dialog -------------// -#elif TU_CHECK_MCU(DA1469X) +#elif TU_CHECK_MCU(OPT_MCU_DA1469X) #define DCD_ATTR_ENDPOINT_MAX 4 //------------- Raspberry Pi -------------// -#elif TU_CHECK_MCU(RP2040) +#elif TU_CHECK_MCU(OPT_MCU_RP2040) #define DCD_ATTR_ENDPOINT_MAX 16 //------------- Silabs -------------// -#elif TU_CHECK_MCU(EFM32GG) || TU_CHECK_MCU(EFM32GG11) || TU_CHECK_MCU(EFM32GG12) +#elif TU_CHECK_MCU(OPT_MCU_EFM32GG) #define DCD_ATTR_ENDPOINT_MAX 7 //------------- Renesas -------------// -#elif TU_CHECK_MCU(RX63X) || TU_CHECK_MCU(RX65X) || TU_CHECK_MCU(RX72N) +#elif TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N) #define DCD_ATTR_ENDPOINT_MAX 10 -//#elif TU_CHECK_MCU(MM32F327X) -// #define DCD_ATTR_ENDPOINT_MAX not known yet - //------------- GigaDevice -------------// -#elif TU_CHECK_MCU(GD32VF103) +#elif TU_CHECK_MCU(OPT_MCU_GD32VF103) #define DCD_ATTR_ENDPOINT_MAX 4 +//------------- Broadcom -------------// +#elif TU_CHECK_MCU(OPT_MCU_BCM2711) + #define DCD_ATTR_ENDPOINT_MAX 8 + +//------------- Broadcom -------------// +#elif TU_CHECK_MCU(OPT_MCU_XMC4000) + #define DCD_ATTR_ENDPOINT_MAX 8 + //------------- BridgeTek -------------// #elif TU_CHECK_MCU(FT90X) #define DCD_ATTR_ENDPOINT_MAX 8 diff --git a/src/device/usbd.c b/src/device/usbd.c index e12dafcfd..6a5210b34 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -38,7 +38,7 @@ //--------------------------------------------------------------------+ // Debug level of USBD -#define USBD_DBG_LVL 2 +#define USBD_DBG 2 #ifndef CFG_TUD_TASK_QUEUE_SZ #define CFG_TUD_TASK_QUEUE_SZ 16 @@ -143,6 +143,18 @@ static usbd_class_driver_t const _usbd_driver[] = }, #endif + #if CFG_TUD_VIDEO + { + DRIVER_NAME("VIDEO") + .init = videod_init, + .reset = videod_reset, + .open = videod_open, + .control_xfer_cb = videod_control_xfer_cb, + .xfer_cb = videod_xfer_cb, + .sof = NULL + }, + #endif + #if CFG_TUD_MIDI { DRIVER_NAME("MIDI") @@ -203,7 +215,7 @@ static usbd_class_driver_t const _usbd_driver[] = }, #endif - #if CFG_TUD_NET + #if CFG_TUD_ECM_RNDIS || CFG_TUD_NCM { DRIVER_NAME("NET") .init = netd_init, @@ -432,19 +444,22 @@ bool tud_init (uint8_t rhport) return true; } -static void usbd_reset(uint8_t rhport) +static void configuration_reset(uint8_t rhport) { - tu_varclr(&_usbd_dev); + for ( uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++ ) + { + get_driver(i)->reset(rhport); + } + tu_varclr(&_usbd_dev); memset(_usbd_dev.itf2drv, DRVID_INVALID, sizeof(_usbd_dev.itf2drv)); // invalid mapping memset(_usbd_dev.ep2drv , DRVID_INVALID, sizeof(_usbd_dev.ep2drv )); // invalid mapping +} +static void usbd_reset(uint8_t rhport) +{ + configuration_reset(rhport); usbd_control_reset(); - - for ( uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++ ) - { - get_driver(i)->reset(rhport); - } } bool tud_task_event_ready(void) @@ -686,9 +701,29 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const { uint8_t const cfg_num = (uint8_t) p_request->wValue; - if ( !_usbd_dev.cfg_num && cfg_num ) TU_ASSERT( process_set_config(rhport, cfg_num) ); - _usbd_dev.cfg_num = cfg_num; + // Only process if new configure is different + if (_usbd_dev.cfg_num != cfg_num) + { + if ( _usbd_dev.cfg_num ) + { + // already configured: need to clear all endpoints and driver first + TU_LOG(USBD_DBG, " Clear current Configuration (%u) before switching\r\n", _usbd_dev.cfg_num); + + // close all non-control endpoints, cancel all pending transfers if any + dcd_edpt_close_all(rhport); + // close all drivers and current configured state except bus speed + uint8_t const speed = _usbd_dev.speed; + configuration_reset(rhport); + + _usbd_dev.speed = speed; // restore speed + } + + // switch to new configuration if not zero + if ( cfg_num ) TU_ASSERT( process_set_config(rhport, cfg_num) ); + } + + _usbd_dev.cfg_num = cfg_num; tud_control_status(rhport, p_request); } break; @@ -701,7 +736,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // Only support remote wakeup for device feature TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue); - TU_LOG(USBD_DBG_LVL, " Enable Remote Wakeup\r\n"); + TU_LOG(USBD_DBG, " Enable Remote Wakeup\r\n"); // Host may enable remote wake up before suspending especially HID device _usbd_dev.remote_wakeup_en = true; @@ -712,7 +747,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // Only support remote wakeup for device feature TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue); - TU_LOG(USBD_DBG_LVL, " Disable Remote Wakeup\r\n"); + TU_LOG(USBD_DBG, " Disable Remote Wakeup\r\n"); // Host may disable remote wake up after resuming _usbd_dev.remote_wakeup_en = false; @@ -751,16 +786,24 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // driver doesn't use alternate settings or implement this TU_VERIFY(TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type); - if (TUSB_REQ_GET_INTERFACE == p_request->bRequest) + switch(p_request->bRequest) { - uint8_t alternate = 0; - tud_control_xfer(rhport, p_request, &alternate, 1); - }else if (TUSB_REQ_SET_INTERFACE == p_request->bRequest) - { - tud_control_status(rhport, p_request); - } else - { - return false; + case TUSB_REQ_GET_INTERFACE: + case TUSB_REQ_SET_INTERFACE: + // Clear complete callback if driver set since it can also stall the request. + usbd_control_set_complete_callback(NULL); + + if (TUSB_REQ_GET_INTERFACE == p_request->bRequest) + { + uint8_t alternate = 0; + tud_control_xfer(rhport, p_request, &alternate, 1); + }else + { + tud_control_status(rhport, p_request); + } + break; + + default: return false; } } } @@ -843,12 +886,13 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // This function parse configuration descriptor & open drivers accordingly static bool process_set_config(uint8_t rhport, uint8_t cfg_num) { - tusb_desc_configuration_t const * desc_cfg = (tusb_desc_configuration_t const *) tud_descriptor_configuration_cb(cfg_num-1); // index is cfg_num-1 + // index is cfg_num-1 + tusb_desc_configuration_t const * desc_cfg = (tusb_desc_configuration_t const *) tud_descriptor_configuration_cb(cfg_num-1); TU_ASSERT(desc_cfg != NULL && desc_cfg->bDescriptorType == TUSB_DESC_CONFIGURATION); // Parse configuration descriptor _usbd_dev.remote_wakeup_support = (desc_cfg->bmAttributes & TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP) ? 1 : 0; - _usbd_dev.self_powered = (desc_cfg->bmAttributes & TUSB_DESC_CONFIG_ATT_SELF_POWERED) ? 1 : 0; + _usbd_dev.self_powered = (desc_cfg->bmAttributes & TUSB_DESC_CONFIG_ATT_SELF_POWERED ) ? 1 : 0; // Parse interface descriptor uint8_t const * p_desc = ((uint8_t const*) desc_cfg) + sizeof(tusb_desc_configuration_t); @@ -856,66 +900,75 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) while( p_desc < desc_end ) { - tusb_desc_interface_assoc_t const * desc_iad = NULL; + uint8_t assoc_itf_count = 1; // Class will always starts with Interface Association (if any) and then Interface descriptor if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) ) { - desc_iad = (tusb_desc_interface_assoc_t const *) p_desc; + tusb_desc_interface_assoc_t const * desc_iad = (tusb_desc_interface_assoc_t const *) p_desc; + assoc_itf_count = desc_iad->bInterfaceCount; + p_desc = tu_desc_next(p_desc); // next to Interface + + // 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); } 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; - - // 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 + uint16_t const remaining_len = desc_end-p_desc; uint8_t drv_id; for (drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) { usbd_class_driver_t const *driver = get_driver(drv_id); uint16_t const drv_len = driver->open(rhport, desc_itf, remaining_len); - if ( drv_len > 0 ) + if ( (sizeof(tusb_desc_interface_t) <= drv_len) && (drv_len <= remaining_len) ) { - // Open successfully, check if length is correct - TU_ASSERT( sizeof(tusb_desc_interface_t) <= drv_len && drv_len <= remaining_len); - + // Open successfully TU_LOG2(" %s opened\r\n", driver->name); - // bind interface to found driver - _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; + // Some drivers use 2 or more interfaces but may not have IAD e.g MIDI (always) or + // BTH (even CDC) with class in device descriptor (single interface) + if ( assoc_itf_count == 1) + { + #if CFG_TUD_CDC + if ( driver->open == cdcd_open ) assoc_itf_count = 2; + #endif - // If using IAD, bind all interfaces to the same driver - if (desc_iad) + #if CFG_TUD_MIDI + if ( driver->open == midid_open ) assoc_itf_count = 2; + #endif + + #if CFG_TUD_BTH && CFG_TUD_BTH_ISO_ALT_COUNT + if ( driver->open == btd_open ) assoc_itf_count = 2; + #endif + } + + // bind (associated) interfaces to found driver + for(uint8_t i=0; i<assoc_itf_count; i++) { - // 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); + uint8_t const itf_num = desc_itf->bInterfaceNumber+i; - for(uint8_t i=1; i<desc_iad->bInterfaceCount; i++) - { - _usbd_dev.itf2drv[desc_itf->bInterfaceNumber+i] = drv_id; - } + // Interface number must not be used already + TU_ASSERT(DRVID_INVALID == _usbd_dev.itf2drv[itf_num]); + _usbd_dev.itf2drv[itf_num] = drv_id; } // 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 + // next Interface + p_desc += drv_len; break; // exit driver find loop } } - // Failed if cannot find supported driver + // Failed if there is no supported drivers TU_ASSERT(drv_id < TOTAL_DRIVER_COUNT); } @@ -937,19 +990,23 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const { TU_LOG2(" Device\r\n"); - uint16_t len = sizeof(tusb_desc_device_t); + void* desc_device = (void*) (uintptr_t) tud_descriptor_device_cb(); - // Only send up to EP0 Packet Size if not addressed + // Only response with exactly 1 Packet if: not addressed and host requested more data than device descriptor has. // This only happens with the very first get device descriptor and EP0 size = 8 or 16. - if ((CFG_TUD_ENDPOINT0_SIZE < sizeof(tusb_desc_device_t)) && !_usbd_dev.addressed) + if ((CFG_TUD_ENDPOINT0_SIZE < sizeof(tusb_desc_device_t)) && !_usbd_dev.addressed && + ((tusb_control_request_t const*) p_request)->wLength > sizeof(tusb_desc_device_t)) { - len = CFG_TUD_ENDPOINT0_SIZE; - // Hack here: we modify the request length to prevent usbd_control response with zlp - ((tusb_control_request_t*) p_request)->wLength = CFG_TUD_ENDPOINT0_SIZE; - } + // since we are responding with 1 packet & less data than wLength. + tusb_control_request_t mod_request = *p_request; + mod_request.wLength = CFG_TUD_ENDPOINT0_SIZE; - return tud_control_xfer(rhport, p_request, (void*) tud_descriptor_device_cb(), len); + return tud_control_xfer(rhport, &mod_request, desc_device, CFG_TUD_ENDPOINT0_SIZE); + }else + { + return tud_control_xfer(rhport, p_request, desc_device, sizeof(tusb_desc_device_t)); + } } break; @@ -960,24 +1017,37 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const // requested by host if USB > 2.0 ( i.e 2.1 or 3.x ) if (!tud_descriptor_bos_cb) return false; - tusb_desc_bos_t const* desc_bos = (tusb_desc_bos_t const*) tud_descriptor_bos_cb(); + uintptr_t desc_bos = (uintptr_t) tud_descriptor_bos_cb(); + TU_ASSERT(desc_bos); // Use offsetof to avoid pointer to the odd/misaligned address - uint16_t const total_len = tu_le16toh( tu_unaligned_read16((uint8_t*) desc_bos + offsetof(tusb_desc_bos_t, wTotalLength)) ); + uint16_t const total_len = tu_le16toh( tu_unaligned_read16((const void*) (desc_bos + offsetof(tusb_desc_bos_t, wTotalLength))) ); return tud_control_xfer(rhport, p_request, (void*) desc_bos, total_len); } break; case TUSB_DESC_CONFIGURATION: + case TUSB_DESC_OTHER_SPEED_CONFIG: { - TU_LOG2(" Configuration[%u]\r\n", desc_index); + uintptr_t desc_config; + + if ( desc_type == TUSB_DESC_CONFIGURATION ) + { + TU_LOG2(" Configuration[%u]\r\n", desc_index); + desc_config = (uintptr_t) tud_descriptor_configuration_cb(desc_index); + }else + { + // Host only request this after getting Device Qualifier descriptor + TU_LOG2(" Other Speed Configuration\r\n"); + TU_VERIFY( tud_descriptor_other_speed_configuration_cb ); + desc_config = (uintptr_t) tud_descriptor_other_speed_configuration_cb(desc_index); + } - tusb_desc_configuration_t const* desc_config = (tusb_desc_configuration_t const*) tud_descriptor_configuration_cb(desc_index); TU_ASSERT(desc_config); // Use offsetof to avoid pointer to the odd/misaligned address - uint16_t const total_len = tu_le16toh( tu_unaligned_read16((uint8_t*) desc_config + offsetof(tusb_desc_configuration_t, wTotalLength)) ); + uint16_t const total_len = tu_le16toh( tu_unaligned_read16((const void*) (desc_config + offsetof(tusb_desc_configuration_t, wTotalLength))) ); return tud_control_xfer(rhport, p_request, (void*) desc_config, total_len); } @@ -988,38 +1058,26 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const TU_LOG2(" String[%u]\r\n", desc_index); // String Descriptor always uses the desc set from user - uint8_t const* desc_str = (uint8_t const*) tud_descriptor_string_cb(desc_index, p_request->wIndex); + uint8_t const* desc_str = (uint8_t const*) tud_descriptor_string_cb(desc_index, tu_le16toh(p_request->wIndex)); TU_VERIFY(desc_str); // first byte of descriptor is its size - return tud_control_xfer(rhport, p_request, (void*) desc_str, desc_str[0]); + return tud_control_xfer(rhport, p_request, (void*) (uintptr_t) desc_str, tu_desc_len(desc_str)); } break; case TUSB_DESC_DEVICE_QUALIFIER: + { TU_LOG2(" Device Qualifier\r\n"); - // Host sends this request to ask why our device with USB BCD from 2.0 - // but is running at Full/Low Speed. If not highspeed capable stall this request, - // otherwise return the descriptor that could work in highspeed mode - if ( tud_descriptor_device_qualifier_cb ) - { - uint8_t const* desc_qualifier = tud_descriptor_device_qualifier_cb(); - TU_ASSERT(desc_qualifier); + TU_VERIFY( tud_descriptor_device_qualifier_cb ); - // first byte of descriptor is its size - return tud_control_xfer(rhport, p_request, (void*) desc_qualifier, desc_qualifier[0]); - }else - { - return false; - } - break; + uint8_t const* desc_qualifier = tud_descriptor_device_qualifier_cb(); + TU_VERIFY(desc_qualifier); - case TUSB_DESC_OTHER_SPEED_CONFIG: - TU_LOG2(" Other Speed Configuration\r\n"); - - // After Device Qualifier descriptor is received host will ask for this descriptor - return false; // not supported + // first byte of descriptor is its size + return tud_control_xfer(rhport, p_request, (void*) (uintptr_t) desc_qualifier, tu_desc_len(desc_qualifier)); + } break; default: return false; @@ -1034,15 +1092,11 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) switch (event->event_id) { case DCD_EVENT_UNPLUGGED: - // UNPLUGGED event can be bouncing, only processing if we are currently connected - if ( _usbd_dev.connected ) - { - _usbd_dev.connected = 0; - _usbd_dev.addressed = 0; - _usbd_dev.cfg_num = 0; - _usbd_dev.suspended = 0; - osal_queue_send(_usbd_q, event, in_isr); - } + _usbd_dev.connected = 0; + _usbd_dev.addressed = 0; + _usbd_dev.cfg_num = 0; + _usbd_dev.suspended = 0; + osal_queue_send(_usbd_q, event, in_isr); break; case DCD_EVENT_SUSPEND: @@ -1301,27 +1355,33 @@ bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr) void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { - TU_LOG(USBD_DBG_LVL, " Stall EP %02X", ep_addr); uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - dcd_edpt_stall(rhport, ep_addr); - _usbd_dev.ep_status[epnum][dir].stalled = true; - _usbd_dev.ep_status[epnum][dir].busy = true; + // only stalled if currently cleared + if ( !_usbd_dev.ep_status[epnum][dir].stalled ) + { + TU_LOG(USBD_DBG, " Stall EP %02X\r\n", ep_addr); + dcd_edpt_stall(rhport, ep_addr); + _usbd_dev.ep_status[epnum][dir].stalled = true; + _usbd_dev.ep_status[epnum][dir].busy = true; + } } void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { - TU_LOG(USBD_DBG_LVL, " Clear Stall EP %02X", ep_addr); - uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - - dcd_edpt_clear_stall(rhport, ep_addr); - _usbd_dev.ep_status[epnum][dir].stalled = false; - _usbd_dev.ep_status[epnum][dir].busy = false; + // only clear if currently stalled + if ( _usbd_dev.ep_status[epnum][dir].stalled ) + { + TU_LOG(USBD_DBG, " Clear Stall EP %02X\r\n", ep_addr); + dcd_edpt_clear_stall(rhport, ep_addr); + _usbd_dev.ep_status[epnum][dir].stalled = false; + _usbd_dev.ep_status[epnum][dir].busy = false; + } } bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) @@ -1345,7 +1405,13 @@ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) TU_ASSERT(dcd_edpt_close, /**/); TU_LOG2(" CLOSING Endpoint: 0x%02X\r\n", ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + dcd_edpt_close(rhport, ep_addr); + _usbd_dev.ep_status[epnum][dir].stalled = false; + _usbd_dev.ep_status[epnum][dir].busy = false; + _usbd_dev.ep_status[epnum][dir].claimed = false; return; } diff --git a/src/device/usbd.h b/src/device/usbd.h index 9becf2d0d..ec34817fa 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -113,9 +113,16 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid); TU_ATTR_WEAK uint8_t const * tud_descriptor_bos_cb(void); // Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request -// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete. +// device_qualifier descriptor describes information about a high-speed capable device that would +// change if the device were operating at the other speed. If not highspeed capable stall this request. TU_ATTR_WEAK uint8_t const* tud_descriptor_device_qualifier_cb(void); +// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa +TU_ATTR_WEAK uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index); + // Invoked when device is mounted (configured) TU_ATTR_WEAK void tud_mount_cb(void); @@ -171,17 +178,18 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F //--------------------------------------------------------------------+ -// Configuration & Interface Descriptor Templates +// Configuration Descriptor Templates //--------------------------------------------------------------------+ -//------------- Configuration -------------// #define TUD_CONFIG_DESC_LEN (9) // Config number, interface count, string index, total length, attribute, power in mA #define TUD_CONFIG_DESCRIPTOR(config_num, _itfcount, _stridx, _total_len, _attribute, _power_ma) \ 9, TUSB_DESC_CONFIGURATION, U16_TO_U8S_LE(_total_len), _itfcount, config_num, _stridx, TU_BIT(7) | _attribute, (_power_ma)/2 -//------------- CDC -------------// +//--------------------------------------------------------------------+ +// CDC Descriptor Templates +//--------------------------------------------------------------------+ // Length of template descriptor: 66 bytes #define TUD_CDC_DESC_LEN (8+9+5+5+4+5+7+9+7+7) @@ -210,7 +218,9 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Endpoint In */\ 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 -//------------- MSC -------------// +//--------------------------------------------------------------------+ +// MSC Descriptor Templates +//--------------------------------------------------------------------+ // Length of template descriptor: 23 bytes #define TUD_MSC_DESC_LEN (9 + 7 + 7) @@ -224,7 +234,10 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Endpoint In */\ 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 -//------------- HID -------------// + +//--------------------------------------------------------------------+ +// HID Descriptor Templates +//--------------------------------------------------------------------+ // Length of template descriptor: 25 bytes #define TUD_HID_DESC_LEN (9 + 9 + 7) @@ -254,8 +267,10 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Endpoint In */\ 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval -//------------- MIDI -------------// -// MIDI v1.0 is based on Audio v1.0 +//--------------------------------------------------------------------+ +// MIDI Descriptor Templates +// Note: MIDI v1.0 is based on Audio v1.0 +//--------------------------------------------------------------------+ #define TUD_MIDI_DESC_HEAD_LEN (9 + 9 + 9 + 7) #define TUD_MIDI_DESC_HEAD(_itfnum, _stridx, _numcables) \ @@ -312,7 +327,9 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb TUD_MIDI_DESC_EP(_epin, _epsize, 1),\ TUD_MIDI_JACKID_OUT_EMB(1) -//------------- AUDIO -------------// +//--------------------------------------------------------------------+ +// Audio v2.0 Descriptor Templates +//--------------------------------------------------------------------+ /* Standard Interface Association Descriptor (IAD) */ #define TUD_AUDIO_DESC_IAD_LEN 8 @@ -544,7 +561,10 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb ((((_maxFrequency + ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 7999 : 999)) / ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 8000 : 1000)) + 1) * _nBytesPerSample * _nChannels) -//------------- TUD_USBTMC/USB488 -------------// +//--------------------------------------------------------------------+ +// USBTMC/USB488 Descriptor Templates +//--------------------------------------------------------------------+ + #define TUD_USBTMC_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) #define TUD_USBTMC_APP_SUBCLASS 0x03u @@ -574,8 +594,10 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb #define TUD_USBTMC_INT_DESCRIPTOR_LEN (7u) +//--------------------------------------------------------------------+ +// Vendor Descriptor Templates +//--------------------------------------------------------------------+ -//------------- Vendor -------------// #define TUD_VENDOR_DESC_LEN (9+7+7) // Interface number, string index, EP Out & IN address, EP size @@ -587,7 +609,10 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Endpoint In */\ 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 -//------------- DFU Runtime -------------// +//--------------------------------------------------------------------+ +// DFU Runtime Descriptor Templates +//--------------------------------------------------------------------+ + #define TUD_DFU_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) #define TUD_DFU_APP_SUBCLASS (APP_SUBCLASS_DFU_RUNTIME) @@ -602,6 +627,10 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Function */ \ 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) +//--------------------------------------------------------------------+ +// DFU Descriptor Templates +//--------------------------------------------------------------------+ + // Length of template descriptor: 9 bytes + number of alternatives * 9 #define TUD_DFU_DESC_LEN(_alt_count) (9 + (_alt_count) * 9) @@ -647,8 +676,9 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ _TUD_DFU_ALT_7(_itfnum, _alt_count+1, _stridx+1) - -//------------- CDC-ECM -------------// +//--------------------------------------------------------------------+ +// CDC-ECM Descriptor Templates +//--------------------------------------------------------------------+ // Length of template descriptor: 71 bytes #define TUD_CDC_ECM_DESC_LEN (8+9+5+5+13+7+9+9+7+7) @@ -677,8 +707,9 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Endpoint Out */\ 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 - -//------------- RNDIS -------------// +//--------------------------------------------------------------------+ +// RNDIS Descriptor Templates +//--------------------------------------------------------------------+ #if 0 /* Windows XP */ @@ -719,7 +750,10 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Endpoint Out */\ 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 -//------------- BT Radio -------------// +//--------------------------------------------------------------------+ +// Bluetooth Radio Descriptor Templates +//--------------------------------------------------------------------+ + #define TUD_BT_APP_CLASS (TUSB_CLASS_WIRELESS_CONTROLLER) #define TUD_BT_APP_SUBCLASS 0x01 #define TUD_BT_PROTOCOL_PRIMARY_CONTROLLER 0x01 @@ -729,8 +763,8 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb #define CFG_TUD_BTH_ISO_ALT_COUNT 0 #endif -// Length of template descriptor: 30 bytes + number of ISO alternatives * 23 -#define TUD_BTH_DESC_LEN (9 + 7 + 7 + 7 + (CFG_TUD_BTH_ISO_ALT_COUNT) * (9 + 7 + 7)) +// Length of template descriptor: 38 bytes + number of ISO alternatives * 23 +#define TUD_BTH_DESC_LEN (8 + 9 + 7 + 7 + 7 + (CFG_TUD_BTH_ISO_ALT_COUNT) * (9 + 7 + 7)) /* Primary Interface */ #define TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ @@ -770,10 +804,46 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb // BT Primary controller descriptor // Interface number, string index, attributes, event endpoint, event endpoint size, interval, data in, data out, data endpoint size, iso endpoint sizes +// TODO BTH should also use IAD like CDC for composite device #define TUD_BTH_DESCRIPTOR(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size,...) \ + /* Interface Associate */\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0,\ TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ TUD_BTH_ISO_ITFS(_itfnum + 1, _ep_in + 1, _ep_out + 1, __VA_ARGS__) +//--------------------------------------------------------------------+ +// CDC-NCM Descriptor Templates +//--------------------------------------------------------------------+ + +// Length of template descriptor +#define TUD_CDC_NCM_DESC_LEN (8+9+5+5+13+6+7+9+9+7+7) + +// CDC-ECM Descriptor Template +// Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. +#define TUD_CDC_NCM_DESCRIPTOR(_itfnum, _desc_stridx, _mac_stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize, _maxsegmentsize) \ + /* Interface Association */\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_NETWORK_CONTROL_MODEL, 0, 0,\ + /* CDC Control Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_NETWORK_CONTROL_MODEL, 0, _desc_stridx,\ + /* CDC-NCM Header */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0110),\ + /* CDC-NCM Union */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ + /* CDC-NCM Functional Descriptor */\ + 13, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ETHERNET_NETWORKING, _mac_stridx, 0, 0, 0, 0, U16_TO_U8S_LE(_maxsegmentsize), U16_TO_U8S_LE(0), 0, \ + /* CDC-NCM Functional Descriptor */\ + 6, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_NCM, U16_TO_U8S_LE(0x0100), 0, \ + /* Endpoint Notification */\ + 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 50,\ + /* CDC Data Interface (default inactive) */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 0, TUSB_CLASS_CDC_DATA, 0, NCM_DATA_PROTOCOL_NETWORK_TRANSFER_BLOCK, 0,\ + /* CDC Data Interface (alternative active) */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 1, 2, TUSB_CLASS_CDC_DATA, 0, NCM_DATA_PROTOCOL_NETWORK_TRANSFER_BLOCK, 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + #ifdef __cplusplus } #endif diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 6a4b30956..7607b9895 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -81,7 +81,7 @@ bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr); // Release an endpoint without submitting a transfer bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr); -// Check if endpoint transferring is complete +// Check if endpoint is busy transferring bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr); // Stall endpoint @@ -93,6 +93,7 @@ void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr); // Check if endpoint is stalled bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr); +// Check if endpoint is ready (not busy and not stalled) TU_ATTR_ALWAYS_INLINE static inline bool usbd_edpt_ready(uint8_t rhport, uint8_t ep_addr) { |
