diff options
author | Ryan Mallon <rmallon@gmail.com> | 2013-09-18 15:40:47 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2013-09-19 11:57:56 -0400 |
commit | cbf0541374e2fcfdfdcaf8365c957a137eb9feea (patch) | |
tree | 04cc9e72bbf9c6298c7cc415452d161724e832ea | |
parent | 8474caddccedcbf6da59f3ed3bc5c4d9442f8e5d (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.c | 26 |
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 | ||
433 | static ssize_t uinput_inject_event(struct uinput_device *udev, | 433 | static 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 | ||
449 | static ssize_t uinput_write(struct file *file, const char __user *buffer, | 459 | static 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); |