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