diff --git a/README.md b/README.md index 011d2222..a0645bbc 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ CherryUSB Device Stack has the following functions: - Support Device Firmware Upgrade CLASS (DFU) - Support USB MIDI CLASS (MIDI) - Support Remote NDIS (RNDIS) -- Support WINUSB1.0、WINUSB2.0(with BOS) +- Support WINUSB1.0、WINUSB2.0、WEBUSB、BOS - Support Vendor class - Support UF2 - Support multi device with the same USB IP diff --git a/README_zh.md b/README_zh.md index 59e623e6..41334f3c 100644 --- a/README_zh.md +++ b/README_zh.md @@ -65,7 +65,7 @@ CherryUSB Device 协议栈当前实现以下功能: - 支持 Device Firmware Upgrade CLASS (DFU) - 支持 USB MIDI CLASS (MIDI) - 支持 Remote NDIS (RNDIS) -- 支持 WINUSB1.0、WINUSB2.0(带 BOS ) +- 支持 WINUSB1.0、WINUSB2.0、WEBUSB、BOS - 支持 Vendor 类 class - 支持 UF2 - 支持相同 USB IP 的多从机 diff --git a/common/usb_def.h b/common/usb_def.h index aea3d6ad..27b4d821 100644 --- a/common/usb_def.h +++ b/common/usb_def.h @@ -614,7 +614,7 @@ struct usb_webusb_url_descriptor { char URL[]; } __PACKED; -struct usb_webusb_url_ex_descriptor { +struct usb_webusb_descriptor { uint8_t vendor_code; const uint8_t *string; uint32_t string_len; diff --git a/core/usbd_core.c b/core/usbd_core.c index b3564248..21022e74 100644 --- a/core/usbd_core.c +++ b/core/usbd_core.c @@ -45,6 +45,7 @@ USB_NOCACHE_RAM_SECTION struct usbd_core_priv { struct usb_msosv1_descriptor *msosv1_desc; struct usb_msosv2_descriptor *msosv2_desc; struct usb_bos_descriptor *bos_desc; + struct usb_webusb_descriptor *webusb_url_desc; #endif /* Buffer used for storing standard, class and vendor request data */ USB_MEM_ALIGNX uint8_t req_data[CONFIG_USBDEV_REQUEST_BUFFER_LEN]; @@ -908,10 +909,12 @@ static int usbd_vendor_request_handler(uint8_t busid, struct usb_setup_packet *s return -1; } } - } else if (g_usbd_core[busid].descriptors->webusb_url_descriptor) { + } + + if (g_usbd_core[busid].descriptors->webusb_url_descriptor) { if (setup->bRequest == g_usbd_core[busid].descriptors->webusb_url_descriptor->vendor_code) { switch (setup->wIndex) { - case WINUSB_REQUEST_GET_DESCRIPTOR_SET: + case WEBUSB_REQUEST_GET_URL: desclen = g_usbd_core[busid].descriptors->webusb_url_descriptor->string_len; *data = (uint8_t *)g_usbd_core[busid].descriptors->webusb_url_descriptor->string; //memcpy(*data, g_usbd_core[busid].descriptors->webusb_url_descriptor->string, desclen); @@ -964,6 +967,22 @@ static int usbd_vendor_request_handler(uint8_t busid, struct usb_setup_packet *s } } } + + if (g_usbd_core[busid].webusb_url_desc) { + if (setup->bRequest == g_usbd_core[busid].webusb_url_desc->vendor_code) { + switch (setup->wIndex) { + case WEBUSB_REQUEST_GET_URL: + desclen = g_usbd_core[busid].webusb_url_desc->string_len; + *data = (uint8_t *)g_usbd_core[busid].webusb_url_desc->string; + //memcpy(*data, g_usbd_core[busid].webusb_url_desc->string, desclen); + *len = desclen; + return 0; + default: + USB_LOG_ERR("unknown vendor code\r\n"); + return -1; + } + } + } #endif for (uint8_t i = 0; i < g_usbd_core[busid].intf_offset; i++) { struct usbd_interface *intf = g_usbd_core[busid].intf[i]; @@ -1280,6 +1299,11 @@ void usbd_bos_desc_register(uint8_t busid, struct usb_bos_descriptor *desc) { g_usbd_core[busid].bos_desc = desc; } + +void usbd_webusb_desc_register(uint8_t busid, struct usb_webusb_descriptor *desc) +{ + g_usbd_core[busid].webusb_url_desc = desc; +} #endif void usbd_add_interface(uint8_t busid, struct usbd_interface *intf) diff --git a/core/usbd_core.h b/core/usbd_core.h index 01335f2f..87a386fe 100644 --- a/core/usbd_core.h +++ b/core/usbd_core.h @@ -93,6 +93,7 @@ void usbd_desc_register(uint8_t busid, const uint8_t *desc); void usbd_msosv1_desc_register(uint8_t busid, struct usb_msosv1_descriptor *desc); void usbd_msosv2_desc_register(uint8_t busid, struct usb_msosv2_descriptor *desc); void usbd_bos_desc_register(uint8_t busid, struct usb_bos_descriptor *desc); +void usbd_webusb_desc_register(uint8_t busid, struct usb_webusb_descriptor *desc); #endif void usbd_add_interface(uint8_t busid, struct usbd_interface *intf); diff --git a/demo/webusb_hid_template.c b/demo/webusb_hid_template.c new file mode 100644 index 00000000..7dd0845b --- /dev/null +++ b/demo/webusb_hid_template.c @@ -0,0 +1,382 @@ +/* + * Copyright (c) 2024, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "usbd_core.h" +#include "usbd_hid.h" + +#define USBD_VID 0xffff +#define USBD_PID 0xffff +#define USBD_MAX_POWER 100 +#define USBD_LANGID_STRING 1033 + +#define HID_INT_EP 0x81 +#define HID_INT_EP_SIZE 8 +#define HID_INT_EP_INTERVAL 10 + +#define USB_HID_CONFIG_DESC_SIZ (34 + 9) +#define HID_KEYBOARD_REPORT_DESC_SIZE 63 + +#define USBD_WEBUSB_VENDOR_CODE (0x22) +#define USBD_WINUSB_VENDOR_CODE (0x21) + +#define USBD_WINUSB_DESC_SET_LEN (0xB2) +#define URL_DESCRIPTOR_LENGTH (3 + 36) + +#define USBD_WEBUSB_INTF_NUM 0x01 + +#define WEBUSB_URL_STRINGS \ + 'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o', 'm', '/', \ + 'c', 'h', 'e', 'r', 'r', 'y', '-', 'e', 'm', 'b', 'e', 'd', 'd', 'e', 'd', '/', 'C', 'h', 'e', 'r', 'r', 'y', 'U', 'S', 'B', + +const uint8_t USBD_WinUSBDescriptorSetDescriptor[USBD_WINUSB_DESC_SET_LEN] = { + // Microsoft OS 2.0 描述符集标头 + 0x0A, 0x00, // Descriptor size (10 bytes) + 0x00, 0x00, // MS OS 2.0 descriptor set header + 0x00, 0x00, 0x03, 0x06, // Windows version (8.1) (0x06030000) + USBD_WINUSB_DESC_SET_LEN, 0x00, // Size, MS OS 2.0 descriptor set + + // Microsoft OS 2.0 配置子集标头 + 0x08, 0x00, // wLength + 0x01, 0x00, // wDescriptorType + 0x00, // 适用于配置 1 + 0x00, // bReserved + 0XA8, 0X00, // Size, MS OS 2.0 configuration subset + + // Microsoft OS 2.0 功能子集头 + 0x08, 0x00, // Descriptor size (8 bytes) + 0x02, 0x00, // MS OS 2.0 function subset header + USBD_WEBUSB_INTF_NUM, // bFirstInterface + 0x00, // 必须设置为 0 + 0xA0, 0x00, + + // Microsoft OS 2.0 兼容 ID 描述符 + // 兼容 ID 描述符告诉 Windows 此设备与 WinUSB 驱动程序兼容 + 0x14, 0x00, // wLength 20 + 0x03, 0x00, // MS_OS_20_FEATURE_COMPATIBLE_ID + 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + // Microsoft OS 2.0 注册表属性描述符 + // 注册表属性分配设备接口 GUID + 0x84, 0x00, //wLength: 132 + 0x04, 0x00, // wDescriptorType: MS_OS_20_FEATURE_REG_PROPERTY: 0x04 (Table 9) + 0x07, 0x00, //wPropertyDataType: REG_MULTI_SZ (Table 15) + 0x2a, 0x00, //wPropertyNameLength: + //bPropertyName: “DeviceInterfaceGUID” + 'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, 'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, 't', 0x00, 'e', 0x00, + 'r', 0x00, 'f', 0x00, 'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, 'U', 0x00, 'I', 0x00, 'D', 0x00, 's', 0x00, + 0x00, 0x00, + 0x50, 0x00, // wPropertyDataLength + //bPropertyData: “{975F44D9-0D08-43FD-8B3E-127CA8AFFF9D}”. + '{', 0x00, '9', 0x00, 'd', 0x00, '7', 0x00, 'd', 0x00, 'e', 0x00, 'b', 0x00, 'b', 0x00, 'c', 0x00, '-', 0x00, + 'c', 0x00, '8', 0x00, '5', 0x00, 'd', 0x00, '-', 0x00, '1', 0x00, '1', 0x00, 'd', 0x00, '1', 0x00, '-', 0x00, + '9', 0x00, 'e', 0x00, 'b', 0x00, '4', 0x00, '-', 0x00, '0', 0x00, '0', 0x00, '6', 0x00, '0', 0x00, '0', 0x00, + '8', 0x00, 'c', 0x00, '3', 0x00, 'a', 0x00, '1', 0x00, '9', 0x00, 'a', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +const uint8_t USBD_WebUSBURLDescriptor[URL_DESCRIPTOR_LENGTH] = { + URL_DESCRIPTOR_LENGTH, + WEBUSB_URL_TYPE, + WEBUSB_URL_SCHEME_HTTPS, + WEBUSB_URL_STRINGS +}; + +#define USBD_BOS_WTOTALLENGTH 0x39 + +#define LANDING_PAGE 0x01 +uint8_t USBD_BinaryObjectStoreDescriptor[USBD_BOS_WTOTALLENGTH] = { + // BOS描述符 + 0x05, // bLength 固长为5 + 0x0F, // bDescriptorType 固定为15 + USBD_BOS_WTOTALLENGTH, 0x00, // wTotalLength BOS描述符的总大小 + 0x02, // bNumDeviceCaps BOS描述符中独立设备功能特性描述符的数量 + + // WebUSB 平台功能描述符 + 0x18, // Descriptor size (24 bytes) + 0x10, // Descriptor type (Device Capability) 设备功能描述符 + 0x05, // Capability type (Platform) 平台描述符 + 0x00, // Reserved + + // WebUSB Platform Capability ID (3408b638-09a9-47a0-8bfd-a0768815b665) + // 平台功能 UUID 将此标识为WebUSB 平台功能描述符,它提供有关设备的基本信息 + 0x38, 0xB6, 0x08, 0x34, + 0xA9, 0x09, + 0xA0, 0x47, + 0x8B, 0xFD, + 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65, + + 0x00, 0x01, // WebUSB version 1.0 + USBD_WEBUSB_VENDOR_CODE, // Vendor-assigned WebUSB request code + LANDING_PAGE, // Landing page + + // Microsoft 平台功能描述符 + // 标头 + 0x1C, // Descriptor size (28 bytes) + 0x10, // Descriptor type (Device Capability) + 0x05, // Capability type (Platform) + 0x00, // Reserved + + 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 最低兼容 Windows 版本 */ + + USBD_WINUSB_DESC_SET_LEN, 0X00, /* wDescriptorSetTotalLength */ + + USBD_WINUSB_VENDOR_CODE, /* bVendorCode */ + 0X00 /* bAltEnumCode */ +}; + +struct usb_webusb_descriptor webusb_url_desc = { + .vendor_code = USBD_WEBUSB_VENDOR_CODE, + .string = USBD_WebUSBURLDescriptor, + .string_len = USBD_WINUSB_DESC_SET_LEN +}; + +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 +}; + +static const uint8_t webusb_hid_descriptor[] = { + USB_DEVICE_DESCRIPTOR_INIT(USB_2_1, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01), + USB_CONFIG_DESCRIPTOR_INIT(USB_HID_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_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 */ + 0x01, /* 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_KEYBOARD_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 */ + USB_INTERFACE_DESCRIPTOR_INIT(USBD_WEBUSB_INTF_NUM, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00), + /////////////////////////////////////// + /// 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 +}; + +/* USB HID device Configuration Descriptor */ +static uint8_t hid_desc[9] __ALIGN_END = { + /* 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_KEYBOARD_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */ + 0x00, +}; + +static const uint8_t hid_keyboard_report_desc[HID_KEYBOARD_REPORT_DESC_SIZE] = { + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x06, // USAGE (Keyboard) + 0xa1, 0x01, // COLLECTION (Application) + 0x05, 0x07, // USAGE_PAGE (Keyboard) + 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl) + 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, 0x08, // REPORT_COUNT (8) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0x95, 0x01, // REPORT_COUNT (1) + 0x75, 0x08, // REPORT_SIZE (8) + 0x81, 0x03, // INPUT (Cnst,Var,Abs) + 0x95, 0x05, // REPORT_COUNT (5) + 0x75, 0x01, // REPORT_SIZE (1) + 0x05, 0x08, // USAGE_PAGE (LEDs) + 0x19, 0x01, // USAGE_MINIMUM (Num Lock) + 0x29, 0x05, // USAGE_MAXIMUM (Kana) + 0x91, 0x02, // OUTPUT (Data,Var,Abs) + 0x95, 0x01, // REPORT_COUNT (1) + 0x75, 0x03, // REPORT_SIZE (3) + 0x91, 0x03, // OUTPUT (Cnst,Var,Abs) + 0x95, 0x06, // REPORT_COUNT (6) + 0x75, 0x08, // REPORT_SIZE (8) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0xFF, // LOGICAL_MAXIMUM (255) + 0x05, 0x07, // USAGE_PAGE (Keyboard) + 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated)) + 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application) + 0x81, 0x00, // INPUT (Data,Ary,Abs) + 0xc0 // END_COLLECTION +}; + +#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; + } +} + +void usbd_hid_int_callback(uint8_t busid, uint8_t ep, uint32_t nbytes) +{ + hid_state = HID_STATE_IDLE; +} + +static struct usbd_endpoint hid_in_ep = { + .ep_cb = usbd_hid_int_callback, + .ep_addr = HID_INT_EP +}; + +static struct usbd_interface intf0; + +void webusb_hid_keyboard_init(uint8_t busid, uint32_t reg_base) +{ + usbd_desc_register(busid, webusb_hid_descriptor); + usbd_bos_desc_register(busid, &bos_desc); + usbd_msosv2_desc_register(busid, &msosv2_desc); + usbd_webusb_desc_register(busid, &webusb_url_desc); + usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_keyboard_report_desc, HID_KEYBOARD_REPORT_DESC_SIZE)); + usbd_add_endpoint(busid, &hid_in_ep); + + usbd_initialize(busid, reg_base, usbd_event_handler); +} + +USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[64]; + +void hid_keyboard_test(uint8_t busid) +{ + const uint8_t sendbuffer[8] = { 0x00, 0x00, HID_KBD_USAGE_A, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + memcpy(write_buffer, sendbuffer, 8); + int ret = usbd_ep_start_write(busid, HID_INT_EP, write_buffer, 8); + if (ret < 0) { + return; + } + hid_state = HID_STATE_BUSY; + while (hid_state == HID_STATE_BUSY) { + } +} diff --git a/demo/webusb_template.c b/demo/webusb_template.c deleted file mode 100644 index dc8bc573..00000000 --- a/demo/webusb_template.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2024, sakumisu - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include "usbd_core.h" - -#define MS_OS_20_DESCRIPTOR_LENGTH (0xB2) - -#define WEBUSB_URL_STRINGS \ - 'd', 'e', 'v', 'a', 'n', 'l', 'a', 'i', '.', 'g', 'i', 't', 'h', 'u', 'b', '.', 'i', 'o', '/', 'w', 'e', 'b', 'd', 'f', 'u', '/', 'd', 'f', 'u', '-', 'u', 't', 'i', 'l' - -#define WL_REQUEST_WEBUSB (0x22) -#define WL_REQUEST_WINUSB (0x21) - -#define URL_DESCRIPTOR_LENGTH 0x2C - -// 描述符集信息 -const uint8_t MS_OS_20_DESCRIPTOR_SET[MS_OS_20_DESCRIPTOR_LENGTH] = { - // Microsoft OS 2.0 描述符集标头 - 0x0A, 0x00, // Descriptor size (10 bytes) - 0x00, 0x00, // MS OS 2.0 descriptor set header - 0x00, 0x00, 0x03, 0x06, // Windows version (8.1) (0x06030000) - MS_OS_20_DESCRIPTOR_LENGTH, 0x00, // Size, MS OS 2.0 descriptor set - - // Microsoft OS 2.0 配置子集标头 - 0x08, 0x00, // wLength - 0x01, 0x00, // wDescriptorType - 0x00, // 适用于配置 1 - 0x00, // bReserved - 0XA8, 0X00, // Size, MS OS 2.0 configuration subset - - // Microsoft OS 2.0 功能子集头 - 0x08, 0x00, // Descriptor size (8 bytes) - 0x02, 0x00, // MS OS 2.0 function subset header - 0x01, // 第2个接口 - 0x00, // 必须设置为 0 - 0xA0, 0x00, - - // Microsoft OS 2.0 兼容 ID 描述符 - // 兼容 ID 描述符告诉 Windows 此设备与 WinUSB 驱动程序兼容 - 0x14, 0x00, // wLength 20 - 0x03, 0x00, // MS_OS_20_FEATURE_COMPATIBLE_ID - 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - // Microsoft OS 2.0 注册表属性描述符 - // 注册表属性分配设备接口 GUID - 0x84, 0x00, //wLength: 132 - 0x04, 0x00, // wDescriptorType: MS_OS_20_FEATURE_REG_PROPERTY: 0x04 (Table 9) - 0x07, 0x00, //wPropertyDataType: REG_MULTI_SZ (Table 15) - 0x2a, 0x00, //wPropertyNameLength: - //bPropertyName: “DeviceInterfaceGUID” - 'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, 'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, 't', 0x00, 'e', 0x00, - 'r', 0x00, 'f', 0x00, 'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, 'U', 0x00, 'I', 0x00, 'D', 0x00, 's', 0x00, - 0x00, 0x00, - 0x50, 0x00, // wPropertyDataLength - //bPropertyData: “{975F44D9-0D08-43FD-8B3E-127CA8AFFF9D}”. - '{', 0x00, '9', 0x00, 'd', 0x00, '7', 0x00, 'd', 0x00, 'e', 0x00, 'b', 0x00, 'b', 0x00, 'c', 0x00, '-', 0x00, - 'c', 0x00, '8', 0x00, '5', 0x00, 'd', 0x00, '-', 0x00, '1', 0x00, '1', 0x00, 'd', 0x00, '1', 0x00, '-', 0x00, - '9', 0x00, 'e', 0x00, 'b', 0x00, '4', 0x00, '-', 0x00, '0', 0x00, '0', 0x00, '6', 0x00, '0', 0x00, '0', 0x00, - '8', 0x00, 'c', 0x00, '3', 0x00, 'a', 0x00, '1', 0x00, '9', 0x00, 'a', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -const uint8_t USBD_WebUSBURLDescriptor[URL_DESCRIPTOR_LENGTH] = { - URL_DESCRIPTOR_LENGTH, - WEBUSB_URL_TYPE, - WEBUSB_URL_SCHEME_HTTPS, - WEBUSB_URL_STRINGS -}; - -struct usb_webusb_url_ex_descriptor webusb_url_desc = { - .vendor_code = WL_REQUEST_WEBUSB, - .string = MS_OS_20_DESCRIPTOR_SET, - .string_len = MS_OS_20_DESCRIPTOR_LENGTH -}; \ No newline at end of file