summaryrefslogtreecommitdiff
path: root/drivers/input/misc/gpio_axis.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_axis.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_axis.c')
-rw-r--r--drivers/input/misc/gpio_axis.c29
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: