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