summaryrefslogtreecommitdiff
path: root/drivers/input/misc/gpio_matrix.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/misc/gpio_matrix.c')
-rw-r--r--drivers/input/misc/gpio_matrix.c43
1 files changed, 30 insertions, 13 deletions
diff --git a/drivers/input/misc/gpio_matrix.c b/drivers/input/misc/gpio_matrix.c
index 10b44110166..adb00ab47b6 100644
--- a/drivers/input/misc/gpio_matrix.c
+++ b/drivers/input/misc/gpio_matrix.c
@@ -22,7 +22,7 @@
#include <linux/wakelock.h>
struct gpio_kp {
- struct input_dev *input_dev;
+ struct gpio_event_input_devs *input_devs;
struct gpio_event_matrix_info *keypad_info;
struct hrtimer timer;
struct wake_lock wake_lock;
@@ -38,9 +38,11 @@ static void clear_phantom_key(struct gpio_kp *kp, int out, int in)
{
struct gpio_event_matrix_info *mi = kp->keypad_info;
int key_index = out * mi->ninputs + in;
- unsigned short keycode = mi->keymap[key_index];;
+ unsigned short keyentry = mi->keymap[key_index];
+ unsigned short keycode = keyentry & MATRIX_KEY_MASK;
+ unsigned short dev = keyentry >> MATRIX_CODE_BITS;
- if (!test_bit(keycode, kp->input_dev->key)) {
+ if (!test_bit(keycode, kp->input_devs->dev[dev]->key)) {
if (mi->flags & GPIOKPF_PRINT_PHANTOM_KEYS)
pr_info("gpiomatrix: phantom key %x, %d-%d (%d-%d) "
"cleared\n", keycode, out, in,
@@ -105,8 +107,11 @@ static void report_key(struct gpio_kp *kp, int key_index, int out, int in)
{
struct gpio_event_matrix_info *mi = kp->keypad_info;
int pressed = test_bit(key_index, kp->keys_pressed);
- unsigned short keycode = mi->keymap[key_index];
- if (pressed != test_bit(keycode, kp->input_dev->key)) {
+ unsigned short keyentry = mi->keymap[key_index];
+ unsigned short keycode = keyentry & MATRIX_KEY_MASK;
+ unsigned short dev = keyentry >> MATRIX_CODE_BITS;
+
+ if (pressed != test_bit(keycode, kp->input_devs->dev[dev]->key)) {
if (keycode == KEY_RESERVED) {
if (mi->flags & GPIOKPF_PRINT_UNMAPPED_KEYS)
pr_info("gpiomatrix: unmapped key, %d-%d "
@@ -119,7 +124,7 @@ static void report_key(struct gpio_kp *kp, int key_index, int out, int in)
"changed to %d\n", keycode,
out, in, mi->output_gpios[out],
mi->input_gpios[in], pressed);
- input_report_key(kp->input_dev, keycode, pressed);
+ input_report_key(kp->input_devs->dev[dev], keycode, pressed);
}
}
}
@@ -280,7 +285,7 @@ err_gpio_get_irq_num_failed:
return err;
}
-int gpio_event_matrix_func(struct input_dev *input_dev,
+int gpio_event_matrix_func(struct gpio_event_input_devs *input_devs,
struct gpio_event_info *info, void **data, int func)
{
int i;
@@ -312,12 +317,22 @@ int gpio_event_matrix_func(struct input_dev *input_dev,
pr_err("gpiomatrix: Failed to allocate private data\n");
goto err_kp_alloc_failed;
}
- kp->input_dev = input_dev;
+ kp->input_devs = input_devs;
kp->keypad_info = mi;
- set_bit(EV_KEY, input_dev->evbit);
for (i = 0; i < key_count; i++) {
- if (mi->keymap[i] && mi->keymap[i] <= KEY_MAX)
- set_bit(mi->keymap[i], input_dev->keybit);
+ unsigned short keyentry = mi->keymap[i];
+ unsigned short keycode = keyentry & MATRIX_KEY_MASK;
+ unsigned short dev = keyentry >> MATRIX_CODE_BITS;
+ if (dev >= input_devs->count) {
+ pr_err("gpiomatrix: bad device index %d >= "
+ "%d for key code %d\n",
+ dev, input_devs->count, keycode);
+ err = -EINVAL;
+ goto err_bad_keymap;
+ }
+ if (keycode && keycode <= KEY_MAX)
+ input_set_capability(input_devs->dev[dev],
+ EV_KEY, keycode);
}
for (i = 0; i < mi->noutputs; i++) {
@@ -367,8 +382,9 @@ int gpio_event_matrix_func(struct input_dev *input_dev,
err = gpio_keypad_request_irqs(kp);
kp->use_irq = err == 0;
- pr_info("GPIO Matrix Keypad Driver: Start keypad matrix for %s "
- "in %s mode\n", input_dev->name,
+ pr_info("GPIO Matrix Keypad Driver: Start keypad matrix for "
+ "%s%s in %s mode\n", input_devs->dev[0]->name,
+ (input_devs->count > 1) ? "..." : "",
kp->use_irq ? "interrupt" : "polling");
if (kp->use_irq)
@@ -399,6 +415,7 @@ err_output_gpio_configure_failed:
err_request_output_gpio_failed:
;
}
+err_bad_keymap:
kfree(kp);
err_kp_alloc_failed:
err_invalid_platform_data: