summaryrefslogtreecommitdiff
path: root/src/device
diff options
context:
space:
mode:
authorHa Thach <[email protected]>2021-08-30 17:31:50 +0700
committerGitHub <[email protected]>2021-08-30 17:31:50 +0700
commit38f5aee9c31299874dcda1758cb98e4404c6ad9d (patch)
tree3d29d52b6305d32e4c7960ad358a3cfe289b5ec8 /src/device
parent36dc25a22d05cf9826944e363dd9ca4eb3416661 (diff)
parentfdf1ff545f41c23f63e86d6debaa852e731d7644 (diff)
Merge pull request #1058 from hathach/usbcv-compliant-test
nrf5x USB Compliance Verification Test suite
Diffstat (limited to 'src/device')
-rw-r--r--src/device/dcd.h5
-rw-r--r--src/device/usbd.c81
2 files changed, 61 insertions, 25 deletions
diff --git a/src/device/dcd.h b/src/device/dcd.h
index 66767c1fe..8d042bbde 100644
--- a/src/device/dcd.h
+++ b/src/device/dcd.h
@@ -137,6 +137,11 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re
// Configure endpoint's registers according to descriptor
bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_ep);
+// Close all non-control endpoints, cancel all pending transfers if any.
+// Invoked when switching from a non-zero Configuration by SET_CONFIGURE therefore
+// required for multiple configuration support.
+void dcd_edpt_close_all (uint8_t rhport);
+
// Close an endpoint.
// Since it is weak, caller must TU_ASSERT this function's existence before calling it.
void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK;
diff --git a/src/device/usbd.c b/src/device/usbd.c
index e12dafcfd..7cd8fad42 100644
--- a/src/device/usbd.c
+++ b/src/device/usbd.c
@@ -38,7 +38,7 @@
//--------------------------------------------------------------------+
// Debug level of USBD
-#define USBD_DBG_LVL 2
+#define USBD_DBG 2
#ifndef CFG_TUD_TASK_QUEUE_SZ
#define CFG_TUD_TASK_QUEUE_SZ 16
@@ -432,19 +432,22 @@ bool tud_init (uint8_t rhport)
return true;
}
-static void usbd_reset(uint8_t rhport)
+static void configuration_reset(uint8_t rhport)
{
- tu_varclr(&_usbd_dev);
+ for ( uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++ )
+ {
+ get_driver(i)->reset(rhport);
+ }
+ tu_varclr(&_usbd_dev);
memset(_usbd_dev.itf2drv, DRVID_INVALID, sizeof(_usbd_dev.itf2drv)); // invalid mapping
memset(_usbd_dev.ep2drv , DRVID_INVALID, sizeof(_usbd_dev.ep2drv )); // invalid mapping
+}
+static void usbd_reset(uint8_t rhport)
+{
+ configuration_reset(rhport);
usbd_control_reset();
-
- for ( uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++ )
- {
- get_driver(i)->reset(rhport);
- }
}
bool tud_task_event_ready(void)
@@ -686,9 +689,29 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
{
uint8_t const cfg_num = (uint8_t) p_request->wValue;
- if ( !_usbd_dev.cfg_num && cfg_num ) TU_ASSERT( process_set_config(rhport, cfg_num) );
- _usbd_dev.cfg_num = cfg_num;
+ // Only process if new configure is different
+ if (_usbd_dev.cfg_num != cfg_num)
+ {
+ if ( _usbd_dev.cfg_num )
+ {
+ // already configured: need to clear all endpoints and driver first
+ TU_LOG(USBD_DBG, " Clear current Configuration (%u) before switching\r\n", _usbd_dev.cfg_num);
+ // close all non-control endpoints, cancel all pending transfers if any
+ dcd_edpt_close_all(rhport);
+
+ // close all drivers and current configured state except bus speed
+ uint8_t const speed = _usbd_dev.speed;
+ configuration_reset(rhport);
+
+ _usbd_dev.speed = speed; // restore speed
+ }
+
+ // switch to new configuration if not zero
+ if ( cfg_num ) TU_ASSERT( process_set_config(rhport, cfg_num) );
+ }
+
+ _usbd_dev.cfg_num = cfg_num;
tud_control_status(rhport, p_request);
}
break;
@@ -701,7 +724,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
// Only support remote wakeup for device feature
TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue);
- TU_LOG(USBD_DBG_LVL, " Enable Remote Wakeup\r\n");
+ TU_LOG(USBD_DBG, " Enable Remote Wakeup\r\n");
// Host may enable remote wake up before suspending especially HID device
_usbd_dev.remote_wakeup_en = true;
@@ -712,7 +735,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
// Only support remote wakeup for device feature
TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue);
- TU_LOG(USBD_DBG_LVL, " Disable Remote Wakeup\r\n");
+ TU_LOG(USBD_DBG, " Disable Remote Wakeup\r\n");
// Host may disable remote wake up after resuming
_usbd_dev.remote_wakeup_en = false;
@@ -751,16 +774,24 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
// driver doesn't use alternate settings or implement this
TU_VERIFY(TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type);
- if (TUSB_REQ_GET_INTERFACE == p_request->bRequest)
+ switch(p_request->bRequest)
{
- uint8_t alternate = 0;
- tud_control_xfer(rhport, p_request, &alternate, 1);
- }else if (TUSB_REQ_SET_INTERFACE == p_request->bRequest)
- {
- tud_control_status(rhport, p_request);
- } else
- {
- return false;
+ case TUSB_REQ_GET_INTERFACE:
+ case TUSB_REQ_SET_INTERFACE:
+ // Clear complete callback if driver set since it can also stall the request.
+ usbd_control_set_complete_callback(NULL);
+
+ if (TUSB_REQ_GET_INTERFACE == p_request->bRequest)
+ {
+ uint8_t alternate = 0;
+ tud_control_xfer(rhport, p_request, &alternate, 1);
+ }else
+ {
+ tud_control_status(rhport, p_request);
+ }
+ break;
+
+ default: return false;
}
}
}
@@ -843,7 +874,8 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
// This function parse configuration descriptor & open drivers accordingly
static bool process_set_config(uint8_t rhport, uint8_t cfg_num)
{
- tusb_desc_configuration_t const * desc_cfg = (tusb_desc_configuration_t const *) tud_descriptor_configuration_cb(cfg_num-1); // index is cfg_num-1
+ // index is cfg_num-1
+ tusb_desc_configuration_t const * desc_cfg = (tusb_desc_configuration_t const *) tud_descriptor_configuration_cb(cfg_num-1);
TU_ASSERT(desc_cfg != NULL && desc_cfg->bDescriptorType == TUSB_DESC_CONFIGURATION);
// Parse configuration descriptor
@@ -1301,7 +1333,7 @@ bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr)
void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
{
- TU_LOG(USBD_DBG_LVL, " Stall EP %02X", ep_addr);
+ TU_LOG(USBD_DBG, " Stall EP %02X\r\n", ep_addr);
uint8_t const epnum = tu_edpt_number(ep_addr);
uint8_t const dir = tu_edpt_dir(ep_addr);
@@ -1313,12 +1345,11 @@ void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
{
- TU_LOG(USBD_DBG_LVL, " Clear Stall EP %02X", ep_addr);
+ TU_LOG(USBD_DBG, " Clear Stall EP %02X\r\n", ep_addr);
uint8_t const epnum = tu_edpt_number(ep_addr);
uint8_t const dir = tu_edpt_dir(ep_addr);
-
dcd_edpt_clear_stall(rhport, ep_addr);
_usbd_dev.ep_status[epnum][dir].stalled = false;
_usbd_dev.ep_status[epnum][dir].busy = false;