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