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