From c14c0cfc9fec9101b63df682c5fa5ac0576de0f8 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 29 Apr 2020 10:49:58 +0700 Subject: support class drivers implemented by application --- src/device/usbd.c | 114 ++++++++++++++++++++++++++++---------------------- src/device/usbd_pvt.h | 23 ++++++++++ 2 files changed, 87 insertions(+), 50 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 1f660f0f2..432786140 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -79,21 +79,7 @@ enum { DRVID_INVALID = 0xFFu }; #define DRIVER_NAME(_name) #endif -typedef struct -{ - #if CFG_TUSB_DEBUG >= 2 - char const* name; - #endif - - void (* init ) (void); - void (* reset ) (uint8_t rhport); - bool (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t* p_length); - bool (* control_request ) (uint8_t rhport, tusb_control_request_t const * request); - bool (* control_complete ) (uint8_t rhport, tusb_control_request_t const * request); - bool (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - void (* sof ) (uint8_t rhport); /* optional */ -} usbd_class_driver_t; - +// Built-in class drivers static usbd_class_driver_t const _usbd_driver[] = { #if CFG_TUD_CDC @@ -203,6 +189,29 @@ static usbd_class_driver_t const _usbd_driver[] = enum { USBD_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; +// Additional class drivers implemented by application +static usbd_class_driver_t const * _app_driver = NULL; +static uint8_t _app_driver_count = 0; + +// virtually joins built-in and application drivers together +// All drivers = built-in + application +static inline usbd_class_driver_t const * get_driver(uint8_t drvid) +{ + // Built-in drivers + if (drvid < USBD_CLASS_DRIVER_COUNT) return &_usbd_driver[drvid]; + + // App drivers + if ( usbd_app_driver_get_cb ) + { + drvid -= USBD_CLASS_DRIVER_COUNT; + if ( drvid < _app_driver_count ) return &_app_driver[drvid]; + } + + return NULL; +} + +#define TOTAL_DRIVER_COUNT (USBD_CLASS_DRIVER_COUNT+_app_driver_count) + //--------------------------------------------------------------------+ // DCD Event //--------------------------------------------------------------------+ @@ -263,11 +272,12 @@ static char const* const _tusb_std_request_str[] = // for usbd_control to print the name of control complete driver void usbd_driver_print_control_complete_name(bool (*control_complete) (uint8_t, tusb_control_request_t const * )) { - for (uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++) + for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) { - if (_usbd_driver[i].control_complete == control_complete ) + usbd_class_driver_t const * driver = get_driver(i); + if ( driver->control_complete == control_complete ) { - TU_LOG2(" %s control complete\r\n", _usbd_driver[i].name); + TU_LOG2(" %s control complete\r\n", driver->name); return; } } @@ -309,11 +319,18 @@ bool tud_init (void) _usbd_q = osal_queue_create(&_usbd_qdef); TU_ASSERT(_usbd_q != NULL); + // Get application driver if available + if ( usbd_app_driver_get_cb ) + { + _app_driver = usbd_app_driver_get_cb(&_app_driver_count); + } + // Init class drivers - for (uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++) + for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) { - TU_LOG2("%s init\r\n", _usbd_driver[i].name); - _usbd_driver[i].init(); + usbd_class_driver_t const * driver = get_driver(i); + TU_LOG2("%s init\r\n", driver->name); + driver->init(); } // Init device controller driver @@ -333,9 +350,9 @@ static void usbd_reset(uint8_t rhport) usbd_control_reset(); - for (uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++) + for ( uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++ ) { - if ( _usbd_driver[i].reset ) _usbd_driver[i].reset( rhport ); + get_driver(i)->reset(rhport); } } @@ -420,11 +437,11 @@ void tud_task (void) } else { - uint8_t const drv_id = _usbd_dev.ep2drv[epnum][ep_dir]; - TU_ASSERT(drv_id < USBD_CLASS_DRIVER_COUNT,); + usbd_class_driver_t const * driver = get_driver( _usbd_dev.ep2drv[epnum][ep_dir] ); + TU_ASSERT(driver, ); - TU_LOG2(" %s xfer callback\r\n", _usbd_driver[drv_id].name); - _usbd_driver[drv_id].xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + TU_LOG2(" %s xfer callback\r\n", driver->name); + driver->xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len); } } break; @@ -438,12 +455,10 @@ void tud_task (void) break; case DCD_EVENT_SOF: - for ( uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++ ) + for ( uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++ ) { - if ( _usbd_driver[i].sof ) - { - _usbd_driver[i].sof(event.rhport); - } + usbd_class_driver_t const * driver = get_driver(i); + if ( driver->sof ) driver->sof(event.rhport); } break; @@ -463,11 +478,11 @@ void tud_task (void) //--------------------------------------------------------------------+ // Helper to invoke class driver control request handler -static bool invoke_class_control(uint8_t rhport, uint8_t drvid, tusb_control_request_t const * request) +static bool invoke_class_control(uint8_t rhport, usbd_class_driver_t const * driver, tusb_control_request_t const * request) { - usbd_control_set_complete_callback(_usbd_driver[drvid].control_complete); - TU_LOG2(" %s control request\r\n", _usbd_driver[drvid].name); - return _usbd_driver[drvid].control_request(rhport, request); + usbd_control_set_complete_callback(driver->control_complete); + TU_LOG2(" %s control request\r\n", driver->name); + return driver->control_request(rhport, request); } // This handles the actual request and its response. @@ -580,12 +595,12 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const uint8_t const itf = tu_u16_low(p_request->wIndex); TU_VERIFY(itf < TU_ARRAY_SIZE(_usbd_dev.itf2drv)); - uint8_t const drvid = _usbd_dev.itf2drv[itf]; - TU_VERIFY(drvid < USBD_CLASS_DRIVER_COUNT); + usbd_class_driver_t const * driver = get_driver(_usbd_dev.itf2drv[itf]); + TU_VERIFY(driver); // all requests to Interface (STD or Class) is forwarded to class driver. // notable requests are: GET HID REPORT DESCRIPTOR, SET_INTERFACE, GET_INTERFACE - if ( !invoke_class_control(rhport, drvid, p_request) ) + if ( !invoke_class_control(rhport, driver, p_request) ) { // For GET_INTERFACE, it is mandatory to respond even if the class // driver doesn't use alternate settings. @@ -607,8 +622,6 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const TU_ASSERT(ep_num < TU_ARRAY_SIZE(_usbd_dev.ep2drv) ); - uint8_t const drvid = _usbd_dev.ep2drv[ep_num][ep_dir]; - bool ret = false; // Handle STD request to endpoint @@ -647,16 +660,17 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const } } - if (drvid < 0xFF) { - TU_ASSERT(drvid < USBD_CLASS_DRIVER_COUNT); - + usbd_class_driver_t const * driver = get_driver(_usbd_dev.ep2drv[ep_num][ep_dir]); + + if (driver) + { // Some classes such as USBTMC needs to clear/re-init its buffer when receiving CLEAR_FEATURE request // We will forward all request targeted endpoint to class drivers after // - For class-type requests: driver is fully responsible to reply to host // - For std-type requests : driver init/re-init internal variable/buffer only, and // must not call tud_control_status(), driver's return value will have no effect. // EP state has already affected (stalled/cleared) - if ( invoke_class_control(rhport, drvid, p_request) ) ret = true; + if ( invoke_class_control(rhport, driver, p_request) ) ret = true; } if ( TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type ) @@ -708,17 +722,17 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) uint8_t drv_id; uint16_t drv_len; - for (drv_id = 0; drv_id < USBD_CLASS_DRIVER_COUNT; drv_id++) + for (drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) { - usbd_class_driver_t const *driver = &_usbd_driver[drv_id]; + usbd_class_driver_t const *driver = get_driver(drv_id); drv_len = 0; if ( driver->open(rhport, desc_itf, &drv_len) ) { // Interface number must not be used already - TU_ASSERT( DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] ); + TU_ASSERT(DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber]); - TU_LOG2(" %s opened\r\n", _usbd_driver[drv_id].name); + TU_LOG2(" %s opened\r\n", driver->name); _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; // If IAD exist, assign all interfaces to the same driver @@ -741,7 +755,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) } // Assert if cannot find supported driver - TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT && drv_len >= sizeof(tusb_desc_interface_t) ); + TU_ASSERT( drv_id < TOTAL_DRIVER_COUNT && drv_len >= sizeof(tusb_desc_interface_t) ); mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, drv_len, drv_id); // TODO refactor diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 48188ec99..d6eb289c1 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -33,6 +33,29 @@ extern "C" { #endif +//--------------------------------------------------------------------+ +// Class Drivers +//--------------------------------------------------------------------+ + +typedef struct +{ +#if CFG_TUSB_DEBUG >= 2 + char const* name; +#endif + + void (* init ) (void); + void (* reset ) (uint8_t rhport); + bool (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t* p_length); + bool (* control_request ) (uint8_t rhport, tusb_control_request_t const * request); + bool (* control_complete ) (uint8_t rhport, tusb_control_request_t const * request); + bool (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); + void (* sof ) (uint8_t rhport); /* optional */ +} usbd_class_driver_t; + +// Invoked when initializing device stack to get additional class drivers. +// Can optionally implemented by application to extend/overwrite class driver support. +usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) TU_ATTR_WEAK; + //--------------------------------------------------------------------+ // USBD Endpoint API //--------------------------------------------------------------------+ -- cgit v1.3.1 From d4bf777c943659a4e985ce8514ef077c5bf2b40d Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 27 May 2020 11:01:33 +0700 Subject: try to get synopsys work with OTG HS + external PHY --- src/device/usbd.c | 1 + src/portable/st/synopsys/dcd_synopsys.c | 80 +++++++++++++++++++++++++++------ 2 files changed, 68 insertions(+), 13 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index f7918c07e..bd892e389 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -384,6 +384,7 @@ void tud_task (void) { case DCD_EVENT_BUS_RESET: usbd_reset(event.rhport); + // TODO DCD should report operational speed (LS/FS/HS) break; case DCD_EVENT_UNPLUGGED: diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index b68794712..8ca67dbb4 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -99,7 +99,7 @@ static const dcd_rhport_t _dcd_rhport[] = { .regs = USB_OTG_FS_PERIPH_BASE, .irqnum = OTG_FS_IRQn } #ifdef USB_OTG_HS - ,{ .regs = USB_OTG_HS_PERIPH_BASE, .irqnum = OTG_HS_IRQn } + ,{ .regs = USB_OTG_HS_PERIPH_BASE, .irqnum = OTG_HS_IRQn } #endif }; @@ -218,16 +218,48 @@ static void end_of_reset(uint8_t rhport) *------------------------------------------------------------------*/ void dcd_init (uint8_t rhport) { + dcd_disconnect(rhport); + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); - // Programming model begins in the last section of the chapter on the USB - // peripheral in each Reference Manual. - usb_otg->GAHBCFG |= USB_OTG_GAHBCFG_GINT; + // No HNP/SRP (no OTG support), program timeout later. +#if TUD_OPT_HIGH_SPEED // TODO may pass parameter instead of using macro for HighSpeed + if ( rhport == 1 ) + { + // Highspeed with external ULPI PHY + + // deactivate internal PHY + usb_otg->GCCFG &= ~USB_OTG_GCCFG_PWRDWN; + + // On selected MCUs HS port1 can be used with external PHY via ULPI interface + // Select ULPI highspeed PHY with default external VBUS Indicator and Drive + usb_otg->GUSBCFG &= ~(USB_OTG_GUSBCFG_TSDPS | USB_OTG_GUSBCFG_ULPIFSLS | USB_OTG_GUSBCFG_PHYSEL | + USB_OTG_GUSBCFG_ULPIEVBUSD | USB_OTG_GUSBCFG_ULPIEVBUSI); + + // Turn around time for Highspeed is 0x09 + usb_otg->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT; + usb_otg->GUSBCFG |= (0x09 << USB_OTG_GUSBCFG_TRDT_Pos); + }else +#endif + { + // Turn around programmed for 32+ MHz is 0x06 + usb_otg->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT; + usb_otg->GUSBCFG |= (0x06 << USB_OTG_GUSBCFG_TRDT_Pos) | USB_OTG_GUSBCFG_PHYSEL; + } + + // Reset core after selecting PHY + // Wait AHB IDLE, reset then wait until it is cleared + while ((usb_otg->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0U) {} + usb_otg->GRSTCTL |= USB_OTG_GRSTCTL_CSRST; + while ((usb_otg->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST) {} + + // Force device mode + usb_otg->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD; + + TU_LOG2_LOCATION(); - // No HNP/SRP (no OTG support), program timeout later, turnaround - // programmed for 32+ MHz. - // TODO: PHYSEL is read-only on some cores (STM32F407). Worth gating? - usb_otg->GUSBCFG |= (0x06 << USB_OTG_GUSBCFG_TRDT_Pos) | USB_OTG_GUSBCFG_PHYSEL; + // Restart PHY clock + *((volatile uint32_t *)(_dcd_rhport[rhport].regs + USB_OTG_PCGCCTL_BASE)) = 0; // Clear all interrupts usb_otg->GINTSTS |= usb_otg->GINTSTS; @@ -241,14 +273,33 @@ void dcd_init (uint8_t rhport) // If USB host misbehaves during status portion of control xfer // (non zero-length packet), send STALL back and discard. Full speed. - dev->DCFG |= USB_OTG_DCFG_NZLSOHSK | (3 << USB_OTG_DCFG_DSPD_Pos); + dev->DCFG |= USB_OTG_DCFG_NZLSOHSK; + +#if TUD_OPT_HIGH_SPEED + if ( rhport == 1 ) + { + // high speed = 0x00 + dev->DCFG &= ~(3 << USB_OTG_DCFG_DSPD_Pos); + + // Transceiver delay, necessary for some ULPI PHYs + dev->DCFG |= (1 << 14); + } +#endif + { + // full speed with internal phy + dev->DCFG |= (3 << USB_OTG_DCFG_DSPD_Pos); + + // Enable USB transceiver. + usb_otg->GCCFG |= USB_OTG_GCCFG_PWRDWN; + } usb_otg->GINTMSK |= USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM | - USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_WUIM | - USB_OTG_GINTMSK_RXFLVLM | (USE_SOF ? USB_OTG_GINTMSK_SOFM : 0); + USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_WUIM | + USB_OTG_GINTMSK_RXFLVLM | (USE_SOF ? USB_OTG_GINTMSK_SOFM : 0); - // Enable USB transceiver. - usb_otg->GCCFG |= USB_OTG_GCCFG_PWRDWN; + // Programming model begins in the last section of the chapter on the USB + // peripheral in each Reference Manual. + usb_otg->GAHBCFG |= USB_OTG_GAHBCFG_GINT; } void dcd_int_enable (uint8_t rhport) @@ -739,6 +790,9 @@ void dcd_int_handler(uint8_t rhport) // ENUMDNE detects speed of the link. For full-speed, we // always expect the same value. This interrupt is considered // the end of reset. + + TU_LOG2_HEX(dev->DSTS); + usb_otg->GINTSTS = USB_OTG_GINTSTS_ENUMDNE; end_of_reset(rhport); dcd_event_bus_signal(rhport, DCD_EVENT_BUS_RESET, true); -- cgit v1.3.1 From e3404049686adfd934a6444fadf9ae00f1f94f8a Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 27 May 2020 19:01:59 +0700 Subject: changing usbd driver open() return type, add max_len only done with cdc and msc, push this interim for feedback first --- src/class/cdc/cdc_device.c | 26 ++++++++++++++------------ src/class/cdc/cdc_device.h | 12 ++++++------ src/class/msc/msc_device.c | 16 ++++++++++------ src/class/msc/msc_device.h | 12 ++++++------ src/device/usbd.c | 30 ++++++++++++++++++------------ 5 files changed, 54 insertions(+), 42 deletions(-) (limited to 'src/device') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 2d8f986ae..a24f348f4 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -222,14 +222,16 @@ void cdcd_reset(uint8_t rhport) } } -bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) +uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { // Only support ACM subclass TU_VERIFY ( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && - CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass); + CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass, 0); // Note: 0xFF can be used with RNDIS - TU_VERIFY(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA)); + TU_VERIFY(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA), 0); + + uint16_t len = 0; // Find available interface cdcd_interface_t * p_cdc = NULL; @@ -242,29 +244,29 @@ bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t break; } } - TU_ASSERT(p_cdc); + TU_ASSERT(p_cdc, 0); //------------- Control Interface -------------// p_cdc->itf_num = itf_desc->bInterfaceNumber; uint8_t const * p_desc = tu_desc_next( itf_desc ); - (*p_length) = sizeof(tusb_desc_interface_t); + len = sizeof(tusb_desc_interface_t); // Communication Functional Descriptors - while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) ) + while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && len <= max_len ) { - (*p_length) += tu_desc_len(p_desc); + len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) { // notification endpoint if any - TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc) ); + TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0 ); p_cdc->ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - (*p_length) += tu_desc_len(p_desc); + len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } @@ -276,15 +278,15 @@ bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t p_desc = tu_desc_next(p_desc); // Open endpoint pair - TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &p_cdc->ep_out, &p_cdc->ep_in) ); + TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &p_cdc->ep_out, &p_cdc->ep_in), 0 ); - (*p_length) += sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); + len += sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); } // Prepare for incoming data _prep_out_transaction(cdc_id); - return true; + return len; } // Invoked when class request DATA stage is finished. diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 69542a3b3..a2523d8d0 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -229,12 +229,12 @@ static inline uint32_t tud_cdc_write_available(void) //--------------------------------------------------------------------+ // INTERNAL USBD-CLASS DRIVER API //--------------------------------------------------------------------+ -void cdcd_init (void); -void cdcd_reset (uint8_t rhport); -bool cdcd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); -bool cdcd_control_request (uint8_t rhport, tusb_control_request_t const * request); -bool cdcd_control_complete (uint8_t rhport, tusb_control_request_t const * request); -bool cdcd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +void cdcd_init (void); +void cdcd_reset (uint8_t rhport); +uint16_t cdcd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool cdcd_control_request (uint8_t rhport, tusb_control_request_t const * request); +bool cdcd_control_complete (uint8_t rhport, tusb_control_request_t const * request); +bool cdcd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); #ifdef __cplusplus } diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 70ba956aa..9955f2f05 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -154,25 +154,29 @@ void mscd_reset(uint8_t rhport) tu_memclr(&_mscd_itf, sizeof(mscd_interface_t)); } -bool mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_len) +uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { // only support SCSI's BOT protocol TU_VERIFY(TUSB_CLASS_MSC == itf_desc->bInterfaceClass && MSC_SUBCLASS_SCSI == itf_desc->bInterfaceSubClass && - MSC_PROTOCOL_BOT == itf_desc->bInterfaceProtocol); + MSC_PROTOCOL_BOT == itf_desc->bInterfaceProtocol, 0); + // Max length mus be at least 1 interface + 2 endpoints + TU_VERIFY(max_len >= sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t), 0); + + uint16_t len = 0; mscd_interface_t * p_msc = &_mscd_itf; // Open endpoint pair - TU_ASSERT( usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_msc->ep_out, &p_msc->ep_in) ); + TU_ASSERT( usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_msc->ep_out, &p_msc->ep_in), 0 ); p_msc->itf_num = itf_desc->bInterfaceNumber; - (*p_len) = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); + len = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); // Prepare for Command Block Wrapper - TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)) ); + TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)), 0 ); - return true; + return len; } // Handle class control request diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index 66180777e..30ffd02e1 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -151,12 +151,12 @@ TU_ATTR_WEAK bool tud_msc_is_writable_cb(uint8_t lun); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void mscd_init (void); -void mscd_reset (uint8_t rhport); -bool mscd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); -bool mscd_control_request (uint8_t rhport, tusb_control_request_t const * p_request); -bool mscd_control_complete (uint8_t rhport, tusb_control_request_t const * p_request); -bool mscd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void mscd_init (void); +void mscd_reset (uint8_t rhport); +uint16_t mscd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool mscd_control_request (uint8_t rhport, tusb_control_request_t const * p_request); +bool mscd_control_complete (uint8_t rhport, tusb_control_request_t const * p_request); +bool mscd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); #ifdef __cplusplus } diff --git a/src/device/usbd.c b/src/device/usbd.c index f7918c07e..971417a35 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -85,13 +85,13 @@ typedef struct char const* name; #endif - void (* init ) (void); - void (* reset ) (uint8_t rhport); - bool (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t* p_length); - bool (* control_request ) (uint8_t rhport, tusb_control_request_t const * request); - bool (* control_complete ) (uint8_t rhport, tusb_control_request_t const * request); - bool (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - void (* sof ) (uint8_t rhport); /* optional */ + void (* init ) (void); + void (* reset ) (uint8_t rhport); + uint16_t (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t max_len); + bool (* control_request ) (uint8_t rhport, tusb_control_request_t const * request); + bool (* control_complete ) (uint8_t rhport, tusb_control_request_t const * request); + bool (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); + void (* sof ) (uint8_t rhport); /* optional */ } usbd_class_driver_t; static usbd_class_driver_t const _usbd_driver[] = @@ -713,6 +713,8 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) 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; + uint8_t drv_id; uint16_t drv_len; @@ -720,13 +722,17 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) { usbd_class_driver_t const *driver = &_usbd_driver[drv_id]; - drv_len = 0; - if ( driver->open(rhport, desc_itf, &drv_len) ) + drv_len = driver->open(rhport, desc_itf, remaining_len); + + if ( drv_len > 0 ) { + // 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", _usbd_driver[drv_id].name); + TU_LOG2(" %s opened\r\n", driver->name); _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; // If IAD exist, assign all interfaces to the same driver @@ -748,8 +754,8 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) } } - // Assert if cannot find supported driver - TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT && drv_len >= sizeof(tusb_desc_interface_t) ); + // Failed if cannot find supported driver + TU_ASSERT(drv_id < USBD_CLASS_DRIVER_COUNT); mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, drv_len, drv_id); // TODO refactor -- cgit v1.3.1 From 077437b3dc2772ba87e6d43baf906d29b7539ca5 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Wed, 13 May 2020 16:45:01 +0200 Subject: Add non standard request handling in class For some reason bluetooth stack implementations send class requests to device instead of interface. To implement HCI interface over USB non device addressed requests for class need to be handled. --- src/device/usbd.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 971417a35..3cbd50644 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -507,6 +507,18 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const { //------------- Device Requests e.g in enumeration -------------// case TUSB_REQ_RCPT_DEVICE: + if ( TUSB_REQ_TYPE_CLASS == p_request->bmRequestType_bit.type ) + { + uint8_t const itf = tu_u16_low(p_request->wIndex); + TU_VERIFY(itf < TU_ARRAY_SIZE(_usbd_dev.itf2drv)); + + uint8_t const drvid = _usbd_dev.itf2drv[itf]; + TU_VERIFY(drvid < USBD_CLASS_DRIVER_COUNT); + + // forward to class driver: "non-STD request to Interface" + TU_VERIFY(invoke_class_control(rhport, drvid, p_request)); + return true; + } if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) { // Non standard request is not supported -- cgit v1.3.1 From 56d46483e48879cb8a38dc13d7327daa15165754 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Wed, 13 May 2020 17:04:10 +0200 Subject: Add bt hci device class Code implements USB transport for bluetooth HCI. --- src/class/bth/bth_device.c | 252 +++++++++++++++++++++++++++++++++++++++++++++ src/class/bth/bth_device.h | 110 ++++++++++++++++++++ src/device/usbd.c | 13 +++ src/device/usbd.h | 54 ++++++++++ src/tusb.h | 4 + src/tusb_option.h | 4 + 6 files changed, 437 insertions(+) create mode 100755 src/class/bth/bth_device.c create mode 100755 src/class/bth/bth_device.h (limited to 'src/device') diff --git a/src/class/bth/bth_device.c b/src/class/bth/bth_device.c new file mode 100755 index 000000000..04011bcdb --- /dev/null +++ b/src/class/bth/bth_device.c @@ -0,0 +1,252 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Jerzy Kasenberg + * + * 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 "tusb_option.h" + +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_BTH) + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "bth_device.h" +#include +#include + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +typedef struct +{ + uint8_t itf_num; + uint8_t ep_ev; + uint8_t ep_acl_in; + uint8_t ep_acl_out; + uint8_t ep_voice[2]; // Not used yet + uint8_t ep_voice_size[2][CFG_TUD_BTH_ISO_ALT_COUNT]; + + // Endpoint Transfer buffer + CFG_TUSB_MEM_ALIGN bt_hci_cmd_t hci_cmd; + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_BTH_DATA_EPSIZE]; + +} btd_interface_t; + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +CFG_TUSB_MEM_SECTION btd_interface_t _btd_itf; + +static bool bt_tx_data(uint8_t ep, void *data, uint16_t len) +{ + // skip if previous transfer not complete + TU_VERIFY(!usbd_edpt_busy(TUD_OPT_RHPORT, ep)); + + TU_ASSERT(usbd_edpt_xfer(TUD_OPT_RHPORT, ep, data, len)); + + return true; +} + +//--------------------------------------------------------------------+ +// READ API +//--------------------------------------------------------------------+ + + +//--------------------------------------------------------------------+ +// WRITE API +//--------------------------------------------------------------------+ + +bool tud_bt_event_send(void *event, uint16_t event_len) +{ + return bt_tx_data(_btd_itf.ep_ev, event, event_len); +} + +bool tud_bt_acl_data_send(void *event, uint16_t event_len) +{ + return bt_tx_data(_btd_itf.ep_acl_in, event, event_len); +} + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ +void btd_init(void) +{ + tu_memclr(&_btd_itf, sizeof(_btd_itf)); +} + +void btd_reset(uint8_t rhport) +{ + (void)rhport; +} + +uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_t max_len) +{ + tusb_desc_endpoint_t const *desc_ep; + uint16_t drv_len = 0; + // Size of single alternative of ISO interface + const uint16_t iso_alt_itf_size = sizeof(tusb_desc_interface_t) + 2 * sizeof(tusb_desc_endpoint_t); + // Size of hci interface + const uint16_t hci_itf_size = sizeof(tusb_desc_interface_t) + 3 * sizeof(tusb_desc_endpoint_t); + // Ensure this is BT Primary Controller + TU_VERIFY(TUSB_CLASS_WIRELESS_CONTROLLER == itf_desc->bInterfaceClass && + TUD_BT_APP_SUBCLASS == itf_desc->bInterfaceSubClass && + TUD_BT_PROTOCOL_PRIMARY_CONTROLLER == itf_desc->bInterfaceProtocol, 0); + + // Distinguish interface by number of endpoints, as both interface have same class, subclass and protocol + if (itf_desc->bNumEndpoints == 3 && max_len >= hci_itf_size) + { + _btd_itf.itf_num = itf_desc->bInterfaceNumber; + + desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); + + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0); + TU_ASSERT(dcd_edpt_open(rhport, desc_ep), 0); + _btd_itf.ep_ev = desc_ep->bEndpointAddress; + + // Open endpoint pair + TU_ASSERT(usbd_open_edpt_pair(rhport, tu_desc_next(desc_ep), 2, TUSB_XFER_BULK, &_btd_itf.ep_acl_out, + &_btd_itf.ep_acl_in), 0); + + // Prepare for incoming data from host + TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_itf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE), 0); + + drv_len = hci_itf_size; + } + else if (itf_desc->bNumEndpoints == 2 && max_len >= iso_alt_itf_size) + { + uint8_t dir; + + desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(itf_desc); + TU_ASSERT(itf_desc->bAlternateSetting < CFG_TUD_BTH_ISO_ALT_COUNT, 0); + TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT, 0); + dir = tu_edpt_dir(desc_ep->bEndpointAddress); + _btd_itf.ep_voice[dir] = desc_ep->bEndpointAddress; + // Store endpoint size for alternative + _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t)desc_ep->wMaxPacketSize.size; + + desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(desc_ep); + TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT, 0); + dir = tu_edpt_dir(desc_ep->bEndpointAddress); + _btd_itf.ep_voice[dir] = desc_ep->bEndpointAddress; + // Store endpoint size for alternative + _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t)desc_ep->wMaxPacketSize.size; + drv_len += iso_alt_itf_size; + + for (int i = 1; i < CFG_TUD_BTH_ISO_ALT_COUNT && drv_len + iso_alt_itf_size <= max_len; ++i) { + // Make sure rest of alternatives matches + itf_desc = (tusb_desc_interface_t const *)tu_desc_next(desc_ep); + if (itf_desc->bDescriptorType != TUSB_DESC_INTERFACE || + TUSB_CLASS_WIRELESS_CONTROLLER != itf_desc->bInterfaceClass || + TUD_BT_APP_SUBCLASS != itf_desc->bInterfaceSubClass || + TUD_BT_PROTOCOL_PRIMARY_CONTROLLER != itf_desc->bInterfaceProtocol) + { + // Not an Iso interface instance + break; + } + TU_ASSERT(itf_desc->bAlternateSetting < CFG_TUD_BTH_ISO_ALT_COUNT, 0); + + desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(itf_desc); + dir = tu_edpt_dir(desc_ep->bEndpointAddress); + // Verify that alternative endpoint are same as first ones + TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT && + _btd_itf.ep_voice[dir] == desc_ep->bEndpointAddress, 0); + _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t)desc_ep->wMaxPacketSize.size; + + desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(desc_ep); + dir = tu_edpt_dir(desc_ep->bEndpointAddress); + // Verify that alternative endpoint are same as first ones + TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT && + _btd_itf.ep_voice[dir] == desc_ep->bEndpointAddress, 0); + _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t)desc_ep->wMaxPacketSize.size; + drv_len += iso_alt_itf_size; + } + } + + return drv_len; +} + +bool btd_control_complete(uint8_t rhport, tusb_control_request_t const *request) +{ + (void)rhport; + + // Handle class request only + TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + + if (tud_bt_hci_cmd_cb) tud_bt_hci_cmd_cb(&_btd_itf.hci_cmd, request->wLength); + + return true; +} + +bool btd_control_request(uint8_t rhport, tusb_control_request_t const *request) +{ + (void)rhport; + + if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && + request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE) + { + // HCI command packet addressing for single function Primary Controllers + TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == 0); + } + else if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE) + { + if (request->bRequest == TUSB_REQ_SET_INTERFACE && _btd_itf.itf_num + 1 == request->wIndex) + { + // TODO: Set interface it would involve changing size of endpoint size + } + else + { + // HCI command packet for Primary Controller function in a composite device + TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == _btd_itf.itf_num); + } + } + else return false; + + return tud_control_xfer(rhport, request, &_btd_itf.hci_cmd, request->wLength); +} + +bool btd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void)result; + + // received new data from host + if (ep_addr == _btd_itf.ep_acl_out) + { + if (tud_bt_acl_data_received_cb) tud_bt_acl_data_received_cb(_btd_itf.epout_buf, xferred_bytes); + + // prepare for next data + TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_itf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE)); + } + else if (ep_addr == _btd_itf.ep_ev) + { + if (tud_bt_event_sent_cb) tud_bt_event_sent_cb((uint16_t)xferred_bytes); + } + else if (ep_addr == _btd_itf.ep_acl_in) + { + if (tud_bt_acl_data_sent_cb) tud_bt_acl_data_sent_cb((uint16_t)xferred_bytes); + } + + return TUSB_ERROR_NONE; +} + +#endif diff --git a/src/class/bth/bth_device.h b/src/class/bth/bth_device.h new file mode 100755 index 000000000..5e5468084 --- /dev/null +++ b/src/class/bth/bth_device.h @@ -0,0 +1,110 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Jerzy Kasenberg + * + * 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_BTH_DEVICE_H_ +#define _TUSB_BTH_DEVICE_H_ + +#include +#include + +//--------------------------------------------------------------------+ +// Class Driver Configuration +//--------------------------------------------------------------------+ +#ifndef CFG_TUD_BTH_EVENT_EPSIZE +#define CFG_TUD_BTH_EVENT_EPSIZE 16 +#endif +#ifndef CFG_TUD_BTH_DATA_EPSIZE +#define CFG_TUD_BTH_DATA_EPSIZE 64 +#endif + +typedef struct TU_ATTR_PACKED +{ + uint16_t op_code; + uint8_t param_length; + uint8_t param[255]; +} bt_hci_cmd_t; + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Application Callback API (weak is optional) +//--------------------------------------------------------------------+ + +// Invoked when HCI command was received over USB from Bluetooth host. +// Detailed format is described in Bluetooth core specification Vol 2, +// Part E, 5.4.1. +// Length of the command is from 3 bytes (2 bytes for OpCode, +// 1 byte for parameter total length) to 258. +TU_ATTR_WEAK void tud_bt_hci_cmd_cb(void *hci_cmd, size_t cmd_len); + +// Invoked when ACL data was received over USB from Bluetooth host. +// Detailed format is described in Bluetooth core specification Vol 2, +// Part E, 5.4.2. +// Length is from 4 bytes, (12 bits for Handle, 4 bits for flags +// and 16 bits for data total length) to endpoint size. +TU_ATTR_WEAK void tud_bt_acl_data_received_cb(void *acl_data, uint16_t data_len); + +// Called when event sent with tud_bt_event_send() was delivered to BT stack. +// Controller can release/reuse buffer with Event packet at this point. +TU_ATTR_WEAK void tud_bt_event_sent_cb(uint16_t sent_bytes); + +// Called when ACL data that was sent with tud_bt_acl_data_send() +// was delivered to BT stack. +// Controller can release/reuse buffer with ACL packet at this point. +TU_ATTR_WEAK void tud_bt_acl_data_sent_cb(uint16_t sent_bytes); + +// Bluetooth controller calls this function when it wants to send even packet +// as described in Bluetooth core specification Vol 2, Part E, 5.4.4. +// Event has at least 2 bytes, first is Event code second contains parameter +// total length. Controller can release/reuse event memory after +// tud_bt_event_sent_cb() is called. +bool tud_bt_event_send(void *event, uint16_t event_len); + +// Bluetooth controller calls this to send ACL data packet +// as described in Bluetooth core specification Vol 2, Part E, 5.4.2 +// Minimum length is 4 bytes, (12 bits for Handle, 4 bits for flags +// and 16 bits for data total length). Upper limit is not limited +// to endpoint size since buffer is allocate by controller +// and must not be reused till tud_bt_acl_data_sent_cb() is called. +bool tud_bt_acl_data_send(void *acl_data, uint16_t data_len); + +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ +void btd_init (void); +void btd_reset (uint8_t rhport); +uint16_t btd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool btd_control_request (uint8_t rhport, tusb_control_request_t const * request); +bool btd_control_complete (uint8_t rhport, tusb_control_request_t const * request); +bool btd_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_BTH_DEVICE_H_ */ diff --git a/src/device/usbd.c b/src/device/usbd.c index 3cbd50644..fe392ef6e 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -199,6 +199,19 @@ static usbd_class_driver_t const _usbd_driver[] = .sof = NULL, }, #endif + + #if CFG_TUD_BTH + { + DRIVER_NAME("BTH") + .init = btd_init, + .reset = btd_reset, + .open = btd_open, + .control_request = btd_control_request, + .control_complete = btd_control_complete, + .xfer_cb = btd_xfer_cb, + .sof = NULL + }, + #endif }; enum { USBD_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; diff --git a/src/device/usbd.h b/src/device/usbd.h index ecef63e18..2070b50c6 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -438,6 +438,60 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re /* Endpoint Out */\ 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 +//------------- BT Radio -------------// +#define TUD_BT_APP_CLASS (TUSB_CLASS_WIRELESS_CONTROLLER) +#define TUD_BT_APP_SUBCLASS 0x01 +#define TUD_BT_PROTOCOL_PRIMARY_CONTROLLER 0x01 +#define TUD_BT_PROTOCOL_AMP_CONTROLLER 0x02 + +#ifndef CFG_TUD_BTH_ISO_ALT_COUNT +#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)) + +/* 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, \ + /* 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 */ \ + 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1, \ + /* Endpoint Out for ACL data */ \ + 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1 + +#define TUD_BTH_ISO_ITF(_itfnum, _alt, _ep_in, _ep_out, _n) ,\ + /* Interface with 2 endpoints */ \ + 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 2, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \ + /* Isochronous endpoints */ \ + 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1, \ + 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1 + +#define _FIRST(a, ...) a +#define _REST(a, ...) __VA_ARGS__ + +#define TUD_BTH_ISO_ITF_0(_itfnum, ...) +#define TUD_BTH_ISO_ITF_1(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 1, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) +#define TUD_BTH_ISO_ITF_2(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 2, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ + TUD_BTH_ISO_ITF_1(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) +#define TUD_BTH_ISO_ITF_3(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 3, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ + TUD_BTH_ISO_ITF_2(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) +#define TUD_BTH_ISO_ITF_4(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 4, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ + TUD_BTH_ISO_ITF_3(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) +#define TUD_BTH_ISO_ITF_5(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 5, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ + TUD_BTH_ISO_ITF_4(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) +#define TUD_BTH_ISO_ITF_6(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 6, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ + TUD_BTH_ISO_ITF_5(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) + +#define TUD_BTH_ISO_ITFS(_itfnum, _ep_in, _ep_out, ...) \ + TU_XSTRCAT(TUD_BTH_ISO_ITF_, CFG_TUD_BTH_ISO_ALT_COUNT)(_itfnum, _ep_in, _ep_out, __VA_ARGS__) + +// 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 +#define TUD_BTH_DESCRIPTOR(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size,...) \ + 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__) #ifdef __cplusplus } diff --git a/src/tusb.h b/src/tusb.h index 55c105121..defbc54fb 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -95,6 +95,10 @@ #if CFG_TUD_NET #include "class/net/net_device.h" #endif + + #if CFG_TUD_BTH + #include "class/bth/bth_device.h" + #endif #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 9e6a2b532..0a227483f 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -219,6 +219,10 @@ #define CFG_TUD_NET 0 #endif +#ifndef CFG_TUD_BTH + #define CFG_TUD_BTH 0 +#endif + //-------------------------------------------------------------------- // HOST OPTIONS //-------------------------------------------------------------------- -- cgit v1.3.1 From d6d29897f38ebc8bc8b660d2749e472b39537b34 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 May 2020 23:16:16 +0700 Subject: add get device qualifier descriptor --- src/device/usbd.c | 24 +++++++++++++++++++++--- src/device/usbd.h | 10 ++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 971417a35..3af9491e2 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -867,9 +867,27 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const case TUSB_DESC_DEVICE_QUALIFIER: TU_LOG2(" Device Qualifier\r\n"); - // TODO If not highspeed capable stall this request otherwise - // return the descriptor that could work in highspeed - return false; + // 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); + + // first byte of descriptor is its size + return tud_control_xfer(rhport, p_request, (void*) desc_qualifier, desc_qualifier[0]); + }else + { + return false; + } + break; + + 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 break; default: return false; diff --git a/src/device/usbd.h b/src/device/usbd.h index ecef63e18..9af700886 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -68,6 +68,8 @@ static inline bool tud_ready(void) // Remote wake up host, only if suspended and enabled by host bool tud_remote_wakeup(void); +// Enable pull-up resistor on D+ D- +// Return false on unsupported MCUs static inline bool tud_disconnect(void) { TU_VERIFY(dcd_disconnect); @@ -75,6 +77,8 @@ static inline bool tud_disconnect(void) return true; } +// Disable pull-up resistor on D+ D- +// Return false on unsupported MCUs static inline bool tud_connect(void) { TU_VERIFY(dcd_connect); @@ -110,6 +114,10 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index); // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid); +// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +TU_ATTR_WEAK uint8_t const* tud_descriptor_device_qualifier_cb(void); + // Invoked when device is mounted (configured) TU_ATTR_WEAK void tud_mount_cb(void); @@ -125,6 +133,8 @@ TU_ATTR_WEAK void tud_resume_cb(void); // Invoked when received control request with VENDOR TYPE TU_ATTR_WEAK bool tud_vendor_control_request_cb(uint8_t rhport, tusb_control_request_t const * request); + +// Invoked when vendor control request is complete TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request); -- cgit v1.3.1 From f771afe6af894a5f3ee029756d4521b56d74c1c0 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 31 May 2020 23:43:29 +0700 Subject: fixed EP0 size to 64 since LS is not supported in device mode - set turn-around and report actual speed in Enum Done - add dcd_event_bus_reset() helper to report speed --- src/device/dcd.h | 15 ++++-- src/device/usbd.c | 9 +++- src/portable/st/synopsys/dcd_synopsys.c | 85 ++++++++++++++++----------------- 3 files changed, 62 insertions(+), 47 deletions(-) (limited to 'src/device') diff --git a/src/device/dcd.h b/src/device/dcd.h index 68798c259..a4635346b 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -60,11 +60,17 @@ typedef struct TU_ATTR_ALIGNED(4) uint8_t rhport; uint8_t event_id; - union { - // USBD_EVT_SETUP_RECEIVED + union + { + // BUS RESET + struct { + tusb_speed_t speed; + } bus_reset; + + // SETUP_RECEIVED tusb_control_request_t setup_received; - // USBD_EVT_XFER_COMPLETE + // XFER_COMPLETE struct { uint8_t ep_addr; uint8_t result; @@ -143,6 +149,9 @@ extern void dcd_event_handler(dcd_event_t const * event, bool in_isr); // helper to send bus signal event extern void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr); +// helper to send bus reset event +extern void dcd_event_bus_reset (uint8_t rhport, tusb_speed_t speed, bool in_isr); + // helper to send setup received extern void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr); diff --git a/src/device/usbd.c b/src/device/usbd.c index bd892e389..275792ab9 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -920,7 +920,14 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr) { - dcd_event_t event = { .rhport = rhport, .event_id = eid, }; + dcd_event_t event = { .rhport = rhport, .event_id = eid }; + dcd_event_handler(&event, in_isr); +} + +void dcd_event_bus_reset (uint8_t rhport, tusb_speed_t speed, bool in_isr) +{ + dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_BUS_RESET }; + event.bus_reset.speed = speed; dcd_event_handler(&event, in_isr); } diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index fe6fe5cea..ed16308da 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -109,6 +109,13 @@ static const dcd_rhport_t _dcd_rhport[] = #define IN_EP_BASE(_port) (USB_OTG_INEndpointTypeDef *) (_dcd_rhport[_port].regs + USB_OTG_IN_ENDPOINT_BASE) #define FIFO_BASE(_port, _x) ((volatile uint32_t *) (_dcd_rhport[_port].regs + USB_OTG_FIFO_BASE + (_x) * USB_OTG_FIFO_SIZE)) +enum +{ + DCD_HIGH_SPEED = 0, // Highspeed mode + DCD_FULL_SPEED_USE_HS = 1, // Full speed in Highspeed port (probably with internal PHY) + DCD_FULL_SPEED = 3, // Full speed with internal PHY +}; + /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM @@ -141,6 +148,7 @@ static void bus_reset(uint8_t rhport) USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); + USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); for(uint8_t n = 0; n < EP_MAX; n++) { out_ep[n].DOEPCTL |= USB_OTG_DOEPCTL_SNAK; @@ -183,34 +191,29 @@ static void bus_reset(uint8_t rhport) // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) usb_otg->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | (usb_otg->GRXFSIZ & 0x0000ffffUL); + // Fixed control EP0 size to 64 bytes + in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); + xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; + out_ep[0].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; } -static void end_of_reset(uint8_t rhport) +// speed is native DCD speed +static void set_turnaround(USB_OTG_GlobalTypeDef * usb_otg, uint32_t speed) { - USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); - USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); + usb_otg->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT; - // On current silicon on the Full Speed core, speed is fixed to Full Speed. - // However, keep for debugging and in case Low Speed is ever supported. - uint32_t enum_spd = (dev->DSTS & USB_OTG_DSTS_ENUMSPD_Msk) >> USB_OTG_DSTS_ENUMSPD_Pos; - - // TODO set turnaround in GUSBCFG accordingly to the speed - - // Maximum packet size for EP 0 is set for both directions by writing - // DIEPCTL. - if(enum_spd == 0x03) { - // 64 bytes - in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = 64; - xfer_status[0][TUSB_DIR_IN].max_size = 64; - } else { - // 8 bytes - in_ep[0].DIEPCTL |= (0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = 8; - xfer_status[0][TUSB_DIR_IN].max_size = 8; + if ( speed == DCD_HIGH_SPEED ) + { + // Use fixed 0x09 for Highspeed + usb_otg->GUSBCFG |= (0x09 << USB_OTG_GUSBCFG_TRDT_Pos); + } + else + { + // Fullspeed depends on MCU clocks, but we will use 0x06 for 32+ Mhz + usb_otg->GUSBCFG |= (0x06 << USB_OTG_GUSBCFG_TRDT_Pos); } } @@ -220,7 +223,8 @@ static void end_of_reset(uint8_t rhport) *------------------------------------------------------------------*/ void dcd_init (uint8_t rhport) { - dcd_disconnect(rhport); + // Programming model begins in the last section of the chapter on the USB + // peripheral in each Reference Manual. USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); @@ -238,16 +242,15 @@ void dcd_init (uint8_t rhport) usb_otg->GUSBCFG &= ~(USB_OTG_GUSBCFG_TSDPS | USB_OTG_GUSBCFG_ULPIFSLS | USB_OTG_GUSBCFG_PHYSEL | USB_OTG_GUSBCFG_ULPIEVBUSD | USB_OTG_GUSBCFG_ULPIEVBUSI); - // Turn around time for Highspeed is 0x09 - usb_otg->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT; - usb_otg->GUSBCFG |= (0x09 << USB_OTG_GUSBCFG_TRDT_Pos); + set_turnaround(usb_otg, DCD_HIGH_SPEED); } else #endif { - // Turn around programmed for 32+ MHz is 0x06 - usb_otg->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT; - usb_otg->GUSBCFG |= (0x06 << USB_OTG_GUSBCFG_TRDT_Pos) | USB_OTG_GUSBCFG_PHYSEL; + set_turnaround(usb_otg, DCD_FULL_SPEED); + + // Enable internal PHY + usb_otg->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL; } // Reset core after selecting PHY @@ -256,9 +259,6 @@ void dcd_init (uint8_t rhport) usb_otg->GRSTCTL |= USB_OTG_GRSTCTL_CSRST; while ((usb_otg->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST) {} - // Force device mode - usb_otg->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD; - // Restart PHY clock *((volatile uint32_t *)(_dcd_rhport[rhport].regs + USB_OTG_PCGCCTL_BASE)) = 0; @@ -273,7 +273,7 @@ void dcd_init (uint8_t rhport) USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); // If USB host misbehaves during status portion of control xfer - // (non zero-length packet), send STALL back and discard. Full speed. + // (non zero-length packet), send STALL back and discard. dev->DCFG |= USB_OTG_DCFG_NZLSOHSK; #if TUD_OPT_HIGH_SPEED @@ -288,10 +288,10 @@ void dcd_init (uint8_t rhport) else #endif { - // full speed with internal phy + // full speed with internal PHY dev->DCFG |= (3 << USB_OTG_DCFG_DSPD_Pos); - // Enable USB transceiver. + // Enable internal USB transceiver. usb_otg->GCCFG |= USB_OTG_GCCFG_PWRDWN; } @@ -299,8 +299,8 @@ void dcd_init (uint8_t rhport) USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_WUIM | USB_OTG_GINTMSK_RXFLVLM | (USE_SOF ? USB_OTG_GINTMSK_SOFM : 0); - // Programming model begins in the last section of the chapter on the USB - // peripheral in each Reference Manual. + + // Enable global interrupt usb_otg->GAHBCFG |= USB_OTG_GAHBCFG_GINT; } @@ -789,15 +789,14 @@ void dcd_int_handler(uint8_t rhport) } if(int_status & USB_OTG_GINTSTS_ENUMDNE) { - // ENUMDNE detects speed of the link. For full-speed, we - // always expect the same value. This interrupt is considered - // the end of reset. - - TU_LOG2_HEX(dev->DSTS); + // ENUMDNE is the end of reset where speed of the link is detected usb_otg->GINTSTS = USB_OTG_GINTSTS_ENUMDNE; - end_of_reset(rhport); - dcd_event_bus_signal(rhport, DCD_EVENT_BUS_RESET, true); + + uint32_t const enum_spd = (dev->DSTS & USB_OTG_DSTS_ENUMSPD_Msk) >> USB_OTG_DSTS_ENUMSPD_Pos; + + set_turnaround(usb_otg, enum_spd); + dcd_event_bus_reset(rhport, (enum_spd == DCD_HIGH_SPEED) ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL, true); } if(int_status & USB_OTG_GINTSTS_USBSUSP) -- cgit v1.3.1 From e92118635cc8055a5ca599eaf9919d99a55bf584 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 1 Jun 2020 13:40:18 +0700 Subject: adding speed detect on bus reset --- hw/bsp/stm32h743eval/board.mk | 2 +- src/device/usbd.c | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src/device') diff --git a/hw/bsp/stm32h743eval/board.mk b/hw/bsp/stm32h743eval/board.mk index 5c6c6ea4f..cbf37a95d 100644 --- a/hw/bsp/stm32h743eval/board.mk +++ b/hw/bsp/stm32h743eval/board.mk @@ -48,7 +48,7 @@ FREERTOS_PORT = ARM_CM7/r0p1 # For flash-jlink target JLINK_DEVICE = stm32h743xi -JLINK_IF = jtag +JLINK_IF = swd # flash target using on-board stlink flash: flash-stlink diff --git a/src/device/usbd.c b/src/device/usbd.c index 275792ab9..eeb5011ec 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -40,7 +40,8 @@ //--------------------------------------------------------------------+ // Device Data //--------------------------------------------------------------------+ -typedef struct { +typedef struct +{ struct TU_ATTR_PACKED { volatile uint8_t connected : 1; @@ -53,6 +54,8 @@ typedef struct { uint8_t self_powered : 1; // configuration descriptor's attribute }; + uint8_t speed; + uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) uint8_t ep2drv[8][2]; // map endpoint to driver ( 0xff is invalid ) @@ -384,7 +387,7 @@ void tud_task (void) { case DCD_EVENT_BUS_RESET: usbd_reset(event.rhport); - // TODO DCD should report operational speed (LS/FS/HS) + _usbd_dev.speed = event.bus_reset.speed; break; case DCD_EVENT_UNPLUGGED: -- cgit v1.3.1 From 48b2e6cf78a3c3a321715938e40166138ed605f5 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 13 Jun 2020 13:51:50 +0200 Subject: Fix too strict checks on subclass and interface of iad descriptor. --- src/device/usbd.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 3708a9aff..040155d41 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -765,9 +765,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) { // IAD's first interface number and class/subclass/protocol should match with opened interface TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber && - desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass && - desc_itf_assoc->bFunctionSubClass == desc_itf->bInterfaceSubClass && - desc_itf_assoc->bFunctionProtocol == desc_itf->bInterfaceProtocol); + desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass); for(uint8_t i=1; ibInterfaceCount; i++) { -- cgit v1.3.1 From 3012175351fa1f262533527c0444ce9d44917943 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 14 Jun 2020 12:57:00 +0200 Subject: Fix alignment. --- src/device/usbd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index 040155d41..f11696e78 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -764,8 +764,8 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) if (desc_itf_assoc) { // IAD's first interface number and class/subclass/protocol should match with opened interface - TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber && - desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass); + TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber && + desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass); for(uint8_t i=1; ibInterfaceCount; i++) { -- cgit v1.3.1 From b25bbf4776cb992f25faf607077f39810165eebe Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 14 Jun 2020 12:58:16 +0200 Subject: Fix alignment. --- src/device/usbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index f11696e78..e5ff52542 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -764,7 +764,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) if (desc_itf_assoc) { // IAD's first interface number and class/subclass/protocol should match with opened interface - TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber && + TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber && desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass); for(uint8_t i=1; ibInterfaceCount; i++) -- cgit v1.3.1 From 95966c22010bf01579f39847624395724298c459 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 14 Jun 2020 18:29:02 +0700 Subject: improve usbd log for control transfer --- src/device/usbd.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index eeb5011ec..c337f1be1 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -380,17 +380,21 @@ void tud_task (void) if ( !osal_queue_receive(_usbd_q, &event) ) return; - TU_LOG2("USBD %s", event.event_id < DCD_EVENT_COUNT ? _usbd_event_str[event.event_id] : "CORRUPTED"); - TU_LOG2("%s", (event.event_id != DCD_EVENT_XFER_COMPLETE && event.event_id != DCD_EVENT_SETUP_RECEIVED) ? "\r\n" : " "); +#if CFG_TUSB_DEBUG >= 2 + if (event.event_id == DCD_EVENT_SETUP_RECEIVED) TU_LOG2("\r\n"); // extra line for setup + TU_LOG2("USBD %s ", event.event_id < DCD_EVENT_COUNT ? _usbd_event_str[event.event_id] : "CORRUPTED"); +#endif switch ( event.event_id ) { case DCD_EVENT_BUS_RESET: + TU_LOG2("\r\n"); usbd_reset(event.rhport); _usbd_dev.speed = event.bus_reset.speed; break; case DCD_EVENT_UNPLUGGED: + TU_LOG2("\r\n"); usbd_reset(event.rhport); // invoke callback @@ -442,14 +446,17 @@ void tud_task (void) break; case DCD_EVENT_SUSPEND: + TU_LOG2("\r\n"); if (tud_suspend_cb) tud_suspend_cb(_usbd_dev.remote_wakeup_en); break; case DCD_EVENT_RESUME: + TU_LOG2("\r\n"); if (tud_resume_cb) tud_resume_cb(); break; case DCD_EVENT_SOF: + TU_LOG2("\r\n"); for ( uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++ ) { if ( _usbd_driver[i].sof ) @@ -460,6 +467,7 @@ void tud_task (void) break; case USBD_EVENT_FUNC_CALL: + TU_LOG2("\r\n"); if ( event.func_call.func ) event.func_call.func(event.func_call.param); break; -- cgit v1.3.1 From bc7e24b659e0d184f3405681af5f13bd4a5094aa Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 14 Jun 2020 14:22:10 +0200 Subject: Fix wrong comment for IAD checks. --- src/device/usbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index e5ff52542..29b10c0fa 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -763,7 +763,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) // If IAD exist, assign all interfaces to the same driver if (desc_itf_assoc) { - // IAD's first interface number and class/subclass/protocol should match with opened interface + // 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); -- cgit v1.3.1 From 57b553e023ccac4c623bd7f57a7370fb43411ec1 Mon Sep 17 00:00:00 2001 From: Mengsk Date: Tue, 16 Jun 2020 14:13:30 +0200 Subject: Fix IAR warnings. Pa039 : use of address of unaligned structure member. Pe188: enumerated type mixed with another type. --- src/class/hid/hid_device.c | 4 +++- src/class/msc/msc_device.c | 6 ++++-- src/device/usbd.c | 13 +++++++------ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 1 - 4 files changed, 14 insertions(+), 10 deletions(-) (limited to 'src/device') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 2a20bc173..526394d4a 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -194,7 +194,9 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1 p_hid->boot_mode = false; // default mode is REPORT p_hid->itf_num = desc_itf->bInterfaceNumber; - memcpy(&p_hid->report_desc_len, &(p_hid->hid_descriptor->wReportLength), 2); + + // Use offsetof to avoid pointer to the odd/misaligned address + memcpy(&p_hid->report_desc_len, (uint8_t*) p_hid->hid_descriptor + offsetof(tusb_hid_descriptor_hid_t, wReportLength), 2); // Prepare for output endpoint if (p_hid->ep_out) diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index b038d00f7..3ddcd4e49 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -80,7 +80,8 @@ static inline uint32_t rdwr10_get_lba(uint8_t const command[]) // copy first to prevent mis-aligned access uint32_t lba; - memcpy(&lba, &p_rdwr10->lba, 4); + // use offsetof to avoid pointer to the odd/misaligned address + memcpy(&lba, (uint8_t*) p_rdwr10 + offsetof(scsi_write10_t, lba), 4); // lba is in Big Endian format return tu_ntohl(lba); @@ -93,7 +94,8 @@ static inline uint16_t rdwr10_get_blockcount(uint8_t const command[]) // copy first to prevent mis-aligned access uint16_t block_count; - memcpy(&block_count, &p_rdwr10->block_count, 2); + // use offsetof to avoid pointer to the odd/misaligned address + memcpy(&block_count, (uint8_t*) p_rdwr10 + offsetof(scsi_write10_t, block_count), 2); return tu_ntohs(block_count); } diff --git a/src/device/usbd.c b/src/device/usbd.c index 29b10c0fa..03ef655bc 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -437,7 +437,7 @@ void tud_task (void) if ( 0 == epnum ) { - usbd_control_xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + usbd_control_xfer_cb(event.rhport, ep_addr, (xfer_result_t)event.xfer_complete.result, event.xfer_complete.len); } else { @@ -445,7 +445,7 @@ void tud_task (void) TU_ASSERT(drv_id < USBD_CLASS_DRIVER_COUNT,); TU_LOG2(" %s xfer callback\r\n", _usbd_driver[drv_id].name); - _usbd_driver[drv_id].xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + _usbd_driver[drv_id].xfer_cb(event.rhport, ep_addr, (xfer_result_t)event.xfer_complete.result, event.xfer_complete.len); } } break; @@ -846,8 +846,10 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const if (!tud_descriptor_bos_cb) return false; tusb_desc_bos_t const* desc_bos = (tusb_desc_bos_t const*) tud_descriptor_bos_cb(); + uint16_t total_len; - memcpy(&total_len, &desc_bos->wTotalLength, 2); // possibly mis-aligned memory + // Use offsetof to avoid pointer to the odd/misaligned address + memcpy(&total_len, (uint8_t*) desc_bos + offsetof(tusb_desc_bos_t, wTotalLength), 2); return tud_control_xfer(rhport, p_request, (void*) desc_bos, total_len); } @@ -861,7 +863,8 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const TU_ASSERT(desc_config); uint16_t total_len; - memcpy(&total_len, &desc_config->wTotalLength, 2); // possibly mis-aligned memory + // Use offsetof to avoid pointer to the odd/misaligned address + memcpy(&total_len, (uint8_t*) desc_config + offsetof(tusb_desc_configuration_t, wTotalLength), 2); return tud_control_xfer(rhport, p_request, (void*) desc_config, total_len); } @@ -915,8 +918,6 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const default: return false; } - - return true; } //--------------------------------------------------------------------+ diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index c5666421b..b539f4795 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -698,7 +698,6 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc default: TU_ASSERT(false); - return false; } pcd_set_eptype(USB, epnum, wType); -- cgit v1.3.1 From 706413f7510a78e262cf3cb398256e06fadbd500 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 16 Jul 2020 00:44:09 +0700 Subject: add tud_speed_get() - define both fs and hs configuration descriptor - rename CFG_TUD_CDC_EPSIZE to CFG_TUD_CDC_EP_BUFSIZE with default size of 64 for FS, and 512 for HS --- .../device/cdc_dual_ports/src/usb_descriptors.c | 48 +++++++++++++++++----- examples/device/cdc_msc/src/usb_descriptors.c | 28 +++++++++++-- .../device/webusb_serial/src/usb_descriptors.c | 6 +-- examples/rules.mk | 8 +++- src/class/cdc/cdc_device.c | 14 +++---- src/class/cdc/cdc_device.h | 4 +- src/device/usbd.c | 5 +++ src/device/usbd.h | 3 ++ tools/build_all.py | 2 +- 9 files changed, 90 insertions(+), 28 deletions(-) (limited to 'src/device') diff --git a/examples/device/cdc_dual_ports/src/usb_descriptors.c b/examples/device/cdc_dual_ports/src/usb_descriptors.c index a4674b7a9..a27a2cdbd 100644 --- a/examples/device/cdc_dual_ports/src/usb_descriptors.c +++ b/examples/device/cdc_dual_ports/src/usb_descriptors.c @@ -74,10 +74,10 @@ uint8_t const * tud_descriptor_device_cb(void) //--------------------------------------------------------------------+ enum { - ITF_NUM_CDC1 = 0, - ITF_NUM_CDC_DATA1, - ITF_NUM_CDC2, - ITF_NUM_CDC_DATA2, + ITF_NUM_CDC_0 = 0, + ITF_NUM_CDC_0_DATA, + ITF_NUM_CDC_1, + ITF_NUM_CDC_1_DATA, ITF_NUM_TOTAL }; @@ -86,30 +86,58 @@ enum #if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... - #define EPNUM_CDC 2 + #define EPNUM_CDC_0_NOTIF 0x81 + #define EPNUM_CDC_0_DATA 0x02 + + #define EPNUM_CDC_1_NOTIF 0x84 + #define EPNUM_CDC_1_DATA 0x05 #else - #define EPNUM_CDC 2 + #define EPNUM_CDC_0_NOTIF 0x81 + #define EPNUM_CDC_0_DATA 0x02 + + #define EPNUM_CDC_1_NOTIF 0x83 + #define EPNUM_CDC_1_DATA 0x04 #endif -uint8_t const desc_configuration[] = +uint8_t const desc_fs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC1, 4, 0x81, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, TUD_OPT_HIGH_SPEED ? 512 : 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_DATA, 0x80 | EPNUM_CDC_0_DATA, 64), // 2nd CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC2, 4, 0x83, 8, EPNUM_CDC + 2, 0x80 | (EPNUM_CDC + 2), TUD_OPT_HIGH_SPEED ? 512 : 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_DATA, 0x80 | EPNUM_CDC_1_DATA, 64), }; +#if TUD_OPT_HIGH_SPEED +uint8_t const desc_hs_configuration[] = +{ + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + + // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_DATA, 0x80 | EPNUM_CDC_0_DATA, 512), + + // 2nd CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_DATA, 0x80 | EPNUM_CDC_1_DATA, 512), +}; +#endif + // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { (void) index; // for multiple configurations - return desc_configuration; + +#if TUD_OPT_HIGH_SPEED + // Although we are highspeed, host may be fullspeed. + return (tud_speed_get() == TUSB_SPEED_HIGH ) ? desc_hs_configuration : desc_fs_configuration; +#else + return desc_fs_configuration; +#endif } //--------------------------------------------------------------------+ diff --git a/examples/device/cdc_msc/src/usb_descriptors.c b/examples/device/cdc_msc/src/usb_descriptors.c index 9a4d71f24..447dc2644 100644 --- a/examples/device/cdc_msc/src/usb_descriptors.c +++ b/examples/device/cdc_msc/src/usb_descriptors.c @@ -114,18 +114,32 @@ enum #endif -uint8_t const desc_configuration[] = +uint8_t const desc_fs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, TUD_OPT_HIGH_SPEED ? 512 : 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), // Interface number, string index, EP Out & EP In address, EP size - TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, TUD_OPT_HIGH_SPEED ? 512 : 64), + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 64), }; +#if TUD_OPT_HIGH_SPEED +uint8_t const desc_hs_configuration[] = +{ + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + + // Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512), + + // Interface number, string index, EP Out & EP In address, EP size + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 512), +}; +#endif + // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor @@ -133,7 +147,13 @@ uint8_t const desc_configuration[] = uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { (void) index; // for multiple configurations - return desc_configuration; + +#if TUD_OPT_HIGH_SPEED + // Although we are highspeed, host may be fullspeed. + return (tud_speed_get() == TUSB_SPEED_HIGH ) ? desc_hs_configuration : desc_fs_configuration; +#else + return desc_fs_configuration; +#endif } //--------------------------------------------------------------------+ diff --git a/examples/device/webusb_serial/src/usb_descriptors.c b/examples/device/webusb_serial/src/usb_descriptors.c index a39b34c3c..935731c0b 100644 --- a/examples/device/webusb_serial/src/usb_descriptors.c +++ b/examples/device/webusb_serial/src/usb_descriptors.c @@ -86,10 +86,10 @@ enum #if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... - #define EPNUM_CDC 2 + #define EPNUM_CDC_0 2 #define EPNUM_VENDOR 5 #else - #define EPNUM_CDC 2 + #define EPNUM_CDC_0 2 #define EPNUM_VENDOR 3 #endif @@ -99,7 +99,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, 0x81, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, TUD_OPT_HIGH_SPEED ? 512 : 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, 0x81, 8, EPNUM_CDC_0, 0x80 | EPNUM_CDC_0, TUD_OPT_HIGH_SPEED ? 512 : 64), // Interface number, string index, EP Out & IN address, EP size TUD_VENDOR_DESCRIPTOR(ITF_NUM_VENDOR, 5, EPNUM_VENDOR, 0x80 | EPNUM_VENDOR, TUD_OPT_HIGH_SPEED ? 512 : 64) diff --git a/examples/rules.mk b/examples/rules.mk index eeb548d08..dacb81363 100644 --- a/examples/rules.mk +++ b/examples/rules.mk @@ -131,8 +131,14 @@ size: $(BUILD)/$(BOARD)-firmware.elf @$(SIZE) $< -@echo '' +.PHONY: clean clean: - rm -rf $(BUILD) + $(RM) -rf $(BUILD) + +# Print out the value of a make variable. +# https://stackoverflow.com/questions/16467718/how-to-print-out-a-variable-in-makefile +print-%: + @echo $* = $($*) # Flash binary using Jlink ifeq ($(OS),Windows_NT) diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 4d6e57878..89326f71d 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -61,8 +61,8 @@ typedef struct #endif // Endpoint Transfer buffer - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_CDC_EPSIZE]; - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_CDC_EPSIZE]; + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_CDC_EP_BUFSIZE]; + CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_CDC_EP_BUFSIZE]; }cdcd_interface_t; @@ -82,9 +82,9 @@ static void _prep_out_transaction (uint8_t itf) // Prepare for incoming data but only allow what we can store in the ring buffer. uint16_t max_read = tu_fifo_remaining(&p_cdc->rx_ff); - if ( max_read >= TU_ARRAY_SIZE(p_cdc->epout_buf) ) + if ( max_read >= sizeof(p_cdc->epout_buf) ) { - usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, TU_ARRAY_SIZE(p_cdc->epout_buf)); + usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); } } @@ -148,7 +148,7 @@ uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize) #if 0 // TODO issue with circuitpython's REPL // flush if queue more than endpoint size - if ( tu_fifo_count(&_cdcd_itf[itf].tx_ff) >= CFG_TUD_CDC_EPSIZE ) + if ( tu_fifo_count(&_cdcd_itf[itf].tx_ff) >= CFG_TUD_CDC_EP_BUFSIZE ) { tud_cdc_n_write_flush(itf); } @@ -164,7 +164,7 @@ uint32_t tud_cdc_n_write_flush (uint8_t itf) // skip if previous transfer not complete yet TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_in), 0 ); - uint16_t count = tu_fifo_read_n(&_cdcd_itf[itf].tx_ff, p_cdc->epin_buf, TU_ARRAY_SIZE(p_cdc->epin_buf)); + uint16_t count = tu_fifo_read_n(&_cdcd_itf[itf].tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf)); if ( count ) { TU_VERIFY( tud_cdc_n_connected(itf), 0 ); // fifo is empty if not connected @@ -420,7 +420,7 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ { // There is no data left, a ZLP should be sent if // xferred_bytes is multiple of EP size and not zero - if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EPSIZE)) ) + if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EP_BUFSIZE)) ) { usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, NULL, 0); } diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 897fd272b..39ccf6b76 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -34,8 +34,8 @@ //--------------------------------------------------------------------+ // Class Driver Configuration //--------------------------------------------------------------------+ -#ifndef CFG_TUD_CDC_EPSIZE -#define CFG_TUD_CDC_EPSIZE 64 +#ifndef CFG_TUD_CDC_EP_BUFSIZE +#define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) #endif #ifdef __cplusplus diff --git a/src/device/usbd.c b/src/device/usbd.c index b607f5939..f59b19427 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -294,6 +294,11 @@ void usbd_driver_print_control_complete_name(bool (*control_complete) (uint8_t, //--------------------------------------------------------------------+ // Application API //--------------------------------------------------------------------+ +tusb_speed_t tud_speed_get(void) +{ + return (tusb_speed_t) _usbd_dev.speed; +} + bool tud_mounted(void) { return _usbd_dev.configured; diff --git a/src/device/usbd.h b/src/device/usbd.h index e9b82747a..d9facf719 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -53,6 +53,9 @@ bool tud_task_event_ready(void); // Interrupt handler, name alias to DCD #define tud_int_handler dcd_int_handler +// Get current bus speed +tusb_speed_t tud_speed_get(void); + // Check if device is connected and configured bool tud_mounted(void); diff --git a/tools/build_all.py b/tools/build_all.py index 25cdc9778..af57cdd5c 100644 --- a/tools/build_all.py +++ b/tools/build_all.py @@ -38,7 +38,7 @@ all_boards.sort() def build_example(example, board): subprocess.run("make -C examples/device/{} BOARD={} clean".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - return subprocess.run("make -j 4 -C examples/device/{} BOARD={} all".format(example, board), shell=True, + return subprocess.run("make -j -C examples/device/{} BOARD={} all".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) def build_size(example, board): -- cgit v1.3.1 From 5cd654838ba590ab49b637ead744cc0bae671946 Mon Sep 17 00:00:00 2001 From: Chang Feng Date: Sun, 19 Jul 2020 19:13:17 +0800 Subject: Remove 0xEE index string if statement & change TU_ASSERT to TU_VERIFY Signed-off-by: Chang Feng --- src/device/usbd.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.c b/src/device/usbd.c index b607f5939..afd46b8ce 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -886,20 +886,11 @@ 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 - if ( desc_index == 0xEE ) - { - // The 0xEE index string is a Microsoft OS Descriptors. - // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - return false; - } - else - { - uint8_t const* desc_str = (uint8_t const*) tud_descriptor_string_cb(desc_index, p_request->wIndex); - TU_ASSERT(desc_str); + uint8_t const* desc_str = (uint8_t const*) tud_descriptor_string_cb(desc_index, 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]); - } + // first byte of descriptor is its size + return tud_control_xfer(rhport, p_request, (void*) desc_str, desc_str[0]); break; case TUSB_DESC_DEVICE_QUALIFIER: -- cgit v1.3.1 From 503c15217edad86426db4792364b88b35ec04d31 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 23 Jul 2020 09:20:45 +0700 Subject: example to call tud_init() after freeRTOS kernel is started add note for usb init when using with RTOS --- examples/device/cdc_msc_freertos/src/main.c | 5 ++++- examples/device/hid_composite_freertos/src/main.c | 5 ++++- src/device/usbd.h | 2 ++ src/host/usbh.h | 3 +++ src/tusb.h | 2 ++ 5 files changed, 15 insertions(+), 2 deletions(-) (limited to 'src/device') diff --git a/examples/device/cdc_msc_freertos/src/main.c b/examples/device/cdc_msc_freertos/src/main.c index a847f4915..1371b84c3 100644 --- a/examples/device/cdc_msc_freertos/src/main.c +++ b/examples/device/cdc_msc_freertos/src/main.c @@ -83,7 +83,6 @@ void cdc_task(void* params); int main(void) { board_init(); - tusb_init(); // soft timer for blinky blinky_tm = xTimerCreateStatic(NULL, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), true, NULL, led_blinky_cb, &blinky_tmdef); @@ -116,6 +115,10 @@ void usb_device_task(void* param) { (void) param; + // This should be called after scheduler/kernel is started. + // Otherwise it could cause kernel issue since USB IRQ handler does use RTOS queue API. + tusb_init(); + // RTOS forever loop while (1) { diff --git a/examples/device/hid_composite_freertos/src/main.c b/examples/device/hid_composite_freertos/src/main.c index 8a8570d60..de065ee64 100644 --- a/examples/device/hid_composite_freertos/src/main.c +++ b/examples/device/hid_composite_freertos/src/main.c @@ -79,7 +79,6 @@ void hid_task(void* params); int main(void) { board_init(); - tusb_init(); // soft timer for blinky blinky_tm = xTimerCreateStatic(NULL, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), true, NULL, led_blinky_cb, &blinky_tmdef); @@ -112,6 +111,10 @@ void usb_device_task(void* param) { (void) param; + // This should be called after scheduler/kernel is started. + // Otherwise it could cause kernel issue since USB IRQ handler does use RTOS queue API. + tusb_init(); + // RTOS forever loop while (1) { diff --git a/src/device/usbd.h b/src/device/usbd.h index d9facf719..098e94075 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -42,6 +42,8 @@ //--------------------------------------------------------------------+ // Init device stack +// Note: when using with RTOS, this should be called after scheduler/kernel is started. +// Otherwise it could cause kernel issue since USB IRQ handler does use RTOS queue API. bool tud_init (void); // Task function should be called in main/rtos loop diff --git a/src/host/usbh.h b/src/host/usbh.h index 42a2bd095..fe39a19f4 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -91,6 +91,9 @@ TU_ATTR_WEAK void tuh_umount_cb(uint8_t dev_addr); //--------------------------------------------------------------------+ // CLASS-USBH & INTERNAL API //--------------------------------------------------------------------+ + +// Note: when using with RTOS, this should be called after scheduler/kernel is started. +// Otherwise it could cause kernel issue since USB IRQ handler does use RTOS queue API. bool usbh_init(void); bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8_t* data); diff --git a/src/tusb.h b/src/tusb.h index defbc54fb..c252a5789 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -109,6 +109,8 @@ * @{ */ // Initialize device/host stack +// Note: when using with RTOS, this should be called after scheduler/kernel is started. +// Otherwise it could cause kernel issue since USB IRQ handler does use RTOS queue API. bool tusb_init(void); // Check if stack is initialized -- cgit v1.3.1 From acde49ccc97466f603dc7face7ab70ea10d38ee3 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 1 Aug 2020 20:14:58 +0700 Subject: enable pull-up in dcd_init() instead of usbd --- docs/porting.md | 2 +- src/device/usbd.c | 1 - src/portable/dialog/da146xx/dcd_da146xx.c | 4 ++-- src/portable/espressif/esp32s2/dcd_esp32s2.c | 4 ++-- src/portable/microchip/samg/dcd_samg.c | 3 +-- src/portable/nxp/lpc17_40/dcd_lpc17_40.c | 2 ++ src/portable/nxp/transdimension/dcd_transdimension.c | 3 ++- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 4 ++-- src/portable/st/synopsys/dcd_synopsys.c | 2 ++ src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 3 +++ test/test/device/msc/test_msc_device.c | 1 - test/test/device/usbd/test_usbd.c | 1 - 12 files changed, 17 insertions(+), 13 deletions(-) (limited to 'src/device') diff --git a/docs/porting.md b/docs/porting.md index 473768450..d3c688a81 100644 --- a/docs/porting.md +++ b/docs/porting.md @@ -62,7 +62,7 @@ All of the code for the low-level device API is in `src/portable//USB_MCTRL_REG = USB_USB_MCTRL_REG_USBEN_Msk; tusb_vbus_changed((CRG_TOP->ANA_STATUS_REG & CRG_TOP_ANA_STATUS_REG_VBUS_AVAILABLE_Msk) != 0); + + dcd_connect(rhport); } void dcd_int_enable(uint8_t rhport) diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index 755e06701..58d92e728 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -165,8 +165,6 @@ static void enum_done_processing(void) *------------------------------------------------------------------*/ void dcd_init(uint8_t rhport) { - (void)rhport; - ESP_LOGV(TAG, "DCD init - Start"); // A. Disconnect @@ -204,6 +202,8 @@ void dcd_init(uint8_t rhport) USB_ENUMDONEMSK_M | USB_RESETDETMSK_M | USB_DISCONNINTMSK_M; // host most only + + dcd_connect(rhport); } void dcd_set_address(uint8_t rhport, uint8_t dev_addr) diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 4a8ed53f3..2b64df50b 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -154,9 +154,8 @@ static void bus_reset(void) // Initialize controller to device mode void dcd_init (uint8_t rhport) { - (void) rhport; - tu_memclr(_dcd_xfer, sizeof(_dcd_xfer)); + dcd_connect(rhport); } // Enable device interrupt diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index f7a59a808..39c5e6638 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c @@ -181,6 +181,8 @@ void dcd_init(uint8_t rhport) LPC_USB->UDCAH = (uint32_t) _dcd.udca; LPC_USB->DMAIntEn = (DMA_INT_END_OF_XFER_MASK /*| DMA_INT_NEW_DD_REQUEST_MASK*/ | DMA_INT_ERROR_MASK); + dcd_connect(rhport); + // Clear pending IRQ NVIC_ClearPendingIRQ(USB_IRQn); } diff --git a/src/portable/nxp/transdimension/dcd_transdimension.c b/src/portable/nxp/transdimension/dcd_transdimension.c index 46751cf5d..755e7635e 100644 --- a/src/portable/nxp/transdimension/dcd_transdimension.c +++ b/src/portable/nxp/transdimension/dcd_transdimension.c @@ -345,7 +345,8 @@ void dcd_init(uint8_t rhport) dcd_reg->USBSTS = dcd_reg->USBSTS; dcd_reg->USBINTR = INTR_USB | INTR_ERROR | INTR_PORT_CHANGE | INTR_RESET | INTR_SUSPEND /*| INTR_SOF*/; - dcd_reg->USBCMD &= ~0x00FF0000; // Interrupt Threshold Interval = 0 + dcd_reg->USBCMD &= ~0x00FF0000; // Interrupt Threshold Interval = 0 + dcd_reg->USBCMD |= USBCMD_RUN_STOP; // Connect } void dcd_int_enable(uint8_t rhport) diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index da184abe7..32179874e 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -205,7 +205,6 @@ static inline void reg16_clear_bits(__IO uint16_t *reg, uint16_t mask) { void dcd_init (uint8_t rhport) { - (void)rhport; /* Clocks should already be enabled */ /* Use __HAL_RCC_USB_CLK_ENABLE(); to enable the clocks before calling this function */ @@ -244,7 +243,8 @@ void dcd_init (uint8_t rhport) USB->CNTR |= USB_CNTR_RESETM | (USE_SOF ? USB_CNTR_SOFM : 0) | USB_CNTR_ESOFM | USB_CNTR_CTRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM; dcd_handle_bus_reset(); - // Data-line pull-up is left disconnected. + // Enable pull-up if supported + if ( dcd_connect ) dcd_connect(rhport); } // Define only on MCU with internal pull-up. BSP can define on MCU without internal PU. diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index f4430f582..a284c0384 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -453,6 +453,8 @@ void dcd_init (uint8_t rhport) // Enable global interrupt usb_otg->GAHBCFG |= USB_OTG_GAHBCFG_GINT; + + dcd_connect(rhport); } void dcd_int_enable (uint8_t rhport) diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 8672050f0..b6951efef 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -134,6 +134,9 @@ void dcd_init (uint8_t rhport) // Enable reset and wait for it before continuing. USBIE |= RSTRIE; + // Enable pullup. + USBCNF |= PUR_EN; + USBKEYPID = 0; } diff --git a/test/test/device/msc/test_msc_device.c b/test/test/device/msc/test_msc_device.c index 0382fb327..a01ef153a 100644 --- a/test/test/device/msc/test_msc_device.c +++ b/test/test/device/msc/test_msc_device.c @@ -199,7 +199,6 @@ void setUp(void) if ( !tusb_inited() ) { dcd_init_Expect(rhport); - dcd_connect_Expect(rhport); tusb_init(); } diff --git a/test/test/device/usbd/test_usbd.c b/test/test/device/usbd/test_usbd.c index 1bb32c1e5..06372b2e4 100644 --- a/test/test/device/usbd/test_usbd.c +++ b/test/test/device/usbd/test_usbd.c @@ -127,7 +127,6 @@ void setUp(void) { mscd_init_Expect(); dcd_init_Expect(rhport); - dcd_connect_Expect(rhport); tusb_init(); } } -- cgit v1.3.1 From 01b9b77d3b94ed83931d6a51c1b357f03f188e76 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 7 Aug 2020 14:47:32 +0700 Subject: allow application driver to overwrite built-in one - position application driver before built-in - remove dcd.h from public include. --- src/class/msc/msc_device.c | 1 + src/class/usbtmc/usbtmc_device.c | 1 - src/device/usbd.c | 47 +++++++++++++++++++++++----------------- src/device/usbd.h | 16 +++----------- 4 files changed, 31 insertions(+), 34 deletions(-) (limited to 'src/device') diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 9b79b68a7..f3f2e536e 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -31,6 +31,7 @@ #include "common/tusb_common.h" #include "msc_device.h" #include "device/usbd_pvt.h" +#include "device/dcd.h" // for faking dcd_event_xfer_complete //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index a3ff76079..bc5f23f42 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -80,7 +80,6 @@ #include #include "usbtmc.h" #include "usbtmc_device.h" -#include "device/dcd.h" #include "device/usbd.h" #include "osal/osal.h" diff --git a/src/device/usbd.c b/src/device/usbd.c index 7fc7189a5..6b91048b6 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -203,30 +203,30 @@ static usbd_class_driver_t const _usbd_driver[] = #endif }; -enum { USBD_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; +enum { BUILTIN_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; // Additional class drivers implemented by application static usbd_class_driver_t const * _app_driver = NULL; static uint8_t _app_driver_count = 0; -// virtually joins built-in and application drivers together -// All drivers = built-in + application +// virtually joins built-in and application drivers together. +// Application is positioned first to allow overwriting built-in ones. static inline usbd_class_driver_t const * get_driver(uint8_t drvid) { - // Built-in drivers - if (drvid < USBD_CLASS_DRIVER_COUNT) return &_usbd_driver[drvid]; - - // App drivers + // Application drivers if ( usbd_app_driver_get_cb ) { - drvid -= USBD_CLASS_DRIVER_COUNT; if ( drvid < _app_driver_count ) return &_app_driver[drvid]; + drvid -= _app_driver_count; } + // Built-in drivers + if (drvid < BUILTIN_DRIVER_COUNT) return &_usbd_driver[drvid]; + return NULL; } -#define TOTAL_DRIVER_COUNT (USBD_CLASS_DRIVER_COUNT+_app_driver_count) +#define TOTAL_DRIVER_COUNT (_app_driver_count + BUILTIN_DRIVER_COUNT) //--------------------------------------------------------------------+ // DCD Event @@ -245,6 +245,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const 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); +// from usbd_control.c void usbd_control_reset(void); void usbd_control_set_request(tusb_control_request_t const *request); void usbd_control_set_complete_callback( bool (*fp) (uint8_t, tusb_control_request_t const * ) ); @@ -252,7 +253,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, //--------------------------------------------------------------------+ -// Debugging +// Debug //--------------------------------------------------------------------+ #if CFG_TUSB_DEBUG >= 2 static char const* const _usbd_event_str[DCD_EVENT_COUNT] = @@ -327,6 +328,20 @@ bool tud_remote_wakeup(void) return true; } +bool tud_disconnect(void) +{ + TU_VERIFY(dcd_disconnect); + dcd_disconnect(TUD_OPT_RHPORT); + return true; +} + +bool tud_connect(void) +{ + TU_VERIFY(dcd_connect); + dcd_connect(TUD_OPT_RHPORT); + return true; +} + //--------------------------------------------------------------------+ // USBD Task //--------------------------------------------------------------------+ @@ -593,7 +608,6 @@ 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.configured && cfg_num ) TU_ASSERT( process_set_config(rhport, cfg_num) ); - _usbd_dev.configured = cfg_num ? 1 : 0; tud_control_status(rhport, p_request); @@ -688,18 +702,12 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const break; case TUSB_REQ_CLEAR_FEATURE: - if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) - { - usbd_edpt_clear_stall(rhport, ep_addr); - } + if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) usbd_edpt_clear_stall(rhport, ep_addr); tud_control_status(rhport, p_request); break; case TUSB_REQ_SET_FEATURE: - if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) - { - usbd_edpt_stall(rhport, ep_addr); - } + if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) usbd_edpt_stall(rhport, ep_addr); tud_control_status(rhport, p_request); break; @@ -773,7 +781,6 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) 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 ) diff --git a/src/device/usbd.h b/src/device/usbd.h index 098e94075..5338be157 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -35,7 +35,6 @@ #endif #include "common/tusb_common.h" -#include "dcd.h" //--------------------------------------------------------------------+ // Application API @@ -53,6 +52,7 @@ void tud_task (void); bool tud_task_event_ready(void); // Interrupt handler, name alias to DCD +extern void dcd_int_handler(uint8_t rhport); #define tud_int_handler dcd_int_handler // Get current bus speed @@ -75,21 +75,11 @@ bool tud_remote_wakeup(void); // Enable pull-up resistor on D+ D- // Return false on unsupported MCUs -static inline bool tud_disconnect(void) -{ - TU_VERIFY(dcd_disconnect); - dcd_disconnect(TUD_OPT_RHPORT); - return true; -} +bool tud_disconnect(void); // Disable pull-up resistor on D+ D- // Return false on unsupported MCUs -static inline bool tud_connect(void) -{ - TU_VERIFY(dcd_connect); - dcd_connect(TUD_OPT_RHPORT); - return true; -} +bool tud_connect(void); // Carry out Data and Status stage of control transfer // - If len = 0, it is equivalent to sending status only -- cgit v1.3.1 From a9d362185b5985062ce3f1a618a67938d9c9d5f7 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 7 Aug 2020 15:06:19 +0700 Subject: update note for app driver list mustbe accesible at all time. --- src/device/usbd_pvt.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src/device') diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index e430a81d9..a5d223329 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -54,6 +54,7 @@ typedef struct // Invoked when initializing device stack to get additional class drivers. // Can optionally implemented by application to extend/overwrite class driver support. +// Note: The drivers array must be accessible at all time when stack is active usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) TU_ATTR_WEAK; //--------------------------------------------------------------------+ -- cgit v1.3.1