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