Explorar el Código

feat(port): add remote wakeup api

sakumisu hace 1 año
padre
commit
bef45dc360

+ 7 - 2
common/usb_dc.h

@@ -33,6 +33,13 @@ int usb_dc_deinit(uint8_t busid);
  */
 int usbd_set_address(uint8_t busid, const uint8_t addr);
 
+/**
+ * @brief Set remote wakeup feature
+ *
+ * @return On success will return 0, and others indicate fail.
+ */
+int usbd_set_remote_wakeup(uint8_t busid);
+
 /**
  * @brief Get USB device speed
  *
@@ -187,8 +194,6 @@ void usbd_event_ep_out_complete_handler(uint8_t busid, uint8_t ep, uint32_t nbyt
 void usbd_execute_test_mode(uint8_t busid, uint8_t test_mode);
 #endif
 
-void usbd_send_remote_wakeup(uint8_t busid);
-
 #ifdef __cplusplus
 }
 #endif

+ 28 - 1
core/usbd_core.c

@@ -52,9 +52,11 @@ USB_NOCACHE_RAM_SECTION struct usbd_core_priv {
 
     /** Currently selected configuration */
     uint8_t configuration;
+    uint8_t device_address;
     bool self_powered;
     bool remote_wakeup_support;
     bool remote_wakeup_enabled;
+    bool is_suspend;
 #ifdef CONFIG_USBDEV_ADVANCE_DESC
     uint8_t speed;
 #endif
