summaryrefslogtreecommitdiff
path: root/src/device
diff options
context:
space:
mode:
authorhathach <[email protected]>2019-04-02 01:30:01 +0700
committerhathach <[email protected]>2019-04-02 01:30:01 +0700
commit491b5936d5abba5030cceea35a4aa31c470e5782 (patch)
tree2f7c050cd66a0a4c086c980cb08b2a486e602b5e /src/device
parente9851f50420ae500476faa54e8fa9eb0a2b8b4b0 (diff)
usbd better support suspend/resume
Diffstat (limited to 'src/device')
-rw-r--r--src/device/usbd.c64
-rw-r--r--src/device/usbd_control.c1
2 files changed, 35 insertions, 30 deletions
diff --git a/src/device/usbd.c b/src/device/usbd.c
index 7b87d1944..cdbd6db5b 100644
--- a/src/device/usbd.c
+++ b/src/device/usbd.c
@@ -262,18 +262,10 @@ void tud_task (void)
if ( !osal_queue_receive(_usbd_q, &event) ) return;
- // Skip event if device is not connected except BUS_RESET & UNPLUGGED & FUNC_CALL
- if ( !(_usbd_dev.connected || event.event_id == DCD_EVENT_UNPLUGGED ||
- event.event_id == DCD_EVENT_BUS_RESET || event.event_id == USBD_EVENT_FUNC_CALL) )
- {
- return;
- }
-
switch ( event.event_id )
{
case DCD_EVENT_BUS_RESET:
usbd_reset(event.rhport);
- _usbd_dev.connected = 1; // connected after bus reset
break;
case DCD_EVENT_UNPLUGGED:
@@ -284,6 +276,10 @@ void tud_task (void)
break;
case DCD_EVENT_SETUP_RECEIVED:
+ // 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
+ _usbd_dev.connected = 1;
+
// Process control request
if ( !process_control_request(event.rhport, &event.setup_received) )
{
@@ -294,27 +290,29 @@ void tud_task (void)
break;
case DCD_EVENT_XFER_COMPLETE:
- {
- // Invoke the class callback associated with the endpoint address
- uint8_t const ep_addr = event.xfer_complete.ep_addr;
-
- if ( 0 == tu_edpt_number(ep_addr) )
+ // Only handle xfer callback in ready state
+ // if (_usbd_dev.connected && !_usbd_dev.suspended)
{
- // control transfer DATA stage callback
- usbd_control_xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len);
- }
- else
- {
- uint8_t const drv_id = _usbd_dev.ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)];
- TU_ASSERT(drv_id < USBD_CLASS_DRIVER_COUNT,);
+ // Invoke the class callback associated with the endpoint address
+ uint8_t const ep_addr = event.xfer_complete.ep_addr;
- usbd_class_drivers[drv_id].xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len);
+ if ( 0 == tu_edpt_number(ep_addr) )
+ {
+ // control transfer DATA stage callback
+ usbd_control_xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len);
+ }
+ else
+ {
+ uint8_t const drv_id = _usbd_dev.ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)];
+ TU_ASSERT(drv_id < USBD_CLASS_DRIVER_COUNT,);
+
+ usbd_class_drivers[drv_id].xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len);
+ }
}
- }
break;
case DCD_EVENT_SUSPEND:
- if (tud_suspend_cb) tud_suspend_cb( _usbd_dev.remote_wakeup_en );
+ if (tud_suspend_cb) tud_suspend_cb(_usbd_dev.remote_wakeup_en);
break;
case DCD_EVENT_RESUME:
@@ -641,16 +639,22 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr)
break;
case DCD_EVENT_SUSPEND:
- // NOTE: When unplugging device, the D+/D- state are unstable and can accidentally meet the
- // SUSPEND condition ( Idle for 3ms ). Most likely when this happen both suspend and resume
- // are submitted by DCD before the actual UNPLUGGED
- _usbd_dev.suspended = 1;
- osal_queue_send(_usbd_q, event, in_isr);
+ // NOTE: When plugging/unplugging device, the D+/D- state are unstable and can accidentally meet the
+ // SUSPEND condition ( Idle for 3ms ). Some MCUs such as samd don't distinguish suspend vs disconnect as well.
+ // We will skip handling SUSPEND/RESUME event if not currently connected
+ if ( _usbd_dev.connected )
+ {
+ _usbd_dev.suspended = 1;
+ osal_queue_send(_usbd_q, event, in_isr);
+ }
break;
case DCD_EVENT_RESUME:
- _usbd_dev.suspended = 0;
- osal_queue_send(_usbd_q, event, in_isr);
+ if ( _usbd_dev.connected )
+ {
+ _usbd_dev.suspended = 0;
+ osal_queue_send(_usbd_q, event, in_isr);
+ }
break;
case DCD_EVENT_SETUP_RECEIVED:
diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c
index 24234f4d2..8460a11b0 100644
--- a/src/device/usbd_control.c
+++ b/src/device/usbd_control.c
@@ -114,6 +114,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result
if ( _control_state.request.bmRequestType_bit.direction == TUSB_DIR_OUT )
{
+ TU_VERIFY(_control_state.buffer);
memcpy(_control_state.buffer, _usbd_ctrl_buf, xferred_bytes);
}