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