Commit 96fd2d57 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 8a83f331 c36b58e8
This diff is collapsed.
...@@ -39,13 +39,13 @@ struct evdev { ...@@ -39,13 +39,13 @@ struct evdev {
}; };
struct evdev_client { struct evdev_client {
int head; unsigned int head;
int tail; unsigned int tail;
spinlock_t buffer_lock; /* protects access to buffer, head and tail */ spinlock_t buffer_lock; /* protects access to buffer, head and tail */
struct fasync_struct *fasync; struct fasync_struct *fasync;
struct evdev *evdev; struct evdev *evdev;
struct list_head node; struct list_head node;
int bufsize; unsigned int bufsize;
struct input_event buffer[]; struct input_event buffer[];
}; };
...@@ -55,16 +55,25 @@ static DEFINE_MUTEX(evdev_table_mutex); ...@@ -55,16 +55,25 @@ static DEFINE_MUTEX(evdev_table_mutex);
static void evdev_pass_event(struct evdev_client *client, static void evdev_pass_event(struct evdev_client *client,
struct input_event *event) struct input_event *event)
{ {
/* /* Interrupts are disabled, just acquire the lock. */
* Interrupts are disabled, just acquire the lock.
* Make sure we don't leave with the client buffer
* "empty" by having client->head == client->tail.
*/
spin_lock(&client->buffer_lock); spin_lock(&client->buffer_lock);
do {
client->buffer[client->head++] = *event; client->buffer[client->head++] = *event;
client->head &= client->bufsize - 1; client->head &= client->bufsize - 1;
} while (client->head == client->tail);
if (unlikely(client->head == client->tail)) {
/*
* This effectively "drops" all unconsumed events, leaving
* EV_SYN/SYN_DROPPED plus the newest event in the queue.
*/
client->tail = (client->head - 2) & (client->bufsize - 1);
client->buffer[client->tail].time = event->time;
client->buffer[client->tail].type = EV_SYN;
client->buffer[client->tail].code = SYN_DROPPED;
client->buffer[client->tail].value = 0;
}
spin_unlock(&client->buffer_lock); spin_unlock(&client->buffer_lock);
if (event->type == EV_SYN) if (event->type == EV_SYN)
......
...@@ -1746,6 +1746,42 @@ void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int ...@@ -1746,6 +1746,42 @@ void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int
} }
EXPORT_SYMBOL(input_set_capability); EXPORT_SYMBOL(input_set_capability);
static unsigned int input_estimate_events_per_packet(struct input_dev *dev)
{
int mt_slots;
int i;
unsigned int events;
if (dev->mtsize) {
mt_slots = dev->mtsize;
} else if (test_bit(ABS_MT_TRACKING_ID, dev->absbit)) {
mt_slots = dev->absinfo[ABS_MT_TRACKING_ID].maximum -
dev->absinfo[ABS_MT_TRACKING_ID].minimum + 1,
clamp(mt_slots, 2, 32);
} else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
mt_slots = 2;
} else {
mt_slots = 0;
}
events = mt_slots + 1; /* count SYN_MT_REPORT and SYN_REPORT */
for (i = 0; i < ABS_CNT; i++) {
if (test_bit(i, dev->absbit)) {
if (input_is_mt_axis(i))
events += mt_slots;
else
events++;
}
}
for (i = 0; i < REL_CNT; i++)
if (test_bit(i, dev->relbit))
events++;
return events;
}
#define INPUT_CLEANSE_BITMASK(dev, type, bits) \ #define INPUT_CLEANSE_BITMASK(dev, type, bits) \
do { \ do { \
if (!test_bit(EV_##type, dev->evbit)) \ if (!test_bit(EV_##type, dev->evbit)) \
...@@ -1793,6 +1829,10 @@ int input_register_device(struct input_dev *dev) ...@@ -1793,6 +1829,10 @@ int input_register_device(struct input_dev *dev)
/* Make sure that bitmasks not mentioned in dev->evbit are clean. */ /* Make sure that bitmasks not mentioned in dev->evbit are clean. */
input_cleanse_bitmasks(dev); input_cleanse_bitmasks(dev);
if (!dev->hint_events_per_packet)
dev->hint_events_per_packet =
input_estimate_events_per_packet(dev);
/* /*
* If delay and period are pre-set by the driver, then autorepeating * If delay and period are pre-set by the driver, then autorepeating
* is handled by the driver itself and we don't do it in input.c. * is handled by the driver itself and we don't do it in input.c.
......
...@@ -332,18 +332,20 @@ static int __devinit twl4030_kp_program(struct twl4030_keypad *kp) ...@@ -332,18 +332,20 @@ static int __devinit twl4030_kp_program(struct twl4030_keypad *kp)
static int __devinit twl4030_kp_probe(struct platform_device *pdev) static int __devinit twl4030_kp_probe(struct platform_device *pdev)
{ {
struct twl4030_keypad_data *pdata = pdev->dev.platform_data; struct twl4030_keypad_data *pdata = pdev->dev.platform_data;
const struct matrix_keymap_data *keymap_data = pdata->keymap_data; const struct matrix_keymap_data *keymap_data;
struct twl4030_keypad *kp; struct twl4030_keypad *kp;
struct input_dev *input; struct input_dev *input;
u8 reg; u8 reg;
int error; int error;
if (!pdata || !pdata->rows || !pdata->cols || if (!pdata || !pdata->rows || !pdata->cols || !pdata->keymap_data ||
pdata->rows > TWL4030_MAX_ROWS || pdata->cols > TWL4030_MAX_COLS) { pdata->rows > TWL4030_MAX_ROWS || pdata->cols > TWL4030_MAX_COLS) {
dev_err(&pdev->dev, "Invalid platform_data\n"); dev_err(&pdev->dev, "Invalid platform_data\n");
return -EINVAL; return -EINVAL;
} }
keymap_data = pdata->keymap_data;
kp = kzalloc(sizeof(*kp), GFP_KERNEL); kp = kzalloc(sizeof(*kp), GFP_KERNEL);
input = input_allocate_device(); input = input_allocate_device();
if (!kp || !input) { if (!kp || !input) {
......
...@@ -303,7 +303,7 @@ static void xenkbd_backend_changed(struct xenbus_device *dev, ...@@ -303,7 +303,7 @@ static void xenkbd_backend_changed(struct xenbus_device *dev,
enum xenbus_state backend_state) enum xenbus_state backend_state)
{ {
struct xenkbd_info *info = dev_get_drvdata(&dev->dev); struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
int val; int ret, val;
switch (backend_state) { switch (backend_state) {
case XenbusStateInitialising: case XenbusStateInitialising:
...@@ -316,6 +316,17 @@ static void xenkbd_backend_changed(struct xenbus_device *dev, ...@@ -316,6 +316,17 @@ static void xenkbd_backend_changed(struct xenbus_device *dev,
case XenbusStateInitWait: case XenbusStateInitWait:
InitWait: InitWait:
ret = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
"feature-abs-pointer", "%d", &val);
if (ret < 0)
val = 0;
if (val) {
ret = xenbus_printf(XBT_NIL, info->xbdev->nodename,
"request-abs-pointer", "1");
if (ret)
pr_warning("xenkbd: can't request abs-pointer");
}
xenbus_switch_state(dev, XenbusStateConnected); xenbus_switch_state(dev, XenbusStateConnected);
break; break;
......
...@@ -399,31 +399,34 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv) ...@@ -399,31 +399,34 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv)
IRQF_SHARED | IRQF_DISABLED, "h3600_action", &ts->dev)) { IRQF_SHARED | IRQF_DISABLED, "h3600_action", &ts->dev)) {
printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n"); printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n");
err = -EBUSY; err = -EBUSY;
goto fail2; goto fail1;
} }
if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler, if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler,
IRQF_SHARED | IRQF_DISABLED, "h3600_suspend", &ts->dev)) { IRQF_SHARED | IRQF_DISABLED, "h3600_suspend", &ts->dev)) {
printk(KERN_ERR "h3600ts.c: Could not allocate Power Button IRQ!\n"); printk(KERN_ERR "h3600ts.c: Could not allocate Power Button IRQ!\n");
err = -EBUSY; err = -EBUSY;
goto fail3; goto fail2;
} }
serio_set_drvdata(serio, ts); serio_set_drvdata(serio, ts);
err = serio_open(serio, drv); err = serio_open(serio, drv);
if (err) if (err)
return err; goto fail3;
//h3600_flite_control(1, 25); /* default brightness */ //h3600_flite_control(1, 25); /* default brightness */
input_register_device(ts->dev); err = input_register_device(ts->dev);
if (err)
goto fail4;
return 0; return 0;
fail3: free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts->dev); fail4: serio_close(serio);
fail3: serio_set_drvdata(serio, NULL);
free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts->dev);
fail2: free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts->dev); fail2: free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts->dev);
fail1: serio_set_drvdata(serio, NULL); fail1: input_free_device(input_dev);
input_free_device(input_dev);
kfree(ts); kfree(ts);
return err; return err;
} }
......
...@@ -167,6 +167,7 @@ struct input_keymap_entry { ...@@ -167,6 +167,7 @@ struct input_keymap_entry {
#define SYN_REPORT 0 #define SYN_REPORT 0
#define SYN_CONFIG 1 #define SYN_CONFIG 1
#define SYN_MT_REPORT 2 #define SYN_MT_REPORT 2
#define SYN_DROPPED 3
/* /*
* Keys and buttons * Keys and buttons
...@@ -553,8 +554,8 @@ struct input_keymap_entry { ...@@ -553,8 +554,8 @@ struct input_keymap_entry {
#define KEY_DVD 0x185 /* Media Select DVD */ #define KEY_DVD 0x185 /* Media Select DVD */
#define KEY_AUX 0x186 #define KEY_AUX 0x186
#define KEY_MP3 0x187 #define KEY_MP3 0x187
#define KEY_AUDIO 0x188 #define KEY_AUDIO 0x188 /* AL Audio Browser */
#define KEY_VIDEO 0x189 #define KEY_VIDEO 0x189 /* AL Movie Browser */
#define KEY_DIRECTORY 0x18a #define KEY_DIRECTORY 0x18a
#define KEY_LIST 0x18b #define KEY_LIST 0x18b
#define KEY_MEMO 0x18c /* Media Select Messages */ #define KEY_MEMO 0x18c /* Media Select Messages */
...@@ -603,8 +604,9 @@ struct input_keymap_entry { ...@@ -603,8 +604,9 @@ struct input_keymap_entry {
#define KEY_FRAMEFORWARD 0x1b5 #define KEY_FRAMEFORWARD 0x1b5
#define KEY_CONTEXT_MENU 0x1b6 /* GenDesc - system context menu */ #define KEY_CONTEXT_MENU 0x1b6 /* GenDesc - system context menu */
#define KEY_MEDIA_REPEAT 0x1b7 /* Consumer - transport control */ #define KEY_MEDIA_REPEAT 0x1b7 /* Consumer - transport control */
#define KEY_10CHANNELSUP 0x1b8 /* 10 channels up (10+) */ #define KEY_10CHANNELSUP 0x1b8 /* 10 channels up (10+) */
#define KEY_10CHANNELSDOWN 0x1b9 /* 10 channels down (10-) */ #define KEY_10CHANNELSDOWN 0x1b9 /* 10 channels down (10-) */
#define KEY_IMAGES 0x1ba /* AL Image Browser */
#define KEY_DEL_EOL 0x1c0 #define KEY_DEL_EOL 0x1c0
#define KEY_DEL_EOS 0x1c1 #define KEY_DEL_EOS 0x1c1
......
...@@ -48,6 +48,12 @@ static inline void input_mt_slot(struct input_dev *dev, int slot) ...@@ -48,6 +48,12 @@ static inline void input_mt_slot(struct input_dev *dev, int slot)
input_event(dev, EV_ABS, ABS_MT_SLOT, slot); input_event(dev, EV_ABS, ABS_MT_SLOT, slot);
} }
static inline bool input_is_mt_axis(int axis)
{
return axis == ABS_MT_SLOT ||
(axis >= ABS_MT_FIRST && axis <= ABS_MT_LAST);
}
void input_mt_report_slot_state(struct input_dev *dev, void input_mt_report_slot_state(struct input_dev *dev,
unsigned int tool_type, bool active); unsigned int tool_type, bool active);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment