summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLouis Yung-Chieh Lo <yjlou@chromium.org>2012-03-02 11:29:06 +0800
committerLouis Yung-Chieh Lo <yjlou@chromium.org>2012-03-02 11:29:06 +0800
commit763af1f695eb9c6407f83bbe16e37165498a71bc (patch)
treeade118bf0755e53f730d30626139f1954e51047d
parent5cd0f292e9c769264c5fa1f0fe262c910a9194ec (diff)
downloadchrome-ec-763af1f695eb9c6407f83bbe16e37165498a71bc.tar.gz
Handle ghost key in matrix scanner.
implement actual_key_masks[]. A ghost key exists if two columns share more than one row (after ANDed actual_key_masks[]). BUG=chrome-os-partner:7485 TEST=on bds. test cases: single press of all keys. ~ 1 4 5: later 2 keys should be ignored (ghost). h j k: all keys should work. u R-shift 0 P: p should be ignored (ghost). i R-shift ' p: P should show up. Change-Id: I1ac105874a5327e839a5240ccbdd6304637ad404
-rw-r--r--chip/lm4/keyboard_scan.c26
1 files changed, 21 insertions, 5 deletions
diff --git a/chip/lm4/keyboard_scan.c b/chip/lm4/keyboard_scan.c
index 3da4cbbf13..3729a304f5 100644
--- a/chip/lm4/keyboard_scan.c
+++ b/chip/lm4/keyboard_scan.c
@@ -70,8 +70,8 @@ static const uint8_t *actual_key_mask;
/* TODO: (crosbug.com/p/7485) fill in real key mask with 0-bits for coords that
aren't keys */
static const uint8_t actual_key_masks[4][KB_COLS] = {
- {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ {0x14, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff,
+ 0xa4, 0xff, 0xf6, 0x55, 0xfa, 0xc8}, /* full set */
{0},
{0},
{0},
@@ -224,10 +224,11 @@ static void print_raw_state(const char *msg)
/* Returns 1 if any key is still pressed. 0 if no key is pressed. */
static int check_keys_changed(void)
{
- int c;
+ int c, c2;
uint8_t r;
int change = 0;
int num_press = 0;
+ uint8_t keys[KB_COLS];
for (c = 0; c < KB_COLS; c++) {
/* Select column, then wait a bit for it to settle */
@@ -247,7 +248,22 @@ static int check_keys_changed(void)
r |= raw_state[c];
#endif
- /* Check for changes */
+ keys[c] = r;
+ }
+ select_column(COLUMN_TRI_STATE_ALL);
+
+ /* ignore if a ghost key appears. */
+ for (c = 0; c < KB_COLS; c++) {
+ if (!keys[c]) continue;
+ for (c2 = c + 1; c2 < KB_COLS; c2++) {
+ uint8_t common = keys[c] & keys[c2];
+ if (common & (common - 1)) goto out;
+ }
+ }
+
+ /* Check for changes */
+ for (c = 0; c < KB_COLS; c++) {
+ r = keys[c];
if (r != raw_state[c]) {
int i;
for (i = 0; i < 8; ++i) {
@@ -261,11 +277,11 @@ static int check_keys_changed(void)
change = 1;
}
}
- select_column(COLUMN_TRI_STATE_ALL);
if (change)
print_raw_state("KB raw state");
+out:
/* Count number of key pressed */
for (c = 0; c < KB_COLS; c++) {
if (raw_state[c]) ++num_press;