Skip to content

Commit

Permalink
samples: subsys: usb: webusb: Fix Win10 detection
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
maxd-nordic committed Jun 29, 2023
1 parent 8042218 commit ac97f5d
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 26 deletions.
92 changes: 92 additions & 0 deletions include/zephyr/usb/msos_desc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/

/**
* @file
* @brief MS OS 2.0 descriptor definitions
*
*/

#include <stdint.h>

enum ms_os_20_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 ms_os_20_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 ms_os_20_root_desc {
uint16_t wLength;
uint16_t wDescriptorType;
uint32_t dwWindowsVersion;
uint16_t wTotalLength;
} __packed;

/* Microsoft OS 2.0 configuration subset header
* This is header is for composite devices with multiple configurations.
*/
struct ms_os_20_configuration_subset_header_desc {
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 ms_os_20_function_subset_header_desc {
uint16_t wLength;
uint16_t wDescriptorType;
uint8_t bFirstInterface;
uint8_t bReserved;
uint16_t wSubsetLength;
} __packed;

/* Microsoft OS 2.0 compatible ID descriptor */
struct ms_os_20_compatible_id_desc {
uint16_t wLength;
uint16_t wDescriptorType;
uint8_t CompatibleID[8];
uint8_t SubCompatibleID[8];
} __packed;

/* Microsoft OS 2.0 Registry property descriptor: DeviceInterfaceGUIDs */
struct ms_os_20_guids_property_desc {
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
73 changes: 47 additions & 26 deletions samples/subsys/usb/webusb/src/main.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2016-2019 Intel Corporation
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand All @@ -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 */

/* MS OS 2.0 function subset ID descriptor
* This means that the descriptors below will only apply to one
* set of interfaces
/* 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

#define COMPATIBLE_ID_WINUSB \
'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00

static struct msosv2_descriptor_t {
struct ms_os_20_root_desc header;
struct ms_os_20_compatible_id_desc webusb_compatible_id;
struct ms_os_20_guids_property_desc 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 ms_os_20_root_desc),
.wDescriptorType = MS_OS_20_SET_HEADER_DESCRIPTOR,
.dwWindowsVersion = 0x06030000,
.wTotalLength = sizeof(struct msosv2_descriptor_t),
},
.webusb_compatible_id = {
.wLength = sizeof(struct ms_os_20_compatible_id_desc),
.wDescriptorType = MS_OS_20_FEATURE_COMPATIBLE_ID,
.CompatibleID = {COMPATIBLE_ID_WINUSB},
},
.webusb_guids_property = {
.wLength = sizeof(struct ms_os_20_guids_property_desc),
.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 {
Expand Down Expand Up @@ -113,7 +132,7 @@ 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)),
.bMS_VendorCode = 0x02,
.bAltEnumCode = 0x00
},
Expand Down Expand Up @@ -198,6 +217,8 @@ static const uint8_t msos1_compatid_descriptor[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* reserved */
};



/**
* @brief Custom handler for standard requests in
* order to catch the request and return the
Expand Down Expand Up @@ -271,8 +292,8 @@ int vendor_handle_req(struct usb_setup_packet *pSetup,
} else if (pSetup->bRequest == 0x02 && pSetup->wIndex == 0x07) {
/* 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");

Expand Down

0 comments on commit ac97f5d

Please sign in to comment.