1 /*
2  * Copyright (c) 2018 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/ztest.h>
8 #include <zephyr/tc_util.h>
9 
10 #include <zephyr/sys/byteorder.h>
11 #include <zephyr/usb/usb_device.h>
12 #include <usb_descriptor.h>
13 #include <zephyr/sys/iterable_sections.h>
14 #include <zephyr/logging/log.h>
15 LOG_MODULE_REGISTER(test_main, LOG_LEVEL_DBG);
16 
17 /* Linker-defined symbols bound the USB descriptor structs */
18 extern struct usb_desc_header __usb_descriptor_start[];
19 extern struct usb_desc_header __usb_descriptor_end[];
20 extern struct usb_cfg_data _usb_cfg_data_list_start[];
21 extern struct usb_cfg_data _usb_cfg_data_list_end[];
22 
23 uint8_t *usb_get_device_descriptor(void);
24 
25 struct usb_test_config {
26 	struct usb_if_descriptor if0;
27 	struct usb_ep_descriptor if0_out_ep;
28 	struct usb_ep_descriptor if0_in1_ep;
29 	struct usb_ep_descriptor if0_in2_ep;
30 } __packed;
31 
32 #if defined(CONFIG_USB_DC_HAS_HS_SUPPORT)
33 #define TEST_BULK_EP_MPS		512
34 #else
35 #define TEST_BULK_EP_MPS		64
36 #endif
37 
38 #if defined(CONFIG_USB_CONFIGURATION_STRING_DESC_ENABLE)
39 #define TEST_DESCRIPTOR_TABLE_SPAN	201
40 #else
41 #define TEST_DESCRIPTOR_TABLE_SPAN	157
42 #endif
43 
44 #define INITIALIZER_IF							\
45 	{								\
46 		.bLength = sizeof(struct usb_if_descriptor),		\
47 		.bDescriptorType = USB_DESC_INTERFACE,			\
48 		.bInterfaceNumber = 0,					\
49 		.bAlternateSetting = 0,					\
50 		.bNumEndpoints = 3,					\
51 		.bInterfaceClass = USB_BCC_VENDOR,			\
52 		.bInterfaceSubClass = 0,				\
53 		.bInterfaceProtocol = 0,				\
54 		.iInterface = 0,					\
55 	}
56 
57 #define INITIALIZER_IF_EP(addr, attr, mps)				\
58 	{								\
59 		.bLength = sizeof(struct usb_ep_descriptor),		\
60 		.bDescriptorType = USB_DESC_ENDPOINT,			\
61 		.bEndpointAddress = addr,				\
62 		.bmAttributes = attr,					\
63 		.wMaxPacketSize = sys_cpu_to_le16(mps),			\
64 		.bInterval = 0x00,					\
65 	}
66 
67 
68 #define DEFINE_TEST_DESC(x, _)						\
69 	USBD_CLASS_DESCR_DEFINE(primary, x)				\
70 	struct usb_test_config test_cfg_##x = {				\
71 	.if0 = INITIALIZER_IF,						\
72 	.if0_out_ep = INITIALIZER_IF_EP(AUTO_EP_OUT,			\
73 					USB_DC_EP_BULK,			\
74 					TEST_BULK_EP_MPS),		\
75 	.if0_in1_ep = INITIALIZER_IF_EP(AUTO_EP_IN,			\
76 					USB_DC_EP_BULK,			\
77 					TEST_BULK_EP_MPS),		\
78 	.if0_in2_ep = INITIALIZER_IF_EP(AUTO_EP_IN,			\
79 					USB_DC_EP_BULK,			\
80 					TEST_BULK_EP_MPS),		\
81 	}
82 
83 #define INITIALIZER_EP_DATA(cb, addr)					\
84 	{								\
85 		.ep_cb = cb,						\
86 		.ep_addr = addr,					\
87 	}
88 
89 #define DEFINE_TEST_EP_CFG(x, _)				\
90 	static struct usb_ep_cfg_data ep_cfg_##x[] = {		\
91 		INITIALIZER_EP_DATA(NULL, AUTO_EP_OUT),		\
92 		INITIALIZER_EP_DATA(NULL, AUTO_EP_IN),		\
93 		INITIALIZER_EP_DATA(NULL, AUTO_EP_IN),		\
94 	}
95 
96 #define DEFINE_TEST_CFG_DATA(x, _)				\
97 	USBD_DEFINE_CFG_DATA(test_config_##x) = {		\
98 	.usb_device_description = NULL,				\
99 	.interface_config = interface_config,			\
100 	.interface_descriptor = &test_cfg_##x.if0,		\
101 	.cb_usb_status = NULL,					\
102 	.interface = {						\
103 		.class_handler = NULL,				\
104 		.custom_handler = NULL,				\
105 		.vendor_handler = NULL,				\
106 	},							\
107 	.num_endpoints = ARRAY_SIZE(ep_cfg_##x),		\
108 	.endpoint = ep_cfg_##x,					\
109 	}
110 
111 #define NUM_INSTANCES 2
112 
interface_config(struct usb_desc_header * head,uint8_t iface_num)113 static void interface_config(struct usb_desc_header *head,
114 			     uint8_t iface_num)
115 {
116 	struct usb_if_descriptor *if_desc = (struct usb_if_descriptor *)head;
117 
118 	LOG_DBG("head %p iface_num %u", head, iface_num);
119 
120 	if_desc->bInterfaceNumber = iface_num;
121 }
122 
123 LISTIFY(NUM_INSTANCES, DEFINE_TEST_DESC, (;), _);
124 LISTIFY(NUM_INSTANCES, DEFINE_TEST_EP_CFG, (;), _);
125 LISTIFY(NUM_INSTANCES, DEFINE_TEST_CFG_DATA, (;), _);
126 
usb_get_cfg_data(struct usb_if_descriptor * iface)127 static struct usb_cfg_data *usb_get_cfg_data(struct usb_if_descriptor *iface)
128 {
129 	STRUCT_SECTION_FOREACH(usb_cfg_data, cfg_data) {
130 		if (cfg_data->interface_descriptor == iface) {
131 			return cfg_data;
132 		}
133 	}
134 
135 	return NULL;
136 }
137 
find_cfg_data_ep(const struct usb_ep_descriptor * const ep_descr,const struct usb_cfg_data * const cfg_data,uint8_t ep_count)138 static bool find_cfg_data_ep(const struct usb_ep_descriptor * const ep_descr,
139 			     const struct usb_cfg_data * const cfg_data,
140 			     uint8_t ep_count)
141 {
142 	for (int i = 0; i < cfg_data->num_endpoints; i++) {
143 		if (cfg_data->endpoint[i].ep_addr ==
144 				ep_descr->bEndpointAddress) {
145 			LOG_DBG("found ep[%d] %x", i,
146 				ep_descr->bEndpointAddress);
147 
148 			if (ep_count != i) {
149 				LOG_ERR("EPs are assigned in wrong order");
150 				return false;
151 			}
152 
153 			return true;
154 		}
155 	}
156 
157 	return false;
158 }
159 
check_endpoint_allocation(struct usb_desc_header * head)160 static void check_endpoint_allocation(struct usb_desc_header *head)
161 {
162 	struct usb_cfg_data *cfg_data = NULL;
163 	static uint8_t interfaces;
164 	uint8_t ep_count = 0;
165 
166 	while (head->bLength != 0) {
167 		if (head->bDescriptorType == USB_DESC_INTERFACE) {
168 			struct usb_if_descriptor *if_descr = (void *)head;
169 
170 			ep_count = 0;
171 
172 			LOG_DBG("iface %u", if_descr->bInterfaceNumber);
173 
174 			/* Check that interfaces get correct numbers */
175 			zassert_equal(if_descr->bInterfaceNumber, interfaces,
176 				      "Interfaces numbering failed");
177 
178 			interfaces++;
179 
180 			cfg_data = usb_get_cfg_data(if_descr);
181 			zassert_not_null(cfg_data, "Check available cfg data");
182 		}
183 
184 		if (head->bDescriptorType == USB_DESC_ENDPOINT) {
185 			struct usb_ep_descriptor *ep_descr =
186 				(struct usb_ep_descriptor *)head;
187 
188 			/* Check that we get iface desc before */
189 			zassert_not_null(cfg_data, "Check available cfg data");
190 
191 			zassert_true(find_cfg_data_ep(ep_descr, cfg_data,
192 						      ep_count),
193 				     "Check endpoint config in cfg_data");
194 			ep_count++;
195 		}
196 
197 		head = (struct usb_desc_header *)((uint8_t *)head + head->bLength);
198 	}
199 }
200 
201 /* Determine the number of bytes spanned between two linker-defined
202  * symbols that are normally interpreted as pointers.
203  */
204 #define SYMBOL_SPAN(_ep, _sp) (int)(intptr_t)((uintptr_t)(_ep) - (uintptr_t)(_sp))
205 
ZTEST(desc_sections,test_desc_sections)206 ZTEST(desc_sections, test_desc_sections)
207 {
208 	struct usb_desc_header *head;
209 
210 	usb_set_config(usb_get_device_descriptor());
211 	TC_PRINT("__usb_descriptor_start %p\n", __usb_descriptor_start);
212 	TC_PRINT("__usb_descriptor_end %p\n",  __usb_descriptor_end);
213 	TC_PRINT("USB Descriptor table span %d\n",
214 		 SYMBOL_SPAN(__usb_descriptor_end, __usb_descriptor_start));
215 
216 	TC_PRINT("_usb_cfg_data_list_start %p\n", _usb_cfg_data_list_start);
217 	TC_PRINT("_usb_cfg_data_list_end %p\n", _usb_cfg_data_list_end);
218 	TC_PRINT("USB Configuration data span %d\n",
219 		 SYMBOL_SPAN(_usb_cfg_data_list_end, _usb_cfg_data_list_start));
220 
221 	TC_PRINT("sizeof usb_cfg_data %zu\n", sizeof(struct usb_cfg_data));
222 
223 	LOG_DBG("Starting logs");
224 
225 	LOG_HEXDUMP_DBG((uint8_t *)__usb_descriptor_start,
226 			SYMBOL_SPAN(__usb_descriptor_end, __usb_descriptor_start),
227 			"USB Descriptor table section");
228 
229 	LOG_HEXDUMP_DBG((uint8_t *)_usb_cfg_data_list_start,
230 			SYMBOL_SPAN(_usb_cfg_data_list_end, _usb_cfg_data_list_start),
231 			"USB Configuration structures section");
232 
233 	head = (struct usb_desc_header *)__usb_descriptor_start;
234 	zassert_not_null(head, NULL);
235 
236 	zassert_equal(SYMBOL_SPAN(__usb_descriptor_end, __usb_descriptor_start),
237 		      TEST_DESCRIPTOR_TABLE_SPAN, NULL);
238 
239 	/* Calculate number of structures */
240 	zassert_equal(_usb_cfg_data_list_end - _usb_cfg_data_list_start,
241 		      NUM_INSTANCES, NULL);
242 	zassert_equal(SYMBOL_SPAN(_usb_cfg_data_list_end, _usb_cfg_data_list_start),
243 		      NUM_INSTANCES * sizeof(struct usb_cfg_data), NULL);
244 
245 	check_endpoint_allocation(head);
246 }
247 
248 /*test case main entry*/
249 ZTEST_SUITE(desc_sections, NULL, NULL, NULL, NULL, NULL);
250