@@ -561,6 +563,7 @@ static bool usbd_std_device_req_handler(uint8_t busid, struct usb_setup_packet *
             break;
 
         case USB_REQUEST_SET_ADDRESS:
+            g_usbd_core[busid].device_address = value;
             usbd_set_address(busid, value);
             *len = 0;
             break;
@@ -587,6 +590,7 @@ static bool usbd_std_device_req_handler(uint8_t busid, struct usb_setup_packet *
                 ret = false;
             } else {
                 g_usbd_core[busid].configuration = value;
+                g_usbd_core[busid].is_suspend = false;
                 usbd_class_event_notify_handler(busid, USBD_EVENT_CONFIGURED, NULL);
                 g_usbd_core[busid].event_handler(busid, USBD_EVENT_CONFIGURED);
             }
@@ -1071,17 +1075,22 @@ void usbd_event_disconnect_handler(uint8_t busid)
 
 void usbd_event_resume_handler(uint8_t busid)
 {
+    g_usbd_core[busid].is_suspend = false;
     g_usbd_core[busid].event_handler(busid, USBD_EVENT_RESUME);
 }
 
 void usbd_event_suspend_handler(uint8_t busid)
 {
-    g_usbd_core[busid].event_handler(busid, USBD_EVENT_SUSPEND);
+    if (g_usbd_core[busid].device_address > 0) {
+        g_usbd_core[busid].is_suspend = true;
+        g_usbd_core[busid].event_handler(busid, USBD_EVENT_SUSPEND);
+    }
 }
 
 void usbd_event_reset_handler(uint8_t busid)
 {
     usbd_set_address(busid, 0);
+    g_usbd_core[busid].device_address = 0;
     g_usbd_core[busid].configuration = 0;
 #ifdef CONFIG_USBDEV_ADVANCE_DESC
     g_usbd_core[busid].speed = USB_SPEED_UNKNOWN;
@@ -1347,6 +1356,24 @@ bool usb_device_is_configured(uint8_t busid)
     return g_usbd_core[busid].configuration;
 }
 
+int usbd_send_remote_wakeup(uint8_t busid)
+{
+    if (g_usbd_core[busid].remote_wakeup_support && g_usbd_core[busid].remote_wakeup_enabled && g_usbd_core[busid].is_suspend) {
+        return usbd_set_remote_wakeup(busid);
+    } else {
+        if (!g_usbd_core[busid].remote_wakeup_support) {
+            USB_LOG_ERR("device does not support remote wakeup\r\n");
+        }
+        if (!g_usbd_core[busid].remote_wakeup_enabled) {
+            USB_LOG_ERR("device remote wakeup is not enabled\r\n");
+        }
+        if (!g_usbd_core[busid].is_suspend) {
+            USB_LOG_ERR("device is not in suspend state\r\n");
+        }
+        return -1;
+    }
+}
+
 int usbd_initialize(uint8_t busid, uint32_t reg_base, void (*event_handler)(uint8_t busid, uint8_t event))
 {
     int ret;

+ 1 - 0
core/usbd_core.h

@@ -102,6 +102,7 @@ void usbd_add_endpoint(uint8_t busid, struct usbd_endpoint *ep);
 uint16_t usbd_get_ep_mps(uint8_t busid, uint8_t ep);
 uint8_t usbd_get_ep_mult(uint8_t busid, uint8_t ep);
 bool usb_device_is_configured(uint8_t busid);
+int usbd_send_remote_wakeup(uint8_t busid);
 
 int usbd_initialize(uint8_t busid, uint32_t reg_base, void (*event_handler)(uint8_t busid, uint8_t event));
 int usbd_deinitialize(uint8_t busid);

+ 330 - 0
demo/hid_remote_wakeup_template.c

@@ -0,0 +1,330 @@
+/*
+ * Copyright (c) 2024, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "usbd_core.h"
+#include "usbd_hid.h"
+
+/*!< endpoint address */
+#define HID_INT_EP          0x81
+#define HID_INT_EP_SIZE     4
+#define HID_INT_EP_INTERVAL 1
+
+#define USBD_VID           0xffff
+#define USBD_PID           0xffff
+#define USBD_MAX_POWER     100
+#define USBD_LANGID_STRING 1033
+
+/*!< config descriptor size */
+#define USB_HID_CONFIG_DESC_SIZ 34
+/*!< report descriptor size */
+#define HID_MOUSE_REPORT_DESC_SIZE 74
+
+/*!< global descriptor */
+const uint8_t hid_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01),
+    USB_CONFIG_DESCRIPTOR_INIT(USB_HID_CONFIG_DESC_SIZ, 0x01, 0x01, USB_CONFIG_REMOTE_WAKEUP | USB_CONFIG_SELF_POWERED, USBD_MAX_POWER),
+
+    /************** Descriptor of Joystick Mouse interface ****************/
+    /* 09 */
+    0x09,                          /* bLength: Interface Descriptor size */
+    USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
+    0x00,                          /* bInterfaceNumber: Number of Interface */
+    0x00,                          /* bAlternateSetting: Alternate setting */
+    0x01,                          /* bNumEndpoints */
+    0x03,                          /* bInterfaceClass: HID */
+    0x01,                          /* bInterfaceSubClass : 1=BOOT, 0=no boot */
+    0x02,                          /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
+    0,                             /* iInterface: Index of string descriptor */
+    /******************** Descriptor of Joystick Mouse HID ********************/
+    /* 18 */
+    0x09,                    /* bLength: HID Descriptor size */
+    HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */
+    0x11,                    /* bcdHID: HID Class Spec release number */
+    0x01,
+    0x00,                       /* bCountryCode: Hardware target country */
+    0x01,                       /* bNumDescriptors: Number of HID class descriptors to follow */
+    0x22,                       /* bDescriptorType */
+    HID_MOUSE_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
+    0x00,
+    /******************** Descriptor of Mouse endpoint ********************/
+    /* 27 */
+    0x07,                         /* bLength: Endpoint Descriptor size */
+    USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
+    HID_INT_EP,                   /* bEndpointAddress: Endpoint Address (IN) */
+    0x03,                         /* bmAttributes: Interrupt endpoint */
+    HID_INT_EP_SIZE,              /* wMaxPacketSize: 4 Byte max */
+    0x00,
+    HID_INT_EP_INTERVAL, /* bInterval: Polling Interval */
+    /* 34 */
+    ///////////////////////////////////////
+    /// string0 descriptor
+    ///////////////////////////////////////
+    USB_LANGID_INIT(USBD_LANGID_STRING),
+    ///////////////////////////////////////
+    /// string1 descriptor
+    ///////////////////////////////////////
+    0x14,                       /* bLength */
+    USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
+    'C', 0x00,                  /* wcChar0 */
+    'h', 0x00,                  /* wcChar1 */
+    'e', 0x00,                  /* wcChar2 */
+    'r', 0x00,                  /* wcChar3 */
+    'r', 0x00,                  /* wcChar4 */
+    'y', 0x00,                  /* wcChar5 */
+    'U', 0x00,                  /* wcChar6 */
+    'S', 0x00,                  /* wcChar7 */
+    'B', 0x00,                  /* wcChar8 */
+    ///////////////////////////////////////
+    /// string2 descriptor
+    ///////////////////////////////////////
+    0x26,                       /* bLength */
+    USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
+    'C', 0x00,                  /* wcChar0 */
+    'h', 0x00,                  /* wcChar1 */
+    'e', 0x00,                  /* wcChar2 */
+    'r', 0x00,                  /* wcChar3 */
+    'r', 0x00,                  /* wcChar4 */
+    'y', 0x00,                  /* wcChar5 */
+    'U', 0x00,                  /* wcChar6 */
+    'S', 0x00,                  /* wcChar7 */
+    'B', 0x00,                  /* wcChar8 */
+    ' ', 0x00,                  /* wcChar9 */
+    'H', 0x00,                  /* wcChar10 */
+    'I', 0x00,                  /* wcChar11 */
+    'D', 0x00,                  /* wcChar12 */
+    ' ', 0x00,                  /* wcChar13 */
+    'D', 0x00,                  /* wcChar14 */
+    'E', 0x00,                  /* wcChar15 */
+    'M', 0x00,                  /* wcChar16 */
+    'O', 0x00,                  /* wcChar17 */
+    ///////////////////////////////////////
+    /// string3 descriptor
+    ///////////////////////////////////////
+    0x16,                       /* bLength */
+    USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
+    '2', 0x00,                  /* wcChar0 */
+    '0', 0x00,                  /* wcChar1 */
+    '2', 0x00,                  /* wcChar2 */
+    '2', 0x00,                  /* wcChar3 */
+    '1', 0x00,                  /* wcChar4 */
+    '2', 0x00,                  /* wcChar5 */
+    '3', 0x00,                  /* wcChar6 */
+    '4', 0x00,                  /* wcChar7 */
+    '5', 0x00,                  /* wcChar8 */
+    '6', 0x00,                  /* wcChar9 */
+#ifdef CONFIG_USB_HS
+    ///////////////////////////////////////
+    /// device qualifier descriptor
+    ///////////////////////////////////////
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x00,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x01,
+    0x00,
+#endif
+    0x00
+};
+
+/*!< hid mouse report descriptor */
+static const uint8_t hid_mouse_report_desc[HID_MOUSE_REPORT_DESC_SIZE] = {
+    0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+    0x09, 0x02, // USAGE (Mouse)
+    0xA1, 0x01, // COLLECTION (Application)
+    0x09, 0x01, //   USAGE (Pointer)
+
+    0xA1, 0x00, //   COLLECTION (Physical)
+    0x05, 0x09, //     USAGE_PAGE (Button)
+    0x19, 0x01, //     USAGE_MINIMUM (Button 1)
+    0x29, 0x03, //     USAGE_MAXIMUM (Button 3)
+
+    0x15, 0x00, //     LOGICAL_MINIMUM (0)
+    0x25, 0x01, //     LOGICAL_MAXIMUM (1)
+    0x95, 0x03, //     REPORT_COUNT (3)
+    0x75, 0x01, //     REPORT_SIZE (1)
+
+    0x81, 0x02, //     INPUT (Data,Var,Abs)
+    0x95, 0x01, //     REPORT_COUNT (1)
+    0x75, 0x05, //     REPORT_SIZE (5)
+    0x81, 0x01, //     INPUT (Cnst,Var,Abs)
+
+    0x05, 0x01, //     USAGE_PAGE (Generic Desktop)
+    0x09, 0x30, //     USAGE (X)
+    0x09, 0x31, //     USAGE (Y)
+    0x09, 0x38,
+
+    0x15, 0x81, //     LOGICAL_MINIMUM (-127)
+    0x25, 0x7F, //     LOGICAL_MAXIMUM (127)
+    0x75, 0x08, //     REPORT_SIZE (8)
+    0x95, 0x03, //     REPORT_COUNT (2)
+
+    0x81, 0x06, //     INPUT (Data,Var,Rel)
+    0xC0, 0x09,
+    0x3c, 0x05,
+    0xff, 0x09,
+
+    0x01, 0x15,
+    0x00, 0x25,
+    0x01, 0x75,
+    0x01, 0x95,
+
+    0x02, 0xb1,
+    0x22, 0x75,
+    0x06, 0x95,
+    0x01, 0xb1,
+
+    0x01, 0xc0 //   END_COLLECTION
+};
+
+/*!< mouse report struct */
+struct hid_mouse {
+    uint8_t buttons;
+    int8_t x;
+    int8_t y;
+    int8_t wheel;
+};
+
+/*!< mouse report */
+static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX struct hid_mouse mouse_cfg;
+
+#define HID_STATE_IDLE 0
+#define HID_STATE_BUSY 1
+
+/*!< hid state ! Data can be sent only when state is idle  */
+static volatile uint8_t hid_state = HID_STATE_IDLE;
+
+static void usbd_event_handler(uint8_t busid, uint8_t event)
+{
+    switch (event) {
+        case USBD_EVENT_RESET:
+            break;
+        case USBD_EVENT_CONNECTED:
+            break;
+        case USBD_EVENT_DISCONNECTED:
+            break;
+        case USBD_EVENT_RESUME:
+            break;
+        case USBD_EVENT_SUSPEND:
+            break;
+        case USBD_EVENT_CONFIGURED:
+            hid_state = HID_STATE_IDLE;
+            break;
+        case USBD_EVENT_SET_REMOTE_WAKEUP:
+            break;
+        case USBD_EVENT_CLR_REMOTE_WAKEUP:
+            break;
+
+        default:
+            break;
+    }
+}
+
+/* function ------------------------------------------------------------------*/
+static void usbd_hid_int_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
+{
+    hid_state = HID_STATE_IDLE;
+}
+
+/*!< endpoint call back */
+static struct usbd_endpoint hid_in_ep = {
+    .ep_cb = usbd_hid_int_callback,
+    .ep_addr = HID_INT_EP
+};
+
+static struct usbd_interface intf0;
+
+void hid_mouse_init(uint8_t busid, uint32_t reg_base)
+{
+    usbd_desc_register(busid, hid_descriptor);
+    usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_mouse_report_desc, HID_MOUSE_REPORT_DESC_SIZE));
+    usbd_add_endpoint(busid, &hid_in_ep);
+
+    usbd_initialize(busid, reg_base, usbd_event_handler);
+
+    /*!< init mouse report data */
+    mouse_cfg.buttons = 0;
+    mouse_cfg.wheel = 0;
+    mouse_cfg.x = 0;
+    mouse_cfg.y = 0;
+}
+
+#define CURSOR_STEP  2U
+#define CURSOR_WIDTH 20U
+
+void draw_circle(uint8_t *buf)
+{
+    static int32_t move_cnt = 0;
+    static uint8_t step_x_y = 0;
+    static int8_t x = 0, y = 0;
+
+    move_cnt++;
+    if (move_cnt > CURSOR_WIDTH) {
+        step_x_y++;
+        step_x_y = step_x_y % 4;
+        move_cnt = 0;
+    }
+    switch (step_x_y) {
+        case 0: {
+            y = 0;
+            x = CURSOR_STEP;
+
+        } break;
+
+        case 1: {
+            x = 0;
+            y = CURSOR_STEP;
+
+        } break;
+
+        case 2: {
+            y = 0;
+            x = (int8_t)(-CURSOR_STEP);
+
+        } break;
+
+        case 3: {
+            x = 0;
+            y = (int8_t)(-CURSOR_STEP);
+
+        } break;
+    }
+
+    buf[0] = 0;
+    buf[1] = x;
+    buf[2] = y;
+    buf[3] = 0;
+}
+
+/* https://cps-check.com/cn/polling-rate-check */
+void hid_mouse_test(uint8_t busid)
+{
+    static uint32_t count = 1000;
+    int ret;
+
+    // if (gpio_read_pin(GPIO_PIN) == 1) {
+    //     ret = usbd_send_remote_wakeup(busid);
+    //     if (ret < 0) {
+    //         return;
+    //     }
+    //     count = 5000;
+    // }
+
+    while (count) {
+        draw_circle((uint8_t *)&mouse_cfg);
+        int ret = usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
+        if (ret < 0) {
+            return;
+        }
+        hid_state = HID_STATE_BUSY;
+        while (hid_state == HID_STATE_BUSY) {
+        }
+
+        count--;
+    }
+}

