diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-04 15:35:08 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-04 15:35:08 -0700 |
commit | f5b63ac0f77ecab46796ba5d368ea5dd51834e6e (patch) | |
tree | 66788b3327afa62aa7f8fe05951945a2ee1e9e4e /drivers/input | |
parent | 98f486f18d16e2214728d101ed8b6a12dce75539 (diff) | |
parent | 57961e3ba72f4a8a1aa52e978020ecc2ca03a79f (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input updates from Dmitry Torokhov:
"First round of updates for the input subsystem.
You will get a new touchsreen driver for Cypress 4th generation
devices, a driver for a special controller implementing PS/2 protocol
in OLPC devices, and a driver for power key for SiRFprimaII PWRC.
HID and bcm5497 now support for the 2013 MacBook Air.
EVIOCGKEY and the rest of evdev ioctls now flush events of matching
type from the client's event queue so that clients can be sure any
events received after issuing EVIOCG* ioctl are new events.
And a host of cleanups and improvements in other drivers"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (87 commits)
Input: cyttsp4 - kfree xfer_buf on error path in probe()
Input: tps6507x-ts - select INPUT_POLLDEV
Input: bcm5974 - add support for the 2013 MacBook Air
HID: apple: Add support for the 2013 Macbook Air
Input: cyttsp4 - leak on error path in probe()
Input: cyttsp4 - silence NULL dereference warning
Input: cyttsp4 - silence shift wrap warning
Input: tps6507x-ts - convert to polled input device infrastructure
ARM: davinci: da850-evm: remove vref from touchscreen platform data
Input: cyttsp4 - SPI driver for Cypress TMA4XX touchscreen devices
Input: cyttsp4 - I2C driver for Cypress TMA4XX touchscreen devices
Input: cyttsp4 - add core driver for Cypress TMA4XX touchscreen devices
Input: cyttsp - I2C driver split into two modules
Input: add OLPC AP-SP driver
Input: nspire-keypad - remove redundant dev_err call in nspire_keypad_probe()
Input: tps6507x-ts - remove vref from platform data
Input: tps6507x-ts - use bool for booleans
Input: tps6507x-ts - remove bogus unreachable code
Input: samsung-keypad - let device core setup the default pin configuration
Input: wacom_i2c - implement hovering capability
...
Diffstat (limited to 'drivers/input')
76 files changed, 4391 insertions, 417 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index f0f8928b3c8..d2b34fbbc42 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -52,6 +52,82 @@ struct evdev_client { struct input_event buffer[]; }; +/* flush queued events of type @type, caller must hold client->buffer_lock */ +static void __evdev_flush_queue(struct evdev_client *client, unsigned int type) +{ + unsigned int i, head, num; + unsigned int mask = client->bufsize - 1; + bool is_report; + struct input_event *ev; + + BUG_ON(type == EV_SYN); + + head = client->tail; + client->packet_head = client->tail; + + /* init to 1 so a leading SYN_REPORT will not be dropped */ + num = 1; + + for (i = client->tail; i != client->head; i = (i + 1) & mask) { + ev = &client->buffer[i]; + is_report = ev->type == EV_SYN && ev->code == SYN_REPORT; + + if (ev->type == type) { + /* drop matched entry */ + continue; + } else if (is_report && !num) { + /* drop empty SYN_REPORT groups */ + continue; + } else if (head != i) { + /* move entry to fill the gap */ + client->buffer[head].time = ev->time; + client->buffer[head].type = ev->type; + client->buffer[head].code = ev->code; + client->buffer[head].value = ev->value; + } + + num++; + head = (head + 1) & mask; + + if (is_report) { + num = 0; + client->packet_head = head; + } + } + + client->head = head; +} + +/* queue SYN_DROPPED event */ +static void evdev_queue_syn_dropped(struct evdev_client *client) +{ + unsigned long flags; + struct input_event ev; + ktime_t time; + + time = ktime_get(); + if (client->clkid != CLOCK_MONOTONIC) + time = ktime_sub(time, ktime_get_monotonic_offset()); + + ev.time = ktime_to_timeval(time); + ev.type = EV_SYN; + ev.code = SYN_DROPPED; + ev.value = 0; + + spin_lock_irqsave(&client->buffer_lock, flags); + + client->buffer[client->head++] = ev; + client->head &= client->bufsize - 1; + + if (unlikely(client->head == client->tail)) { + /* drop queue but keep our SYN_DROPPED event */ + client->tail = (client->head - 1) & (client->bufsize - 1); + client->packet_head = client->tail; + } + + spin_unlock_irqrestore(&client->buffer_lock, flags); +} + static void __pass_event(struct evdev_client *client, const struct input_event *event) { @@ -650,6 +726,51 @@ static int evdev_handle_set_keycode_v2(struct input_dev *dev, void __user *p) return input_set_keycode(dev, &ke); } +/* + * If we transfer state to the user, we should flush all pending events + * of the same type from the client's queue. Otherwise, they might end up + * with duplicate events, which can screw up client's state tracking. + * If bits_to_user fails after flushing the queue, we queue a SYN_DROPPED + * event so user-space will notice missing events. + * + * LOCKING: + * We need to take event_lock before buffer_lock to avoid dead-locks. But we + * need the even_lock only to guarantee consistent state. We can safely release + * it while flushing the queue. This allows input-core to handle filters while + * we flush the queue. + */ +static int evdev_handle_get_val(struct evdev_client *client, + struct input_dev *dev, unsigned int type, + unsigned long *bits, unsigned int max, + unsigned int size, void __user *p, int compat) +{ + int ret; + unsigned long *mem; + + mem = kmalloc(sizeof(unsigned long) * max, GFP_KERNEL); + if (!mem) + return -ENOMEM; + + spin_lock_irq(&dev->event_lock); + spin_lock(&client->buffer_lock); + + memcpy(mem, bits, sizeof(unsigned long) * max); + + spin_unlock(&dev->event_lock); + + __evdev_flush_queue(client, type); + + spin_unlock_irq(&client->buffer_lock); + + ret = bits_to_user(mem, max, size, p, compat); + if (ret < 0) + evdev_queue_syn_dropped(client); + + kfree(mem); + + return ret; +} + static int evdev_handle_mt_request(struct input_dev *dev, unsigned int size, int __user *ip) @@ -771,16 +892,20 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, return evdev_handle_mt_request(dev, size, ip); case EVIOCGKEY(0): - return bits_to_user(dev->key, KEY_MAX, size, p, compat_mode); + return evdev_handle_get_val(client, dev, EV_KEY, dev->key, + KEY_MAX, size, p, compat_mode); case EVIOCGLED(0): - return bits_to_user(dev->led, LED_MAX, size, p, compat_mode); + return evdev_handle_get_val(client, dev, EV_LED, dev->led, + LED_MAX, size, p, compat_mode); case EVIOCGSND(0): - return bits_to_user(dev->snd, SND_MAX, size, p, compat_mode); + return evdev_handle_get_val(client, dev, EV_SND, dev->snd, + SND_MAX, size, p, compat_mode); case EVIOCGSW(0): - return bits_to_user(dev->sw, SW_MAX, size, p, compat_mode); + return evdev_handle_get_val(client, dev, EV_SW, dev->sw, + SW_MAX, size, p, compat_mode); case EVIOCGNAME(0): return str_to_user(dev->name, size, p); diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 7ac9c9818d5..269d4c3658c 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -418,6 +418,16 @@ config KEYBOARD_NOMADIK To compile this driver as a module, choose M here: the module will be called nmk-ske-keypad. +config KEYBOARD_NSPIRE + tristate "TI-NSPIRE built-in keyboard" + depends on ARCH_NSPIRE && OF + select INPUT_MATRIXKMAP + help + Say Y here if you want to use the built-in keypad on TI-NSPIRE. + + To compile this driver as a module, choose M here: the + module will be called nspire-keypad. + config KEYBOARD_TEGRA tristate "NVIDIA Tegra internal matrix keyboard controller support" depends on ARCH_TEGRA && OF @@ -442,6 +452,7 @@ config KEYBOARD_OPENCORES config KEYBOARD_PXA27x tristate "PXA27x/PXA3xx keypad support" depends on PXA27x || PXA3xx || ARCH_MMP + select INPUT_MATRIXKMAP help Enable support for PXA27x/PXA3xx keypad controller. diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 0c43e8cf8d0..a699b617230 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_KEYBOARD_MCS) += mcs_touchkey.o obj-$(CONFIG_KEYBOARD_MPR121) += mpr121_touchkey.o obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o obj-$(CONFIG_KEYBOARD_NOMADIK) += nomadik-ske-keypad.o +obj-$(CONFIG_KEYBOARD_NSPIRE) += nspire-keypad.o obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o obj-$(CONFIG_KEYBOARD_OMAP4) += omap4-keypad.o obj-$(CONFIG_KEYBOARD_OPENCORES) += opencores-kbd.o diff --git a/drivers/input/keyboard/amikbd.c b/drivers/input/keyboard/amikbd.c index ba0b36f7dae..096d6067ae1 100644 --- a/drivers/input/keyboard/amikbd.c +++ b/drivers/input/keyboard/amikbd.c @@ -246,7 +246,6 @@ static int __exit amikbd_remove(struct platform_device *pdev) { struct input_dev *dev = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); free_irq(IRQ_AMIGA_CIAA_SP, dev); input_unregister_device(dev); return 0; diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index 20b9fa91fb9..fc88fb48d70 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c @@ -326,7 +326,6 @@ out0: kfree(bf54x_kpad->keycode); out: kfree(bf54x_kpad); - platform_set_drvdata(pdev, NULL); return error; } @@ -346,7 +345,6 @@ static int bfin_kpad_remove(struct platform_device *pdev) kfree(bf54x_kpad->keycode); kfree(bf54x_kpad); - platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/input/keyboard/davinci_keyscan.c b/drivers/input/keyboard/davinci_keyscan.c index 829753702b6..d15977a8361 100644 --- a/drivers/input/keyboard/davinci_keyscan.c +++ b/drivers/input/keyboard/davinci_keyscan.c @@ -314,8 +314,6 @@ static int davinci_ks_remove(struct platform_device *pdev) iounmap(davinci_ks->base); release_mem_region(davinci_ks->pbase, davinci_ks->base_size); - platform_set_drvdata(pdev, NULL); - kfree(davinci_ks); return 0; diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c index 9857e8fd098..47206bdba41 100644 --- a/drivers/input/keyboard/ep93xx_keypad.c +++ b/drivers/input/keyboard/ep93xx_keypad.c @@ -329,8 +329,7 @@ static int ep93xx_keypad_probe(struct platform_device *pdev) return 0; failed_free_irq: - free_irq(keypad->irq, pdev); - platform_set_drvdata(pdev, NULL); + free_irq(keypad->irq, keypad); failed_free_dev: input_free_device(input_dev); failed_put_clk: @@ -351,9 +350,7 @@ static int ep93xx_keypad_remove(struct platform_device *pdev) struct ep93xx_keypad *keypad = platform_get_drvdata(pdev); struct resource *res; - free_irq(keypad->irq, pdev); - - platform_set_drvdata(pdev, NULL); + free_irq(keypad->irq, keypad); if (keypad->enabled) clk_disable(keypad->clk); diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index b29ca651a39..440ce32462b 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -767,7 +767,6 @@ static int gpio_keys_probe(struct platform_device *pdev) while (--i >= 0) gpio_remove_key(&ddata->data[i]); - platform_set_drvdata(pdev, NULL); fail1: input_free_device(input); kfree(ddata); diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c index 21147164874..cd5ed9e2216 100644 --- a/drivers/input/keyboard/gpio_keys_polled.c +++ b/drivers/input/keyboard/gpio_keys_polled.c @@ -324,7 +324,6 @@ err_free_gpio: err_free_bdev: kfree(bdev); - platform_set_drvdata(pdev, NULL); err_free_pdata: /* If we have no platform_data, we allocated pdata dynamically. */ @@ -355,7 +354,6 @@ static int gpio_keys_polled_remove(struct platform_device *pdev) kfree(pdata); kfree(bdev); - platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/input/keyboard/jornada680_kbd.c b/drivers/input/keyboard/jornada680_kbd.c index 74e75a6e8de..a2a034c25f0 100644 --- a/drivers/input/keyboard/jornada680_kbd.c +++ b/drivers/input/keyboard/jornada680_kbd.c @@ -233,7 +233,6 @@ static int jornada680kbd_probe(struct platform_device *pdev) failed: printk(KERN_ERR "Jornadakbd: failed to register driver, error: %d\n", error); - platform_set_drvdata(pdev, NULL); input_free_polled_device(poll_dev); kfree(jornadakbd); return error; @@ -244,7 +243,6 @@ static int jornada680kbd_remove(struct platform_device *pdev) { struct jornadakbd *jornadakbd = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); input_unregister_polled_device(jornadakbd->poll_dev); input_free_polled_device(jornadakbd->poll_dev); kfree(jornadakbd); diff --git a/drivers/input/keyboard/jornada720_kbd.c b/drivers/input/keyboard/jornada720_kbd.c index 5ceef636df2..b0ad457ca9d 100644 --- a/drivers/input/keyboard/jornada720_kbd.c +++ b/drivers/input/keyboard/jornada720_kbd.c @@ -146,7 +146,6 @@ static int jornada720_kbd_probe(struct platform_device *pdev) fail2: /* IRQ, DEVICE, MEMORY */ free_irq(IRQ_GPIO0, pdev); fail1: /* DEVICE, MEMORY */ - platform_set_drvdata(pdev, NULL); input_free_device(input_dev); kfree(jornadakbd); return err; @@ -157,7 +156,6 @@ static int jornada720_kbd_remove(struct platform_device *pdev) struct jornadakbd *jornadakbd = platform_get_drvdata(pdev); free_irq(IRQ_GPIO0, pdev); - platform_set_drvdata(pdev, NULL); input_unregister_device(jornadakbd->input); kfree(jornadakbd); diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index 71d77192ac1..90ff73ace42 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c @@ -549,8 +549,6 @@ static int matrix_keypad_remove(struct platform_device *pdev) input_unregister_device(keypad->input_dev); kfree(keypad); - platform_set_drvdata(pdev, NULL); - return 0; } diff --git a/drivers/input/keyboard/nspire-keypad.c b/drivers/input/keyboard/nspire-keypad.c new file mode 100644 index 00000000000..e0a1339e40e --- /dev/null +++ b/drivers/input/keyboard/nspire-keypad.c @@ -0,0 +1,283 @@ +/* + * Copyright (C) 2013 Daniel Tang <tangrs@tangrs.id.au> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + */ + +#include <linux/input/matrix_keypad.h> +#include <linux/platform_device.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/delay.h> +#include <linux/input.h> +#include <linux/slab.h> +#include <linux/clk.h> +#include <linux/module.h> +# |