1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (C) 2015 Google, Inc
4 */
5
6 #include <common.h>
7 #include <console.h>
8 #include <dm.h>
9 #include <part.h>
10 #include <usb.h>
11 #include <asm/io.h>
12 #include <asm/state.h>
13 #include <asm/test.h>
14 #include <dm/device-internal.h>
15 #include <dm/test.h>
16 #include <dm/uclass-internal.h>
17 #include <test/test.h>
18 #include <test/ut.h>
19
20 struct keyboard_test_data {
21 const char modifiers;
22 const char scancode;
23 const char result[6];
24 };
25
26 /* Test that sandbox USB works correctly */
dm_test_usb_base(struct unit_test_state * uts)27 static int dm_test_usb_base(struct unit_test_state *uts)
28 {
29 struct udevice *bus;
30
31 ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_USB, 0, &bus));
32 ut_assertok(uclass_get_device(UCLASS_USB, 0, &bus));
33 ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_USB, 2, &bus));
34
35 return 0;
36 }
37 DM_TEST(dm_test_usb_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
38
39 /*
40 * Test that we can use the flash stick. This is more of a functional test. It
41 * covers scanning the bug, setting up a hub and a flash stick and reading
42 * data from the flash stick.
43 */
dm_test_usb_flash(struct unit_test_state * uts)44 static int dm_test_usb_flash(struct unit_test_state *uts)
45 {
46 struct udevice *dev;
47 struct blk_desc *dev_desc;
48 char cmp[1024];
49
50 state_set_skip_delays(true);
51 ut_assertok(usb_init());
52 ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &dev));
53 ut_assertok(blk_get_device_by_str("usb", "0", &dev_desc));
54
55 /* Read a few blocks and look for the string we expect */
56 ut_asserteq(512, dev_desc->blksz);
57 memset(cmp, '\0', sizeof(cmp));
58 ut_asserteq(2, blk_dread(dev_desc, 0, 2, cmp));
59 ut_assertok(strcmp(cmp, "this is a test"));
60 ut_assertok(usb_stop());
61
62 return 0;
63 }
64 DM_TEST(dm_test_usb_flash, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
65
66 /* test that we can handle multiple storage devices */
dm_test_usb_multi(struct unit_test_state * uts)67 static int dm_test_usb_multi(struct unit_test_state *uts)
68 {
69 struct udevice *dev;
70
71 state_set_skip_delays(true);
72 ut_assertok(usb_init());
73 ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &dev));
74 ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 1, &dev));
75 ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 2, &dev));
76 ut_assertok(usb_stop());
77
78 return 0;
79 }
80 DM_TEST(dm_test_usb_multi, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
81
82 /* test that we have an associated ofnode with the usb device */
dm_test_usb_fdt_node(struct unit_test_state * uts)83 static int dm_test_usb_fdt_node(struct unit_test_state *uts)
84 {
85 struct udevice *dev;
86 ofnode node;
87
88 state_set_skip_delays(true);
89 ut_assertok(usb_init());
90 ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &dev));
91 node = ofnode_path("/usb@1/hub/usbstor@1");
92 ut_asserteq(1, ofnode_equal(node, dev_ofnode(dev)));
93 ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 1, &dev));
94 ut_asserteq(1, ofnode_equal(ofnode_null(), dev_ofnode(dev)));
95 ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 2, &dev));
96 node = ofnode_path("/usb@1/hub/usbstor@3");
97 ut_asserteq(1, ofnode_equal(node, dev_ofnode(dev)));
98 ut_assertok(usb_stop());
99
100 return 0;
101 }
102 DM_TEST(dm_test_usb_fdt_node, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
103
count_usb_devices(void)104 static int count_usb_devices(void)
105 {
106 struct udevice *hub;
107 struct uclass *uc;
108 int count = 0;
109 int ret;
110
111 ret = uclass_get(UCLASS_USB_HUB, &uc);
112 if (ret)
113 return ret;
114
115 uclass_foreach_dev(hub, uc) {
116 struct udevice *dev;
117
118 count++;
119 for (device_find_first_child(hub, &dev);
120 dev;
121 device_find_next_child(&dev)) {
122 count++;
123 }
124 }
125
126 return count;
127 }
128
129 /* test that no USB devices are found after we stop the stack */
dm_test_usb_stop(struct unit_test_state * uts)130 static int dm_test_usb_stop(struct unit_test_state *uts)
131 {
132 struct udevice *dev;
133
134 /* Scan and check that all devices are present */
135 state_set_skip_delays(true);
136 ut_assertok(usb_init());
137 ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &dev));
138 ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 1, &dev));
139 ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 2, &dev));
140 ut_asserteq(6, count_usb_devices());
141 ut_assertok(usb_stop());
142 ut_asserteq(0, count_usb_devices());
143
144 return 0;
145 }
146 DM_TEST(dm_test_usb_stop, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
147
148 /**
149 * dm_test_usb_keyb() - test USB keyboard driver
150 *
151 * This test copies USB keyboard scan codes into the key buffer of the USB
152 * keyboard emulation driver. These are picked up during emulated interrupts
153 * by the USB keyboard driver and converted to characters and escape sequences.
154 * The test then reads and verifies these characters and escape sequences from
155 * the standard input.
156 *
157 * TODO: The following features are not yet tested:
158 *
159 * * LED status
160 * * caps-lock
161 * * num-lock
162 * * numerical pad keys
163 *
164 * TODO: The following features are not yet implemented by the USB keyboard
165 * driver and therefore not tested:
166 *
167 * * modifiers for non-alpha-numeric keys, e.g. <SHIFT><TAB> and <ALT><F4>
168 * * some special keys, e.g. <PRINT>
169 * * some modifiers, e.g. <ALT> and <META>
170 * * alternative keyboard layouts
171 *
172 * @uts: unit test state
173 * Return: 0 on success
174 */
dm_test_usb_keyb(struct unit_test_state * uts)175 static int dm_test_usb_keyb(struct unit_test_state *uts)
176 {
177 struct udevice *dev;
178 const struct keyboard_test_data *pos;
179 const struct keyboard_test_data kbd_test_data[] = {
180 /* <A> */
181 {0x00, 0x04, "a"},
182 /* <B> */
183 {0x00, 0x05, "b"},
184 /* <C> */
185 {0x00, 0x06, "c"},
186 /* <D> */
187 {0x00, 0x07, "d"},
188 /* <E> */
189 {0x00, 0x08, "e"},
190 /* <F> */
191 {0x00, 0x09, "f"},
192 /* <G> */
193 {0x00, 0x0a, "g"},
194 /* <H> */
195 {0x00, 0x0b, "h"},
196 /* <I> */
197 {0x00, 0x0c, "i"},
198 /* <J> */
199 {0x00, 0x0d, "j"},
200 /* <K> */
201 {0x00, 0x0e, "k"},
202 /* <L> */
203 {0x00, 0x0f, "l"},
204 /* <M> */
205 {0x00, 0x10, "m"},
206 /* <N> */
207 {0x00, 0x11, "n"},
208 /* <O> */
209 {0x00, 0x12, "o"},
210 /* <P> */
211 {0x00, 0x13, "p"},
212 /* <Q> */
213 {0x00, 0x14, "q"},
214 /* <R> */
215 {0x00, 0x15, "r"},
216 /* <S> */
217 {0x00, 0x16, "s"},
218 /* <T> */
219 {0x00, 0x17, "t"},
220 /* <U> */
221 {0x00, 0x18, "u"},
222 /* <V> */
223 {0x00, 0x19, "v"},
224 /* <W> */
225 {0x00, 0x1a, "w"},
226 /* <X> */
227 {0x00, 0x1b, "x"},
228 /* <Y> */
229 {0x00, 0x1c, "y"},
230 /* <Z> */
231 {0x00, 0x1d, "z"},
232
233 /* <LEFT-SHIFT><A> */
234 {0x02, 0x04, "A"},
235 /* <RIGHT-SHIFT><Z> */
236 {0x20, 0x1d, "Z"},
237
238 /* <LEFT-CONTROL><A> */
239 {0x01, 0x04, "\x01"},
240 /* <RIGHT-CONTROL><Z> */
241 {0x10, 0x1d, "\x1a"},
242
243 /* <1> */
244 {0x00, 0x1e, "1"},
245 /* <2> */
246 {0x00, 0x1f, "2"},
247 /* <3> */
248 {0x00, 0x20, "3"},
249 /* <4> */
250 {0x00, 0x21, "4"},
251 /* <5> */
252 {0x00, 0x22, "5"},
253 /* <6> */
254 {0x00, 0x23, "6"},
255 /* <7> */
256 {0x00, 0x24, "7"},
257 /* <8> */
258 {0x00, 0x25, "8"},
259 /* <9> */
260 {0x00, 0x26, "9"},
261 /* <0> */
262 {0x00, 0x27, "0"},
263
264 /* <LEFT-SHIFT><1> */
265 {0x02, 0x1e, "!"},
266 /* <RIGHT-SHIFT><2> */
267 {0x20, 0x1f, "@"},
268 /* <LEFT-SHIFT><3> */
269 {0x02, 0x20, "#"},
270 /* <RIGHT-SHIFT><4> */
271 {0x20, 0x21, "$"},
272 /* <LEFT-SHIFT><5> */
273 {0x02, 0x22, "%"},
274 /* <RIGHT-SHIFT><6> */
275 {0x20, 0x23, "^"},
276 /* <LEFT-SHIFT><7> */
277 {0x02, 0x24, "&"},
278 /* <RIGHT-SHIFT><8> */
279 {0x20, 0x25, "*"},
280 /* <LEFT-SHIFT><9> */
281 {0x02, 0x26, "("},
282 /* <RIGHT-SHIFT><0> */
283 {0x20, 0x27, ")"},
284
285 /* <ENTER> */
286 {0x00, 0x28, "\r"},
287 /* <ESCAPE> */
288 {0x00, 0x29, "\x1b"},
289 /* <BACKSPACE> */
290 {0x00, 0x2a, "\x08"},
291 /* <TAB> */
292 {0x00, 0x2b, "\x09"},
293 /* <SPACE> */
294 {0x00, 0x2c, " "},
295 /* <MINUS> */
296 {0x00, 0x2d, "-"},
297 /* <EQUAL> */
298 {0x00, 0x2e, "="},
299 /* <LEFT BRACE> */
300 {0x00, 0x2f, "["},
301 /* <RIGHT BRACE> */
302 {0x00, 0x30, "]"},
303 /* <BACKSLASH> */
304 {0x00, 0x31, "\\"},
305 /* <HASH-TILDE> */
306 {0x00, 0x32, "#"},
307 /* <SEMICOLON> */
308 {0x00, 0x33, ";"},
309 /* <APOSTROPHE> */
310 {0x00, 0x34, "'"},
311 /* <GRAVE> */
312 {0x00, 0x35, "`"},
313 /* <COMMA> */
314 {0x00, 0x36, ","},
315 /* <DOT> */
316 {0x00, 0x37, "."},
317 /* <SLASH> */
318 {0x00, 0x38, "/"},
319
320 /* <LEFT-SHIFT><ENTER> */
321 {0x02, 0x28, "\r"},
322 /* <RIGHT-SHIFT><ESCAPE> */
323 {0x20, 0x29, "\x1b"},
324 /* <LEFT-SHIFT><BACKSPACE> */
325 {0x02, 0x2a, "\x08"},
326 /* <RIGHT-SHIFT><TAB> */
327 {0x20, 0x2b, "\x09"},
328 /* <LEFT-SHIFT><SPACE> */
329 {0x02, 0x2c, " "},
330 /* <MINUS> */
331 {0x20, 0x2d, "_"},
332 /* <LEFT-SHIFT><EQUAL> */
333 {0x02, 0x2e, "+"},
334 /* <RIGHT-SHIFT><LEFT BRACE> */
335 {0x20, 0x2f, "{"},
336 /* <LEFT-SHIFT><RIGHT BRACE> */
337 {0x02, 0x30, "}"},
338 /* <RIGHT-SHIFT><BACKSLASH> */
339 {0x20, 0x31, "|"},
340 /* <LEFT-SHIFT><HASH-TILDE> */
341 {0x02, 0x32, "~"},
342 /* <RIGHT-SHIFT><SEMICOLON> */
343 {0x20, 0x33, ":"},
344 /* <LEFT-SHIFT><APOSTROPHE> */
345 {0x02, 0x34, "\""},
346 /* <RIGHT-SHIFT><GRAVE> */
347 {0x20, 0x35, "~"},
348 /* <LEFT-SHIFT><COMMA> */
349 {0x02, 0x36, "<"},
350 /* <RIGHT-SHIFT><DOT> */
351 {0x20, 0x37, ">"},
352 /* <LEFT-SHIFT><SLASH> */
353 {0x02, 0x38, "?"},
354 #ifdef CONFIG_USB_KEYBOARD_FN_KEYS
355 /* <F1> */
356 {0x00, 0x3a, "\x1bOP"},
357 /* <F2> */
358 {0x00, 0x3b, "\x1bOQ"},
359 /* <F3> */
360 {0x00, 0x3c, "\x1bOR"},
361 /* <F4> */
362 {0x00, 0x3d, "\x1bOS"},
363 /* <F5> */
364 {0x00, 0x3e, "\x1b[15~"},
365 /* <F6> */
366 {0x00, 0x3f, "\x1b[17~"},
367 /* <F7> */
368 {0x00, 0x40, "\x1b[18~"},
369 /* <F8> */
370 {0x00, 0x41, "\x1b[19~"},
371 /* <F9> */
372 {0x00, 0x42, "\x1b[20~"},
373 /* <F10> */
374 {0x00, 0x43, "\x1b[21~"},
375 /* <F11> */
376 {0x00, 0x44, "\x1b[23~"},
377 /* <F12> */
378 {0x00, 0x45, "\x1b[24~"},
379 /* <INSERT> */
380 {0x00, 0x49, "\x1b[2~"},
381 /* <HOME> */
382 {0x00, 0x4a, "\x1b[H"},
383 /* <PAGE UP> */
384 {0x00, 0x4b, "\x1b[5~"},
385 /* <DELETE> */
386 {0x00, 0x4c, "\x1b[3~"},
387 /* <END> */
388 {0x00, 0x4d, "\x1b[F"},
389 /* <PAGE DOWN> */
390 {0x00, 0x4e, "\x1b[6~"},
391 /* <RIGHT> */
392 {0x00, 0x4f, "\x1b[C"},
393 /* <LEFT> */
394 {0x00, 0x50, "\x1b[D"},
395 /* <DOWN> */
396 {0x00, 0x51, "\x1b[B"},
397 /* <UP> */
398 {0x00, 0x52, "\x1b[A"},
399 #endif /* CONFIG_USB_KEYBOARD_FN_KEYS */
400
401 /* End of list */
402 {0x00, 0x00, "\0"}
403 };
404
405
406 state_set_skip_delays(true);
407 ut_assertok(usb_init());
408
409 /* Initially there should be no characters */
410 ut_asserteq(0, tstc());
411
412 ut_assertok(uclass_get_device_by_name(UCLASS_USB_EMUL, "keyb@3",
413 &dev));
414
415 /*
416 * Add scan codes to the USB keyboard buffer. They should appear as
417 * corresponding characters and escape sequences in stdin.
418 */
419 for (pos = kbd_test_data; pos->scancode; ++pos) {
420 const char *c;
421 char scancodes[USB_KBD_BOOT_REPORT_SIZE] = {0};
422
423 scancodes[0] = pos->modifiers;
424 scancodes[2] = pos->scancode;
425
426 ut_assertok(sandbox_usb_keyb_add_string(dev, scancodes));
427
428 for (c = pos->result; *c; ++c) {
429 ut_asserteq(1, tstc());
430 ut_asserteq(*c, getchar());
431 }
432 ut_asserteq(0, tstc());
433 }
434 ut_assertok(usb_stop());
435
436 return 0;
437 }
438 DM_TEST(dm_test_usb_keyb, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
439