Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

samples: subsys: usb: webusb: Fix Win10 detection #59758

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
*
*/

maxd-nordic marked this conversation as resolved.
Show resolved Hide resolved
#ifndef ZEPHYR_INCLUDE_USB_MSOS_DESC_H
#define ZEPHYR_INCLUDE_USB_MSOS_DESC_H

#include <stdint.h>

maxd-nordic marked this conversation as resolved.
Show resolved Hide resolved
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 */
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 = {
maxd-nordic marked this conversation as resolved.
Show resolved Hide resolved
/* 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,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wish zephyr had sizeof_field() macro like Linux kernel does.

.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,
maxd-nordic marked this conversation as resolved.
Show resolved Hide resolved
.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