+ 5 - 0
port/aic/usb_dc_aic.c

@@ -661,6 +661,11 @@ int usbd_set_address(uint8_t busid, const uint8_t addr)
     return 0;
 }
 
+int usbd_set_remote_wakeup(uint8_t busid)
+{
+    return -1;
+}
+
 uint8_t usbd_get_port_speed(uint8_t busid)
 {
     uint8_t speed;

+ 17 - 0
port/bouffalolab/usb_dc_bl.c

@@ -613,6 +613,23 @@ int usbd_set_address(uint8_t busid, const uint8_t addr)
     return 0;
 }
 
+int usbd_set_remote_wakeup(uint8_t busid)
+{
+    uint32_t regval;
+
+    regval = getreg32(BFLB_USB_BASE + USB_DEV_CTL_OFFSET);
+    regval |= USB_CAP_RMWAKUP;
+    putreg32(regval, BFLB_USB_BASE + USB_DEV_CTL_OFFSET);
+
+    bflb_mtimer_delay_ms(10);
+
+    regval = getreg32(BFLB_USB_BASE + USB_DEV_CTL_OFFSET);
+    regval &= ~USB_CAP_RMWAKUP;
+    putreg32(regval, BFLB_USB_BASE + USB_DEV_CTL_OFFSET);
+
+    return 0;
+}
+
 uint8_t usbd_get_port_speed(uint8_t busid)
 {
     uint8_t speed = 3;

+ 6 - 1
port/ch32/usb_ch58x_dc_usbfs.c

@@ -223,6 +223,11 @@ int usbd_set_address(uint8_t busid, const uint8_t address)
     return 0;
 }
 
