1 /*
2 * Copyright (c) 2018 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <bos_desc.h>
8
9 #include <zephyr/ztest.h>
10 #include <zephyr/tc_util.h>
11
12 #include <zephyr/sys/byteorder.h>
13 #include <zephyr/usb/usb_device.h>
14
15 #include <zephyr/usb/bos.h>
16
17 #include <zephyr/logging/log.h>
18 LOG_MODULE_REGISTER(test_main, LOG_LEVEL_DBG);
19
20 /*
21 * Compare old style USB BOS definition with section aligned
22 */
23
24 static struct webusb_bos_desc {
25 struct usb_bos_descriptor bos;
26 struct usb_bos_platform_descriptor platform_webusb;
27 struct usb_bos_capability_webusb capability_data_webusb;
28 struct usb_bos_platform_descriptor platform_msos;
29 struct usb_bos_capability_msos capability_data_msos;
30 } __packed webusb_bos_descriptor = {
31 .bos = {
32 .bLength = sizeof(struct usb_bos_descriptor),
33 .bDescriptorType = USB_DESC_BOS,
34 .wTotalLength = sizeof(struct webusb_bos_desc),
35 .bNumDeviceCaps = 2,
36 },
37 /* WebUSB Platform Capability Descriptor:
38 * https://wicg.github.io/webusb/#webusb-platform-capability-descriptor
39 */
40 .platform_webusb = {
41 .bLength = sizeof(struct usb_bos_platform_descriptor)
42 + sizeof(struct usb_bos_capability_webusb),
43 .bDescriptorType = USB_DESC_DEVICE_CAPABILITY,
44 .bDevCapabilityType = USB_BOS_CAPABILITY_PLATFORM,
45 .bReserved = 0,
46 /* WebUSB Platform Capability UUID
47 * 3408b638-09a9-47a0-8bfd-a0768815b665
48 */
49 .PlatformCapabilityUUID = {
50 0x38, 0xB6, 0x08, 0x34,
51 0xA9, 0x09,
52 0xA0, 0x47,
53 0x8B, 0xFD,
54 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65,
55 },
56 },
57 .capability_data_webusb = {
58 .bcdVersion = sys_cpu_to_le16(0x0100),
59 .bVendorCode = 0x01,
60 .iLandingPage = 0x01
61 },
62 /* Microsoft OS 2.0 Platform Capability Descriptor
63 * See https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/
64 * microsoft-defined-usb-descriptors
65 * Adapted from the source:
66 * https://github.com/sowbug/weblight/blob/master/firmware/webusb.c
67 * (BSD-2) Thanks http://janaxelson.com/files/ms_os_20_descriptors.c
68 */
69 .platform_msos = {
70 .bLength = sizeof(struct usb_bos_platform_descriptor)
71 + sizeof(struct usb_bos_capability_msos),
72 .bDescriptorType = USB_DESC_DEVICE_CAPABILITY,
73 .bDevCapabilityType = USB_BOS_CAPABILITY_PLATFORM,
74 .bReserved = 0,
75 .PlatformCapabilityUUID = {
76 /**
77 * MS OS 2.0 Platform Capability ID
78 * D8DD60DF-4589-4CC7-9CD2-659D9E648A9F
79 */
80 0xDF, 0x60, 0xDD, 0xD8,
81 0x89, 0x45,
82 0xC7, 0x4C,
83 0x9C, 0xD2,
84 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F,
85 },
86 },
87 .capability_data_msos = {
88 /* Windows version (8.1) (0x06030000) */
89 .dwWindowsVersion = sys_cpu_to_le32(0x06030000),
90 /* The MSOS2.0 descriptor is not relevant here. */
91 .wMSOSDescriptorSetTotalLength = 0,
92 .bMS_VendorCode = 0x02,
93 .bAltEnumCode = 0x00
94 }
95 };
96
97 /* In a case linker places data in a different order */
98 static struct webusb_bos_desc_2 {
99 struct usb_bos_descriptor bos;
100 struct usb_bos_platform_descriptor platform_msos;
101 struct usb_bos_capability_msos capability_data_msos;
102 struct usb_bos_platform_descriptor platform_webusb;
103 struct usb_bos_capability_webusb capability_data_webusb;
104 } __packed webusb_bos_descriptor_2;
105
106 USB_DEVICE_BOS_DESC_DEFINE_CAP struct usb_bos_webusb {
107 struct usb_bos_platform_descriptor platform;
108 struct usb_bos_capability_webusb cap;
109 } __packed cap_webusb = {
110 .platform = {
111 .bLength = sizeof(struct usb_bos_platform_descriptor) +
112 sizeof(struct usb_bos_capability_webusb),
113 .bDescriptorType = USB_DESC_DEVICE_CAPABILITY,
114 .bDevCapabilityType = USB_BOS_CAPABILITY_PLATFORM,
115 .bReserved = 0,
116 /* WebUSB Platform Capability UUID
117 * 3408b638-09a9-47a0-8bfd-a0768815b665
118 */
119 .PlatformCapabilityUUID = {
120 0x38, 0xB6, 0x08, 0x34,
121 0xA9, 0x09,
122 0xA0, 0x47,
123 0x8B, 0xFD,
124 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65,
125 },
126 },
127 .cap = {
128 .bcdVersion = sys_cpu_to_le16(0x0100),
129 .bVendorCode = 0x01,
130 .iLandingPage = 0x01
131 },
132 };
133
134 USB_DEVICE_BOS_DESC_DEFINE_CAP struct usb_bos_msosv2 {
135 struct usb_bos_platform_descriptor platform;
136 struct usb_bos_capability_msos cap;
137 } __packed cap_msosv2 = {
138 .platform = {
139 .bLength = sizeof(struct usb_bos_platform_descriptor)
140 + sizeof(struct usb_bos_capability_msos),
141 .bDescriptorType = USB_DESC_DEVICE_CAPABILITY,
142 .bDevCapabilityType = USB_BOS_CAPABILITY_PLATFORM,
143 .bReserved = 0,
144 .PlatformCapabilityUUID = {
145 /**
146 * MS OS 2.0 Platform Capability ID
147 * D8DD60DF-4589-4CC7-9CD2-659D9E648A9F
148 */
149 0xDF, 0x60, 0xDD, 0xD8,
150 0x89, 0x45,
151 0xC7, 0x4C,
152 0x9C, 0xD2,
153 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F,
154 },
155 },
156 .cap = {
157 /* Windows version (8.1) (0x06030000) */
158 .dwWindowsVersion = sys_cpu_to_le32(0x06030000),
159 /* The MSOS2.0 descriptor is not relevant here. */
160 .wMSOSDescriptorSetTotalLength = 0,
161 .bMS_VendorCode = 0x02,
162 .bAltEnumCode = 0x00,
163 },
164 };
165
test_usb_bos_macros(void)166 static void test_usb_bos_macros(void)
167 {
168 const struct usb_bos_descriptor *hdr = usb_bos_get_header();
169 size_t len = usb_bos_get_length();
170
171 TC_PRINT("length %zu\n", len);
172
173 usb_bos_register_cap((void *)&cap_webusb);
174 usb_bos_register_cap((void *)&cap_msosv2);
175
176 /* usb_bos_fix_total_length(); corrected with register */
177
178 LOG_HEXDUMP_DBG((void *)hdr, len, "Header");
179 LOG_HEXDUMP_DBG((void *)&webusb_bos_descriptor, sizeof(cap_webusb),
180 "webusb cap");
181 LOG_HEXDUMP_DBG((void *)&webusb_bos_descriptor_2, sizeof(cap_msosv2),
182 "webusb cap msos v2");
183
184 zassert_true(len ==
185 sizeof(struct usb_bos_descriptor) +
186 sizeof(cap_webusb) +
187 sizeof(cap_msosv2),
188 "Incorrect calculated length");
189 zassert_true(!memcmp(hdr, &webusb_bos_descriptor, len) ||
190 !memcmp(hdr, &webusb_bos_descriptor_2, len),
191 "Wrong data");
192 }
193
test_usb_bos(void)194 static void test_usb_bos(void)
195 {
196 struct usb_setup_packet setup;
197 int32_t len = 0;
198 uint8_t *data = NULL;
199 int ret;
200
201 /* Already registered due to previous test */
202
203 setup.wValue = (USB_DESC_BOS & 0xFF) << 8;
204
205 ret = usb_handle_bos(&setup, &len, &data);
206
207 TC_PRINT("%s: ret %d len %u data %p\n", __func__, ret, len, data);
208
209 zassert_true(!ret, "Return code failed");
210 zassert_equal(len, sizeof(webusb_bos_descriptor), "Wrong length");
211 zassert_true(!memcmp(data, &webusb_bos_descriptor, len) ||
212 !memcmp(data, &webusb_bos_descriptor_2, len),
213 "Wrong data");
214 }
215
216 /* test case main entry */
ZTEST(osdesc_bos,test_osdesc)217 ZTEST(osdesc_bos, test_osdesc)
218 {
219 /* Prepare webusb_bos_descriptor_2 */
220 memcpy(&webusb_bos_descriptor_2.bos,
221 &webusb_bos_descriptor.bos,
222 sizeof(struct usb_bos_descriptor));
223
224 memcpy(&webusb_bos_descriptor_2.platform_msos,
225 &webusb_bos_descriptor.platform_msos,
226 sizeof(struct usb_bos_platform_descriptor));
227 memcpy(&webusb_bos_descriptor_2.capability_data_msos,
228 &webusb_bos_descriptor.capability_data_msos,
229 sizeof(struct usb_bos_capability_msos));
230
231 memcpy(&webusb_bos_descriptor_2.platform_webusb,
232 &webusb_bos_descriptor.platform_webusb,
233 sizeof(struct usb_bos_platform_descriptor));
234 memcpy(&webusb_bos_descriptor_2.capability_data_webusb,
235 &webusb_bos_descriptor.capability_data_webusb,
236 sizeof(struct usb_bos_capability_webusb));
237
238 test_usb_bos_macros();
239 test_usb_bos();
240 }
241 ZTEST_SUITE(osdesc_bos, NULL, NULL, NULL, NULL, NULL);
242