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