diff options
| author | Ha Thach <[email protected]> | 2019-12-24 21:11:40 +0700 |
|---|---|---|
| committer | GitHub <[email protected]> | 2019-12-24 21:11:40 +0700 |
| commit | 21cc8237e1130c489bc4ef3b7dea1c41eef25d56 (patch) | |
| tree | de9ef9a7d0bff897e84ec46853f21170900d250e /src/device | |
| parent | a601f59df5e61801cbbe87467c70a48b740d4bfd (diff) | |
| parent | bbada1d3e6dba5b339c7cd4129e5df7b3203c11b (diff) | |
Merge pull request #243 from hathach/port-samg55
merge WIP branch for samd dcd fix
Diffstat (limited to 'src/device')
| -rw-r--r-- | src/device/dcd.h | 4 | ||||
| -rw-r--r-- | src/device/usbd.c | 50 | ||||
| -rw-r--r-- | src/device/usbd_control.c | 14 |
3 files changed, 35 insertions, 33 deletions
diff --git a/src/device/dcd.h b/src/device/dcd.h index dca289e78..8ae232fa6 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -110,6 +110,10 @@ void dcd_remote_wakeup(uint8_t rhport); // Endpoint API
//--------------------------------------------------------------------+
+// Invoked when a control transfer's status stage is complete.
+// May help DCD to prepare for next control transfer, this API is optional.
+void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) TU_ATTR_WEAK;
+
// Configure endpoint's registers according to descriptor
bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc);
diff --git a/src/device/usbd.c b/src/device/usbd.c index 1797dfafa..949e14096 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -202,15 +202,16 @@ 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);
-void usbd_control_reset (uint8_t rhport);
-bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
+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 * ) );
+bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
//--------------------------------------------------------------------+
// Debugging
//--------------------------------------------------------------------+
-#if CFG_TUSB_DEBUG > 1
+#if CFG_TUSB_DEBUG >= 2
static char const* const _usbd_event_str[DCD_EVENT_COUNT] =
{
"INVALID" ,
@@ -321,7 +322,7 @@ static void usbd_reset(uint8_t rhport) memset(_usbd_dev.itf2drv, DRVID_INVALID, sizeof(_usbd_dev.itf2drv)); // invalid mapping
memset(_usbd_dev.ep2drv , DRVID_INVALID, sizeof(_usbd_dev.ep2drv )); // invalid mapping
- usbd_control_reset(rhport);
+ usbd_control_reset();
for (uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++)
{
@@ -375,8 +376,7 @@ void tud_task (void) break;
case DCD_EVENT_SETUP_RECEIVED:
- TU_LOG2(" ");
- TU_LOG1_MEM(&event.setup_received, 1, 8);
+ TU_LOG2_MEM(&event.setup_received, 8, 2);
// Mark as connected after receiving 1st setup packet.
// But it is easier to set it every time instead of wasting time to check then set
@@ -385,7 +385,7 @@ void tud_task (void) // Process control request
if ( !process_control_request(event.rhport, &event.setup_received) )
{
- TU_LOG1(" Stall EP0\r\n");
+ TU_LOG2(" Stall EP0\r\n");
// Failed -> stall both control endpoint IN and OUT
dcd_edpt_stall(event.rhport, 0);
dcd_edpt_stall(event.rhport, 0 | TUSB_DIR_IN_MASK);
@@ -405,7 +405,6 @@ void tud_task (void) if ( 0 == epnum )
{
- TU_LOG1(" EP Addr = 0x%02X, len = %ld\r\n", ep_addr, event.xfer_complete.len);
usbd_control_xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len);
}
else
@@ -500,10 +499,12 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const switch ( p_request->bRequest )
{
case TUSB_REQ_SET_ADDRESS:
- // Depending on mcu, status phase could be sent either before or after changing device address
- // Therefore DCD must include zero-length status response
+ // Depending on mcu, status phase could be sent either before or after changing device address,
+ // or even require stack to not response with status at all
+ // Therefore DCD must take full responsibility to response and include zlp status packet if needed.
+ usbd_control_set_request(p_request); // set request since DCD has no access to tud_control_status() API
dcd_set_address(rhport, (uint8_t) p_request->wValue);
- return true; // skip status
+ // skip tud_control_status()
break;
case TUSB_REQ_GET_CONFIGURATION:
@@ -830,19 +831,15 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) {
switch (event->event_id)
{
- case DCD_EVENT_BUS_RESET:
- osal_queue_send(_usbd_q, event, in_isr);
- break;
-
case DCD_EVENT_UNPLUGGED:
- _usbd_dev.connected = 0;
+ _usbd_dev.connected = 0;
_usbd_dev.configured = 0;
- _usbd_dev.suspended = 0;
+ _usbd_dev.suspended = 0;
osal_queue_send(_usbd_q, event, in_isr);
break;
case DCD_EVENT_SOF:
- // nothing to do now
+ return; // skip SOF event for now
break;
case DCD_EVENT_SUSPEND:
@@ -857,6 +854,7 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) break;
case DCD_EVENT_RESUME:
+ // skip event if not connected (especially required for SAMD)
if ( _usbd_dev.connected )
{
_usbd_dev.suspended = 0;
@@ -864,21 +862,9 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) }
break;
- case DCD_EVENT_SETUP_RECEIVED:
- osal_queue_send(_usbd_q, event, in_isr);
- break;
-
- case DCD_EVENT_XFER_COMPLETE:
+ default:
osal_queue_send(_usbd_q, event, in_isr);
- TU_ASSERT(event->xfer_complete.result == XFER_RESULT_SUCCESS,);
break;
-
- // Not an DCD event, just a convenient way to defer ISR function should we need to
- case USBD_EVENT_FUNC_CALL:
- osal_queue_send(_usbd_q, event, in_isr);
- break;
-
- default: break;
}
}
@@ -962,6 +948,8 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t TU_VERIFY( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes) );
_usbd_dev.ep_status[epnum][dir].busy = true;
+ TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\r\n", ep_addr, total_bytes);
+
return true;
}
diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 7f6cf5a40..e6d1caf4b 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -64,6 +64,7 @@ static inline bool _status_stage_xact(uint8_t rhport, tusb_control_request_t con return dcd_edpt_xfer(rhport, request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN, NULL, 0); } +// Status phase bool tud_control_status(uint8_t rhport, tusb_control_request_t const * request) { _ctrl_xfer.request = (*request); @@ -118,9 +119,8 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo // USBD API //--------------------------------------------------------------------+ -void usbd_control_reset (uint8_t rhport) +void usbd_control_reset(void) { - (void) rhport; tu_varclr(&_ctrl_xfer); } @@ -130,6 +130,15 @@ void usbd_control_set_complete_callback( bool (*fp) (uint8_t, tusb_control_reque _ctrl_xfer.complete_cb = fp; } +// useful for dcd_set_address where DCD is responsible for status response +void usbd_control_set_request(tusb_control_request_t const *request) +{ + _ctrl_xfer.request = (*request); + _ctrl_xfer.buffer = NULL; + _ctrl_xfer.total_xferred = 0; + _ctrl_xfer.data_len = 0; +} + // callback when a transaction complete on // - DATA stage of control endpoint or // - Status stage @@ -141,6 +150,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result if ( tu_edpt_dir(ep_addr) != _ctrl_xfer.request.bmRequestType_bit.direction ) { TU_ASSERT(0 == xferred_bytes); + if (dcd_edpt0_status_complete) dcd_edpt0_status_complete(rhport, &_ctrl_xfer.request); return true; } |
