summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVic Yang <victoryang@chromium.org>2013-07-08 09:54:36 +0800
committerChromeBot <chrome-bot@google.com>2013-07-11 22:32:52 -0700
commit2475cce9ad0e505a45562189e5427683d4ebd65c (patch)
tree1110f516e9d50900ce1cb4492f2743f1639cd8e2
parentb2bc8aaa20479a87261aed8611367f11cf33c909 (diff)
downloadchrome-ec-2475cce9ad0e505a45562189e5427683d4ebd65c.tar.gz
Add I8042 keyboard unit test
This tests I8042 scancode and typematic. BUG=chrome-os-partner:19236 TEST=Pass all tests many times. BRANCH=None Change-Id: I8457b7b807b694b0bae32abf1647961f946dc5e1 Signed-off-by: Vic Yang <victoryang@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/61553 Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--Makefile3
-rw-r--r--Makefile.toolchain3
-rw-r--r--board/host/board.h8
-rw-r--r--chip/host/build.mk2
-rw-r--r--chip/host/lpc.c33
-rw-r--r--test/build.mk4
-rw-r--r--test/kb_8042.c206
-rw-r--r--test/kb_8042.tasklist20
-rw-r--r--test/test_config.mk9
9 files changed, 284 insertions, 4 deletions
diff --git a/Makefile b/Makefile
index 485a4f9f8a..93b7b43028 100644
--- a/Makefile
+++ b/Makefile
@@ -17,6 +17,9 @@ include Makefile.toolchain
# Get CHIP name
include board/$(BOARD)/build.mk
+# Get test configuration
+include test/test_config.mk
+
# Transform the configuration into make variables
includes=include core/$(CORE)/include $(dirs) $(out)
ifeq "$(TEST_BUILD)" "y"
diff --git a/Makefile.toolchain b/Makefile.toolchain
index 9eaf2c4ceb..2686ceb45a 100644
--- a/Makefile.toolchain
+++ b/Makefile.toolchain
@@ -29,7 +29,8 @@ CFLAGS_INCLUDE=$(foreach i,$(includes),-I$(i) )
CFLAGS_TEST=$(if $(TEST_BUILD),-DTEST_BUILD \
-DTEST_TASKFILE=$(PROJECT).tasklist,) \
$(if $(EMU_BUILD),-DEMU_BUILD) \
- $(if $($(PROJECT)-scale),-DTEST_TIME_SCALE=$($(PROJECT)-scale))
+ $(if $($(PROJECT)-scale),-DTEST_TIME_SCALE=$($(PROJECT)-scale)) \
+ $(CFLAGS-$(PROJECT))
CFLAGS_COVERAGE=$(if $(TEST_COVERAGE),-fprofile-arcs -ftest-coverage \
-DTEST_COVERAGE,)
CFLAGS_DEFINE=-DOUTDIR=$(out) -DCHIP=$(CHIP) -DBOARD_TASKFILE=ec.tasklist \
diff --git a/board/host/board.h b/board/host/board.h
index b4f82cf441..9d4d3257a8 100644
--- a/board/host/board.h
+++ b/board/host/board.h
@@ -15,11 +15,17 @@
/* Optional features */
#define CONFIG_HOSTCMD
#define CONFIG_HOST_EMU
-#define CONFIG_KEYBOARD_PROTOCOL_MKBP
#define CONFIG_LID_SWITCH
#define CONFIG_POWER_BUTTON
#define CONFIG_TEMP_SENSOR
+/* Keyboard protocol */
+#ifdef KB_8042
+#define CONFIG_KEYBOARD_PROTOCOL_8042
+#else
+#define CONFIG_KEYBOARD_PROTOCOL_MKBP
+#endif
+
#define CONFIG_WP_ACTIVE_HIGH
enum gpio_signal {
diff --git a/chip/host/build.mk b/chip/host/build.mk
index 866c84da20..10630914ce 100644
--- a/chip/host/build.mk
+++ b/chip/host/build.mk
@@ -8,5 +8,5 @@
CORE:=host
-chip-y=system.o gpio.o uart.o persistence.o flash.o
+chip-y=system.o gpio.o uart.o persistence.o flash.o lpc.o
chip-$(HAS_TASK_KEYSCAN)+=keyboard_raw.o
diff --git a/chip/host/lpc.c b/chip/host/lpc.c
new file mode 100644
index 0000000000..86921bd4e7
--- /dev/null
+++ b/chip/host/lpc.c
@@ -0,0 +1,33 @@
+/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* LPC module for Chrome EC emulator */
+
+#include "lpc.h"
+
+test_mockable int lpc_keyboard_has_char(void)
+{
+ return 0;
+}
+
+test_mockable int lpc_keyboard_input_pending(void)
+{
+ return 0;
+}
+
+test_mockable void lpc_keyboard_put_char(uint8_t chr, int send_irq)
+{
+ /* Do nothing */
+}
+
+test_mockable void lpc_keyboard_clear_buffer(void)
+{
+ /* Do nothing */
+}
+
+test_mockable void lpc_keyboard_resume_irq(void)
+{
+ /* Do nothing */
+}
diff --git a/test/build.mk b/test/build.mk
index dedbc68c4e..ed2e437c5b 100644
--- a/test/build.mk
+++ b/test/build.mk
@@ -29,10 +29,12 @@ test-list-$(BOARD_wolf)=
# Emulator tests
test-list-host=mutex pingpong utils kb_scan kb_mkbp lid_sw power_button hooks
-test-list-host+=thermal flash queue
+test-list-host+=thermal flash queue kb_8042
flash-y=flash.o
hooks-y=hooks.o
+kb_8042-y=kb_8042.o
+kb_8042-scale=3
kb_mkbp-y=kb_mkbp.o
kb_scan-y=kb_scan.o
lid_sw-y=lid_sw.o
diff --git a/test/kb_8042.c b/test/kb_8042.c
new file mode 100644
index 0000000000..8fa3158dd7
--- /dev/null
+++ b/test/kb_8042.c
@@ -0,0 +1,206 @@
+/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Tests for keyboard MKBP protocol
+ */
+
+#include "common.h"
+#include "console.h"
+#include "ec_commands.h"
+#include "gpio.h"
+#include "i8042_protocol.h"
+#include "keyboard_8042.h"
+#include "keyboard_protocol.h"
+#include "keyboard_scan.h"
+#include "lpc.h"
+#include "test_util.h"
+#include "timer.h"
+#include "util.h"
+
+static const char *action[2] = {"release", "press"};
+
+#define BUF_SIZE 16
+static char lpc_char_buf[BUF_SIZE];
+static unsigned int lpc_char_cnt;
+
+/*****************************************************************************/
+/* Mock functions */
+
+int lid_is_open(void)
+{
+ return 1;
+}
+
+void lpc_keyboard_put_char(uint8_t chr, int send_irq)
+{
+ lpc_char_buf[lpc_char_cnt++] = chr;
+}
+
+/*****************************************************************************/
+/* Test utilities */
+
+static void press_key(int c, int r, int pressed)
+{
+ ccprintf("Input %s (%d, %d)\n", action[pressed], c, r);
+ keyboard_state_changed(r, c, pressed);
+}
+
+static void enable_keystroke(int enabled)
+{
+ uint8_t data = enabled ? I8042_CMD_ENABLE : I8042_CMD_RESET_DIS;
+ keyboard_host_write(data, 0);
+ msleep(30);
+}
+
+static void reset_8042(void)
+{
+ keyboard_host_write(I8042_CMD_RESET_DEF, 0);
+ msleep(30);
+}
+
+static void set_typematic(uint8_t val)
+{
+ keyboard_host_write(I8042_CMD_SETREP, 0);
+ msleep(30);
+ keyboard_host_write(val, 0);
+ msleep(30);
+}
+
+static void set_scancode(uint8_t s)
+{
+ keyboard_host_write(I8042_CMD_SSCANSET, 0);
+ msleep(30);
+ keyboard_host_write(s, 0);
+ msleep(30);
+}
+
+static void write_cmd_byte(uint8_t val)
+{
+ keyboard_host_write(I8042_WRITE_CMD_BYTE, 1);
+ msleep(30);
+ keyboard_host_write(val, 0);
+ msleep(30);
+}
+
+static uint8_t read_cmd_byte(void)
+{
+ lpc_char_cnt = 0;
+ keyboard_host_write(I8042_READ_CMD_BYTE, 1);
+ msleep(30);
+ return lpc_char_buf[0];
+}
+
+static int __verify_lpc_char(char *arr, unsigned int sz, int delay_ms)
+{
+ int i;
+
+ lpc_char_cnt = 0;
+ for (i = 0; i < sz; ++i)
+ lpc_char_buf[i] = 0;
+ msleep(delay_ms);
+ TEST_ASSERT_ARRAY_EQ(arr, lpc_char_buf, sz);
+ return EC_SUCCESS;
+}
+
+#define VERIFY_LPC_CHAR(s) \
+ TEST_ASSERT(__verify_lpc_char(s, strlen(s), 30) == EC_SUCCESS)
+#define VERIFY_LPC_CHAR_DELAY(s, t) \
+ TEST_ASSERT(__verify_lpc_char(s, strlen(s), t) == EC_SUCCESS)
+
+static int __verify_no_char(void)
+{
+ lpc_char_cnt = 0;
+ msleep(30);
+ TEST_CHECK(lpc_char_cnt == 0);
+}
+
+#define VERIFY_NO_CHAR() TEST_ASSERT(__verify_no_char() == EC_SUCCESS)
+
+/*****************************************************************************/
+/* Tests */
+
+static int test_single_key_press(void)
+{
+ enable_keystroke(1);
+ press_key(1, 1, 1);
+ VERIFY_LPC_CHAR("\x01");
+ press_key(1, 1, 0);
+ VERIFY_LPC_CHAR("\x81");
+
+ press_key(12, 6, 1);
+ VERIFY_LPC_CHAR("\xe0\x4d");
+ press_key(12, 6, 0);
+ VERIFY_LPC_CHAR("\xe0\xcd");
+
+ return EC_SUCCESS;
+}
+
+static int test_disable_keystroke(void)
+{
+ enable_keystroke(0);
+ press_key(1, 1, 1);
+ VERIFY_NO_CHAR();
+ press_key(1, 1, 0);
+ VERIFY_NO_CHAR();
+
+ return EC_SUCCESS;
+}
+
+static int test_typematic(void)
+{
+ enable_keystroke(1);
+
+ /*
+ * 250ms delay, 8 chars / sec.
+ */
+ set_typematic(0xf);
+
+ press_key(1, 1, 1);
+ VERIFY_LPC_CHAR_DELAY("\x01\x01\x01\x01\x01", 650);
+ press_key(1, 1, 0);
+ VERIFY_LPC_CHAR_DELAY("\x81", 300);
+
+ /*
+ * 500ms delay, 10.9 chars / sec.
+ */
+ reset_8042();
+
+ press_key(1, 1, 1);
+ VERIFY_LPC_CHAR_DELAY("\x01\x01\x01", 650);
+ press_key(1, 1, 0);
+ VERIFY_LPC_CHAR_DELAY("\x81", 200);
+
+ return EC_SUCCESS;
+}
+
+static int test_scancode_set2(void)
+{
+ set_scancode(2);
+
+ write_cmd_byte(read_cmd_byte() | I8042_XLATE);
+ press_key(1, 1, 1);
+ VERIFY_LPC_CHAR("\x01");
+ press_key(1, 1, 0);
+ VERIFY_LPC_CHAR("\x81");
+
+ write_cmd_byte(read_cmd_byte() & ~I8042_XLATE);
+ press_key(1, 1, 1);
+ VERIFY_LPC_CHAR("\x76");
+ press_key(1, 1, 0);
+ VERIFY_LPC_CHAR("\xf0\x76");
+
+ return EC_SUCCESS;
+}
+
+void run_test(void)
+{
+ test_reset();
+
+ RUN_TEST(test_single_key_press);
+ RUN_TEST(test_disable_keystroke);
+ RUN_TEST(test_typematic);
+ RUN_TEST(test_scancode_set2);
+
+ test_print_result();
+}
diff --git a/test/kb_8042.tasklist b/test/kb_8042.tasklist
new file mode 100644
index 0000000000..7f87e24129
--- /dev/null
+++ b/test/kb_8042.tasklist
@@ -0,0 +1,20 @@
+/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/**
+ * List of enabled tasks in the priority order
+ *
+ * The first one has the lowest priority.
+ *
+ * For each task, use the macro TASK_TEST(n, r, d, s) where :
+ * 'n' in the name of the task
+ * 'r' in the main routine of the task
+ * 'd' in an opaque parameter passed to the routine at startup
+ * 's' is the stack size in bytes; must be a multiple of 8
+ */
+#define CONFIG_TEST_TASK_LIST \
+ TASK_TEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \
+ TASK_TEST(KEYSCAN, keyboard_scan_task, NULL, 256) \
+ TASK_TEST(CHIPSET, chipset_task, NULL, TASK_STACK_SIZE)
diff --git a/test/test_config.mk b/test/test_config.mk
new file mode 100644
index 0000000000..968519fa22
--- /dev/null
+++ b/test/test_config.mk
@@ -0,0 +1,9 @@
+# -*- makefile -*-
+# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# per-test configuration
+#
+
+CFLAGS-kb_8042=-DKB_8042