diff options
author | Arve Hjønnevåg <arve@android.com> | 2009-07-24 15:19:56 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:37:56 -0800 |
commit | 029dcd0b6f943f31f86b625c9c8e16d88381acb4 (patch) | |
tree | 322d08f08e9ca08d6548b8f02788d860210030c6 /drivers/input/misc/gpio_axis.c | |
parent | 27dea20c8713e6d28c119e6668a0ea50e17d94b3 (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_axis.c')
-rw-r--r-- | drivers/input/misc/gpio_axis.c | 29 |
1 files changed, 20 insertions, 9 deletions
diff --git a/drivers/input/misc/gpio_axis.c b/drivers/input/misc/gpio_axis.c index 61782207bce1..0acf4a576f53 100644 --- a/drivers/input/misc/gpio_axis.c +++ b/drivers/input/misc/gpio_axis.c @@ -20,7 +20,7 @@ #include <linux/slab.h> struct gpio_axis_state { - struct input_dev *input_dev; + struct gpio_event_input_devs *input_devs; struct gpio_event_axis_info *info; uint32_t pos; }; @@ -88,14 +88,16 @@ static void gpio_event_update_axis(struct gpio_axis_state *as, int report) if (ai->flags & GPIOEAF_PRINT_EVENT) pr_info("axis %d-%d change %d\n", ai->type, ai->code, change); - input_report_rel(as->input_dev, ai->code, change); + input_report_rel(as->input_devs->dev[ai->dev], + ai->code, change); } else { if (ai->flags & GPIOEAF_PRINT_EVENT) pr_info("axis %d-%d now %d\n", ai->type, ai->code, pos); - input_event(as->input_dev, ai->type, ai->code, pos); + input_event(as->input_devs->dev[ai->dev], + ai->type, ai->code, pos); } - input_sync(as->input_dev); + input_sync(as->input_devs->dev[ai->dev]); } as->pos = pos; } @@ -107,7 +109,7 @@ static irqreturn_t gpio_axis_irq_handler(int irq, void *dev_id) return IRQ_HANDLED; } -int gpio_event_axis_func(struct input_dev *input_dev, +int gpio_event_axis_func(struct gpio_event_input_devs *input_devs, struct gpio_event_info *info, void **data, int func) { int ret; @@ -134,13 +136,21 @@ int gpio_event_axis_func(struct input_dev *input_dev, ret = -ENOMEM; goto err_alloc_axis_state_failed; } - as->input_dev = input_dev; + as->input_devs = input_devs; as->info = ai; + if (ai->dev >= input_devs->count) { + pr_err("gpio_event_axis: bad device index %d >= %d " + "for %d:%d\n", ai->dev, input_devs->count, + ai->type, ai->code); + ret = -EINVAL; + goto err_bad_device_index; + } - input_set_capability(input_dev, ai->type, ai->code); + input_set_capability(input_devs->dev[ai->dev], + ai->type, ai->code); if (ai->type == EV_ABS) { - input_set_abs_params(input_dev, ai->code, 0, - ai->decoded_size - 1, 0, 0); + input_set_abs_params(input_devs->dev[ai->dev], ai->code, + 0, ai->decoded_size - 1, 0, 0); } for (i = 0; i < ai->count; i++) { ret = gpio_request(ai->gpio[i], "gpio_event_axis"); @@ -174,6 +184,7 @@ err_gpio_direction_input_failed: err_request_gpio_failed: ; } +err_bad_device_index: kfree(as); *data = NULL; err_alloc_axis_state_failed: |