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