+int usbd_set_remote_wakeup(uint8_t busid)
+{
+    return -1;
+}
+
 uint8_t usbd_get_port_speed(uint8_t busid)
 {
     return USB_SPEED_FULL;
@@ -543,7 +548,7 @@ USBD_IRQHandler(void)
                     break;
                 case UIS_TOKEN_OUT:
                     EPn_SET_RX_NAK(epid);
-                    
+
                     if (epid == 0) {
                         /*!< ep0 out */
                         CH58x_USBFS_DEV->UEP0_CTRL ^= RB_UEP_R_TOG;

+ 5 - 0
port/ch32/usb_dc_usbfs.c

@@ -101,6 +101,11 @@ int usbd_set_address(uint8_t busid, const uint8_t addr)
     return 0;
 }
 
+int usbd_set_remote_wakeup(uint8_t busid)
+{
+    return -1;
+}
+
 uint8_t usbd_get_port_speed(uint8_t busid)
 {
     return USB_SPEED_FULL;

+ 5 - 0
port/ch32/usb_dc_usbhs.c

@@ -101,6 +101,11 @@ int usbd_set_address(uint8_t busid, const uint8_t addr)
     return 0;
 }
 
+int usbd_set_remote_wakeup(uint8_t busid)
+{
+    return -1;
+}
+
 uint8_t usbd_get_port_speed(uint8_t busid)
 {
     return USB_SPEED_HIGH;

+ 14 - 0
port/dwc2/usb_dc_dwc2.c

@@ -571,6 +571,7 @@ int usb_dc_init(uint8_t busid)
     /* Enable interrupts matching to the Device mode ONLY */
     USB_OTG_GLB->GINTMSK = USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM |
                            USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT |
+                           USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_WUIM |
                            USB_OTG_GINTMSK_IISOIXFRM | USB_OTG_GINTMSK_PXFRM_IISOOXFRM;
 
 #ifdef CONFIG_USB_DWC2_DMA_ENABLE
@@ -678,6 +679,17 @@ int usbd_set_address(uint8_t busid, const uint8_t addr)
     return 0;
 }
 
+int usbd_set_remote_wakeup(uint8_t busid)
+{
+    if (!(USB_OTG_DEV->DSTS & USB_OTG_DSTS_SUSPSTS)) {
+        return -1;
+    }
+    USB_OTG_DEV->DCTL |= USB_OTG_DCTL_RWUSIG;
+    usbd_dwc2_delay_ms(10);
+    USB_OTG_DEV->DCTL &= ~USB_OTG_DCTL_RWUSIG;
+    return 0;
+}
+
 uint8_t usbd_get_port_speed(uint8_t busid)
 {
     uint8_t speed;
@@ -1188,9 +1200,11 @@ void USBD_IRQHandler(uint8_t busid)
         }
         if (gint_status & USB_OTG_GINTSTS_USBSUSP) {
             USB_OTG_GLB->GINTSTS |= USB_OTG_GINTSTS_USBSUSP;
+            usbd_event_suspend_handler(0);
         }
         if (gint_status & USB_OTG_GINTSTS_WKUINT) {
             USB_OTG_GLB->GINTSTS |= USB_OTG_GINTSTS_WKUINT;
+            usbd_event_resume_handler(0);
         }
         if (gint_status & USB_OTG_GINTSTS_OTGINT) {
             temp = USB_OTG_GLB->GOTGINT;

+ 1 - 0
port/dwc2/usb_dwc2_reg.h

@@ -1718,4 +1718,5 @@ typedef struct
 
 uint32_t usbd_get_dwc2_gccfg_conf(uint32_t reg_base);
 uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base);
+void usbd_dwc2_delay_ms(uint8_t ms);
 #endif

+ 6 - 1
port/dwc2/usb_glue_at.c

@@ -12,7 +12,7 @@
  *  usbx->gccfg_bit.pwrdown = TRUE;
  *  usbx->gccfg_bit.avalidsesen = TRUE;
  *  usbx->gccfg_bit.bvalidsesen = TRUE;
- * 
+ *
 */
 
 uint32_t usbd_get_dwc2_gccfg_conf(uint32_t reg_base)
@@ -49,4 +49,9 @@ uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base)
     return ((1 << 16) | (1 << 21));
 #endif
 #endif
