mirror of
https://github.com/torvalds/linux.git
synced 2026-06-08 14:42:37 +02:00
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>
This commit is contained in:
parent
8f836aa8da
commit
0da26bfb4e
|
|
@ -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 @@ int gpio_event_axis_func(struct input_dev *input_dev,
|
|||
err_request_gpio_failed:
|
||||
;
|
||||
}
|
||||
err_bad_device_index:
|
||||
kfree(as);
|
||||
*data = NULL;
|
||||
err_alloc_axis_state_failed:
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
#include <linux/slab.h>
|
||||
|
||||
struct gpio_event {
|
||||
struct input_dev *input_dev;
|
||||
struct gpio_event_input_devs *input_devs;
|
||||
const struct gpio_event_platform_data *info;
|
||||
struct early_suspend early_suspend;
|
||||
void *state[0];
|
||||
|
|
@ -32,15 +32,25 @@ static int gpio_input_event(
|
|||
struct input_dev *dev, unsigned int type, unsigned int code, int value)
|
||||
{
|
||||
int i;
|
||||
int devnr;
|
||||
int ret = 0;
|
||||
int tmp_ret;
|
||||
struct gpio_event_info **ii;
|
||||
struct gpio_event *ip = input_get_drvdata(dev);
|
||||
|
||||
for (devnr = 0; devnr < ip->input_devs->count; devnr++)
|
||||
if (ip->input_devs->dev[devnr] == dev)
|
||||
break;
|
||||
if (devnr == ip->input_devs->count) {
|
||||
pr_err("gpio_input_event: unknown device %p\n", dev);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
for (i = 0, ii = ip->info->info; i < ip->info->info_count; i++, ii++) {
|
||||
if ((*ii)->event) {
|
||||
tmp_ret = (*ii)->event(ip->input_dev, *ii,
|
||||
&ip->state[i], type, code, value);
|
||||
tmp_ret = (*ii)->event(ip->input_devs, *ii,
|
||||
&ip->state[i],
|
||||
devnr, type, code, value);
|
||||
if (tmp_ret)
|
||||
ret = tmp_ret;
|
||||
}
|
||||
|
|
@ -63,7 +73,9 @@ static int gpio_event_call_all_func(struct gpio_event *ip, int func)
|
|||
"no function\n");
|
||||
goto err_no_func;
|
||||
}
|
||||
ret = (*ii)->func(ip->input_dev, *ii, &ip->state[i],
|
||||
if (func == GPIO_EVENT_FUNC_RESUME && (*ii)->no_suspend)
|
||||
continue;
|
||||
ret = (*ii)->func(ip->input_devs, *ii, &ip->state[i],
|
||||
func);
|
||||
if (ret) {
|
||||
pr_err("gpio_event_probe: function failed\n");
|
||||
|
|
@ -79,7 +91,9 @@ static int gpio_event_call_all_func(struct gpio_event *ip, int func)
|
|||
while (i > 0) {
|
||||
i--;
|
||||
ii--;
|
||||
(*ii)->func(ip->input_dev, *ii, &ip->state[i], func & ~1);
|
||||
if ((func & ~1) == GPIO_EVENT_FUNC_SUSPEND && (*ii)->no_suspend)
|
||||
continue;
|
||||
(*ii)->func(ip->input_devs, *ii, &ip->state[i], func & ~1);
|
||||
err_func_failed:
|
||||
err_no_func:
|
||||
;
|
||||
|
|
@ -109,37 +123,51 @@ static int __init gpio_event_probe(struct platform_device *pdev)
|
|||
{
|
||||
int err;
|
||||
struct gpio_event *ip;
|
||||
struct input_dev *input_dev;
|
||||
struct gpio_event_platform_data *event_info;
|
||||
int dev_count = 1;
|
||||
int i;
|
||||
int registered = 0;
|
||||
|
||||
event_info = pdev->dev.platform_data;
|
||||
if (event_info == NULL) {
|
||||
pr_err("gpio_event_probe: No pdata\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
if (event_info->name == NULL ||
|
||||
event_info->info == NULL ||
|
||||
event_info->info_count == 0) {
|
||||
if ((!event_info->name && !event_info->names[0]) ||
|
||||
!event_info->info || !event_info->info_count) {
|
||||
pr_err("gpio_event_probe: Incomplete pdata\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
if (!event_info->name)
|
||||
while (event_info->names[dev_count])
|
||||
dev_count++;
|
||||
ip = kzalloc(sizeof(*ip) +
|
||||
sizeof(ip->state[0]) * event_info->info_count, GFP_KERNEL);
|
||||
sizeof(ip->state[0]) * event_info->info_count +
|
||||
sizeof(*ip->input_devs) +
|
||||
sizeof(ip->input_devs->dev[0]) * dev_count, GFP_KERNEL);
|
||||
if (ip == NULL) {
|
||||
err = -ENOMEM;
|
||||
pr_err("gpio_event_probe: Failed to allocate private data\n");
|
||||
goto err_kp_alloc_failed;
|
||||
}
|
||||
ip->input_devs = (void*)&ip->state[event_info->info_count];
|
||||
platform_set_drvdata(pdev, ip);
|
||||
|
||||
input_dev = input_allocate_device();
|
||||
if (input_dev == NULL) {
|
||||
err = -ENOMEM;
|
||||
pr_err("gpio_event_probe: Failed to allocate input device\n");
|
||||
goto err_input_dev_alloc_failed;
|
||||
for (i = 0; i < dev_count; i++) {
|
||||
struct input_dev *input_dev = input_allocate_device();
|
||||
if (input_dev == NULL) {
|
||||
err = -ENOMEM;
|
||||
pr_err("gpio_event_probe: "
|
||||
"Failed to allocate input device\n");
|
||||
goto err_input_dev_alloc_failed;
|
||||
}
|
||||
input_set_drvdata(input_dev, ip);
|
||||
input_dev->name = event_info->name ?
|
||||
event_info->name : event_info->names[i];
|
||||
input_dev->event = gpio_input_event;
|
||||
ip->input_devs->dev[i] = input_dev;
|
||||
}
|
||||
input_set_drvdata(input_dev, ip);
|
||||
ip->input_dev = input_dev;
|
||||
ip->input_devs->count = dev_count;
|
||||
ip->info = event_info;
|
||||
if (event_info->power) {
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
|
|
@ -151,18 +179,18 @@ static int __init gpio_event_probe(struct platform_device *pdev)
|
|||
ip->info->power(ip->info, 1);
|
||||
}
|
||||
|
||||
input_dev->name = ip->info->name;
|
||||
input_dev->event = gpio_input_event;
|
||||
|
||||
err = gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_INIT);
|
||||
if (err)
|
||||
goto err_call_all_func_failed;
|
||||
|
||||
err = input_register_device(input_dev);
|
||||
if (err) {
|
||||
pr_err("gpio_event_probe: Unable to register %s input device\n",
|
||||
input_dev->name);
|
||||
goto err_input_register_device_failed;
|
||||
for (i = 0; i < dev_count; i++) {
|
||||
err = input_register_device(ip->input_devs->dev[i]);
|
||||
if (err) {
|
||||
pr_err("gpio_event_probe: Unable to register %s "
|
||||
"input device\n", ip->input_devs->dev[i]->name);
|
||||
goto err_input_register_device_failed;
|
||||
}
|
||||
registered++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -176,8 +204,13 @@ static int __init gpio_event_probe(struct platform_device *pdev)
|
|||
#endif
|
||||
ip->info->power(ip->info, 0);
|
||||
}
|
||||
input_free_device(input_dev);
|
||||
for (i = 0; i < registered; i++)
|
||||
input_unregister_device(ip->input_devs->dev[i]);
|
||||
for (i = dev_count - 1; i >= registered; i--) {
|
||||
input_free_device(ip->input_devs->dev[i]);
|
||||
err_input_dev_alloc_failed:
|
||||
;
|
||||
}
|
||||
kfree(ip);
|
||||
err_kp_alloc_failed:
|
||||
return err;
|
||||
|
|
@ -186,6 +219,7 @@ static int __init gpio_event_probe(struct platform_device *pdev)
|
|||
static int gpio_event_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct gpio_event *ip = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
|
||||
gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_UNINIT);
|
||||
if (ip->info->power) {
|
||||
|
|
@ -194,7 +228,8 @@ static int gpio_event_remove(struct platform_device *pdev)
|
|||
#endif
|
||||
ip->info->power(ip->info, 0);
|
||||
}
|
||||
input_unregister_device(ip->input_dev);
|
||||
for (i = 0; i < ip->input_devs->count; i++)
|
||||
input_unregister_device(ip->input_devs->dev[i]);
|
||||
kfree(ip);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 @@ static int gpio_event_input_request_irqs(struct gpio_input_state *ds)
|
|||
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 @@ int gpio_event_input_func(struct input_dev *input_dev,
|
|||
err_gpio_request_failed:
|
||||
;
|
||||
}
|
||||
err_bad_keymap:
|
||||
wake_lock_destroy(&ds->wake_lock);
|
||||
kfree(ds);
|
||||
err_ds_alloc_failed:
|
||||
|
|
|
|||
|
|
@ -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 @@ static int gpio_keypad_request_irqs(struct gpio_kp *kp)
|
|||
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 @@ int gpio_event_matrix_func(struct input_dev *input_dev,
|
|||
err_request_output_gpio_failed:
|
||||
;
|
||||
}
|
||||
err_bad_keymap:
|
||||
kfree(kp);
|
||||
err_kp_alloc_failed:
|
||||
err_invalid_platform_data:
|
||||
|
|
|
|||
|
|
@ -18,8 +18,9 @@
|
|||
#include <linux/gpio_event.h>
|
||||
|
||||
int gpio_event_output_event(
|
||||
struct input_dev *input_dev, struct gpio_event_info *info, void **data,
|
||||
unsigned int type, unsigned int code, int value)
|
||||
struct gpio_event_input_devs *input_devs, struct gpio_event_info *info,
|
||||
void **data, unsigned int dev, unsigned int type,
|
||||
unsigned int code, int value)
|
||||
{
|
||||
int i;
|
||||
struct gpio_event_output_info *oi;
|
||||
|
|
@ -29,14 +30,14 @@ int gpio_event_output_event(
|
|||
if (!(oi->flags & GPIOEDF_ACTIVE_HIGH))
|
||||
value = !value;
|
||||
for (i = 0; i < oi->keymap_size; i++)
|
||||
if (code == oi->keymap[i].code)
|
||||
if (dev == oi->keymap[i].dev && code == oi->keymap[i].code)
|
||||
gpio_set_value(oi->keymap[i].gpio, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gpio_event_output_func(
|
||||
struct input_dev *input_dev, struct gpio_event_info *info, void **data,
|
||||
int func)
|
||||
struct gpio_event_input_devs *input_devs, struct gpio_event_info *info,
|
||||
void **data, int func)
|
||||
{
|
||||
int ret;
|
||||
int i;
|
||||
|
|
@ -48,9 +49,20 @@ int gpio_event_output_func(
|
|||
|
||||
if (func == GPIO_EVENT_FUNC_INIT) {
|
||||
int output_level = !(oi->flags & GPIOEDF_ACTIVE_HIGH);
|
||||
for (i = 0; i < oi->keymap_size; i++)
|
||||
input_set_capability(input_dev, oi->type,
|
||||
|
||||
for (i = 0; i < oi->keymap_size; i++) {
|
||||
int dev = oi->keymap[i].dev;
|
||||
if (dev >= input_devs->count) {
|
||||
pr_err("gpio_event_output_func: bad device "
|
||||
"index %d >= %d for key code %d\n",
|
||||
dev, input_devs->count,
|
||||
oi->keymap[i].code);
|
||||
ret = -EINVAL;
|
||||
goto err_bad_keymap;
|
||||
}
|
||||
input_set_capability(input_devs->dev[dev], oi->type,
|
||||
oi->keymap[i].code);
|
||||
}
|
||||
|
||||
for (i = 0; i < oi->keymap_size; i++) {
|
||||
ret = gpio_request(oi->keymap[i].gpio,
|
||||
|
|
@ -79,6 +91,7 @@ int gpio_event_output_func(
|
|||
err_gpio_request_failed:
|
||||
;
|
||||
}
|
||||
err_bad_keymap:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,10 @@
|
|||
|
||||
#include <linux/input.h>
|
||||
|
||||
struct gpio_event_input_devs {
|
||||
int count;
|
||||
struct input_dev *dev[];
|
||||
};
|
||||
enum {
|
||||
GPIO_EVENT_FUNC_UNINIT = 0x0,
|
||||
GPIO_EVENT_FUNC_INIT = 0x1,
|
||||
|
|
@ -25,13 +29,14 @@ enum {
|
|||
GPIO_EVENT_FUNC_RESUME = 0x3,
|
||||
};
|
||||
struct gpio_event_info {
|
||||
int (*func)(struct input_dev *input_dev,
|
||||
int (*func)(struct gpio_event_input_devs *input_devs,
|
||||
struct gpio_event_info *info,
|
||||
void **data, int func);
|
||||
int (*event)(struct input_dev *input_dev,
|
||||
int (*event)(struct gpio_event_input_devs *input_devs,
|
||||
struct gpio_event_info *info,
|
||||
void **data, unsigned int type,
|
||||
void **data, unsigned int dev, unsigned int type,
|
||||
unsigned int code, int value); /* out events */
|
||||
bool no_suspend;
|
||||
};
|
||||
|
||||
struct gpio_event_platform_data {
|
||||
|
|
@ -39,6 +44,8 @@ struct gpio_event_platform_data {
|
|||
struct gpio_event_info **info;
|
||||
size_t info_count;
|
||||
int (*power)(const struct gpio_event_platform_data *pdata, bool on);
|
||||
const char *names[]; /* If name is NULL, names contain a NULL */
|
||||
/* terminated list of input devices to create */
|
||||
};
|
||||
|
||||
#define GPIO_EVENT_DEV_NAME "gpio-event"
|
||||
|
|
@ -59,7 +66,12 @@ enum gpio_event_matrix_flags {
|
|||
GPIOKPF_PRINT_PHANTOM_KEYS = 1U << 18,
|
||||
};
|
||||
|
||||
extern int gpio_event_matrix_func(struct input_dev *input_dev,
|
||||
#define MATRIX_CODE_BITS (10)
|
||||
#define MATRIX_KEY_MASK ((1U << MATRIX_CODE_BITS) - 1)
|
||||
#define MATRIX_KEY(dev, code) \
|
||||
(((dev) << MATRIX_CODE_BITS) | (code & MATRIX_KEY_MASK))
|
||||
|
||||
extern int gpio_event_matrix_func(struct gpio_event_input_devs *input_devs,
|
||||
struct gpio_event_info *info, void **data, int func);
|
||||
struct gpio_event_matrix_info {
|
||||
/* initialize to gpio_event_matrix_func */
|
||||
|
|
@ -89,12 +101,13 @@ enum gpio_event_direct_flags {
|
|||
};
|
||||
|
||||
struct gpio_event_direct_entry {
|
||||
uint32_t gpio:23;
|
||||
uint32_t code:9;
|
||||
uint32_t gpio:16;
|
||||
uint32_t code:10;
|
||||
uint32_t dev:6;
|
||||
};
|
||||
|
||||
/* inputs */
|
||||
extern int gpio_event_input_func(struct input_dev *input_dev,
|
||||
extern int gpio_event_input_func(struct gpio_event_input_devs *input_devs,
|
||||
struct gpio_event_info *info, void **data, int func);
|
||||
struct gpio_event_input_info {
|
||||
/* initialize to gpio_event_input_func */
|
||||
|
|
@ -108,11 +121,12 @@ struct gpio_event_input_info {
|
|||
};
|
||||
|
||||
/* outputs */
|
||||
extern int gpio_event_output_func(struct input_dev *input_dev,
|
||||
extern int gpio_event_output_func(struct gpio_event_input_devs *input_devs,
|
||||
struct gpio_event_info *info, void **data, int func);
|
||||
extern int gpio_event_output_event(struct input_dev *input_dev,
|
||||
extern int gpio_event_output_event(struct gpio_event_input_devs *input_devs,
|
||||
struct gpio_event_info *info, void **data,
|
||||
unsigned int type, unsigned int code, int value);
|
||||
unsigned int dev, unsigned int type,
|
||||
unsigned int code, int value);
|
||||
struct gpio_event_output_info {
|
||||
/* initialize to gpio_event_output_func and gpio_event_output_event */
|
||||
struct gpio_event_info info;
|
||||
|
|
@ -131,12 +145,13 @@ enum gpio_event_axis_flags {
|
|||
GPIOEAF_PRINT_EVENT = 1U << 18,
|
||||
};
|
||||
|
||||
extern int gpio_event_axis_func(struct input_dev *input_dev,
|
||||
extern int gpio_event_axis_func(struct gpio_event_input_devs *input_devs,
|
||||
struct gpio_event_info *info, void **data, int func);
|
||||
struct gpio_event_axis_info {
|
||||
/* initialize to gpio_event_axis_func */
|
||||
struct gpio_event_info info;
|
||||
uint8_t count;
|
||||
uint8_t count; /* number of gpios for this axis */
|
||||
uint8_t dev; /* device index when using multiple input devices */
|
||||
uint8_t type; /* EV_REL or EV_ABS */
|
||||
uint16_t code;
|
||||
uint16_t decoded_size;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user