summaryrefslogtreecommitdiff
path: root/drivers/input/misc/gpio_input.c
diff options
context:
space:
mode:
authorArve Hjønnevåg <arve@android.com>2009-07-24 15:19:56 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:37:56 -0800
commit029dcd0b6f943f31f86b625c9c8e16d88381acb4 (patch)
tree322d08f08e9ca08d6548b8f02788d860210030c6 /drivers/input/misc/gpio_input.c
parent27dea20c8713e6d28c119e6668a0ea50e17d94b3 (diff)
Input: gpio_event: Allow multiple input devices per gpio_event device
This is needed to support devices that put non-keyboard buttons in the keyboard matrix. For instance several devices put the trackball button in the keyboard matrix. In this case BTN_MOUSE should be reported from the same input device as REL_X/Y. It is also useful for devices that have multiple logical keyboard in the same matrix. The HTC dream has a menu key on the external keyboard and another menu key on the slide-out keyboard. With a single input device only one of these menu keys can be mapped to KEY_MENU. Signed-off-by: Arve Hjønnevåg <arve@android.com>
Diffstat (limited to 'drivers/input/misc/gpio_input.c')
-rw-r--r--drivers/input/misc/gpio_input.c29
1 files changed, 20 insertions, 9 deletions
diff --git a/drivers/input/misc/gpio_input.c b/drivers/input/misc/gpio_input.c
index 15c89ec5083b..6aef289e6e14 100644
--- a/drivers/input/misc/gpio_input.c
+++ b/drivers/input/misc/gpio_input.c
@@ -39,7 +39,7 @@ struct gpio_key_state {
};
struct gpio_input_state {
- struct input_dev *input_dev;
+ struct gpio_event_input_devs *input_devs;
const struct gpio_event_input_info *info;
struct hrtimer timer;
int use_irq;
@@ -127,7 +127,7 @@ static enum hrtimer_restart gpio_event_input_timer_func(struct hrtimer *timer)
pr_info("gpio_keys_scan_keys: key %x-%x, %d (%d) "
"changed to %d\n", ds->info->type,
key_entry->code, i, key_entry->gpio, pressed);
- input_event(ds->input_dev, ds->info->type,
+ input_event(ds->input_devs->dev[key_entry->dev], ds->info->type,
key_entry->code, pressed);
}
@@ -194,7 +194,7 @@ static irqreturn_t gpio_event_input_irq_handler(int irq, void *dev_id)
"(%d) changed to %d\n",
ds->info->type, key_entry->code, keymap_index,
key_entry->gpio, pressed);
- input_event(ds->input_dev, ds->info->type,
+ input_event(ds->input_devs->dev[key_entry->dev], ds->info->type,
key_entry->code, pressed);
}
return IRQ_HANDLED;
@@ -233,7 +233,7 @@ err_gpio_get_irq_num_failed:
return err;
}
-int gpio_event_input_func(struct input_dev *input_dev,
+int gpio_event_input_func(struct gpio_event_input_devs *input_devs,
struct gpio_event_info *info, void **data, int func)
{
int ret;
@@ -276,13 +276,22 @@ int gpio_event_input_func(struct input_dev *input_dev,
goto err_ds_alloc_failed;
}
ds->debounce_count = di->keymap_size;
- ds->input_dev = input_dev;
+ ds->input_devs = input_devs;
ds->info = di;
wake_lock_init(&ds->wake_lock, WAKE_LOCK_SUSPEND, "gpio_input");
spin_lock_init(&ds->irq_lock);
for (i = 0; i < di->keymap_size; i++) {
- input_set_capability(input_dev, di->type,
+ int dev = di->keymap[i].dev;
+ if (dev >= input_devs->count) {
+ pr_err("gpio_event_input_func: bad device "
+ "index %d >= %d for key code %d\n",
+ dev, input_devs->count,
+ di->keymap[i].code);
+ ret = -EINVAL;
+ goto err_bad_keymap;
+ }
+ input_set_capability(input_devs->dev[dev], di->type,
di->keymap[i].code);
ds->key_state[i].ds = ds;
ds->key_state[i].debounce = DEBOUNCE_UNKNOWN;
@@ -309,9 +318,10 @@ int gpio_event_input_func(struct input_dev *input_dev,
spin_lock_irqsave(&ds->irq_lock, irqflags);
ds->use_irq = ret == 0;
- pr_info("GPIO Input Driver: Start gpio inputs for %s in %s "
- "mode\n",
- input_dev->name, ret == 0 ? "interrupt" : "polling");
+ pr_info("GPIO Input Driver: Start gpio inputs for %s%s in %s "
+ "mode\n", input_devs->dev[0]->name,
+ (input_devs->count > 1) ? "..." : "",
+ ret == 0 ? "interrupt" : "polling");
hrtimer_init(&ds->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
ds->timer.function = gpio_event_input_timer_func;
@@ -337,6 +347,7 @@ err_gpio_configure_failed:
err_gpio_request_failed:
;
}
+err_bad_keymap:
wake_lock_destroy(&ds->wake_lock);
kfree(ds);
err_ds_alloc_failed: