Skip to content

Commit 1e5af64

Browse files
committed
MS OS 2.0 descriptors for composite test device
1 parent 2f2ae94 commit 1e5af64

File tree

9 files changed

+587
-191
lines changed

9 files changed

+587
-191
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"files.associations": {
3+
"usbd.h": "c",
4+
"usb_bos.h": "c",
5+
"usb_bos_desc.h": "c"
6+
}
7+
}
Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
//
2+
// Java Does USB
3+
// Loopback device for testing
4+
//
5+
// Copyright (c) 2022 Manuel Bleichenbacher
6+
// Licensed under MIT License
7+
// https://opensource.org/licenses/MIT
8+
//
9+
// USB binary device object store (BOS)
10+
//
11+
12+
#pragma once
13+
14+
#include <libopencm3/usb/usbd.h>
15+
16+
#ifdef __cplusplus
17+
extern "C" {
18+
#endif
19+
20+
/// Descriptor type Binary Device Object Store (BOS)
21+
22+
static const uint8_t USB_DT_BOS = 15;
23+
/// Descriptor type Device Capability
24+
#define USB_DT_DEVICE_CAPABILITY 16
25+
26+
/// Microsoft WCID string index
27+
static const uint8_t USB_WIN_MSFT_WCID_STR_IDX = 0xee;
28+
29+
/// Microsoft compatible ID feature descriptor request index (wIndex)
30+
static const uint16_t USB_WIN_COMP_ID_REQ_INDEX = 0x0004;
31+
32+
#define USB_WIN_WCID_DEFAULT_VENDOR_CODE 0xf0
33+
34+
35+
36+
/// USB BOS device capability types
37+
typedef enum {
38+
/// USB BOS device capability type for Wireless USB-specific device level capabilities
39+
USB_DEV_CAPA_WIRELESS_USB = 0x01,
40+
/// USB BOS device capability type for USB 2.0 extension descriptor
41+
USB_DEV_CAPA_USB_2_0_EXTENSION = 0x02,
42+
/// USB BOS device capability type for SuperSpeed USB specific device level capabilities
43+
USB_DEV_CAPA_SUPERSPEED_USB = 0x03,
44+
/// USB BOS device capability type for instance unique ID used to identify the instance across all operating modes
45+
USB_DEV_CAPA_CONTAINER_ID = 0x04,
46+
/// USB BOS device capability type for device capability specific to a particular platform/operating system
47+
USB_DEV_CAPA_PLATFORM = 0x05,
48+
/// USB BOS device capability type for various PD capabilities of this device
49+
USB_DEV_CAPA_POWER_DELIVERY_CAPABILITY = 0x06,
50+
/// USB BOS device capability type for information on each battery supported by the device
51+
USB_DEV_CAPA_BATTERY_INFO_CAPABILITY = 0x07,
52+
/// USB BOS device capability type for consumer characteristics of a port on the device
53+
USB_DEV_CAPA_PD_CONSUMER_PORT_CAPABILITY = 0x08,
54+
/// USB BOS device capability type for provider characteristics of a port on the device
55+
USB_DEV_CAPA_PD_PROVIDER_PORT_CAPABILITY = 0x09,
56+
/// USB BOS device capability type for SuperSpeed Plus USB specific device level capabilities
57+
USB_DEV_CAPA_SUPERSPEED_PLUS = 0x0a,
58+
/// USB BOS device capability type for precision time measurement (PTM) capability descriptor
59+
USB_DEV_CAPA_PRECISION_TIME_MEASUREMENT = 0x0b,
60+
/// USB BOS device capability type for wireless USB 1.1-specific device level capabilities
61+
USB_DEV_CAPA_WIRELESS_USB_EXT = 0x0c,
62+
/// USB BOS device capability type for billboard capability
63+
USB_DEV_CAPA_BILLBOARD = 0x0d,
64+
/// USB BOS device capability type for authentication capability descriptor
65+
USB_DEV_CAPA_AUTHENTICATION = 0x0e,
66+
/// USB BOS device capability type billboard ex capability
67+
USB_DEV_CAPA_BILLBOARD_EX = 0x0f,
68+
/// USB BOS device capability type for summarizing configuration information for a function implemented by the device
69+
USB_DEV_CAPA_CONFIGURATION_SUMMARY = 0x10,
70+
} usb_dev_capa_type_e;
71+
72+
/// USB BOS descriptor
73+
typedef struct usb_bos_desc {
74+
/// Size of this descriptor
75+
uint8_t bLength;
76+
/// Type of this descriptor (use USB_DT_BOS)
77+
uint8_t bDescriptorType;
78+
/// Length of this descriptor and all of its sub descriptors
79+
uint16_t wTotalLength;
80+
/// The number of separate device capability descriptors in the BOS
81+
uint8_t bNumDeviceCaps;
82+
} __attribute__((packed)) usb_bos_desc;
83+
84+
/// USB BOS device capability descriptor (generic)
85+
typedef struct usb_bos_device_capability_desc {
86+
/// Size of this descriptor
87+
uint8_t bLength;
88+
/// Type of this descriptor (use USB_DT_DEVICE_CAPABILITY)
89+
uint8_t bDescriptorType;
90+
/// Device capability type (see usb_dev_capa_type_e)
91+
uint8_t bDevCapabilityType;
92+
/// Capability-specific data
93+
uint8_t data[];
94+
} __attribute__((packed)) usb_bos_device_capability_desc;
95+
96+
/// USB BOS device capability platform descriptor
97+
typedef struct usb_bos_platform_desc {
98+
/// Size of this descriptor
99+
uint8_t bLength;
100+
/// Type of this descriptor (use USB_DT_DEVICE_CAPABILITY)
101+
uint8_t bDescriptorType;
102+
/// Device capability type (use USB_DEV_CAPA_PLATFORM)
103+
uint8_t bDevCapabilityType;
104+
/// Reserved. Set to 0.
105+
uint8_t bReserved;
106+
/// A 128-bit number (UUID) that uniquely identifies a platform specific capability of the device
107+
uint8_t platformCapabilityUUID[16];
108+
/// Platform-specific capability data
109+
uint8_t capabilityData[];
110+
} __attribute__((packed)) usb_bos_platform_desc;
111+
112+
113+
/// Microsoft OS 2.0 request `wIndex` value to retrieve MS OS 2.0 vendor-specific descriptor
114+
static const uint8_t USB_MSOS20_CTRL_INDEX_DESC = 0x07;
115+
/// Microsoft OS 2.0 request `wIndex` value to set alternate enumeration
116+
static const uint8_t USB_MSOS20_CTRL_INDEX_SET_ALT_ENUM = 0x08;
117+
118+
/// UUID for Microsoft OS 2.0 platform capability: {d8dd60df-4589-4cc7-9cd2-659d9e648a9f}
119+
#define USB_PLATFORM_CAPABILITY_MICROSOFT_OS20_UUID {0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C, 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F}
120+
121+
/// Microsoft OS 2.0 descriptor types
122+
typedef enum {
123+
/// Microsoft OS 2.0 descriptor type for set header
124+
USB_MSOS20_DT_SET_HEADER_DESCRIPTOR = 0x00,
125+
/// Microsoft OS 2.0 descriptor type for configuration subset header
126+
USB_MSOS20_DT_SUBSET_HEADER_CONFIGURATION = 0x01,
127+
/// Microsoft OS 2.0 descriptor type for function subset header
128+
USB_MSOS20_DT_SUBSET_HEADER_FUNCTION = 0x02,
129+
/// Microsoft OS 2.0 feature descriptor type for compatible ID descriptor
130+
USB_MSOS20_DT_FEATURE_COMPATBLE_ID = 0x03,
131+
/// Microsoft OS 2.0 feature descriptor type for registry propery descriptor
132+
USB_MSOS20_DT_FEATURE_REG_PROPERTY = 0x04,
133+
/// Microsoft OS 2.0 feature descriptor type for minimum USB resume time descriptor
134+
USB_MSOS20_DT_FEATURE_MIN_RESUME_TIME = 0x05,
135+
/// Microsoft OS 2.0 feature descriptor type for model ID descriptor
136+
USB_MSOS20_DT_FEATURE_MODEL_ID = 0x06,
137+
/// Microsoft OS 2.0 feature descriptor type for CCGP device descriptor
138+
USB_MSOS20_DT_FEATURE_CCGP_DEVICE = 0x07,
139+
/// Microsoft OS 2.0 feature descriptor type for vendor revision descriptor
140+
USB_MSOS20_DT_FEATURE_VENDOR_REVISION = 0x08,
141+
} usb_msos20_desc_type_e;
142+
143+
/// Microsoft OS 2.0 property types
144+
typedef enum {
145+
/// A NULL-terminated Unicode String (REG_SZ)
146+
USB_MSOS20_PROP_DATA_TYPE_STRING = 1,
147+
/// A NULL-terminated Unicode String that includes environment variables (REG_EXPAND_SZ)
148+
USB_MSOS20_PROP_DATA_TYPE_STRING_EXPAND = 2,
149+
/// Free-form binary (REG_BINARY)
150+
USB_MSOS20_PROP_DATA_TYPE_BINARY = 3,
151+
/// A little-endian 32-bit integer (REG_DWORD_LITTLE_ENDIAN)
152+
USB_MSOS20_PROP_DATA_TYPE_INT32LE = 4,
153+
/// A big-endian 32-bit integer (REG_DWORD_BIG_ENDIAN)
154+
USB_MSOS20_PROP_DATA_TYPE_INT32BE = 5,
155+
/// A NULL-terminated Unicode string that contains a symbolic link (REG_LINK)
156+
USB_MSOS20_PROP_DATA_TYPE_STRING_LINK = 6,
157+
/// Multiple NULL-terminated Unicode strings (REG_MULTI_SZ)
158+
USB_MSOS20_PROP_DATA_TYPE_STRING_MULTI = 7,
159+
} usb_msos20_prop_data_type_e;
160+
161+
/// Microsoft OS 2.0 descriptor Windows version
162+
typedef enum {
163+
/// Windows version 8.1
164+
USB_MSOS20_WIN_VER_8_1 = 0x06030000,
165+
/// Windows version 10
166+
USB_MSOS20_WIN_VER_10 = 0x0a000000,
167+
} usb_msos20_win_ver_e;
168+
169+
/// USB BOS device capability platform descriptor for Microsoft OS 2.0
170+
typedef struct usb_msos20_platform_desc {
171+
/// Size of this descriptor
172+
uint8_t bLength;
173+
/// Type of this descriptor (use USB_DT_DEVICE_CAPABILITY)
174+
uint8_t bDescriptorType;
175+
/// Device capability type (use USB_DEV_CAPA_PLATFORM)
176+
uint8_t bDevCapabilityType;
177+
/// Reserved. Set to 0.
178+
uint8_t bReserved;
179+
/// A 128-bit number / UUID (use USB_PLATFORM_CAPABILITY_MICROSOFT_OS20_UUID)
180+
uint8_t platformCapabilityUUID[16];
181+
/// Minimum Windows version (see usb_msos20_win_ver_e)
182+
uint32_t dwWindowsVersion;
183+
/// The length, in bytes, of the MS OS 2.0 descriptor set
184+
uint16_t wMSOSDescriptorSetTotalLength;
185+
/// Vendor defined code to use to retrieve this version of the MS OS 2.0 descriptor and also to set alternate enumeration behavior on the device
186+
uint8_t bMS_VendorCode;
187+
/// A non-zero value to send to the device to indicate that the device may return non-default USB descriptors for enumeration. If the device does not support alternate enumeration, this value shall be 0.
188+
uint8_t bAltEnumCode;
189+
} __attribute__((packed)) usb_msos20_platform_desc;
190+
191+
/// Microsoft OS 2.0 descriptor set header
192+
typedef struct usb_msos20_desc_set_header
193+
{
194+
/// The length, in bytes, of this header
195+
uint16_t wLength;
196+
/// The type of this descriptor (use USB_MSOS20_DT_SET_HEADER_DESCRIPTOR)
197+
uint16_t wDescriptorType;
198+
/// Windows version (see usb_msos20_win_ver_e)
199+
uint32_t dwWindowsVersion;
200+
/// The size of entire MS OS 2.0 descriptor set. The value shall match the value in the descriptor set information structure.
201+
uint16_t wTotalLength;
202+
} __attribute__((packed)) usb_msos20_desc_set_header;
203+
204+
/// Microsoft OS 2.0 descriptor configuration subset header
205+
typedef struct usb_msos20_desc_subset_header_config
206+
{
207+
/// The length, in bytes, of this header
208+
uint16_t wLength;
209+
/// The type of this descriptor (use USB_MSOS20_DT_SUBSET_HEADER_CONFIGURATION)
210+
uint16_t wDescriptorType;
211+
/// The configuration value for the USB configuration to which this subset applies
212+
uint8_t bConfigurationValue;
213+
/// Reserved. Set to 0.
214+
uint8_t bReserved;
215+
/// The size of entire configuration subset including this header.
216+
uint16_t wTotalLength;
217+
} __attribute__((packed)) usb_msos20_desc_subset_header_config;
218+
219+
/// Microsoft OS 2.0 descriptor function subset header
220+
typedef struct usb_msos20_desc_subset_header_function
221+
{
222+
/// The length, in bytes, of this header
223+
uint16_t wLength;
224+
/// The type of this descriptor (use USB_MSOS20_DT_SUBSET_HEADER_FUNCTION)
225+
uint16_t wDescriptorType;
226+
/// The interface number for the first interface of the function to which this subset applies.
227+
uint8_t bFirstInterface;
228+
/// Reserved. Set to 0.
229+
uint8_t bReserved;
230+
/// The size of entire function subset including this header.
231+
uint16_t wTotalLength;
232+
} __attribute__((packed)) usb_msos20_desc_subset_header_function;
233+
234+
/// Microsoft OS 2.0 compatible ID descriptor
235+
typedef struct usb_msos20_desc_compatible_id
236+
{
237+
/// The length, in bytes, of this header
238+
uint16_t wLength;
239+
/// The type of this descriptor (use USB_MSOS20_DT_FEATURE_COMPATBLE_ID)
240+
uint16_t wDescriptorType;
241+
/// Compatible ID string
242+
char compatibleID[8];
243+
/// Sub-compatible ID string
244+
char subCompatibleID[8];
245+
} __attribute__((packed)) usb_msos20_desc_compatible_id;
246+
247+
extern const usb_msos20_platform_desc msos_desc;
248+
249+
/**
250+
* Register the control request handler to respond to BOS request (for automatic WinUSB installation)
251+
*
252+
* @param device USB device
253+
* @param bos_descs array of BOS descriptors
254+
* @param num_bos_descs number of BOS descriptors
255+
* @param msos_desc_set MS OS 2.0 descriptor set
256+
*/
257+
void usb_dev_register_bos(usbd_device* device,
258+
const usb_bos_device_capability_desc* const * bos_descs, int num_bos_descs,
259+
const usb_msos20_desc_set_header* msos_desc_set, uint8_t msos_vendor_code);
260+
261+
#ifdef __cplusplus
262+
}
263+
#endif
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//
2+
// Java Does USB
3+
// Loopback device for testing
4+
//
5+
// Copyright (c) 2022 Manuel Bleichenbacher
6+
// Licensed under MIT License
7+
// https://opensource.org/licenses/MIT
8+
//
9+
// USB BOS descriptor
10+
//
11+
12+
#pragma once
13+
14+
#include "usb_bos.h"
15+
#include <libopencm3/usb/usbd.h>
16+
17+
#ifdef __cplusplus
18+
extern "C" {
19+
#endif
20+
21+
#define MSOS_VENDOR_CODE 0x44
22+
23+
extern const usb_bos_device_capability_desc* const bos_descs[1];
24+
extern const usb_msos20_desc_set_header* msos_desc_set;
25+
26+
#ifdef __cplusplus
27+
}
28+
#endif

