X-Git-Url: https://repo.jachan.dev/u-boot.git/blobdiff_plain/a84988c76d1dbca2dbe870d6b4f0ad398f287f85..d678a59d2d719da9e807495b4b021501f2836ca5:/test/dm/usb.c diff --git a/test/dm/usb.c b/test/dm/usb.c index 9939d837a9..7671ef156d 100644 --- a/test/dm/usb.c +++ b/test/dm/usb.c @@ -1,16 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2015 Google, Inc - * - * SPDX-License-Identifier: GPL-2.0+ */ #include +#include #include +#include #include #include +#include +#include +#include #include +#include +#include #include +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) { @@ -22,7 +34,7 @@ static int dm_test_usb_base(struct unit_test_state *uts) return 0; } -DM_TEST(dm_test_usb_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); +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 @@ -31,20 +43,418 @@ DM_TEST(dm_test_usb_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); */ static int dm_test_usb_flash(struct unit_test_state *uts) { - struct udevice *dev; - block_dev_desc_t *dev_desc; + struct blk_desc *dev_desc, *chk; + struct udevice *dev, *blk; char cmp[1024]; + state_set_skip_delays(true); ut_assertok(usb_init()); ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &dev)); - ut_assertok(get_device("usb", "0", &dev_desc)); + ut_assertok(blk_get_device_by_str("usb", "0", &dev_desc)); + chk = blk_get_by_device(dev); + ut_asserteq_ptr(chk, dev_desc); + + ut_assertok(device_find_first_child_by_uclass(dev, UCLASS_BLK, &blk)); + ut_asserteq_ptr(chk, blk_get_by_device(dev)); /* 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, dev_desc->block_read(dev_desc->dev, 0, 2, cmp)); - ut_assertok(strcmp(cmp, "this is a test")); + ut_asserteq(2, blk_read(blk, 0, 2, cmp)); + ut_asserteq_str("this is a test", cmp); + + strcpy(cmp, "another test"); + ut_asserteq(1, blk_write(blk, 1, 1, cmp)); + + memset(cmp, '\0', sizeof(cmp)); + ut_asserteq(2, blk_read(blk, 0, 2, cmp)); + ut_asserteq_str("this is a test", cmp); + ut_asserteq_str("another test", cmp + 512); + + memset(cmp, '\0', sizeof(cmp)); + ut_asserteq(1, blk_write(blk, 1, 1, cmp)); + + memset(cmp, '\0', sizeof(cmp)); + ut_asserteq(2, blk_read(blk, 0, 2, cmp)); + ut_asserteq_str("this is a test", cmp); + ut_asserteq_str("", cmp + 512); + + 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. and + * * some special keys, e.g. + * * some modifiers, e.g. and + * * 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[] = { + /* */ + {0x00, 0x04, "a"}, + /* */ + {0x00, 0x05, "b"}, + /* */ + {0x00, 0x06, "c"}, + /* */ + {0x00, 0x07, "d"}, + /* */ + {0x00, 0x08, "e"}, + /* */ + {0x00, 0x09, "f"}, + /* */ + {0x00, 0x0a, "g"}, + /* */ + {0x00, 0x0b, "h"}, + /* */ + {0x00, 0x0c, "i"}, + /* */ + {0x00, 0x0d, "j"}, + /* */ + {0x00, 0x0e, "k"}, + /* */ + {0x00, 0x0f, "l"}, + /* */ + {0x00, 0x10, "m"}, + /* */ + {0x00, 0x11, "n"}, + /* */ + {0x00, 0x12, "o"}, + /*

