summaryrefslogtreecommitdiff
path: root/test/kb_deghost.c
blob: 3a4384bed431d35aed379fe3060990d9bb61d06a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/* 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.
 * Copyright 2013 Google Inc.
 *
 * Tasks for keyboard scan deghosting.
 */

#include "common.h"
#include "console.h"
#include "keyboard_raw.h"
#include "keyboard_scan.h"
#include "task.h"
#include "timer.h"
#include "util.h"

#define KEYDOWN_DELAY_MS     10
#define KEYDOWN_RETRY        10
#define NO_KEYDOWN_DELAY_MS  200

#define TEST(n) \
	do { \
		if (!n()) { \
			ccprintf("%s failed.\n", #n); \
			return EC_ERROR_UNKNOWN; \
		} \
	} while (0)

uint8_t mock_state[KEYBOARD_COLS];
int column_driven;
int fifo_add_count;

void keyboard_raw_drive_column(int out)
{
	column_driven = out;
}

int keyboard_raw_read_rows(void)
{
	int i;
	int r = 0;

	if (column_driven == KEYBOARD_COLUMN_NONE) {
		return 0;
	} else if (column_driven == KEYBOARD_COLUMN_ALL) {
		for (i = 0; i < KEYBOARD_COLS; ++i)
			r |= mock_state[i];
		return r;
	} else {
		return mock_state[column_driven];
	}
}

int keyboard_fifo_add(const uint8_t *buffp)
{
	fifo_add_count++;
	return EC_SUCCESS;
}

void mock_key(int r, int c, int keydown)
{
	ccprintf("%s (%d, %d)\n", keydown ? "Pressing" : "Releasing", r, c);
	if (keydown)
		mock_state[c] |= (1 << r);
	else
		mock_state[c] &= ~(1 << r);
}

int expect_keychange(void)
{
	int old_count = fifo_add_count;
	int retry = KEYDOWN_RETRY;
	task_wake(TASK_ID_KEYSCAN);
	while (retry--) {
		msleep(KEYDOWN_DELAY_MS);
		if (fifo_add_count > old_count)
			return 1;
	}
	return 0;
}

int expect_no_keychange(void)
{
	int old_count = fifo_add_count;
	task_wake(TASK_ID_KEYSCAN);
	msleep(NO_KEYDOWN_DELAY_MS);
	return fifo_add_count == old_count;
}

int deghost_test(void)
{
	/* Test we can detect a keypress */
	mock_key(1, 1, 1);
	TEST(expect_keychange);
	mock_key(1, 1, 0);
	TEST(expect_keychange);

	/* (1, 1) (1, 2) (2, 1) (2, 2) form ghosting keys */
	mock_key(1, 1, 1);
	TEST(expect_keychange);
	mock_key(2, 2, 1);
	TEST(expect_keychange);
	mock_key(1, 2, 1);
	mock_key(2, 1, 1);
	TEST(expect_no_keychange);
	mock_key(2, 1, 0);
	mock_key(1, 2, 0);
	TEST(expect_no_keychange);
	mock_key(2, 2, 0);
	TEST(expect_keychange);
	mock_key(1, 1, 0);
	TEST(expect_keychange);

	/* (1, 1) (2, 0) (2, 1) don't form ghosting keys */
	mock_key(1, 1, 1);
	TEST(expect_keychange);
	mock_key(2, 0, 1);
	TEST(expect_keychange);
	mock_key(1, 0, 1);
	mock_key(2, 1, 1);
	TEST(expect_keychange);
	mock_key(1, 0, 0);
	mock_key(2, 1, 0);
	TEST(expect_keychange);
	mock_key(2, 0, 0);
	TEST(expect_keychange);
	mock_key(1, 1, 0);
	TEST(expect_keychange);

	return EC_SUCCESS;
}

static int command_run_test(int argc, char **argv)
{
	int r = deghost_test();
	if (r == EC_SUCCESS)
		ccprintf("Pass!\n");
	else
		ccprintf("Fail!\n");
	return r;
}
DECLARE_CONSOLE_COMMAND(runtest, command_run_test,
			NULL, NULL, NULL);