Procházet zdrojové kódy

add winusbv2 template

sakumisu před 1 rokem
rodič
revize
5bd8ea8925

+ 2 - 2
demo/winusb1.0_template.c

@@ -281,7 +281,7 @@ const uint8_t winusb_descriptor[] = {
     'E', 0x00,                  /* wcChar18 */
     'M', 0x00,                  /* wcChar19 */
     'O', 0x00,                  /* wcChar20 */
-        ' ', 0x00,                  /* wcChar16 */
+    ' ', 0x00,                  /* wcChar16 */
     '1', 0x00,                  /* wcChar21 */
     ///////////////////////////////////////
     /// string5 descriptor
@@ -309,7 +309,7 @@ const uint8_t winusb_descriptor[] = {
     'E', 0x00,                  /* wcChar18 */
     'M', 0x00,                  /* wcChar19 */
     'O', 0x00,                  /* wcChar20 */
-        ' ', 0x00,                  /* wcChar16 */
+    ' ', 0x00,                  /* wcChar16 */
     '2', 0x00,                  /* wcChar21 */
 #ifdef CONFIG_USB_HS
     ///////////////////////////////////////

+ 333 - 0
demo/winusb2.0_cdc_template.c

@@ -0,0 +1,333 @@
+#include "usbd_core.h"
+#include "usbd_cdc.h"
+
+#define WINUSB_IN_EP  0x81
+#define WINUSB_OUT_EP 0x02
+
+#define CDC_IN_EP  0x83
+#define CDC_OUT_EP 0x04
+#define CDC_INT_EP 0x85
+
+#define USBD_VID           0xFFFE
+#define USBD_PID           0xFFFF
+#define USBD_MAX_POWER     500
+#define USBD_LANGID_STRING 1033
+
+#define USB_CONFIG_SIZE (9 + 9 + 7 + 7 + CDC_ACM_DESCRIPTOR_LEN)
+#define INTF_NUM        3
+
+#ifdef CONFIG_USB_HS
+#define WINUSB_EP_MPS 512
+#else
+#define WINUSB_EP_MPS 64
+#endif
+
+#define USBD_WINUSB_VENDOR_CODE 0x20
+
+#define USBD_WEBUSB_ENABLE 0
+#define USBD_BULK_ENABLE   1
+#define USBD_WINUSB_ENABLE 1
+
+/* WinUSB Microsoft OS 2.0 descriptor sizes */
+#define WINUSB_DESCRIPTOR_SET_HEADER_SIZE  10
+#define WINUSB_FUNCTION_SUBSET_HEADER_SIZE 8
+#define WINUSB_FEATURE_COMPATIBLE_ID_SIZE  20
+
+#define FUNCTION_SUBSET_LEN                160
+#define DEVICE_INTERFACE_GUIDS_FEATURE_LEN 132
+
+#define USBD_WINUSB_DESC_SET_LEN (WINUSB_DESCRIPTOR_SET_HEADER_SIZE + USBD_WEBUSB_ENABLE * FUNCTION_SUBSET_LEN + USBD_BULK_ENABLE * FUNCTION_SUBSET_LEN)
+
+__ALIGN_BEGIN const uint8_t USBD_WinUSBDescriptorSetDescriptor[] = {
+    WBVAL(WINUSB_DESCRIPTOR_SET_HEADER_SIZE), /* wLength */
+    WBVAL(WINUSB_SET_HEADER_DESCRIPTOR_TYPE), /* wDescriptorType */
+    0x00, 0x00, 0x03, 0x06, /* >= Win 8.1 */  /* dwWindowsVersion*/
+    WBVAL(USBD_WINUSB_DESC_SET_LEN),          /* wDescriptorSetTotalLength */
+#if (USBD_WEBUSB_ENABLE)
+    WBVAL(WINUSB_FUNCTION_SUBSET_HEADER_SIZE), // wLength
+    WBVAL(WINUSB_SUBSET_HEADER_FUNCTION_TYPE), // wDescriptorType
+    0,                                         // bFirstInterface USBD_WINUSB_IF_NUM
+    0,                                         // bReserved
+    WBVAL(FUNCTION_SUBSET_LEN),                // wSubsetLength
+    WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_SIZE),  // wLength
+    WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_TYPE),  // wDescriptorType
+    'W', 'I', 'N', 'U', 'S', 'B', 0, 0,        // CompatibleId
+    0, 0, 0, 0, 0, 0, 0, 0,                    // SubCompatibleId
+    WBVAL(DEVICE_INTERFACE_GUIDS_FEATURE_LEN), // wLength
+    WBVAL(WINUSB_FEATURE_REG_PROPERTY_TYPE),   // wDescriptorType
+    WBVAL(WINUSB_PROP_DATA_TYPE_REG_MULTI_SZ), // wPropertyDataType
+    WBVAL(42),                                 // wPropertyNameLength
+    'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0,
+    'I', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
+    'G', 0, 'U', 0, 'I', 0, 'D', 0, 's', 0, 0, 0,
+    WBVAL(80), // wPropertyDataLength
+    '{', 0,
+    '9', 0, '2', 0, 'C', 0, 'E', 0, '6', 0, '4', 0, '6', 0, '2', 0, '-', 0,
+    '9', 0, 'C', 0, '7', 0, '7', 0, '-', 0,
+    '4', 0, '6', 0, 'F', 0, 'E', 0, '-', 0,
+    '9', 0, '3', 0, '3', 0, 'B', 0, '-',
+    0, '3', 0, '1', 0, 'C', 0, 'B', 0, '9', 0, 'C', 0, '5', 0, 'A', 0, 'A', 0, '3', 0, 'B', 0, '9', 0,
+    '}', 0, 0, 0, 0, 0
+#endif
+#if USBD_BULK_ENABLE
+    WBVAL(WINUSB_FUNCTION_SUBSET_HEADER_SIZE), /* wLength */
+    WBVAL(WINUSB_SUBSET_HEADER_FUNCTION_TYPE), /* wDescriptorType */
+    0,                                         /* bFirstInterface USBD_BULK_IF_NUM*/
+    0,                                         /* bReserved */
+    WBVAL(FUNCTION_SUBSET_LEN),                /* wSubsetLength */
+    WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_SIZE),  /* wLength */
+    WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_TYPE),  /* wDescriptorType */
+    'W', 'I', 'N', 'U', 'S', 'B', 0, 0,        /* CompatibleId*/
+    0, 0, 0, 0, 0, 0, 0, 0,                    /* SubCompatibleId*/
+    WBVAL(DEVICE_INTERFACE_GUIDS_FEATURE_LEN), /* wLength */
+    WBVAL(WINUSB_FEATURE_REG_PROPERTY_TYPE),   /* wDescriptorType */
+    WBVAL(WINUSB_PROP_DATA_TYPE_REG_MULTI_SZ), /* wPropertyDataType */
+    WBVAL(42),                                 /* wPropertyNameLength */
+    'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0,
+    'I', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
+    'G', 0, 'U', 0, 'I', 0, 'D', 0, 's', 0, 0, 0,
+    WBVAL(80), /* wPropertyDataLength */
+    '{', 0,
+    'C', 0, 'D', 0, 'B', 0, '3', 0, 'B', 0, '5', 0, 'A', 0, 'D', 0, '-', 0,
+    '2', 0, '9', 0, '3', 0, 'B', 0, '-', 0,
+    '4', 0, '6', 0, '6', 0, '3', 0, '-', 0,
+    'A', 0, 'A', 0, '3', 0, '6', 0, '-',
+    0, '1', 0, 'A', 0, 'A', 0, 'E', 0, '4', 0, '6', 0, '4', 0, '6', 0, '3', 0, '7', 0, '7', 0, '6', 0,
+    '}', 0, 0, 0, 0, 0
+#endif
+};
+
+#define USBD_NUM_DEV_CAPABILITIES (USBD_WEBUSB_ENABLE + USBD_WINUSB_ENABLE)
+
+#define USBD_WEBUSB_DESC_LEN 24
+#define USBD_WINUSB_DESC_LEN 28
+
+#define USBD_BOS_WTOTALLENGTH (0x05 +                                      \
+                               USBD_WEBUSB_DESC_LEN * USBD_WEBUSB_ENABLE + \
+                               USBD_WINUSB_DESC_LEN * USBD_WINUSB_ENABLE)
+
+__ALIGN_BEGIN const uint8_t USBD_BinaryObjectStoreDescriptor[] = {
+    0x05,                         /* bLength */
+    0x0f,                         /* bDescriptorType */
+    WBVAL(USBD_BOS_WTOTALLENGTH), /* wTotalLength */
+    USBD_NUM_DEV_CAPABILITIES,    /* bNumDeviceCaps */
+#if (USBD_WEBUSB_ENABLE)
+    USBD_WEBUSB_DESC_LEN,           /* bLength */
+    0x10,                           /* bDescriptorType */
+    USB_DEVICE_CAPABILITY_PLATFORM, /* bDevCapabilityType */
+    0x00,                           /* bReserved */
+    0x38, 0xB6, 0x08, 0x34,         /* PlatformCapabilityUUID */
+    0xA9, 0x09, 0xA0, 0x47,
+    0x8B, 0xFD, 0xA0, 0x76,
+    0x88, 0x15, 0xB6, 0x65,
+    WBVAL(0x0100), /* 1.00 */ /* bcdVersion */
+    USBD_WINUSB_VENDOR_CODE,  /* bVendorCode */
+    0,                        /* iLandingPage */
+#endif
+#if (USBD_WINUSB_ENABLE)
+    USBD_WINUSB_DESC_LEN,           /* bLength */
+    0x10,                           /* bDescriptorType */
+    USB_DEVICE_CAPABILITY_PLATFORM, /* bDevCapabilityType */
+    0x00,                           /* bReserved */
+    0xDF, 0x60, 0xDD, 0xD8,         /* PlatformCapabilityUUID */
+    0x89, 0x45, 0xC7, 0x4C,
+    0x9C, 0xD2, 0x65, 0x9D,
+    0x9E, 0x64, 0x8A, 0x9F,
+    0x00, 0x00, 0x03, 0x06, /* >= Win 8.1 */ /* dwWindowsVersion*/
+    WBVAL(USBD_WINUSB_DESC_SET_LEN),         /* wDescriptorSetTotalLength */
+    USBD_WINUSB_VENDOR_CODE,                 /* bVendorCode */
+    0,                                       /* bAltEnumCode */
+#endif
+};
+
+const uint8_t winusbv2_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_1, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
+    /* Configuration 0 */
+    USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, INTF_NUM, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+    /* Interface 0 */
+    USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02),
+    /* Endpoint OUT 2 */
+    USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_OUT_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00),
+    /* Endpoint IN 1 */
+    USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_IN_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00),
+    CDC_ACM_DESCRIPTOR_INIT(0x01, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, WINUSB_EP_MPS, 0x00),
+    /* String 0 (LANGID) */
+    USB_LANGID_INIT(USBD_LANGID_STRING),
+    /* String 1 (Manufacturer) */
+    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 */
+    /* String 2 (Product) */
+    0x2C,                       /* 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 */
+    'W', 0x00,                  /* wcChar10 */
+    'I', 0x00,                  /* wcChar11 */
+    'N', 0x00,                  /* wcChar12 */
+    'U', 0x00,                  /* wcChar13 */
+    'S', 0x00,                  /* wcChar14 */
+    'B', 0x00,                  /* wcChar15 */
+    ' ', 0x00,                  /* wcChar16 */
+    'D', 0x00,                  /* wcChar17 */
+    'E', 0x00,                  /* wcChar18 */
+    'M', 0x00,                  /* wcChar19 */
+    'O', 0x00,                  /* wcChar20 */
+    /* String 3 (Serial Number) */
+    0x1A,                       // bLength
+    USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
+    '0', 0,                     // wcChar0
+    '1', 0,                     // wcChar1
+    '2', 0,                     // wcChar2
+    '3', 0,                     // wcChar3
+    '4', 0,                     // wcChar4
+    '5', 0,                     // wcChar5
+    'A', 0,                     // wcChar6
+    'B', 0,                     // wcChar7
+    'C', 0,                     // wcChar8
+    'D', 0,                     // wcChar9
+    'E', 0,                     // wcChar10
+    'F', 0,                     // wcChar11
+#ifdef CONFIG_USB_HS
+    /* Device Qualifier */
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x10,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x01,
+    0x00,
+#endif
+    /* End */
+    0x00
+};
+
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048];
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
+
+volatile bool ep_tx_busy_flag = false;
+
+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:
+            /* setup first out ep read transfer */
+            usbd_ep_start_read(busid, WINUSB_OUT_EP, read_buffer, 2048);
+            break;
+        case USBD_EVENT_SET_REMOTE_WAKEUP:
+            break;
+        case USBD_EVENT_CLR_REMOTE_WAKEUP:
+            break;
+
+        default:
+            break;
+    }
+}
+
+void usbd_winusb_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
+{
+    USB_LOG_RAW("actual out len:%d\r\n", nbytes);
+    // for (int i = 0; i < 100; i++) {
+    //     printf("%02x ", read_buffer[i]);
+    // }
+    // printf("\r\n");
+    usbd_ep_start_write(busid, WINUSB_IN_EP, read_buffer, nbytes);
+    /* setup next out ep read transfer */
+    usbd_ep_start_read(busid, WINUSB_OUT_EP, read_buffer, 2048);
+}
+
+void usbd_winusb_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
+{
+    USB_LOG_RAW("actual in len:%d\r\n", nbytes);
+
+    if ((nbytes % WINUSB_EP_MPS) == 0 && nbytes) {
+        /* send zlp */
+        usbd_ep_start_write(busid, WINUSB_IN_EP, NULL, 0);
+    } else {
+        ep_tx_busy_flag = false;
+    }
+}
+
+struct usbd_endpoint winusb_out_ep1 = {
+    .ep_addr = WINUSB_OUT_EP,
+    .ep_cb = usbd_winusb_out
+};
+
+struct usbd_endpoint winusb_in_ep1 = {
+    .ep_addr = WINUSB_IN_EP,
+    .ep_cb = usbd_winusb_in
+};
+
+static struct usbd_endpoint cdc_out_ep = {
+    .ep_addr = CDC_OUT_EP,
+    .ep_cb = NULL
+};
+
+static struct usbd_endpoint cdc_in_ep = {
+    .ep_addr = CDC_IN_EP,
+    .ep_cb = NULL
+};
+
+struct usbd_interface winusb_intf;
+struct usbd_interface intf1;
+struct usbd_interface intf2;
+
+struct usb_msosv2_descriptor msosv2_desc = {
+    .vendor_code = USBD_WINUSB_VENDOR_CODE,
+    .compat_id = USBD_WinUSBDescriptorSetDescriptor,
+    .compat_id_len = USBD_WINUSB_DESC_SET_LEN,
+};
+
+struct usb_bos_descriptor bos_desc = {
+    .string = USBD_BinaryObjectStoreDescriptor,
+    .string_len = USBD_BOS_WTOTALLENGTH
+};
+
+void winusbv2_init(uint8_t busid, uint32_t reg_base)
+{
+    usbd_desc_register(busid, winusbv2_descriptor);
+    usbd_bos_desc_register(busid, &bos_desc);
+    usbd_msosv2_desc_register(busid, &msosv2_desc);
+
+    /*!< winusb */
+    usbd_add_interface(busid, &winusb_intf);
+    usbd_add_endpoint(busid, &winusb_out_ep1);
+    usbd_add_endpoint(busid, &winusb_in_ep1);
+
+    /*!< cdc acm */
+    usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf1));
+    usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf2));
+    usbd_add_endpoint(busid, &cdc_out_ep);
+    usbd_add_endpoint(busid, &cdc_in_ep);
+
+    usbd_initialize(busid, reg_base, usbd_event_handler);
+}

