blob: fa894c1096e4c6f00fbdd50a8d0ce5e1cb5fd67a [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glass31680482015-03-25 12:23:05 -06002/*
3 * Copyright (C) 2015 Google, Inc
Simon Glass31680482015-03-25 12:23:05 -06004 */
5
Simon Glassa73bda42015-11-08 23:47:45 -07006#include <console.h>
Simon Glass31680482015-03-25 12:23:05 -06007#include <dm.h>
Simon Glass655306c2020-05-10 11:39:58 -06008#include <part.h>
Simon Glass31680482015-03-25 12:23:05 -06009#include <usb.h>
10#include <asm/io.h>
Simon Glass2d7c4992015-11-08 23:47:44 -070011#include <asm/state.h>
Simon Glassc0ccc722015-11-08 23:48:08 -070012#include <asm/test.h>
Simon Glass2d7c4992015-11-08 23:47:44 -070013#include <dm/device-internal.h>
Simon Glass31680482015-03-25 12:23:05 -060014#include <dm/test.h>
Simon Glass4700fe52015-11-08 23:48:01 -070015#include <dm/uclass-internal.h>
Simon Glass75c4d412020-07-19 10:15:37 -060016#include <test/test.h>
Joe Hershberger3a77be52015-05-20 14:27:27 -050017#include <test/ut.h>
Simon Glass31680482015-03-25 12:23:05 -060018
Heinrich Schuchardt513255b2019-11-23 18:15:23 +010019struct keyboard_test_data {
20 const char modifiers;
21 const char scancode;
22 const char result[6];
23};
24
Simon Glass31680482015-03-25 12:23:05 -060025/* Test that sandbox USB works correctly */
Joe Hershberger3a77be52015-05-20 14:27:27 -050026static int dm_test_usb_base(struct unit_test_state *uts)
Simon Glass31680482015-03-25 12:23:05 -060027{
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}
Simon Glass1a92f832024-08-22 07:57:48 -060036DM_TEST(dm_test_usb_base, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass31680482015-03-25 12:23:05 -060037
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 */
Joe Hershberger3a77be52015-05-20 14:27:27 -050043static int dm_test_usb_flash(struct unit_test_state *uts)
Simon Glass31680482015-03-25 12:23:05 -060044{
Simon Glass18861002022-10-20 18:22:54 -060045 struct blk_desc *dev_desc, *chk;
46 struct udevice *dev, *blk;
Simon Glass31680482015-03-25 12:23:05 -060047 char cmp[1024];
48
Simon Glass2d7c4992015-11-08 23:47:44 -070049 state_set_skip_delays(true);
Simon Glass31680482015-03-25 12:23:05 -060050 ut_assertok(usb_init());
51 ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &dev));
Simon Glasse6649a62016-02-29 15:25:43 -070052 ut_assertok(blk_get_device_by_str("usb", "0", &dev_desc));
Simon Glass18861002022-10-20 18:22:54 -060053 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));
Simon Glass31680482015-03-25 12:23:05 -060058
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));
Simon Glass18861002022-10-20 18:22:54 -060062 ut_asserteq(2, blk_read(blk, 0, 2, cmp));
Simon Glass31b4f9e2022-10-20 18:22:55 -060063 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
Simon Glass582b76e2016-02-29 15:26:02 -070081 ut_assertok(usb_stop());
Simon Glass31680482015-03-25 12:23:05 -060082
83 return 0;
84}
Simon Glass1a92f832024-08-22 07:57:48 -060085DM_TEST(dm_test_usb_flash, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass4700fe52015-11-08 23:48:01 -070086
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));
Simon Glass582b76e2016-02-29 15:26:02 -070097 ut_assertok(usb_stop());
Simon Glass4700fe52015-11-08 23:48:01 -070098
99 return 0;
100}
Simon Glass1a92f832024-08-22 07:57:48 -0600101DM_TEST(dm_test_usb_multi, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass4700fe52015-11-08 23:48:01 -0700102
Michael Walle7c961322020-06-02 01:47:07 +0200103/* 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}
Simon Glass1a92f832024-08-22 07:57:48 -0600123DM_TEST(dm_test_usb_fdt_node, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Michael Walle7c961322020-06-02 01:47:07 +0200124
Simon Glass4700fe52015-11-08 23:48:01 -0700125static 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
Bin Mengb6189f22017-10-01 06:19:45 -0700150/* test that no USB devices are found after we stop the stack */
151static int dm_test_usb_stop(struct unit_test_state *uts)
Simon Glass4700fe52015-11-08 23:48:01 -0700152{
Bin Mengb6189f22017-10-01 06:19:45 -0700153 struct udevice *dev;
Simon Glass4700fe52015-11-08 23:48:01 -0700154
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));
Simon Glassf0bfd6d2016-01-07 10:23:42 -0700161 ut_asserteq(6, count_usb_devices());
Simon Glass846bb372015-11-08 23:48:02 -0700162 ut_assertok(usb_stop());
Bin Mengb6189f22017-10-01 06:19:45 -0700163 ut_asserteq(0, count_usb_devices());
Simon Glass846bb372015-11-08 23:48:02 -0700164
165 return 0;
166}
Simon Glass1a92f832024-08-22 07:57:48 -0600167DM_TEST(dm_test_usb_stop, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glassc0ccc722015-11-08 23:48:08 -0700168
Heinrich Schuchardt513255b2019-11-23 18:15:23 +0100169/**
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 */
Simon Glassc0ccc722015-11-08 23:48:08 -0700196static int dm_test_usb_keyb(struct unit_test_state *uts)
197{
198 struct udevice *dev;
Heinrich Schuchardt513255b2019-11-23 18:15:23 +0100199 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
Simon Glassc0ccc722015-11-08 23:48:08 -0700426 state_set_skip_delays(true);
427 ut_assertok(usb_init());
428
429 /* Initially there should be no characters */
430 ut_asserteq(0, tstc());
431
Peng Fane7028102019-05-22 07:08:12 +0000432 ut_assertok(uclass_get_device_by_name(UCLASS_USB_EMUL, "keyb@3",
Simon Glassc0ccc722015-11-08 23:48:08 -0700433 &dev));
434
435 /*
Heinrich Schuchardt513255b2019-11-23 18:15:23 +0100436 * Add scan codes to the USB keyboard buffer. They should appear as
437 * corresponding characters and escape sequences in stdin.
Simon Glassc0ccc722015-11-08 23:48:08 -0700438 */
Heinrich Schuchardt513255b2019-11-23 18:15:23 +0100439 for (pos = kbd_test_data; pos->scancode; ++pos) {
440 const char *c;
441 char scancodes[USB_KBD_BOOT_REPORT_SIZE] = {0};
Simon Glassc0ccc722015-11-08 23:48:08 -0700442
Heinrich Schuchardt513255b2019-11-23 18:15:23 +0100443 scancodes[0] = pos->modifiers;
444 scancodes[2] = pos->scancode;
445
446 ut_assertok(sandbox_usb_keyb_add_string(dev, scancodes));
447
448 for (c = pos->result; *c; ++c) {
449 ut_asserteq(1, tstc());
Heinrich Schuchardtc4954fb2020-10-07 18:11:48 +0200450 ut_asserteq(*c, getchar());
Heinrich Schuchardt513255b2019-11-23 18:15:23 +0100451 }
452 ut_asserteq(0, tstc());
453 }
Simon Glassc0ccc722015-11-08 23:48:08 -0700454 ut_assertok(usb_stop());
455
456 return 0;
457}
Simon Glass1a92f832024-08-22 07:57:48 -0600458DM_TEST(dm_test_usb_keyb, UTF_SCAN_PDATA | UTF_SCAN_FDT);