diff options
author | Vic Yang <victoryang@chromium.org> | 2013-07-08 09:54:36 +0800 |
---|---|---|
committer | ChromeBot <chrome-bot@google.com> | 2013-07-11 22:32:52 -0700 |
commit | 2475cce9ad0e505a45562189e5427683d4ebd65c (patch) | |
tree | 1110f516e9d50900ce1cb4492f2743f1639cd8e2 | |
parent | b2bc8aaa20479a87261aed8611367f11cf33c909 (diff) | |
download | chrome-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-- | Makefile | 3 | ||||
-rw-r--r-- | Makefile.toolchain | 3 | ||||
-rw-r--r-- | board/host/board.h | 8 | ||||
-rw-r--r-- | chip/host/build.mk | 2 | ||||
-rw-r--r-- | chip/host/lpc.c | 33 | ||||
-rw-r--r-- | test/build.mk | 4 | ||||
-rw-r--r-- | test/kb_8042.c | 206 | ||||
-rw-r--r-- | test/kb_8042.tasklist | 20 | ||||
-rw-r--r-- | test/test_config.mk | 9 |
9 files changed, 284 insertions, 4 deletions
@@ -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 |