diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-04-18 16:29:03 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-04-18 16:29:03 -0400 |
| commit | 96fd2d57b8252e16dfacf8941f7a74a6119197f5 (patch) | |
| tree | 095269c51def85fa1be27bb20ec8e562bdc5a564 /drivers | |
| parent | 8a83f33100c691f5a576dba259cc05502dc358f0 (diff) | |
| parent | c36b58e8a9112017c2bcc322cc98e71241814303 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
Input: xen-kbdfront - fix mouse getting stuck after save/restore
Input: estimate number of events per packet
Input: evdev - indicate buffer overrun with SYN_DROPPED
Input: document event types and codes and their intended use
Input: add KEY_IMAGES specifically for AL Image Browser
Input: twl4030_keypad - fix potential NULL dereference in twl4030_kp_probe()
Input: h3600_ts - fix error handling at connect
Input: twl4030_keypad - avoid potential NULL-pointer dereference
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/input/evdev.c | 33 | ||||
| -rw-r--r-- | drivers/input/input.c | 40 | ||||
| -rw-r--r-- | drivers/input/keyboard/twl4030_keypad.c | 6 | ||||
| -rw-r--r-- | drivers/input/misc/xen-kbdfront.c | 13 | ||||
| -rw-r--r-- | drivers/input/touchscreen/h3600_ts_input.c | 17 |
5 files changed, 87 insertions, 22 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 7f42d3a454d2..88d8e4cb419a 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
| @@ -39,13 +39,13 @@ struct evdev { | |||
| 39 | }; | 39 | }; |
| 40 | 40 | ||
| 41 | struct evdev_client { | 41 | struct evdev_client { |
| 42 | int head; | 42 | unsigned int head; |
| 43 | int tail; | 43 | unsigned int tail; |
| 44 | spinlock_t buffer_lock; /* protects access to buffer, head and tail */ | 44 | spinlock_t buffer_lock; /* protects access to buffer, head and tail */ |
| 45 | struct fasync_struct *fasync; | 45 | struct fasync_struct *fasync; |
| 46 | struct evdev *evdev; | 46 | struct evdev *evdev; |
| 47 | struct list_head node; | 47 | struct list_head node; |
| 48 | int bufsize; | 48 | unsigned int bufsize; |
| 49 | struct input_event buffer[]; | 49 | struct input_event buffer[]; |
| 50 | }; | 50 | }; |
| 51 | 51 | ||
| @@ -55,16 +55,25 @@ static DEFINE_MUTEX(evdev_table_mutex); | |||
| 55 | static void evdev_pass_event(struct evdev_client *client, | 55 | static void evdev_pass_event(struct evdev_client *client, |
| 56 | struct input_event *event) | 56 | struct input_event *event) |
| 57 | { | 57 | { |
| 58 | /* | 58 | /* Interrupts are disabled, just acquire the lock. */ |
| 59 | * Interrupts are disabled, just acquire the lock. | ||
| 60 | * Make sure we don't leave with the client buffer | ||
| 61 | * "empty" by having client->head == client->tail. | ||
| 62 | */ | ||
| 63 | spin_lock(&client->buffer_lock); | 59 | spin_lock(&client->buffer_lock); |
| 64 | do { | 60 | |
| 65 | client->buffer[client->head++] = *event; | 61 | client->buffer[client->head++] = *event; |
| 66 | client->head &= client->bufsize - 1; | 62 | client->head &= client->bufsize - 1; |
| 67 | } while (client->head == client->tail); | 63 | |
| 64 | if (unlikely(client->head == client->tail)) { | ||
| 65 | /* | ||
| 66 | * This effectively "drops" all unconsumed events, leaving | ||
| 67 | * EV_SYN/SYN_DROPPED plus the newest event in the queue. | ||
| 68 | */ | ||
| 69 | client->tail = (client->head - 2) & (client->bufsize - 1); | ||
| 70 | |||
| 71 | client->buffer[client->tail].time = event->time; | ||
| 72 | client->buffer[client->tail].type = EV_SYN; | ||
| 73 | client->buffer[client->tail].code = SYN_DROPPED; | ||
| 74 | client->buffer[client->tail].value = 0; | ||
| 75 | } | ||
| 76 | |||
| 68 | spin_unlock(&client->buffer_lock); | 77 | spin_unlock(&client->buffer_lock); |
| 69 | 78 | ||
| 70 | if (event->type == EV_SYN) | 79 | if (event->type == EV_SYN) |
diff --git a/drivers/input/input.c b/drivers/input/input.c index d6e8bd8a851c..ebbceedc92f4 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
| @@ -1746,6 +1746,42 @@ void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int | |||
| 1746 | } | 1746 | } |
| 1747 | EXPORT_SYMBOL(input_set_capability); | 1747 | EXPORT_SYMBOL(input_set_capability); |
| 1748 | 1748 | ||
| 1749 | static unsigned int input_estimate_events_per_packet(struct input_dev *dev) | ||
| 1750 | { | ||
| 1751 | int mt_slots; | ||
| 1752 | int i; | ||
| 1753 | unsigned int events; | ||
| 1754 | |||
| 1755 | if (dev->mtsize) { | ||
| 1756 | mt_slots = dev->mtsize; | ||
| 1757 | } else if (test_bit(ABS_MT_TRACKING_ID, dev->absbit)) { | ||
| 1758 | mt_slots = dev->absinfo[ABS_MT_TRACKING_ID].maximum - | ||
| 1759 | dev->absinfo[ABS_MT_TRACKING_ID].minimum + 1, | ||
| 1760 | clamp(mt_slots, 2, 32); | ||
| 1761 | } else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) { | ||
| 1762 | mt_slots = 2; | ||
| 1763 | } else { | ||
| 1764 | mt_slots = 0; | ||
| 1765 | } | ||
| 1766 | |||
| 1767 | events = mt_slots + 1; /* count SYN_MT_REPORT and SYN_REPORT */ | ||
| 1768 | |||
| 1769 | for (i = 0; i < ABS_CNT; i++) { | ||
| 1770 | if (test_bit(i, dev->absbit)) { | ||
| 1771 | if (input_is_mt_axis(i)) | ||
| 1772 | events += mt_slots; | ||
| 1773 | else | ||
| 1774 | events++; | ||
| 1775 | } | ||
| 1776 | } | ||
| 1777 | |||
| 1778 | for (i = 0; i < REL_CNT; i++) | ||
| 1779 | if (test_bit(i, dev->relbit)) | ||
| 1780 | events++; | ||
| 1781 | |||
| 1782 | return events; | ||
| 1783 | } | ||
| 1784 | |||
| 1749 | #define INPUT_CLEANSE_BITMASK(dev, type, bits) \ | 1785 | #define INPUT_CLEANSE_BITMASK(dev, type, bits) \ |
| 1750 | do { \ | 1786 | do { \ |
| 1751 | if (!test_bit(EV_##type, dev->evbit)) \ | 1787 | if (!test_bit(EV_##type, dev->evbit)) \ |
| @@ -1793,6 +1829,10 @@ int input_register_device(struct input_dev *dev) | |||
| 1793 | /* Make sure that bitmasks not mentioned in dev->evbit are clean. */ | 1829 | /* Make sure that bitmasks not mentioned in dev->evbit are clean. */ |
| 1794 | input_cleanse_bitmasks(dev); | 1830 | input_cleanse_bitmasks(dev); |
| 1795 | 1831 | ||
| 1832 | if (!dev->hint_events_per_packet) | ||
| 1833 | dev->hint_events_per_packet = | ||
| 1834 | input_estimate_events_per_packet(dev); | ||
| 1835 | |||
| 1796 | /* | 1836 | /* |
| 1797 | * If delay and period are pre-set by the driver, then autorepeating | 1837 | * If delay and period are pre-set by the driver, then autorepeating |
| 1798 | * is handled by the driver itself and we don't do it in input.c. | 1838 | * is handled by the driver itself and we don't do it in input.c. |
diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c index 09bef79d9da1..a26922cf0e84 100644 --- a/drivers/input/keyboard/twl4030_keypad.c +++ b/drivers/input/keyboard/twl4030_keypad.c | |||
| @@ -332,18 +332,20 @@ static int __devinit twl4030_kp_program(struct twl4030_keypad *kp) | |||
| 332 | static int __devinit twl4030_kp_probe(struct platform_device *pdev) | 332 | static int __devinit twl4030_kp_probe(struct platform_device *pdev) |
| 333 | { | 333 | { |
| 334 | struct twl4030_keypad_data *pdata = pdev->dev.platform_data; | 334 | struct twl4030_keypad_data *pdata = pdev->dev.platform_data; |
| 335 | const struct matrix_keymap_data *keymap_data = pdata->keymap_data; | 335 | const struct matrix_keymap_data *keymap_data; |
| 336 | struct twl4030_keypad *kp; | 336 | struct twl4030_keypad *kp; |
| 337 | struct input_dev *input; | 337 | struct input_dev *input; |
| 338 | u8 reg; | 338 | u8 reg; |
| 339 | int error; | 339 | int error; |
| 340 | 340 | ||
| 341 | if (!pdata || !pdata->rows || !pdata->cols || | 341 | if (!pdata || !pdata->rows || !pdata->cols || !pdata->keymap_data || |
| 342 | pdata->rows > TWL4030_MAX_ROWS || pdata->cols > TWL4030_MAX_COLS) { | 342 | pdata->rows > TWL4030_MAX_ROWS || pdata->cols > TWL4030_MAX_COLS) { |
| 343 | dev_err(&pdev->dev, "Invalid platform_data\n"); | 343 | dev_err(&pdev->dev, "Invalid platform_data\n"); |
| 344 | return -EINVAL; | 344 | return -EINVAL; |
| 345 | } | 345 | } |
| 346 | 346 | ||
| 347 | keymap_data = pdata->keymap_data; | ||
| 348 | |||
| 347 | kp = kzalloc(sizeof(*kp), GFP_KERNEL); | 349 | kp = kzalloc(sizeof(*kp), GFP_KERNEL); |
| 348 | input = input_allocate_device(); | 350 | input = input_allocate_device(); |
| 349 | if (!kp || !input) { | 351 | if (!kp || !input) { |
diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index 7077f9bf5ead..62bae99424e6 100644 --- a/drivers/input/misc/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c | |||
| @@ -303,7 +303,7 @@ static void xenkbd_backend_changed(struct xenbus_device *dev, | |||
| 303 | enum xenbus_state backend_state) | 303 | enum xenbus_state backend_state) |
| 304 | { | 304 | { |
| 305 | struct xenkbd_info *info = dev_get_drvdata(&dev->dev); | 305 | struct xenkbd_info *info = dev_get_drvdata(&dev->dev); |
| 306 | int val; | 306 | int ret, val; |
| 307 | 307 | ||
| 308 | switch (backend_state) { | 308 | switch (backend_state) { |
| 309 | case XenbusStateInitialising: | 309 | case XenbusStateInitialising: |
| @@ -316,6 +316,17 @@ static void xenkbd_backend_changed(struct xenbus_device *dev, | |||
| 316 | 316 | ||
| 317 | case XenbusStateInitWait: | 317 | case XenbusStateInitWait: |
| 318 | InitWait: | 318 | InitWait: |
| 319 | ret = xenbus_scanf(XBT_NIL, info->xbdev->otherend, | ||
| 320 | "feature-abs-pointer", "%d", &val); | ||
| 321 | if (ret < 0) | ||
| 322 | val = 0; | ||
| 323 | if (val) { | ||
| 324 | ret = xenbus_printf(XBT_NIL, info->xbdev->nodename, | ||
| 325 | "request-abs-pointer", "1"); | ||
| 326 | if (ret) | ||
| 327 | pr_warning("xenkbd: can't request abs-pointer"); | ||
| 328 | } | ||
| 329 | |||
| 319 | xenbus_switch_state(dev, XenbusStateConnected); | 330 | xenbus_switch_state(dev, XenbusStateConnected); |
| 320 | break; | 331 | break; |
| 321 | 332 | ||
diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c index efa06882de00..45f93d0f5592 100644 --- a/drivers/input/touchscreen/h3600_ts_input.c +++ b/drivers/input/touchscreen/h3600_ts_input.c | |||
| @@ -399,31 +399,34 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv) | |||
| 399 | IRQF_SHARED | IRQF_DISABLED, "h3600_action", &ts->dev)) { | 399 | IRQF_SHARED | IRQF_DISABLED, "h3600_action", &ts->dev)) { |
| 400 | printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n"); | 400 | printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n"); |
| 401 | err = -EBUSY; | 401 | err = -EBUSY; |
| 402 | goto fail2; | 402 | goto fail1; |
| 403 | } | 403 | } |
| 404 | 404 | ||
| 405 | if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler, | 405 | if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler, |
| 406 | IRQF_SHARED | IRQF_DISABLED, "h3600_suspend", &ts->dev)) { | 406 | IRQF_SHARED | IRQF_DISABLED, "h3600_suspend", &ts->dev)) { |
| 407 | printk(KERN_ERR "h3600ts.c: Could not allocate Power Button IRQ!\n"); | 407 | printk(KERN_ERR "h3600ts.c: Could not allocate Power Button IRQ!\n"); |
| 408 | err = -EBUSY; | 408 | err = -EBUSY; |
| 409 | goto fail3; | 409 | goto fail2; |
| 410 | } | 410 | } |
| 411 | 411 | ||
| 412 | serio_set_drvdata(serio, ts); | 412 | serio_set_drvdata(serio, ts); |
| 413 | 413 | ||
| 414 | err = serio_open(serio, drv); | 414 | err = serio_open(serio, drv); |
| 415 | if (err) | 415 | if (err) |
| 416 | return err; | 416 | goto fail3; |
| 417 | 417 | ||
| 418 | //h3600_flite_control(1, 25); /* default brightness */ | 418 | //h3600_flite_control(1, 25); /* default brightness */ |
| 419 | input_register_device(ts->dev); | 419 | err = input_register_device(ts->dev); |
| 420 | if (err) | ||
| 421 | goto fail4; | ||
| 420 | 422 | ||
| 421 | return 0; | 423 | return 0; |
| 422 | 424 | ||
| 423 | fail3: free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts->dev); | 425 | fail4: serio_close(serio); |
| 426 | fail3: serio_set_drvdata(serio, NULL); | ||
| 427 | free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts->dev); | ||
| 424 | fail2: free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts->dev); | 428 | fail2: free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts->dev); |
| 425 | fail1: serio_set_drvdata(serio, NULL); | 429 | fail1: input_free_device(input_dev); |
| 426 | input_free_device(input_dev); | ||
| 427 | kfree(ts); | 430 | kfree(ts); |
| 428 | return err; | 431 | return err; |
| 429 | } | 432 | } |
