From 1c2beba85c223bcf401f877b0c29025490fcdaa4 Mon Sep 17 00:00:00 2001
From: hathach <thach@tinyusb.org>
Date: Fri, 29 Mar 2019 16:23:00 +0700
Subject: [PATCH] working on suspend and resume

change dcd_init signature
---
 examples/device/cdc_msc_hid/src/main.c        | 12 ++++++
 src/class/cdc/cdc_device.h                    |  1 -
 src/common/tusb_types.h                       |  7 ++++
 src/device/dcd.h                              |  9 +++-
 src/device/usbd.c                             | 42 +++++++++++++------
 src/device/usbd.h                             | 11 +++--
 src/portable/microchip/samd21/dcd_samd21.c    |  4 +-
 src/portable/microchip/samd51/dcd_samd51.c    |  4 +-
 src/portable/nordic/nrf5x/dcd_nrf5x.c         |  3 +-
 .../nxp/lpc11_13_15/dcd_lpc11_13_15.c         |  4 +-
 src/portable/nxp/lpc17_40/dcd_lpc17_40.c      |  4 +-
 src/portable/nxp/lpc18_43/dcd_lpc18_43.c      |  4 +-
 src/portable/st/stm32f3/dcd_stm32f3.c         |  4 +-
 src/portable/st/stm32f4/dcd_stm32f4.c         |  4 +-
 14 files changed, 71 insertions(+), 42 deletions(-)

diff --git a/examples/device/cdc_msc_hid/src/main.c b/examples/device/cdc_msc_hid/src/main.c
index 75d9a31dc..1416852f7 100644
--- a/examples/device/cdc_msc_hid/src/main.c
+++ b/examples/device/cdc_msc_hid/src/main.c
@@ -127,6 +127,7 @@ void usb_hid_task(void)
   if ( board_millis() < start_ms + interval_ms) return; // not enough time
   start_ms += interval_ms;
 
+#if 1
   uint32_t const btn = board_buttons();
 
   /*------------- Keyboard -------------*/
@@ -160,18 +161,29 @@ void usb_hid_task(void)
     if ( btn & 0x04 ) tud_hid_mouse_move(  0   , -DELTA); // up
     if ( btn & 0x08 ) tud_hid_mouse_move(  0   ,  DELTA); // down
   }
+#endif
 }
 
 uint16_t tud_hid_generic_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen)
 {
   // TODO not Implemented
+  (void) report_id;
+  (void) report_type;
+  (void) buffer;
+  (void) reqlen;
+
   return 0;
 }
 
 void tud_hid_generic_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize)
 {
   // TODO not Implemented
+  (void) report_id;
+  (void) report_type;
+  (void) buffer;
+  (void) bufsize;
 }
+
 #endif
 
 //--------------------------------------------------------------------+
diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h
index d9a200dd4..25c721e13 100644
--- a/src/class/cdc/cdc_device.h
+++ b/src/class/cdc/cdc_device.h
@@ -38,7 +38,6 @@
 #define CFG_TUD_CDC_EPSIZE 64
 #endif
 
-
 #ifdef __cplusplus
  extern "C" {
 #endif
diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h
index d4a623aaa..5e4da8985 100644
--- a/src/common/tusb_types.h
+++ b/src/common/tusb_types.h
@@ -103,6 +103,13 @@ typedef enum
   TUSB_REQ_SYNCH_FRAME         ///< 12
 }tusb_request_code_t;
 
