From 4ccd62d77a5b28bc47ab2b80652751efddb09f14 Mon Sep 17 00:00:00 2001 From: XiNGRZ Date: Tue, 24 Jan 2023 14:52:54 +0800 Subject: [PATCH] usb_comm: Implement WinUSB and WebUSB descriptors --- .../hw75_dynamic/app/usb_comm/CMakeLists.txt | 1 + .../arm/hw75_dynamic/app/usb_comm/Kconfig | 1 + .../arm/hw75_dynamic/app/usb_comm/usb_comm.c | 26 +-- .../app/usb_comm/usb_comm_webusb.c | 196 ++++++++++++++++++ .../app/usb_comm/usb_comm_webusb.h | 12 ++ 5 files changed, 212 insertions(+), 24 deletions(-) create mode 100644 config/boards/arm/hw75_dynamic/app/usb_comm/usb_comm_webusb.c create mode 100644 config/boards/arm/hw75_dynamic/app/usb_comm/usb_comm_webusb.h diff --git a/config/boards/arm/hw75_dynamic/app/usb_comm/CMakeLists.txt b/config/boards/arm/hw75_dynamic/app/usb_comm/CMakeLists.txt index 3bd06146..e4ee0c13 100644 --- a/config/boards/arm/hw75_dynamic/app/usb_comm/CMakeLists.txt +++ b/config/boards/arm/hw75_dynamic/app/usb_comm/CMakeLists.txt @@ -15,6 +15,7 @@ zephyr_library_include_directories(${CMAKE_CURRENT_BINARY_DIR}) zephyr_library_sources(${PROTO_SRCS} ${PROTO_HDRS}) zephyr_library_sources(usb_comm.c) +zephyr_library_sources(usb_comm_webusb.c) zephyr_library_sources(usb_comm_proto.c) add_subdirectory(handler) diff --git a/config/boards/arm/hw75_dynamic/app/usb_comm/Kconfig b/config/boards/arm/hw75_dynamic/app/usb_comm/Kconfig index 53494420..2eb63416 100644 --- a/config/boards/arm/hw75_dynamic/app/usb_comm/Kconfig +++ b/config/boards/arm/hw75_dynamic/app/usb_comm/Kconfig @@ -4,6 +4,7 @@ config HW75_USB_COMM bool depends on USB_DEVICE_DRIVER + select USB_DEVICE_BOS default y if HW75_USB_COMM diff --git a/config/boards/arm/hw75_dynamic/app/usb_comm/usb_comm.c b/config/boards/arm/hw75_dynamic/app/usb_comm/usb_comm.c index 2d115c1f..3007b88c 100644 --- a/config/boards/arm/hw75_dynamic/app/usb_comm/usb_comm.c +++ b/config/boards/arm/hw75_dynamic/app/usb_comm/usb_comm.c @@ -12,6 +12,7 @@ LOG_MODULE_REGISTER(usb_comm, CONFIG_HW75_USB_COMM_LOG_LEVEL); #include #include +#include "usb_comm_webusb.h" #include "usb_comm_proto.h" #define USB_IN_EP_IDX 0 @@ -74,36 +75,13 @@ static void usb_comm_status_cb(struct usb_cfg_data *cfg, enum usb_dc_status_code } } -static int usb_comm_vendor_handler(struct usb_setup_packet *setup, int32_t *len, uint8_t **data) -{ - LOG_DBG("Class request: bRequest 0x%x bmRequestType 0x%x len %d", setup->bRequest, - setup->bmRequestType, *len); - - if (setup->RequestType.recipient != USB_REQTYPE_RECIPIENT_DEVICE) { - return -ENOTSUP; - } - - if (usb_reqtype_is_to_device(setup)) { - LOG_DBG("Host-to-Device, data %p", *data); - LOG_HEXDUMP_DBG(*data, setup->wLength, "H2D"); - return 0; - } - - if ((usb_reqtype_is_to_host(setup))) { - LOG_DBG("Device-to-Host, wLength %d, data %p", setup->wLength, *data); - return 0; - } - - return -ENOTSUP; -} - USBD_DEFINE_CFG_DATA(usb_config) = { .usb_device_description = NULL, .interface_descriptor = &usb_comm_desc.if0, .cb_usb_status = usb_comm_status_cb, .interface = { .class_handler = NULL, - .custom_handler = NULL, + .custom_handler = usb_comm_custom_handler, .vendor_handler = usb_comm_vendor_handler, }, .num_endpoints = ARRAY_SIZE(usb_comm_ep_data), diff --git a/config/boards/arm/hw75_dynamic/app/usb_comm/usb_comm_webusb.c b/config/boards/arm/hw75_dynamic/app/usb_comm/usb_comm_webusb.c new file mode 100644 index 00000000..c10fd9b4 --- /dev/null +++ b/config/boards/arm/hw75_dynamic/app/usb_comm/usb_comm_webusb.c @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2022-2023 XiNGRZ + * SPDX-License-Identifier: MIT + */ + +#include + +#include +LOG_MODULE_DECLARE(usb_comm, CONFIG_HW75_USB_COMM_LOG_LEVEL); + +#include +#include +#include + +#include "usb_comm_webusb.h" + +#define WBVAL(x) (x & 0xFF), ((x >> 8) & 0xFF) + +#define WINUSB_VENDOR_CODE 0x01 +#define WINUSB_REQUEST_GET_DESCRIPTOR_SET 0x07 + +#define WINUSB_DESCRIPTOR_SET_HEADER_SIZE 10 +#define WINUSB_FUNCTION_SUBSET_HEADER_SIZE 8 +#define WINUSB_FEATURE_COMPATIBLE_ID_SIZE 20 +#define WINUSB_FEATURE_REG_PROPERTY_SIZE 132 + +#define WINUSB_SET_HEADER_DESCRIPTOR_TYPE 0x00 +#define WINUSB_SUBSET_HEADER_CONFIGURATION_TYPE 0x01 +#define WINUSB_SUBSET_HEADER_FUNCTION_TYPE 0x02 +#define WINUSB_FEATURE_COMPATIBLE_ID_TYPE 0x03 +#define WINUSB_FEATURE_REG_PROPERTY_TYPE 0x04 + +#define WINUSB_PROP_DATA_TYPE_REG_MULTI_SZ 0x07 + +static const uint8_t msos2_descriptor[] = { + /* Microsoft OS 2.0 descriptor set header */ + WBVAL(WINUSB_DESCRIPTOR_SET_HEADER_SIZE), // wLength + WBVAL(WINUSB_SET_HEADER_DESCRIPTOR_TYPE), // wDescriptorType + 0x00, 0x00, 0x03, 0x06, // Windows version (8.1) (0x06030000) + WBVAL(178), // wTotalLength + + /* Microsoft OS 2.0 configuration subset header */ + WBVAL(WINUSB_FUNCTION_SUBSET_HEADER_SIZE), // wLength + WBVAL(WINUSB_SUBSET_HEADER_CONFIGURATION_TYPE), // wDescriptorType + 0, // bConfigurationValue + 0, // bReserved + WBVAL(168), // wSubsetLength + + /* Microsoft OS 2.0 function subset header */ + WBVAL(WINUSB_FUNCTION_SUBSET_HEADER_SIZE), // wLength + WBVAL(WINUSB_SUBSET_HEADER_FUNCTION_TYPE), // wDescriptorType + 0, // bFirstInterface + 0, // bReserved + WBVAL(160), // wSubsetLength + + /* Microsoft OS 2.0 compatible ID descriptor */ + 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 + + /* Microsoft OS 2.0 registry property descriptor */ + WBVAL(WINUSB_FEATURE_REG_PROPERTY_SIZE), // wLength + WBVAL(WINUSB_FEATURE_REG_PROPERTY_TYPE), // wDescriptorType + WBVAL(WINUSB_PROP_DATA_TYPE_REG_MULTI_SZ), // wPropertyDataType + WBVAL(42), // wPropertyNameLength + /* "DeviceInterfaceGUIDs\0" */ + '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, 0x00, 0, // + WBVAL(80), // wPropertyDataLength + /* "{52267e5b-818d-43c2-a17d-7b185f4d9afe}\0\0" */ + '{', 0, // + '5', 0, '2', 0, '2', 0, '6', 0, '7', 0, 'E', 0, '5', 0, 'B', 0, '-', 0, // + '8', 0, '1', 0, '8', 0, 'D', 0, '-', 0, // + '4', 0, '3', 0, 'C', 0, '2', 0, '-', 0, // + 'A', 0, '1', 0, '7', 0, 'D', 0, '-', 0, // + '7', 0, 'B', 0, '1', 0, '8', 0, // + '5', 0, 'F', 0, '4', 0, 'D', 0, // + '9', 0, 'A', 0, 'F', 0, 'E', 0, // + '}', 0, 0x00, 0, 0x00, 0, // +}; + +USB_DEVICE_BOS_DESC_DEFINE_CAP struct usb_bos_msosv2_desc { + struct usb_bos_platform_descriptor platform; + struct usb_bos_capability_msos cap; +} __packed bos_cap_msosv2 = { + .platform = { + .bLength = sizeof(struct usb_bos_platform_descriptor) + + sizeof(struct usb_bos_capability_msos), + .bDescriptorType = USB_DESC_DEVICE_CAPABILITY, + .bDevCapabilityType = USB_BOS_CAPABILITY_PLATFORM, + .bReserved = 0, + /** + * MS OS 2.0 Platform Capability ID + * D8DD60DF-4589-4CC7-9CD2-659D9E648A9F + */ + .PlatformCapabilityUUID = { + 0xDF, 0x60, 0xDD, 0xD8, + 0x89, 0x45, + 0xC7, 0x4C, + 0x9C, 0xD2, + 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F, + }, + }, + .cap = { + /* Windows version (8.1) (0x06030000) */ + .dwWindowsVersion = sys_cpu_to_le32(0x06030000), + .wMSOSDescriptorSetTotalLength = + sys_cpu_to_le16(sizeof(msos2_descriptor)), + .bMS_VendorCode = WINUSB_VENDOR_CODE, + .bAltEnumCode = 0x00, + }, +}; + +#define WEBUSB_VENDOR_CODE 0x02 +#define WEBUSB_REQUEST_GET_URL 0x02 + +static const uint8_t webusb_origin_url[] = { + /* URL Descriptor */ + 0x0f, // bLength + 0x03, // bDescriptorType (url) + 0x01, 'h', 'w', '.', 'x', 'i', 'n', 'g', 'r', 'z', '.', 'm', 'e' +}; + +USB_DEVICE_BOS_DESC_DEFINE_CAP struct usb_bos_webusb_desc { + struct usb_bos_platform_descriptor platform; + struct usb_bos_capability_webusb cap; +} __packed bos_cap_webusb = { + .platform = { + .bLength = sizeof(struct usb_bos_platform_descriptor) + + sizeof(struct usb_bos_capability_webusb), + .bDescriptorType = USB_DESC_DEVICE_CAPABILITY, + .bDevCapabilityType = USB_BOS_CAPABILITY_PLATFORM, + .bReserved = 0, + /** + * WebUSB Platform Capability UUID + * 3408b638-09a9-47a0-8bfd-a0768815b665 + */ + .PlatformCapabilityUUID = { + 0x38, 0xB6, 0x08, 0x34, + 0xA9, 0x09, + 0xA0, 0x47, + 0x8B, 0xFD, + 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65, + }, + }, + .cap = { + .bcdVersion = sys_cpu_to_le16(0x0100), + .bVendorCode = WEBUSB_VENDOR_CODE, + .iLandingPage = 1, + } +}; + +int usb_comm_custom_handler(struct usb_setup_packet *setup, int32_t *len, uint8_t **data) +{ + return -EINVAL; +} + +int usb_comm_vendor_handler(struct usb_setup_packet *setup, int32_t *len, uint8_t **data) +{ + if (usb_reqtype_is_to_device(setup)) { + return -ENOTSUP; + } + + if (setup->bRequest == WEBUSB_VENDOR_CODE && setup->wIndex == WEBUSB_REQUEST_GET_URL) { + *data = (uint8_t *)(&webusb_origin_url); + *len = sizeof(webusb_origin_url); + + LOG_DBG("Get webusb_origin_url"); + + return 0; + } else if (setup->bRequest == WINUSB_VENDOR_CODE && + setup->wIndex == WINUSB_REQUEST_GET_DESCRIPTOR_SET) { + *data = (uint8_t *)(&msos2_descriptor); + *len = sizeof(msos2_descriptor); + + LOG_DBG("Get MS OS Descriptors v2"); + + return 0; + } + + return -ENOTSUP; +} + +static int usb_comm_init(const struct device *dev) +{ + ARG_UNUSED(dev); + + usb_bos_register_cap((void *)&bos_cap_msosv2); + usb_bos_register_cap((void *)&bos_cap_webusb); + + return 0; +} + +SYS_INIT(usb_comm_init, APPLICATION, CONFIG_ZMK_USB_INIT_PRIORITY); diff --git a/config/boards/arm/hw75_dynamic/app/usb_comm/usb_comm_webusb.h b/config/boards/arm/hw75_dynamic/app/usb_comm/usb_comm_webusb.h new file mode 100644 index 00000000..b7da1df6 --- /dev/null +++ b/config/boards/arm/hw75_dynamic/app/usb_comm/usb_comm_webusb.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2022-2023 XiNGRZ + * SPDX-License-Identifier: MIT + */ + +#pragma once + +#include +#include + +int usb_comm_custom_handler(struct usb_setup_packet *setup, int32_t *len, uint8_t **data); +int usb_comm_vendor_handler(struct usb_setup_packet *setup, int32_t *len, uint8_t **data);