+}
+
+void usbd_dwc2_delay_ms(uint8_t ms)
+{
+    /* implement later */
 }

+ 5 - 0
port/dwc2/usb_glue_esp.c

@@ -118,3 +118,8 @@ uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base)
 {
     return 0;
 }
+
+void usbd_dwc2_delay_ms(uint8_t ms)
+{
+    vTaskDelay(pdMS_TO_TICKS(ms));
+}

+ 6 - 1
port/dwc2/usb_glue_gd.c

@@ -10,7 +10,7 @@
 /* you can find this config in function:usb_core_init, file:drv_usb_core.c, for example:
  *
  *  usb_regs->gr->GCCFG |= GCCFG_PWRON | GCCFG_VBUSACEN | GCCFG_VBUSBCEN;
- * 
+ *
 */
 
 uint32_t usbd_get_dwc2_gccfg_conf(uint32_t reg_base)
@@ -29,4 +29,9 @@ uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base)
 #else
     return ((1 << 16) | (1 << 18) | (1 << 19) | (1 << 21));
 #endif
+}
+
+void usbd_dwc2_delay_ms(uint8_t ms)
+{
+    /* implement later */
 }

+ 5 - 0
port/dwc2/usb_glue_hc.c

@@ -24,3 +24,8 @@ uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base)
     USB_OTG_GLB->GOTGCTL &= ~USB_OTG_GOTGCTL_BVALOVAL;
     return 0;
 }
