Skip to content

Commit

Permalink
Input: twl40300-keypad - fix handling of "all ground" rows
Browse files Browse the repository at this point in the history
The Nokia RX51 board code (arch/arm/mach-omap2/board-rx51-peripherals.c)
defines a key map for the matrix keypad keyboard. The hardware seems to
use all of the 8 rows and 8 columns of the keypad, although not all
possible locations are used.

The TWL4030 supports keypads with at most 8 rows and 8 columns. Most keys
are defined with a row and column number between 0 and 7, except

        KEY(0xff, 2, KEY_F9),
        KEY(0xff, 4, KEY_F10),
        KEY(0xff, 5, KEY_F11),

which represent keycodes that should be emitted when entire row is
connected to the ground.  since the driver handles this case as if we
had an extra column in the key matrix. Unfortunately we do not allocate
enough space and end up owerwriting some random memory.

Reported-and-tested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: stable@kernel.org
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
  • Loading branch information
Dmitry Torokhov committed Jul 21, 2010
1 parent c25f7b7 commit 3fea602
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 9 deletions.
17 changes: 14 additions & 3 deletions arch/arm/mach-omap2/board-rx51-peripherals.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,13 +175,18 @@ static void __init rx51_add_gpio_keys(void)
#endif /* CONFIG_KEYBOARD_GPIO || CONFIG_KEYBOARD_GPIO_MODULE */

static int board_keymap[] = {
/*
* Note that KEY(x, 8, KEY_XXX) entries represent "entrire row
* connected to the ground" matrix state.
*/
KEY(0, 0, KEY_Q),
KEY(0, 1, KEY_O),
KEY(0, 2, KEY_P),
KEY(0, 3, KEY_COMMA),
KEY(0, 4, KEY_BACKSPACE),
KEY(0, 6, KEY_A),
KEY(0, 7, KEY_S),

KEY(1, 0, KEY_W),
KEY(1, 1, KEY_D),
KEY(1, 2, KEY_F),
Expand All @@ -190,13 +195,16 @@ static int board_keymap[] = {
KEY(1, 5, KEY_J),
KEY(1, 6, KEY_K),
KEY(1, 7, KEY_L),

KEY(2, 0, KEY_E),
KEY(2, 1, KEY_DOT),
KEY(2, 2, KEY_UP),
KEY(2, 3, KEY_ENTER),
KEY(2, 5, KEY_Z),
KEY(2, 6, KEY_X),
KEY(2, 7, KEY_C),
KEY(2, 8, KEY_F9),

KEY(3, 0, KEY_R),
KEY(3, 1, KEY_V),
KEY(3, 2, KEY_B),
Expand All @@ -205,20 +213,23 @@ static int board_keymap[] = {
KEY(3, 5, KEY_SPACE),
KEY(3, 6, KEY_SPACE),
KEY(3, 7, KEY_LEFT),

KEY(4, 0, KEY_T),
KEY(4, 1, KEY_DOWN),
KEY(4, 2, KEY_RIGHT),
KEY(4, 4, KEY_LEFTCTRL),
KEY(4, 5, KEY_RIGHTALT),
KEY(4, 6, KEY_LEFTSHIFT),
KEY(4, 8, KEY_10),

KEY(5, 0, KEY_Y),
KEY(5, 8, KEY_11),

KEY(6, 0, KEY_U),

KEY(7, 0, KEY_I),
KEY(7, 1, KEY_F7),
KEY(7, 2, KEY_F8),
KEY(0xff, 2, KEY_F9),
KEY(0xff, 4, KEY_F10),
KEY(0xff, 5, KEY_F11),
};

static struct matrix_keymap_data board_map_data = {
Expand Down
17 changes: 11 additions & 6 deletions drivers/input/keyboard/twl4030_keypad.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,12 @@
*/
#define TWL4030_MAX_ROWS 8 /* TWL4030 hard limit */
#define TWL4030_MAX_COLS 8
#define TWL4030_ROW_SHIFT 3
#define TWL4030_KEYMAP_SIZE (TWL4030_MAX_ROWS * TWL4030_MAX_COLS)
/*
* Note that we add space for an extra column so that we can handle
* row lines connected to the gnd (see twl4030_col_xlate()).
*/
#define TWL4030_ROW_SHIFT 4
#define TWL4030_KEYMAP_SIZE (TWL4030_MAX_ROWS << TWL4030_ROW_SHIFT)

struct twl4030_keypad {
unsigned short keymap[TWL4030_KEYMAP_SIZE];
Expand Down Expand Up @@ -182,7 +186,7 @@ static int twl4030_read_kp_matrix_state(struct twl4030_keypad *kp, u16 *state)
return ret;
}

static int twl4030_is_in_ghost_state(struct twl4030_keypad *kp, u16 *key_state)
static bool twl4030_is_in_ghost_state(struct twl4030_keypad *kp, u16 *key_state)
{
int i;
u16 check = 0;
Expand All @@ -191,12 +195,12 @@ static int twl4030_is_in_ghost_state(struct twl4030_keypad *kp, u16 *key_state)
u16 col = key_state[i];

if ((col & check) && hweight16(col) > 1)
return 1;
return true;

check |= col;
}

return 0;
return false;
}

static void twl4030_kp_scan(struct twl4030_keypad *kp, bool release_all)
Expand Down Expand Up @@ -225,7 +229,8 @@ static void twl4030_kp_scan(struct twl4030_keypad *kp, bool release_all)
if (!changed)
continue;

for (col = 0; col < kp->n_cols; col++) {
/* Extra column handles "all gnd" rows */
for (col = 0; col < kp->n_cols + 1; col++) {
int code;

if (!(changed & (1 << col)))
Expand Down

0 comments on commit 3fea602

Please sign in to comment.