[U-Boot] [PATCH v4 6/7] dm: test: usb: rework keyboard test

Heinrich Schuchardt xypron.glpk at gmx.de
Sat Nov 23 17:15:23 UTC 2019


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. <SHIFT><TAB> and <ALT><F4>
* some special keys, e.g. <PRINT>
* some modifiers, e.g. <ALT> and <META>
* alternative keyboard layouts

Signed-off-by: Heinrich Schuchardt <xypron.glpk at gmx.de>
---
v4:
	adjust test scope to CONFIG_USB_KEYBOARD_FN_KEYS
v3:
	no change
v2:
	new patch
---
 drivers/usb/emul/sandbox_keyb.c |  27 +--
 test/dm/usb.c                   | 284 +++++++++++++++++++++++++++++++-
 2 files changed, 293 insertions(+), 18 deletions(-)

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 <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)
 {
@@ -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. <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());
@@ -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;
--
2.24.0



More information about the U-Boot mailing list