*/ + {0x00, 0x13, "p"}, + /* */ + {0x00, 0x14, "q"}, + /* */ + {0x00, 0x15, "r"}, + /* */ + {0x00, 0x16, "s"}, + /* */ + {0x00, 0x17, "t"}, + /* */ + {0x00, 0x18, "u"}, + /* */ + {0x00, 0x19, "v"}, + /* */ + {0x00, 0x1a, "w"}, + /* */ + {0x00, 0x1b, "x"}, + /* */ + {0x00, 0x1c, "y"}, + /* */ + {0x00, 0x1d, "z"}, + + /* */ + {0x02, 0x04, "A"}, + /* */ + {0x20, 0x1d, "Z"}, + + /* */ + {0x01, 0x04, "\x01"}, + /* */ + {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"}, + + /* <1> */ + {0x02, 0x1e, "!"}, + /* <2> */ + {0x20, 0x1f, "@"}, + /* <3> */ + {0x02, 0x20, "#"}, + /* <4> */ + {0x20, 0x21, "$"}, + /* <5> */ + {0x02, 0x22, "%"}, + /* <6> */ + {0x20, 0x23, "^"}, + /* <7> */ + {0x02, 0x24, "&"}, + /* <8> */ + {0x20, 0x25, "*"}, + /* <9> */ + {0x02, 0x26, "("}, + /* <0> */ + {0x20, 0x27, ")"}, + + /* */ + {0x00, 0x28, "\r"}, + /* */ + {0x00, 0x29, "\x1b"}, + /* */ + {0x00, 0x2a, "\x08"}, + /* */ + {0x00, 0x2b, "\x09"}, + /* */ + {0x00, 0x2c, " "}, + /* */ + {0x00, 0x2d, "-"}, + /* */ + {0x00, 0x2e, "="}, + /* */ + {0x00, 0x2f, "["}, + /* */ + {0x00, 0x30, "]"}, + /* */ + {0x00, 0x31, "\\"}, + /* */ + {0x00, 0x32, "#"}, + /* */ + {0x00, 0x33, ";"}, + /* */ + {0x00, 0x34, "'"}, + /* */ + {0x00, 0x35, "`"}, + /* */ + {0x00, 0x36, ","}, + /* */ + {0x00, 0x37, "."}, + /* */ + {0x00, 0x38, "/"}, + + /* */ + {0x02, 0x28, "\r"}, + /* */ + {0x20, 0x29, "\x1b"}, + /* */ + {0x02, 0x2a, "\x08"}, + /* */ + {0x20, 0x2b, "\x09"}, + /* */ + {0x02, 0x2c, " "}, + /* */ + {0x20, 0x2d, "_"}, + /* */ + {0x02, 0x2e, "+"}, + /* */ + {0x20, 0x2f, "{"}, + /* */ + {0x02, 0x30, "}"}, + /* */ + {0x20, 0x31, "|"}, + /* */ + {0x02, 0x32, "~"}, + /* */ + {0x20, 0x33, ":"}, + /* */ + {0x02, 0x34, "\""}, + /* */ + {0x20, 0x35, "~"}, + /* */ + {0x02, 0x36, "<"}, + /* */ + {0x20, 0x37, ">"}, + /* */ + {0x02, 0x38, "?"}, +#ifdef CONFIG_USB_KEYBOARD_FN_KEYS + /* */ + {0x00, 0x3a, "\x1bOP"}, + /* */ + {0x00, 0x3b, "\x1bOQ"}, + /* */ + {0x00, 0x3c, "\x1bOR"}, + /* */ + {0x00, 0x3d, "\x1bOS"}, + /* */ + {0x00, 0x3e, "\x1b[15~"}, + /* */ + {0x00, 0x3f, "\x1b[17~"}, + /* */ + {0x00, 0x40, "\x1b[18~"}, + /* */ + {0x00, 0x41, "\x1b[19~"}, + /* */ + {0x00, 0x42, "\x1b[20~"}, + /* */ + {0x00, 0x43, "\x1b[21~"}, + /* */ + {0x00, 0x44, "\x1b[23~"}, + /* */ + {0x00, 0x45, "\x1b[24~"}, + /* */ + {0x00, 0x49, "\x1b[2~"}, + /* */ + {0x00, 0x4a, "\x1b[H"}, + /* */ + {0x00, 0x4b, "\x1b[5~"}, + /* */ + {0x00, 0x4c, "\x1b[3~"}, + /* */ + {0x00, 0x4d, "\x1b[F"}, + /* */ + {0x00, 0x4e, "\x1b[6~"}, + /* */ + {0x00, 0x4f, "\x1b[C"}, + /* */ + {0x00, 0x50, "\x1b[D"}, + /* */ + {0x00, 0x51, "\x1b[B"}, + /* */ + {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_flash, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); +DM_TEST(dm_test_usb_keyb, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);