aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRyan Mallon <rmallon@gmail.com>2013-09-18 15:40:47 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2013-09-19 11:57:56 -0400
commitcbf0541374e2fcfdfdcaf8365c957a137eb9feea (patch)
tree04cc9e72bbf9c6298c7cc415452d161724e832ea
parent8474caddccedcbf6da59f3ed3bc5c4d9442f8e5d (diff)
Input: uinput - support injecting multiple events in one write() call
Rework the code in uinput_inject_event so that it matches the code in evdev_write and allows injecting more than one event, or zero events. Signed-off-by: Ryan Mallon <rmallon@gmail.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
-rw-r--r--drivers/input/misc/uinput.c26
1 files changed, 18 insertions, 8 deletions
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index a0a4bbaef02c..772835938a52 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -430,20 +430,30 @@ static int uinput_setup_device(struct uinput_device *udev,
430 return retval; 430 return retval;
431} 431}
432 432
433static ssize_t uinput_inject_event(struct uinput_device *udev, 433static ssize_t uinput_inject_events(struct uinput_device *udev,
434 const char __user *buffer, size_t count) 434 const char __user *buffer, size_t count)
435{ 435{
436 struct input_event ev; 436 struct input_event ev;
437 size_t bytes = 0;
437 438
438 if (count < input_event_size()) 439 if (count != 0 && count < input_event_size())
439 return -EINVAL; 440 return -EINVAL;
440 441
441 if (input_event_from_user(buffer, &ev)) 442 while (bytes + input_event_size() <= count) {
442 return -EFAULT; 443 /*
444 * Note that even if some events were fetched successfully
445 * we are still going to return EFAULT instead of partial
446 * count to let userspace know that it got it's buffers
447 * all wrong.
448 */
449 if (input_event_from_user(buffer + bytes, &ev))
450 return -EFAULT;
443 451
444 input_event(udev->dev, ev.type, ev.code, ev.value); 452 input_event(udev->dev, ev.type, ev.code, ev.value);
453 bytes += input_event_size();
454 }
445 455
446 return input_event_size(); 456 return bytes;
447} 457}
448 458
449static ssize_t uinput_write(struct file *file, const char __user *buffer, 459static ssize_t uinput_write(struct file *file, const char __user *buffer,
@@ -460,7 +470,7 @@ static ssize_t uinput_write(struct file *file, const char __user *buffer,
460 return retval; 470 return retval;
461 471
462 retval = udev->state == UIST_CREATED ? 472 retval = udev->state == UIST_CREATED ?
463 uinput_inject_event(udev, buffer, count) : 473 uinput_inject_events(udev, buffer, count) :
464 uinput_setup_device(udev, buffer, count); 474 uinput_setup_device(udev, buffer, count);
465 475
466 mutex_unlock(&udev->mutex); 476 mutex_unlock(&udev->mutex);