+
+void usbd_dwc2_delay_ms(uint8_t ms)
+{
+    /* implement later */
+}

+ 8 - 1
port/dwc2/usb_glue_st.c

@@ -13,9 +13,11 @@
  *  USBx->GCCFG |= USB_OTG_GCCFG_NOVBUSSENS;
  *  USBx->GCCFG &= ~USB_OTG_GCCFG_VBUSBSEN;
  *  USBx->GCCFG &= ~USB_OTG_GCCFG_VBUSASEN;
- * 
+ *
 */
 
+extern void HAL_Delay(uint32_t Delay);
+
 #if defined(STM32F722xx) || defined(STM32F723xx) || defined(STM32F730xx) || defined(STM32F732xx) || defined(STM32F733xx)
 /**
   * @brief USB_HS_PHY_Registers
@@ -201,3 +203,8 @@ uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base)
 #endif
 #endif
 }
+
+void usbd_dwc2_delay_ms(uint8_t ms)
+{
+    HAL_Delay(ms);
+}

+ 5 - 0
port/fsdev/usb_dc_fsdev.c

@@ -117,6 +117,11 @@ int usbd_set_address(uint8_t busid, const uint8_t addr)
     return 0;
 }
 
+int usbd_set_remote_wakeup(uint8_t busid)
+{
+    return -1;
+}
+
 uint8_t usbd_get_port_speed(uint8_t busid)
 {
     return USB_SPEED_FULL;

+ 19 - 2
port/hpm/usb_dc_hpm.c

@@ -91,7 +91,7 @@ int usb_dc_init(uint8_t busid)
     }
 
     uint32_t int_mask;
-    int_mask = (USB_USBINTR_UE_MASK | USB_USBINTR_UEE_MASK |
+    int_mask = (USB_USBINTR_UE_MASK | USB_USBINTR_UEE_MASK | USB_USBSTS_SLI_MASK |
                 USB_USBINTR_PCE_MASK | USB_USBINTR_URE_MASK);
 
     usb_device_init(g_hpm_udc[busid].handle, int_mask);
@@ -116,6 +116,23 @@ int usbd_set_address(uint8_t busid, const uint8_t addr)
     return 0;
 }
 
+int usbd_set_remote_wakeup(uint8_t busid)
+{
+    USB_Type *ptr;
+
+    ptr = g_hpm_udc[busid].handle->regs;
+
+    if (!usb_get_suspend_status(ptr)) {
+        return -1;
+    }
+    ptr->PORTSC1 &= ~USB_PORTSC1_PHCD_MASK;
+    usb_force_port_resume(g_hpm_udc[busid].handle->regs);
+    while (ptr->PORTSC1 & USB_PORTSC1_FPR_MASK) {
+    }
+
+    return 0;
+}
+
 uint8_t usbd_get_port_speed(uint8_t busid)
 {
     uint8_t speed;
@@ -314,7 +331,7 @@ void USBD_IRQHandler(uint8_t busid)
                             transfer_len += p_qtd->expected_bytes - p_qtd->total_bytes;
                         }
 
-                        if (p_qtd->next == USB_SOC_DCD_QTD_NEXT_INVALID){
+                        if (p_qtd->next == USB_SOC_DCD_QTD_NEXT_INVALID) {
                             break;
                         } else {
                             p_qtd = (dcd_qtd_t *)p_qtd->next;

+ 11 - 1
port/musb/usb_dc_musb.c

@@ -273,7 +273,7 @@ int usb_dc_init(uint8_t busid)
     }
 
     /* Enable USB interrupts */
