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