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 /drivers/input/misc | |
| 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>
Diffstat (limited to 'drivers/input/misc')
| -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); |
