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 Jul 6, 2023
1 parent 8042218 commit e420eb5
Show file tree
Hide file tree
Showing 2 changed files with 150 additions and 28 deletions.
102 changes: 102 additions & 0 deletions include/zephyr/usb/msos_desc.h
Original file line number Diff line number Diff line change
@@ -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 msos2_descriptor_index {
MS_OS_20_DESCRIPTOR_INDEX = 0x07,
MS_OS_20_SET_ALT_ENUMERATION = 0x08,
};

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 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 */
76 changes: 48 additions & 28 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 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 {
Expand Down Expand Up @@ -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
},
Expand Down Expand Up @@ -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");

Expand Down

0 comments on commit e420eb5

Please sign in to comment.