+typedef enum
+{
+  TUSB_REQ_FEATURE_EDPT_HALT = 0,
+  TUSB_REQ_FEATURE_REMOTE_WAKEUP = 1,
+  TUSB_REQ_FEATURE_TEST_MODE = 2
+}tusb_request_feature_selector_t;
+
 typedef enum
 {
   TUSB_REQ_TYPE_STANDARD = 0,
diff --git a/src/device/dcd.h b/src/device/dcd.h
index 9abebc2af..f47c3714a 100644
--- a/src/device/dcd.h
+++ b/src/device/dcd.h
@@ -80,7 +80,9 @@ TU_VERIFY_STATIC(sizeof(dcd_event_t) <= 12, "size is not correct");
 /*------------------------------------------------------------------*/
 /* Device API
  *------------------------------------------------------------------*/
-bool dcd_init       (uint8_t rhport);
+
+// Initialize controller to device mode
+void dcd_init       (uint8_t rhport);
 
 // Enable device interrupt
 void dcd_int_enable (uint8_t rhport);
@@ -91,9 +93,12 @@ void dcd_int_disable(uint8_t rhport);
 // Receive Set Address request, mcu port must also include status IN response
 void dcd_set_address(uint8_t rhport, uint8_t dev_addr);
 
-// Receive Set Config request
+// Receive Set Configure request
 void dcd_set_config (uint8_t rhport, uint8_t config_num);
 
+// Wake up host
+void dcd_remote_wakeup(uint8_t rhport);
+
 /*------------------------------------------------------------------*/
 /* Endpoint API
  *  - open        : Configure endpoint's registers
diff --git a/src/device/usbd.c b/src/device/usbd.c
index 933e0f846..5127cfaab 100644
--- a/src/device/usbd.c
+++ b/src/device/usbd.c
@@ -40,12 +40,13 @@
 // Device Data
 //--------------------------------------------------------------------+
 typedef struct {
-  volatile uint8_t config_num; // 0 is non-configure ~ disconnect
+  volatile uint8_t config_num; // 0 is non-configured ~ disconnect
+  bool remote_wakeup_en;
 
   uint8_t itf2drv[16];      // map interface number to driver (0xff is invalid)
   uint8_t ep2drv[8][2];     // map endpoint to driver ( 0xff is invalid )
 
-  uint8_t ep_busy_mask[2];  // bit mask for busy endpoint
+//  uint8_t ep_busy_mask[2];  // bit mask for busy endpoint
   uint8_t ep_stall_mask[2]; // bit mask for stalled endpoint
 }usbd_device_t;
 
@@ -186,7 +187,7 @@ bool usbd_init (void)
   for (uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++) usbd_class_drivers[i].init();
 
   // Init device controller driver
-  TU_ASSERT(dcd_init(TUD_OPT_RHPORT));
+  dcd_init(TUD_OPT_RHPORT);
   dcd_int_enable(TUD_OPT_RHPORT);
 
   return true;
@@ -352,6 +353,20 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
         if ( data_buf == NULL || data_len == 0 ) return false;
       break;
 
+      case TUSB_REQ_SET_FEATURE:
+        if ( TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue )
+        {
+          // Host enable remote wake up before suspending especially HID device
+        }
+      break;
+
+      case TUSB_REQ_CLEAR_FEATURE:
+        if ( TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue )
+        {
+          // Host disable remote wake up after resuming
+        }
+      break;
+
       default:
         TU_BREAKPOINT();
       return false;
@@ -386,15 +401,19 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
       break;
 
       case TUSB_REQ_CLEAR_FEATURE:
-        // only endpoint feature is halted/stalled
-        dcd_edpt_clear_stall(rhport, tu_u16_low(p_request->wIndex));
-        usbd_control_status(rhport, p_request);
+        if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue )
+        {
+          dcd_edpt_clear_stall(rhport, tu_u16_low(p_request->wIndex));
+          usbd_control_status(rhport, p_request);
+        }
       break;
 
       case TUSB_REQ_SET_FEATURE:
-        // only endpoint feature is halted/stalled
-        usbd_edpt_stall(rhport, tu_u16_low(p_request->wIndex));
-        usbd_control_status(rhport, p_request);
+        if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue )
+        {
+          usbd_edpt_stall(rhport, tu_u16_low(p_request->wIndex));
+          usbd_control_status(rhport, p_request);
+        }
       break;
 
       default:
@@ -556,11 +575,8 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr)
     break;
 
     case DCD_EVENT_SUSPEND:
-      // TODO support suspended
-    break;
-
     case DCD_EVENT_RESUME:
-      // TODO support resume
+      osal_queue_send(_usbd_q, event, in_isr);
     break;
 
     case DCD_EVENT_SETUP_RECEIVED:
diff --git a/src/device/usbd.h b/src/device/usbd.h
index 614b4f311..6bf7eca02 100644
--- a/src/device/usbd.h
+++ b/src/device/usbd.h
@@ -60,7 +60,6 @@ typedef struct {
 
 }tud_desc_set_t;
 
-
 // Must be defined by application
 extern tud_desc_set_t tud_desc_set;
 
@@ -70,6 +69,8 @@ extern tud_desc_set_t tud_desc_set;
 bool tud_mounted(void);
 void tud_task (void);
 
+bool tud_remote_wakeup(void);
+
 //--------------------------------------------------------------------+
 // APPLICATION CALLBACK (WEAK is optional)
 //--------------------------------------------------------------------+
@@ -77,10 +78,14 @@ void tud_task (void);
 // Callback invoked when device is mounted (configured)
 ATTR_WEAK void tud_mount_cb(void);
 
-// Callback invoked when device is unmounted (bus reset/unplugged)
+// Callback invoked when device is unmounted
 ATTR_WEAK void tud_umount_cb(void);
 
-//void tud_device_suspended_cb(void);
+// Callback invoked when device is suspended
+ATTR_WEAK void tud_suspend_cb(bool remote_wakeup_en);
+
+// Callback invoked when device is resumed
+ATTR_WEAK void tud_resume_cb(void);
 
 #ifdef __cplusplus
  }
diff --git a/src/portable/microchip/samd21/dcd_samd21.c b/src/portable/microchip/samd21/dcd_samd21.c
index 723bd6c3a..a340c888d 100644
--- a/src/portable/microchip/samd21/dcd_samd21.c
+++ b/src/portable/microchip/samd21/dcd_samd21.c
@@ -57,7 +57,7 @@ static void bus_reset(void) {
 /*------------------------------------------------------------------*/
 /* Controller API
  *------------------------------------------------------------------*/
-bool dcd_init (uint8_t rhport)
+void dcd_init (uint8_t rhport)
 {
   (void) rhport;
 
@@ -80,8 +80,6 @@ bool dcd_init (uint8_t rhport)
   while (USB->DEVICE.SYNCBUSY.bit.ENABLE == 1) {}
 
   USB->DEVICE.INTENSET.reg = USB_DEVICE_INTENSET_SOF | USB_DEVICE_INTENSET_EORST;
-
-  return true;
 }
 
 void dcd_int_enable(uint8_t rhport)
diff --git a/src/portable/microchip/samd51/dcd_samd51.c b/src/portable/microchip/samd51/dcd_samd51.c
index 9869956c7..13250c38c 100644
--- a/src/portable/microchip/samd51/dcd_samd51.c
+++ b/src/portable/microchip/samd51/dcd_samd51.c
@@ -57,7 +57,7 @@ static void bus_reset(void) {
 /*------------------------------------------------------------------*/
 /* Controller API
  *------------------------------------------------------------------*/
-bool dcd_init (uint8_t rhport)
+void dcd_init (uint8_t rhport)
 {
   (void) rhport;
 
@@ -79,8 +79,6 @@ bool dcd_init (uint8_t rhport)
   USB->DEVICE.CTRLA.reg = USB_CTRLA_MODE_DEVICE | USB_CTRLA_ENABLE | USB_CTRLA_RUNSTDBY;
   while (USB->DEVICE.SYNCBUSY.bit.ENABLE == 1) {}
   USB->DEVICE.INTENSET.reg = USB_DEVICE_INTENSET_SOF | USB_DEVICE_INTENSET_EORST;
-
-  return true;
 }
 
 void dcd_int_enable(uint8_t rhport)
diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c
index 928ef6713..edaef7cca 100644
--- a/src/portable/nordic/nrf5x/dcd_nrf5x.c
+++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c
@@ -177,10 +177,9 @@ static void xact_in_prepare(uint8_t epnum)
 //--------------------------------------------------------------------+
 // Controller API
 //--------------------------------------------------------------------+
-bool dcd_init (uint8_t rhport)
+void dcd_init (uint8_t rhport)
 {
   (void) rhport;
-  return true;
 }
 
 void dcd_int_enable(uint8_t rhport)
diff --git a/src/portable/nxp/lpc11_13_15/dcd_lpc11_13_15.c b/src/portable/nxp/lpc11_13_15/dcd_lpc11_13_15.c
index 0b0c10bc3..f01bed1c9 100644
--- a/src/portable/nxp/lpc11_13_15/dcd_lpc11_13_15.c
+++ b/src/portable/nxp/lpc11_13_15/dcd_lpc11_13_15.c
@@ -153,7 +153,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
   LPC_USB->DEVCMDSTAT |= dev_addr;
 }
 
-bool dcd_init(uint8_t rhport)
+void dcd_init(uint8_t rhport)
 {
   (void) rhport;
 
@@ -166,8 +166,6 @@ bool dcd_init(uint8_t rhport)
                           CMDSTAT_RESET_CHANGE_MASK | CMDSTAT_CONNECT_CHANGE_MASK | CMDSTAT_SUSPEND_CHANGE_MASK;
 
   NVIC_EnableIRQ(USB0_IRQn);
-
-  return true;
 }
 
 //--------------------------------------------------------------------+
diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c
index ea95918ae..5da18d52b 100644
--- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c
+++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c
@@ -166,7 +166,7 @@ static void bus_reset(void)
   tu_memclr(&_dcd, sizeof(dcd_data_t));
 }
 
