Merge tag 'u-boot-atmel-fixes-2020.07-a' of https://gitlab.denx.de/u-boot/custodians...
[oweals/u-boot.git] / test / dm / usb.c
index 4300bbd5c921c2b6e4bd248cb9fc670c8a0a4ddf..a25c2c1482061d0f2f16c8ac19c73ea31a0ee551 100644 (file)
@@ -1,18 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (C) 2015 Google, Inc
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #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/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)
 {
@@ -34,20 +43,373 @@ 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;
        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));
 
        /* 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_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, DM_TESTF_SCAN_PDATA | DM_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, DM_TESTF_SCAN_PDATA | DM_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, DM_TESTF_SCAN_PDATA | DM_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, getc());
+               }
+               ut_asserteq(0, tstc());
+       }
+       ut_assertok(usb_stop());
+
+       return 0;
+}
+DM_TEST(dm_test_usb_keyb, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);