test-devices/composite-stm32/include/wcid.h

Lines changed: 0 additions & 17 deletions
This file was deleted.

test-devices/composite-stm32/src/main.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#include "circ_buf.h"
2121
#include "common.h"
2222
#include "usb_descriptor.h"
23-
#include "wcid.h"
23+
#include "usb_bos_desc.h"
2424

2525
#define USB_CDC_REQ_GET_LINE_CODING 0x21
2626

@@ -78,6 +78,7 @@ static bool is_serial_tx = false;
7878
// indicates if the serial RX endpoint is forced to NAK to prevent receiving further data
7979
static bool is_serial_rx_nak = false;
8080

81+
8182
void init() {
8283
// Enable required clocks
8384
rcc_clock_setup_in_hse_8mhz_out_72mhz();
@@ -109,18 +110,20 @@ void usb_init() {
109110

110111
// Set callback for config calls
111112
usbd_register_set_config_callback(usb_device, on_usb_set_config);
112-
register_wcid_desc(usb_device);
113+
usb_dev_register_bos(usb_device, bos_descs, sizeof(bos_descs) / sizeof(bos_descs[0]),
114+
msos_desc_set, MSOS_VENDOR_CODE);
113115
}
114116

115117
// Called when the host connects to the device and selects a configuration
116118
void on_usb_set_config(usbd_device *usbd_dev, __attribute__((unused)) uint16_t wValue) {
117-
register_wcid_desc(usbd_dev);
119+
usb_dev_register_bos(usb_device, bos_descs, sizeof(bos_descs) / sizeof(bos_descs[0]),
120+
msos_desc_set, MSOS_VENDOR_CODE);
118121

119122
// register control request handler for vendor specific requests (used for test)
120123
usbd_register_control_callback(usbd_dev, USB_REQ_TYPE_VENDOR | USB_REQ_TYPE_INTERFACE,
121124
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, on_vendor_control_request);
122125

123-
// resgier control request handler for class specific requests (used for CDC ACM)
126+
// register control request handler for class specific requests (used for CDC ACM)
124127
usbd_register_control_callback(usbd_dev, USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
125128
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, on_class_control_request);
126129

0 commit comments

Comments
 (0)