-bool dcd_init(uint8_t rhport)
+void dcd_init(uint8_t rhport)
 {
   (void) rhport;
 
@@ -186,8 +186,6 @@ bool dcd_init(uint8_t rhport)
   // USB IRQ priority should be set by application previously
   NVIC_ClearPendingIRQ(USB_IRQn);
   NVIC_EnableIRQ(USB_IRQn);
-
-  return true;
 }
 
 void dcd_int_enable(uint8_t rhport)
diff --git a/src/portable/nxp/lpc18_43/dcd_lpc18_43.c b/src/portable/nxp/lpc18_43/dcd_lpc18_43.c
index 9be1af679..b272a143e 100644
--- a/src/portable/nxp/lpc18_43/dcd_lpc18_43.c
+++ b/src/portable/nxp/lpc18_43/dcd_lpc18_43.c
@@ -121,7 +121,7 @@ static void bus_reset(uint8_t rhport)
 	p_dcd->qhd[0].int_on_setup = 1; // OUT only
 }
 
-bool dcd_init(uint8_t rhport)
+void dcd_init(uint8_t rhport)
 {
   LPC_USBHS_T* const lpc_usb = LPC_USB[rhport];
   dcd_data_t* p_dcd = dcd_data_ptr[rhport];
@@ -134,8 +134,6 @@ bool dcd_init(uint8_t rhport)
 
   lpc_usb->USBCMD_D &= ~0x00FF0000; // Interrupt Threshold Interval = 0
   lpc_usb->USBCMD_D |= TU_BIT(0); // connect
-
-  return true;
 }
 
 void dcd_int_enable(uint8_t rhport)
