From: Heinrich Schuchardt Date: Sat, 23 Nov 2019 17:15:23 +0000 (+0100) Subject: dm: test: usb: rework keyboard test X-Git-Url: http://git.dujemihanovic.xyz/?a=commitdiff_plain;h=12f1e7908af97d901cc640da17e8ceea890c37a4;p=u-boot.git dm: test: usb: rework keyboard test Allow the unit test to pass full 8 byte scan code sequences to the USB keyboard emulation driver and to parse multi-byte escape sequences. The following features are not yet tested: * LED status * caps-lock * num-lock * numerical pad keys 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 Signed-off-by: Heinrich Schuchardt --- diff --git a/drivers/usb/emul/sandbox_keyb.c b/drivers/usb/emul/sandbox_keyb.c index dc43880d27..32bc9a1698 100644 --- a/drivers/usb/emul/sandbox_keyb.c +++ b/drivers/usb/emul/sandbox_keyb.c @@ -155,14 +155,20 @@ static void *keyb_desc_list[] = { NULL, }; -int sandbox_usb_keyb_add_string(struct udevice *dev, const char *str) +/** + * sandbox_usb_keyb_add_string() - provide a USB scancode buffer + * + * @dev: the keyboard emulation device + * @scancode: scancode buffer with USB_KBD_BOOT_REPORT_SIZE bytes + */ +int sandbox_usb_keyb_add_string(struct udevice *dev, + const char scancode[USB_KBD_BOOT_REPORT_SIZE]) { struct sandbox_keyb_priv *priv = dev_get_priv(dev); - int len, ret; + int ret; - len = strlen(str); - ret = membuff_put(&priv->in, str, len); - if (ret != len) + ret = membuff_put(&priv->in, scancode, USB_KBD_BOOT_REPORT_SIZE); + if (ret != USB_KBD_BOOT_REPORT_SIZE) return -ENOSPC; return 0; @@ -183,12 +189,12 @@ static int sandbox_keyb_interrupt(struct udevice *dev, struct usb_device *udev, { struct sandbox_keyb_priv *priv = dev_get_priv(dev); uint8_t *data = buffer; - int ch; memset(data, '\0', length); - ch = membuff_getbyte(&priv->in); - if (ch != -1) - data[2] = 4 + ch - 'a'; + if (length < USB_KBD_BOOT_REPORT_SIZE) + return 0; + + membuff_get(&priv->in, buffer, USB_KBD_BOOT_REPORT_SIZE); return 0; } @@ -213,7 +219,8 @@ static int sandbox_keyb_probe(struct udevice *dev) { struct sandbox_keyb_priv *priv = dev_get_priv(dev); - return membuff_new(&priv->in, 256); + /* Provide an 80 character keyboard buffer */ + return membuff_new(&priv->in, 80 * USB_KBD_BOOT_REPORT_SIZE); } static const struct dm_usb_ops sandbox_usb_keyb_ops = { diff --git a/test/dm/usb.c b/test/dm/usb.c index ef454b0ae5..e396c2a0ea 100644 --- a/test/dm/usb.c +++ b/test/dm/usb.c @@ -15,6 +15,12 @@ #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) { @@ -115,9 +121,263 @@ static int dm_test_usb_stop(struct unit_test_state *uts) } 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. 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()); @@ -129,16 +389,24 @@ static int dm_test_usb_keyb(struct unit_test_state *uts) &dev)); /* - * Add a string to the USB keyboard buffer - it should appear in - * stdin + * Add scan codes to the USB keyboard buffer. They should appear as + * corresponding characters and escape sequences in stdin. */ - ut_assertok(sandbox_usb_keyb_add_string(dev, "ab")); - ut_asserteq(1, tstc()); - ut_asserteq('a', getc()); - ut_asserteq(1, tstc()); - ut_asserteq('b', getc()); - ut_asserteq(0, tstc()); + 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;