-    HWREGB(USB_BASE + MUSB_IE_OFFSET) = USB_IE_RESET;
+    HWREGB(USB_BASE + MUSB_IE_OFFSET) = USB_IE_RESET | USB_IE_SUSPND | USB_IE_RESUME;
     HWREGH(USB_BASE + MUSB_TXIE_OFFSET) = USB_TXIE_EP0;
     HWREGH(USB_BASE + MUSB_RXIE_OFFSET) = 0;
 
@@ -296,6 +296,14 @@ int usbd_set_address(uint8_t busid, const uint8_t addr)
     return 0;
 }
 
+int usbd_set_remote_wakeup(uint8_t busid)
+{
+    HWREGB(USB_BASE + MUSB_POWER_OFFSET) |= USB_POWER_RESUME;
+    usbd_musb_delay_ms(10);
+    HWREGB(USB_BASE + MUSB_POWER_OFFSET) &= ~USB_POWER_RESUME;
+    return 0;
+}
+
 uint8_t usbd_get_port_speed(uint8_t busid)
 {
     uint8_t speed = USB_SPEED_UNKNOWN;
@@ -726,9 +734,11 @@ void USBD_IRQHandler(uint8_t busid)
     }
 
     if (is & USB_IS_RESUME) {
+        usbd_event_resume_handler(0);
     }
 
     if (is & USB_IS_SUSPEND) {
+        usbd_event_suspend_handler(0);
     }
 
     txis &= HWREGH(USB_BASE + MUSB_TXIE_OFFSET);