+ 434 - 0
demo/winusb2.0_hid_template.c

@@ -0,0 +1,434 @@
+#include "usbd_core.h"
+#include "usbd_hid.h"
+
+#define WINUSB_IN_EP  0x81
+#define WINUSB_OUT_EP 0x02
+
+/*!< endpoint address */
+#define HID_INT_EP          0x83
+#define HID_INT_EP_SIZE     4
+#define HID_INT_EP_INTERVAL 10
+
+#define USBD_VID           0xFFFE
+#define USBD_PID           0xFFFF
+#define USBD_MAX_POWER     500
+#define USBD_LANGID_STRING 1033
+
+#define USB_CONFIG_SIZE (9 + 9 + 7 + 7 + 9 + 9 + 7)
+#define INTF_NUM        2
+
+/*!< config descriptor size */
+#define USB_HID_CONFIG_DESC_SIZ 34
+/*!< report descriptor size */
+#define HID_MOUSE_REPORT_DESC_SIZE 74
+
+#ifdef CONFIG_USB_HS
+#define WINUSB_EP_MPS 512
+#else
+#define WINUSB_EP_MPS 64
+#endif
+
+#define USBD_WINUSB_VENDOR_CODE 0x20
+
+#define USBD_WEBUSB_ENABLE 0
+#define USBD_BULK_ENABLE   1
+#define USBD_WINUSB_ENABLE 1
+
+/* WinUSB Microsoft OS 2.0 descriptor sizes */
+#define WINUSB_DESCRIPTOR_SET_HEADER_SIZE  10
+#define WINUSB_FUNCTION_SUBSET_HEADER_SIZE 8
+#define WINUSB_FEATURE_COMPATIBLE_ID_SIZE  20
+
+#define FUNCTION_SUBSET_LEN                160
+#define DEVICE_INTERFACE_GUIDS_FEATURE_LEN 132
+
+#define USBD_WINUSB_DESC_SET_LEN (WINUSB_DESCRIPTOR_SET_HEADER_SIZE + USBD_WEBUSB_ENABLE * FUNCTION_SUBSET_LEN + USBD_BULK_ENABLE * FUNCTION_SUBSET_LEN)
+
+__ALIGN_BEGIN const uint8_t USBD_WinUSBDescriptorSetDescriptor[] = {
+    WBVAL(WINUSB_DESCRIPTOR_SET_HEADER_SIZE), /* wLength */
+    WBVAL(WINUSB_SET_HEADER_DESCRIPTOR_TYPE), /* wDescriptorType */
+    0x00, 0x00, 0x03, 0x06, /* >= Win 8.1 */  /* dwWindowsVersion*/
+    WBVAL(USBD_WINUSB_DESC_SET_LEN),          /* wDescriptorSetTotalLength */
+#if (USBD_WEBUSB_ENABLE)
+    WBVAL(WINUSB_FUNCTION_SUBSET_HEADER_SIZE), // wLength
+    WBVAL(WINUSB_SUBSET_HEADER_FUNCTION_TYPE), // wDescriptorType
+    0,                                         // bFirstInterface USBD_WINUSB_IF_NUM
+    0,                                         // bReserved
+    WBVAL(FUNCTION_SUBSET_LEN),                // wSubsetLength
+    WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_SIZE),  // wLength
+    WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_TYPE),  // wDescriptorType
+    'W', 'I', 'N', 'U', 'S', 'B', 0, 0,        // CompatibleId
+    0, 0, 0, 0, 0, 0, 0, 0,                    // SubCompatibleId
+    WBVAL(DEVICE_INTERFACE_GUIDS_FEATURE_LEN), // wLength
+    WBVAL(WINUSB_FEATURE_REG_PROPERTY_TYPE),   // wDescriptorType
+    WBVAL(WINUSB_PROP_DATA_TYPE_REG_MULTI_SZ), // wPropertyDataType
+    WBVAL(42),                                 // wPropertyNameLength
+    'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0,
+    'I', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
+    'G', 0, 'U', 0, 'I', 0, 'D', 0, 's', 0, 0, 0,
+    WBVAL(80), // wPropertyDataLength
+    '{', 0,
+    '9', 0, '2', 0, 'C', 0, 'E', 0, '6', 0, '4', 0, '6', 0, '2', 0, '-', 0,
+    '9', 0, 'C', 0, '7', 0, '7', 0, '-', 0,
+    '4', 0, '6', 0, 'F', 0, 'E', 0, '-', 0,
+    '9', 0, '3', 0, '3', 0, 'B', 0, '-',
+    0, '3', 0, '1', 0, 'C', 0, 'B', 0, '9', 0, 'C', 0, '5', 0, 'A', 0, 'A', 0, '3', 0, 'B', 0, '9', 0,
+    '}', 0, 0, 0, 0, 0
+#endif
+#if USBD_BULK_ENABLE
+    WBVAL(WINUSB_FUNCTION_SUBSET_HEADER_SIZE), /* wLength */
+    WBVAL(WINUSB_SUBSET_HEADER_FUNCTION_TYPE), /* wDescriptorType */
+    0,                                         /* bFirstInterface USBD_BULK_IF_NUM*/
+    0,                                         /* bReserved */
+    WBVAL(FUNCTION_SUBSET_LEN),                /* wSubsetLength */
+    WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_SIZE),  /* wLength */
+    WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_TYPE),  /* wDescriptorType */
+    'W', 'I', 'N', 'U', 'S', 'B', 0, 0,        /* CompatibleId*/
+    0, 0, 0, 0, 0, 0, 0, 0,                    /* SubCompatibleId*/
+    WBVAL(DEVICE_INTERFACE_GUIDS_FEATURE_LEN), /* wLength */
+    WBVAL(WINUSB_FEATURE_REG_PROPERTY_TYPE),   /* wDescriptorType */
+    WBVAL(WINUSB_PROP_DATA_TYPE_REG_MULTI_SZ), /* wPropertyDataType */
+    WBVAL(42),                                 /* wPropertyNameLength */
+    'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0,
+    'I', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
+    'G', 0, 'U', 0, 'I', 0, 'D', 0, 's', 0, 0, 0,
+    WBVAL(80), /* wPropertyDataLength */
+    '{', 0,
+    'C', 0, 'D', 0, 'B', 0, '3', 0, 'B', 0, '5', 0, 'A', 0, 'D', 0, '-', 0,
+    '2', 0, '9', 0, '3', 0, 'B', 0, '-', 0,
+    '4', 0, '6', 0, '6', 0, '3', 0, '-', 0,
+    'A', 0, 'A', 0, '3', 0, '6', 0, '-',
+    0, '1', 0, 'A', 0, 'A', 0, 'E', 0, '4', 0, '6', 0, '4', 0, '6', 0, '3', 0, '7', 0, '7', 0, '6', 0,
+    '}', 0, 0, 0, 0, 0
+#endif
+};
+
+#define USBD_NUM_DEV_CAPABILITIES (USBD_WEBUSB_ENABLE + USBD_WINUSB_ENABLE)
+
+#define USBD_WEBUSB_DESC_LEN 24
+#define USBD_WINUSB_DESC_LEN 28
+
+#define USBD_BOS_WTOTALLENGTH (0x05 +                                      \
+                               USBD_WEBUSB_DESC_LEN * USBD_WEBUSB_ENABLE + \
+                               USBD_WINUSB_DESC_LEN * USBD_WINUSB_ENABLE)
+
+__ALIGN_BEGIN const uint8_t USBD_BinaryObjectStoreDescriptor[] = {
+    0x05,                         /* bLength */
+    0x0f,                         /* bDescriptorType */
+    WBVAL(USBD_BOS_WTOTALLENGTH), /* wTotalLength */
+    USBD_NUM_DEV_CAPABILITIES,    /* bNumDeviceCaps */
+#if (USBD_WEBUSB_ENABLE)
+    USBD_WEBUSB_DESC_LEN,           /* bLength */
+    0x10,                           /* bDescriptorType */
+    USB_DEVICE_CAPABILITY_PLATFORM, /* bDevCapabilityType */
+    0x00,                           /* bReserved */
+    0x38, 0xB6, 0x08, 0x34,         /* PlatformCapabilityUUID */
+    0xA9, 0x09, 0xA0, 0x47,
+    0x8B, 0xFD, 0xA0, 0x76,
+    0x88, 0x15, 0xB6, 0x65,
+    WBVAL(0x0100), /* 1.00 */ /* bcdVersion */
+    USBD_WINUSB_VENDOR_CODE,  /* bVendorCode */
+    0,                        /* iLandingPage */
+#endif
+#if (USBD_WINUSB_ENABLE)
+    USBD_WINUSB_DESC_LEN,           /* bLength */
+    0x10,                           /* bDescriptorType */
+    USB_DEVICE_CAPABILITY_PLATFORM, /* bDevCapabilityType */
+    0x00,                           /* bReserved */
+    0xDF, 0x60, 0xDD, 0xD8,         /* PlatformCapabilityUUID */
+    0x89, 0x45, 0xC7, 0x4C,
+    0x9C, 0xD2, 0x65, 0x9D,
+    0x9E, 0x64, 0x8A, 0x9F,
+    0x00, 0x00, 0x03, 0x06, /* >= Win 8.1 */ /* dwWindowsVersion*/
+    WBVAL(USBD_WINUSB_DESC_SET_LEN),         /* wDescriptorSetTotalLength */
+    USBD_WINUSB_VENDOR_CODE,                 /* bVendorCode */
+    0,                                       /* bAltEnumCode */
+#endif
+};
+
+const uint8_t winusbv2_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_1, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
+    /* Configuration 0 */
+    USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, INTF_NUM, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+    /* Interface 0 */
+    USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02),
+    /* Endpoint OUT 2 */
+    USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_OUT_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00),
+    /* Endpoint IN 1 */
+    USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_IN_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00),
+    /************** Descriptor of Joystick Mouse interface ****************/
+    /* 09 */
+    0x09,                          /* bLength: Interface Descriptor size */
+    USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
+    0x01,                          /* 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 */
+    /* String 0 (LANGID) */
+    USB_LANGID_INIT(USBD_LANGID_STRING),
+    /* String 1 (Manufacturer) */
+    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 */
+    /* String 2 (Product) */
+    0x2C,                       /* 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 */
+    'W', 0x00,                  /* wcChar10 */
+    'I', 0x00,                  /* wcChar11 */
+    'N', 0x00,                  /* wcChar12 */
+    'U', 0x00,                  /* wcChar13 */
+    'S', 0x00,                  /* wcChar14 */
+    'B', 0x00,                  /* wcChar15 */
+    ' ', 0x00,                  /* wcChar16 */
+    'D', 0x00,                  /* wcChar17 */
+    'E', 0x00,                  /* wcChar18 */
+    'M', 0x00,                  /* wcChar19 */
+    'O', 0x00,                  /* wcChar20 */
+    /* String 3 (Serial Number) */
+    0x1A,                       // bLength
+    USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
+    '0', 0,                     // wcChar0
+    '1', 0,                     // wcChar1
+    '2', 0,                     // wcChar2
+    '3', 0,                     // wcChar3
+    '4', 0,                     // wcChar4
+    '5', 0,                     // wcChar5
+    'A', 0,                     // wcChar6
+    'B', 0,                     // wcChar7
+    'C', 0,                     // wcChar8
+    'D', 0,                     // wcChar9
+    'E', 0,                     // wcChar10
+    'F', 0,                     // wcChar11
+#ifdef CONFIG_USB_HS
+    /* Device Qualifier */
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x10,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x01,
+    0x00,
+#endif
+    /* End */
+    0x00
+};
+
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048];
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
+
+volatile bool ep_tx_busy_flag = false;
+
+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:
+            /* setup first out ep read transfer */
+            usbd_ep_start_read(busid, WINUSB_OUT_EP, read_buffer, 2048);
+            break;
+        case USBD_EVENT_SET_REMOTE_WAKEUP:
+            break;
+        case USBD_EVENT_CLR_REMOTE_WAKEUP:
+            break;
+
+        default:
+            break;
+    }
+}
+
+void usbd_winusb_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
+{
+    USB_LOG_RAW("actual out len:%d\r\n", nbytes);
+    // for (int i = 0; i < 100; i++) {
+    //     printf("%02x ", read_buffer[i]);
+    // }
+    // printf("\r\n");
+    usbd_ep_start_write(busid, WINUSB_IN_EP, read_buffer, nbytes);
+    /* setup next out ep read transfer */
+    usbd_ep_start_read(busid, WINUSB_OUT_EP, read_buffer, 2048);
+}
+
+void usbd_winusb_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
+{
+    USB_LOG_RAW("actual in len:%d\r\n", nbytes);
+
+    if ((nbytes % WINUSB_EP_MPS) == 0 && nbytes) {
+        /* send zlp */
+        usbd_ep_start_write(busid, WINUSB_IN_EP, NULL, 0);
+    } else {
+        ep_tx_busy_flag = false;
+    }
+}
+
+struct usbd_endpoint winusb_out_ep1 = {
+    .ep_addr = WINUSB_OUT_EP,
+    .ep_cb = usbd_winusb_out
+};
+
+struct usbd_endpoint winusb_in_ep1 = {
+    .ep_addr = WINUSB_IN_EP,
+    .ep_cb = usbd_winusb_in
+};
+
+/*!< 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;
+
+/* 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
+};
+
+struct usbd_interface winusb_intf;
+struct usbd_interface intf1;
+
+struct usb_msosv2_descriptor msosv2_desc = {
+    .vendor_code = USBD_WINUSB_VENDOR_CODE,
+    .compat_id = USBD_WinUSBDescriptorSetDescriptor,
+    .compat_id_len = USBD_WINUSB_DESC_SET_LEN,
+};
+
+struct usb_bos_descriptor bos_desc = {
+    .string = USBD_BinaryObjectStoreDescriptor,
+    .string_len = USBD_BOS_WTOTALLENGTH
+};
+
+void winusbv2_init(uint8_t busid, uint32_t reg_base)
+{
+    usbd_desc_register(busid, winusbv2_descriptor);
+    usbd_bos_desc_register(busid, &bos_desc);
+    usbd_msosv2_desc_register(busid, &msosv2_desc);
+
+    /*!< winusb */
+    usbd_add_interface(busid, &winusb_intf);
+    usbd_add_endpoint(busid, &winusb_out_ep1);
+    usbd_add_endpoint(busid, &winusb_in_ep1);
+
+    usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf1, hid_mouse_report_desc, HID_MOUSE_REPORT_DESC_SIZE));
+    usbd_add_endpoint(busid, &hid_in_ep);
+
+    usbd_initialize(busid, reg_base, usbd_event_handler);
+}