samples: subsys: usb: webusb: Fix Win10 detection

This patch refactors the usage of MS OS 2.0 descriptors in the
WebUSB sample. The function subset header was removed since it
is not allowed for non-composite devices.
Also, a new random GUID was added for automatic driver installation.

Signed-off-by: Maximilian Deubel <maximilian.deubel@nordicsemi.no>
This commit is contained in:
Maximilian Deubel 2023-06-26 14:43:24 +02:00 committed by Carles Cufí
parent fbacedaef8
commit 860515a3ad
2 changed files with 149 additions and 27 deletions

View file

@ -0,0 +1,102 @@
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief MS OS 2.0 descriptor definitions
*
*/
#ifndef ZEPHYR_INCLUDE_USB_MSOS_DESC_H
#define ZEPHYR_INCLUDE_USB_MSOS_DESC_H
#include <stdint.h>
enum msosv2_descriptor_index {
MS_OS_20_DESCRIPTOR_INDEX = 0x07,
MS_OS_20_SET_ALT_ENUMERATION = 0x08,
};
enum msosv2_descriptor_type {
MS_OS_20_SET_HEADER_DESCRIPTOR = 0x00,
MS_OS_20_SUBSET_HEADER_CONFIGURATION = 0x01,
MS_OS_20_SUBSET_HEADER_FUNCTION = 0x02,
MS_OS_20_FEATURE_COMPATIBLE_ID = 0x03,
MS_OS_20_FEATURE_REG_PROPERTY = 0x04,
MS_OS_20_FEATURE_MIN_RESUME_TIME = 0x05,
MS_OS_20_FEATURE_MODEL_ID = 0x06,
MS_OS_20_FEATURE_CCGP_DEVICE = 0x07,
MS_OS_20_FEATURE_VENDOR_REVISION = 0x08
};
enum msosv2_property_data_type {
MS_OS_20_PROPERTY_DATA_RESERVED = 0,
MS_OS_20_PROPERTY_DATA_REG_SZ = 1,
MS_OS_20_PROPERTY_DATA_REG_EXPAND_SZ = 2,
MS_OS_20_PROPERTY_DATA_REG_BINARY = 3,
MS_OS_20_PROPERTY_DATA_REG_DWORD_LITTLE_ENDIAN = 4,
MS_OS_20_PROPERTY_DATA_REG_DWORD_BIG_ENDIAN = 5,
MS_OS_20_PROPERTY_DATA_REG_LINK = 6,
MS_OS_20_PROPERTY_DATA_REG_MULTI_SZ = 7
};
/* Microsoft OS 2.0 descriptor set header */
struct msosv2_descriptor_set_header {
uint16_t wLength;
uint16_t wDescriptorType;
uint32_t dwWindowsVersion;
uint16_t wTotalLength;
} __packed;
/* Microsoft OS 2.0 configuration subset header
* This header is for composite devices with multiple configurations.
*/
struct msosv2_configuration_subset_header {
uint16_t wLength;
uint16_t wDescriptorType;
uint8_t bConfigurationValue;
uint8_t bReserved;
uint16_t wTotalLength;
} __packed;
/* Microsoft OS 2.0 function subset header
* Note: This must be used if your device has multiple interfaces and cannot be used otherwise.
*/
struct msosv2_function_subset_header {
uint16_t wLength;
uint16_t wDescriptorType;
uint8_t bFirstInterface;
uint8_t bReserved;
uint16_t wSubsetLength;
} __packed;
/* Microsoft OS 2.0 compatible ID descriptor */
struct msosv2_compatible_id {
uint16_t wLength;
uint16_t wDescriptorType;
uint8_t CompatibleID[8];
uint8_t SubCompatibleID[8];
} __packed;
/* Microsoft OS 2.0 Registry property descriptor: DeviceInterfaceGUIDs */
struct msosv2_guids_property {
uint16_t wLength;
uint16_t wDescriptorType;
uint16_t wPropertyDataType;
uint16_t wPropertyNameLength;
uint8_t PropertyName[42];
uint16_t wPropertyDataLength;
uint8_t bPropertyData[80];
} __packed;
/* DeviceInterfaceGUIDs */
#define DEVICE_INTERFACE_GUIDS_PROPERTY_NAME \
'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
#endif /* ZEPHYR_INCLUDE_USB_MSOS_DESC_H */

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2016-2019 Intel Corporation
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -20,33 +21,51 @@ LOG_MODULE_REGISTER(main);
#include <zephyr/sys/byteorder.h>
#include <zephyr/usb/usb_device.h>
#include <zephyr/usb/bos.h>
#include <zephyr/usb/msos_desc.h>
#include "webusb.h"
/* Predefined response to control commands related to MS OS 2.0 descriptors */
static const uint8_t msos2_descriptor[] = {
/* MS OS 2.0 set header descriptor */
0x0A, 0x00, /* Descriptor size (10 bytes) */
0x00, 0x00, /* MS_OS_20_SET_HEADER_DESCRIPTOR */
0x00, 0x00, 0x03, 0x06, /* Windows version (8.1) (0x06030000) */
(0x0A + 0x14 + 0x08), 0x00, /* Length of the MS OS 2.0 descriptor set */
/* random GUID {FA611CC3-7057-42EE-9D82-4919639562B3} */
#define WEBUSB_DEVICE_INTERFACE_GUID \
'{', 0x00, 'F', 0x00, 'A', 0x00, '6', 0x00, '1', 0x00, '1', 0x00, \
'C', 0x00, 'C', 0x00, '3', 0x00, '-', 0x00, '7', 0x00, '0', 0x00, \
'5', 0x00, '7', 0x00, '-', 0x00, '4', 0x00, '2', 0x00, 'E', 0x00, \
'E', 0x00, '-', 0x00, '9', 0x00, 'D', 0x00, '8', 0x00, '2', 0x00, \
'-', 0x00, '4', 0x00, '9', 0x00, '1', 0x00, '9', 0x00, '6', 0x00, \
'3', 0x00, '9', 0x00, '5', 0x00, '6', 0x00, '2', 0x00, 'B', 0x00, \
'3', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00
/* MS OS 2.0 function subset ID descriptor
* This means that the descriptors below will only apply to one
* set of interfaces
#define COMPATIBLE_ID_WINUSB \
'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00
static struct msosv2_descriptor_t {
struct msosv2_descriptor_set_header header;
struct msosv2_compatible_id webusb_compatible_id;
struct msosv2_guids_property webusb_guids_property;
} __packed msosv2_descriptor = {
/* Microsoft OS 2.0 descriptor set
* This tells Windows what kind of device this is and to install the WinUSB driver.
*/
0x08, 0x00, /* Descriptor size (8 bytes) */
0x02, 0x00, /* MS_OS_20_SUBSET_HEADER_FUNCTION */
0x02, /* Index of first interface this subset applies to. */
0x00, /* reserved */
(0x08 + 0x14), 0x00, /* Length of the MS OS 2.0 descriptor subset */
/* MS OS 2.0 compatible ID descriptor */
0x14, 0x00, /* Descriptor size */
0x03, 0x00, /* MS_OS_20_FEATURE_COMPATIBLE_ID */
/* 8-byte compatible ID string, then 8-byte sub-compatible ID string */
'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
.header = {
.wLength = sizeof(struct msosv2_descriptor_set_header),
.wDescriptorType = MS_OS_20_SET_HEADER_DESCRIPTOR,
.dwWindowsVersion = 0x06030000,
.wTotalLength = sizeof(struct msosv2_descriptor_t),
},
.webusb_compatible_id = {
.wLength = sizeof(struct msosv2_compatible_id),
.wDescriptorType = MS_OS_20_FEATURE_COMPATIBLE_ID,
.CompatibleID = {COMPATIBLE_ID_WINUSB},
},
.webusb_guids_property = {
.wLength = sizeof(struct msosv2_guids_property),
.wDescriptorType = MS_OS_20_FEATURE_REG_PROPERTY,
.wPropertyDataType = MS_OS_20_PROPERTY_DATA_REG_MULTI_SZ,
.wPropertyNameLength = 42,
.PropertyName = {DEVICE_INTERFACE_GUIDS_PROPERTY_NAME},
.wPropertyDataLength = 80,
.bPropertyData = {WEBUSB_DEVICE_INTERFACE_GUID},
},
};
USB_DEVICE_BOS_DESC_DEFINE_CAP struct usb_bos_webusb_desc {
@ -113,7 +132,8 @@ USB_DEVICE_BOS_DESC_DEFINE_CAP struct usb_bos_msosv2_desc {
/* Windows version (8.1) (0x06030000) */
.dwWindowsVersion = sys_cpu_to_le32(0x06030000),
.wMSOSDescriptorSetTotalLength =
sys_cpu_to_le16(sizeof(msos2_descriptor)),
sys_cpu_to_le16(sizeof(msosv2_descriptor)),
/* Arbitrary code that is used as bRequest for vendor command */
.bMS_VendorCode = 0x02,
.bAltEnumCode = 0x00
},
@ -268,11 +288,11 @@ int vendor_handle_req(struct usb_setup_packet *pSetup,
LOG_DBG("Get webusb_origin_url");
return 0;
} else if (pSetup->bRequest == 0x02 && pSetup->wIndex == 0x07) {
} else if (pSetup->bRequest == bos_cap_msosv2.cap.bMS_VendorCode &&
pSetup->wIndex == MS_OS_20_DESCRIPTOR_INDEX) {
/* Get MS OS 2.0 Descriptors request */
/* 0x07 means "MS_OS_20_DESCRIPTOR_INDEX" */
*data = (uint8_t *)(&msos2_descriptor);
*len = sizeof(msos2_descriptor);
*data = (uint8_t *)(&msosv2_descriptor);
*len = sizeof(msosv2_descriptor);
LOG_DBG("Get MS OS Descriptors v2");