diff --git a/src/portable/st/stm32f3/dcd_stm32f3.c b/src/portable/st/stm32f3/dcd_stm32f3.c
index 138c454a7..41f82891b 100644
--- a/src/portable/st/stm32f3/dcd_stm32f3.c
+++ b/src/portable/st/stm32f3/dcd_stm32f3.c
@@ -35,10 +35,8 @@
 // MACRO TYPEDEF CONSTANT ENUM DECLARATION
 //--------------------------------------------------------------------+
 
-
-bool dcd_init (uint8_t rhport)
+void dcd_init (uint8_t rhport)
 {
-  return true;
 }
 
 // Enable device interrupt
diff --git a/src/portable/st/stm32f4/dcd_stm32f4.c b/src/portable/st/stm32f4/dcd_stm32f4.c
index db72f92d3..f0d6e7d58 100644
--- a/src/portable/st/stm32f4/dcd_stm32f4.c
+++ b/src/portable/st/stm32f4/dcd_stm32f4.c
@@ -128,7 +128,7 @@ static void end_of_reset(void) {
 /*------------------------------------------------------------------*/
 /* Controller API
  *------------------------------------------------------------------*/
-bool dcd_init (uint8_t rhport)
+void dcd_init (uint8_t rhport)
 {
   (void) rhport;
 
@@ -161,8 +161,6 @@ bool dcd_init (uint8_t rhport)
 
   // Enable pullup, enable peripheral.
   USB_OTG_FS->GCCFG |= USB_OTG_GCCFG_VBUSBSEN | USB_OTG_GCCFG_PWRDWN;
-
-  return true;
 }
 
 void dcd_int_enable (uint8_t rhport)