+ 5 - 0
port/musb/usb_glue_bk.c

@@ -277,6 +277,11 @@ void usb_dc_low_level_deinit(void)
     sys_drv_dev_clk_pwr_up(CLK_PWR_ID_USB_1, CLK_PWR_CTRL_PWR_DOWN);
 }
 
+void usbd_musb_delay_ms(uint8_t ms)
+{
+    /* implement later */
+}
+
 extern void USBH_IRQHandler(uint8_t busid);
 
 void USBH_IRQ(void)

+ 6 - 1
port/musb/usb_glue_es.c

@@ -50,4 +50,9 @@ uint8_t usbh_get_musb_fifo_cfg(struct musb_fifo_cfg **cfg)
 uint32_t usb_get_musb_ram_size(void)
 {
     return 4096;
-}
+}
+
+void usbd_musb_delay_ms(uint8_t ms)
+{
+    /* implement later */
+}

+ 6 - 1
port/musb/usb_glue_sunxi.c

@@ -56,4 +56,9 @@ uint8_t usbh_get_musb_fifo_cfg(struct musb_fifo_cfg **cfg)
 uint32_t usb_get_musb_ram_size(void)
 {
     return 8192;
-}
+}
+
+void usbd_musb_delay_ms(uint8_t ms)
+{
+    /* implement later */
+}

+ 1 - 0
port/musb/usb_musb_reg.h

@@ -3882,5 +3882,6 @@ struct musb_fifo_cfg {
 uint8_t usbd_get_musb_fifo_cfg(struct musb_fifo_cfg **cfg);
 uint8_t usbh_get_musb_fifo_cfg(struct musb_fifo_cfg **cfg);
 uint32_t usb_get_musb_ram_size(void);
+void usbd_musb_delay_ms(uint8_t ms);
 
 #endif

+ 5 - 0
port/nuvoton/usb_dc_usbfs.c

@@ -165,6 +165,11 @@ int usbd_set_address(uint8_t busid, const uint8_t addr)
     return 0;
 }
 
+int usbd_set_remote_wakeup(uint8_t busid)
+{
+    return -1;
+}
+
 uint8_t usbd_get_port_speed(uint8_t busid)
 {
     return USB_SPEED_FULL;

+ 5 - 0
port/template/usb_dc.c

@@ -51,6 +51,11 @@ int usbd_set_address(uint8_t busid, const uint8_t addr)
     return 0;
 }
 
+int usbd_set_remote_wakeup(uint8_t busid)
+{
+    return -1;
+}
+
 int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
 {
     uint8_t ep_idx = USB_EP_GET_IDX(ep->bEndpointAddress);