diff options
Diffstat (limited to 'roms/u-boot/test/dm/usb.c')
-rw-r--r-- | roms/u-boot/test/dm/usb.c | 438 |
1 files changed, 438 insertions, 0 deletions
diff --git a/roms/u-boot/test/dm/usb.c b/roms/u-boot/test/dm/usb.c new file mode 100644 index 000000000..5d6ceefce --- /dev/null +++ b/roms/u-boot/test/dm/usb.c @@ -0,0 +1,438 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015 Google, Inc + */ + +#include <common.h> +#include <console.h> +#include <dm.h> +#include <part.h> +#include <usb.h> +#include <asm/io.h> +#include <asm/state.h> +#include <asm/test.h> +#include <dm/device-internal.h> +#include <dm/test.h> +#include <dm/uclass-internal.h> +#include <test/test.h> +#include <test/ut.h> + +struct keyboard_test_data { + const char modifiers; + const char scancode; + const char result[6]; +}; + +/* Test that sandbox USB works correctly */ +static int dm_test_usb_base(struct unit_test_state *uts) +{ + struct udevice *bus; + + ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_USB, 0, &bus)); + ut_assertok(uclass_get_device(UCLASS_USB, 0, &bus)); + ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_USB, 2, &bus)); + + return 0; +} +DM_TEST(dm_test_usb_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* + * Test that we can use the flash stick. This is more of a functional test. It + * covers scanning the bug, setting up a hub and a flash stick and reading + * data from the flash stick. + */ +static int dm_test_usb_flash(struct unit_test_state *uts) +{ + struct udevice *dev; + struct blk_desc *dev_desc; + char cmp[1024]; + + state_set_skip_delays(true); + ut_assertok(usb_init()); + ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &dev)); + ut_assertok(blk_get_device_by_str("usb", "0", &dev_desc)); + + /* Read a few blocks and look for the string we expect */ + ut_asserteq(512, dev_desc->blksz); + memset(cmp, '\0', sizeof(cmp)); + ut_asserteq(2, blk_dread(dev_desc, 0, 2, cmp)); + ut_assertok(strcmp(cmp, "this is a test")); + ut_assertok(usb_stop()); + + return 0; +} +DM_TEST(dm_test_usb_flash, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* test that we can handle multiple storage devices */ +static int dm_test_usb_multi(struct unit_test_state *uts) +{ + struct udevice *dev; + + state_set_skip_delays(true); + ut_assertok(usb_init()); + ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &dev)); + ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 1, &dev)); + ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 2, &dev)); + ut_assertok(usb_stop()); + + return 0; +} +DM_TEST(dm_test_usb_multi, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* test that we have an associated ofnode with the usb device */ +static int dm_test_usb_fdt_node(struct unit_test_state *uts) +{ + struct udevice *dev; + ofnode node; + + state_set_skip_delays(true); + ut_assertok(usb_init()); + ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &dev)); + node = ofnode_path("/usb@1/hub/usbstor@1"); + ut_asserteq(1, ofnode_equal(node, dev_ofnode(dev))); + ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 1, &dev)); + ut_asserteq(1, ofnode_equal(ofnode_null(), dev_ofnode(dev))); + ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 2, &dev)); + node = ofnode_path("/usb@1/hub/usbstor@3"); + ut_asserteq(1, ofnode_equal(node, dev_ofnode(dev))); + ut_assertok(usb_stop()); + + return 0; +} +DM_TEST(dm_test_usb_fdt_node, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int count_usb_devices(void) +{ + struct udevice *hub; + struct uclass *uc; + int count = 0; + int ret; + + ret = uclass_get(UCLASS_USB_HUB, &uc); + if (ret) + return ret; + + uclass_foreach_dev(hub, uc) { + struct udevice *dev; + + count++; + for (device_find_first_child(hub, &dev); + dev; + device_find_next_child(&dev)) { + count++; + } + } + + return count; +} + +/* test that no USB devices are found after we stop the stack */ +static int dm_test_usb_stop(struct unit_test_state *uts) +{ + struct udevice *dev; + + /* Scan and check that all devices are present */ + state_set_skip_delays(true); + ut_assertok(usb_init()); + ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &dev)); + ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 1, &dev)); + ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 2, &dev)); + ut_asserteq(6, count_usb_devices()); + ut_assertok(usb_stop()); + ut_asserteq(0, count_usb_devices()); + + return 0; +} +DM_TEST(dm_test_usb_stop, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/** + * dm_test_usb_keyb() - test USB keyboard driver + * + * This test copies USB keyboard scan codes into the key buffer of the USB + * keyboard emulation driver. These are picked up during emulated interrupts + * by the USB keyboard driver and converted to characters and escape sequences. + * The test then reads and verifies these characters and escape sequences from + * the standard input. + * + * TODO: The following features are not yet tested: + * + * * LED status + * * caps-lock + * * num-lock + * * numerical pad keys + * + * TODO: The following features are not yet implemented by the USB keyboard + * driver and therefore not tested: + * + * * modifiers for non-alpha-numeric keys, e.g. <SHIFT><TAB> and <ALT><F4> + * * some special keys, e.g. <PRINT> + * * some modifiers, e.g. <ALT> and <META> + * * alternative keyboard layouts + * + * @uts: unit test state + * Return: 0 on success + */ +static int dm_test_usb_keyb(struct unit_test_state *uts) +{ + struct udevice *dev; + const struct keyboard_test_data *pos; + const struct keyboard_test_data kbd_test_data[] = { + /* <A> */ + {0x00, 0x04, "a"}, + /* <B> */ + {0x00, 0x05, "b"}, + /* <C> */ + {0x00, 0x06, "c"}, + /* <D> */ + {0x00, 0x07, "d"}, + /* <E> */ + {0x00, 0x08, "e"}, + /* <F> */ + {0x00, 0x09, "f"}, + /* <G> */ + {0x00, 0x0a, "g"}, + /* <H> */ + {0x00, 0x0b, "h"}, + /* <I> */ + {0x00, 0x0c, "i"}, + /* <J> */ + {0x00, 0x0d, "j"}, + /* <K> */ + {0x00, 0x0e, "k"}, + /* <L> */ + {0x00, 0x0f, "l"}, + /* <M> */ + {0x00, 0x10, "m"}, + /* <N> */ + {0x00, 0x11, "n"}, + /* <O> */ + {0x00, 0x12, "o"}, + /* <P> */ + {0x00, 0x13, "p"}, + /* <Q> */ + {0x00, 0x14, "q"}, + /* <R> */ + {0x00, 0x15, "r"}, + /* <S> */ + {0x00, 0x16, "s"}, + /* <T> */ + {0x00, 0x17, "t"}, + /* <U> */ + {0x00, 0x18, "u"}, + /* <V> */ + {0x00, 0x19, "v"}, + /* <W> */ + {0x00, 0x1a, "w"}, + /* <X> */ + {0x00, 0x1b, "x"}, + /* <Y> */ + {0x00, 0x1c, "y"}, + /* <Z> */ + {0x00, 0x1d, "z"}, + + /* <LEFT-SHIFT><A> */ + {0x02, 0x04, "A"}, + /* <RIGHT-SHIFT><Z> */ + {0x20, 0x1d, "Z"}, + + /* <LEFT-CONTROL><A> */ + {0x01, 0x04, "\x01"}, + /* <RIGHT-CONTROL><Z> */ + {0x10, 0x1d, "\x1a"}, + + /* <1> */ + {0x00, 0x1e, "1"}, + /* <2> */ + {0x00, 0x1f, "2"}, + /* <3> */ + {0x00, 0x20, "3"}, + /* <4> */ + {0x00, 0x21, "4"}, + /* <5> */ + {0x00, 0x22, "5"}, + /* <6> */ + {0x00, 0x23, "6"}, + /* <7> */ + {0x00, 0x24, "7"}, + /* <8> */ + {0x00, 0x25, "8"}, + /* <9> */ + {0x00, 0x26, "9"}, + /* <0> */ + {0x00, 0x27, "0"}, + + /* <LEFT-SHIFT><1> */ + {0x02, 0x1e, "!"}, + /* <RIGHT-SHIFT><2> */ + {0x20, 0x1f, "@"}, + /* <LEFT-SHIFT><3> */ + {0x02, 0x20, "#"}, + /* <RIGHT-SHIFT><4> */ + {0x20, 0x21, "$"}, + /* <LEFT-SHIFT><5> */ + {0x02, 0x22, "%"}, + /* <RIGHT-SHIFT><6> */ + {0x20, 0x23, "^"}, + /* <LEFT-SHIFT><7> */ + {0x02, 0x24, "&"}, + /* <RIGHT-SHIFT><8> */ + {0x20, 0x25, "*"}, + /* <LEFT-SHIFT><9> */ + {0x02, 0x26, "("}, + /* <RIGHT-SHIFT><0> */ + {0x20, 0x27, ")"}, + + /* <ENTER> */ + {0x00, 0x28, "\r"}, + /* <ESCAPE> */ + {0x00, 0x29, "\x1b"}, + /* <BACKSPACE> */ + {0x00, 0x2a, "\x08"}, + /* <TAB> */ + {0x00, 0x2b, "\x09"}, + /* <SPACE> */ + {0x00, 0x2c, " "}, + /* <MINUS> */ + {0x00, 0x2d, "-"}, + /* <EQUAL> */ + {0x00, 0x2e, "="}, + /* <LEFT BRACE> */ + {0x00, 0x2f, "["}, + /* <RIGHT BRACE> */ + {0x00, 0x30, "]"}, + /* <BACKSLASH> */ + {0x00, 0x31, "\\"}, + /* <HASH-TILDE> */ + {0x00, 0x32, "#"}, + /* <SEMICOLON> */ + {0x00, 0x33, ";"}, + /* <APOSTROPHE> */ + {0x00, 0x34, "'"}, + /* <GRAVE> */ + {0x00, 0x35, "`"}, + /* <COMMA> */ + {0x00, 0x36, ","}, + /* <DOT> */ + {0x00, 0x37, "."}, + /* <SLASH> */ + {0x00, 0x38, "/"}, + + /* <LEFT-SHIFT><ENTER> */ + {0x02, 0x28, "\r"}, + /* <RIGHT-SHIFT><ESCAPE> */ + {0x20, 0x29, "\x1b"}, + /* <LEFT-SHIFT><BACKSPACE> */ + {0x02, 0x2a, "\x08"}, + /* <RIGHT-SHIFT><TAB> */ + {0x20, 0x2b, "\x09"}, + /* <LEFT-SHIFT><SPACE> */ + {0x02, 0x2c, " "}, + /* <MINUS> */ + {0x20, 0x2d, "_"}, + /* <LEFT-SHIFT><EQUAL> */ + {0x02, 0x2e, "+"}, + /* <RIGHT-SHIFT><LEFT BRACE> */ + {0x20, 0x2f, "{"}, + /* <LEFT-SHIFT><RIGHT BRACE> */ + {0x02, 0x30, "}"}, + /* <RIGHT-SHIFT><BACKSLASH> */ + {0x20, 0x31, "|"}, + /* <LEFT-SHIFT><HASH-TILDE> */ + {0x02, 0x32, "~"}, + /* <RIGHT-SHIFT><SEMICOLON> */ + {0x20, 0x33, ":"}, + /* <LEFT-SHIFT><APOSTROPHE> */ + {0x02, 0x34, "\""}, + /* <RIGHT-SHIFT><GRAVE> */ + {0x20, 0x35, "~"}, + /* <LEFT-SHIFT><COMMA> */ + {0x02, 0x36, "<"}, + /* <RIGHT-SHIFT><DOT> */ + {0x20, 0x37, ">"}, + /* <LEFT-SHIFT><SLASH> */ + {0x02, 0x38, "?"}, +#ifdef CONFIG_USB_KEYBOARD_FN_KEYS + /* <F1> */ + {0x00, 0x3a, "\x1bOP"}, + /* <F2> */ + {0x00, 0x3b, "\x1bOQ"}, + /* <F3> */ + {0x00, 0x3c, "\x1bOR"}, + /* <F4> */ + {0x00, 0x3d, "\x1bOS"}, + /* <F5> */ + {0x00, 0x3e, "\x1b[15~"}, + /* <F6> */ + {0x00, 0x3f, "\x1b[17~"}, + /* <F7> */ + {0x00, 0x40, "\x1b[18~"}, + /* <F8> */ + {0x00, 0x41, "\x1b[19~"}, + /* <F9> */ + {0x00, 0x42, "\x1b[20~"}, + /* <F10> */ + {0x00, 0x43, "\x1b[21~"}, + /* <F11> */ + {0x00, 0x44, "\x1b[23~"}, + /* <F12> */ + {0x00, 0x45, "\x1b[24~"}, + /* <INSERT> */ + {0x00, 0x49, "\x1b[2~"}, + /* <HOME> */ + {0x00, 0x4a, "\x1b[H"}, + /* <PAGE UP> */ + {0x00, 0x4b, "\x1b[5~"}, + /* <DELETE> */ + {0x00, 0x4c, "\x1b[3~"}, + /* <END> */ + {0x00, 0x4d, "\x1b[F"}, + /* <PAGE DOWN> */ + {0x00, 0x4e, "\x1b[6~"}, + /* <RIGHT> */ + {0x00, 0x4f, "\x1b[C"}, + /* <LEFT> */ + {0x00, 0x50, "\x1b[D"}, + /* <DOWN> */ + {0x00, 0x51, "\x1b[B"}, + /* <UP> */ + {0x00, 0x52, "\x1b[A"}, +#endif /* CONFIG_USB_KEYBOARD_FN_KEYS */ + + /* End of list */ + {0x00, 0x00, "\0"} + }; + + + state_set_skip_delays(true); + ut_assertok(usb_init()); + + /* Initially there should be no characters */ + ut_asserteq(0, tstc()); + + ut_assertok(uclass_get_device_by_name(UCLASS_USB_EMUL, "keyb@3", + &dev)); + + /* + * Add scan codes to the USB keyboard buffer. They should appear as + * corresponding characters and escape sequences in stdin. + */ + for (pos = kbd_test_data; pos->scancode; ++pos) { + const char *c; + char scancodes[USB_KBD_BOOT_REPORT_SIZE] = {0}; + + scancodes[0] = pos->modifiers; + scancodes[2] = pos->scancode; + + ut_assertok(sandbox_usb_keyb_add_string(dev, scancodes)); + + for (c = pos->result; *c; ++c) { + ut_asserteq(1, tstc()); + ut_asserteq(*c, getchar()); + } + ut_asserteq(0, tstc()); + } + ut_assertok(usb_stop()); + + return 0; +} +DM_TEST(dm_test_usb_keyb, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); |