summaryrefslogtreecommitdiff
path: root/drivers/input/misc/uinput.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2023-06-29 20:29:46 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2023-06-29 20:29:46 +0300
commit86e203edf24bb327ce8fcd3c5c8c6bf530a846df (patch)
tree96432b49ba58fc5814b51fd5a9a8f58fe3ee56ec /drivers/input/misc/uinput.c
parent0e382fa72bbf0610be40af9af9b03b0cd149df82 (diff)
parentbf4ed21778f2920ca91a32fd3a1e1130e843e98f (diff)
downloadlinux-86e203edf24bb327ce8fcd3c5c8c6bf530a846df.tar.xz
Merge tag 'input-for-v6.5-rc0' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input updates from Dmitry Torokhov: - improvements to PS/2 handling for case when EC has already latched a scancode in the data register, but the kernel expects to receive an ACK to a command it sent to a device (such as keyboard LED toggle) - input drivers for devices connected over I2C bus have been switched back to using [new] .probe() - uinput allows userspace to inject timestamps for input events - support for capacitive keys in Atmel touch controller driver - assorted fixes to drv260x, pwm-vibra, ili210x, adxl34x, and other drivers * tag 'input-for-v6.5-rc0' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (40 commits) Input: pm8941-powerkey - fix debounce on gen2+ PMICs MAINTAINERS: Adjust Qualcomm driver globbing Input: gameport - provide default trigger() and read() Input: tps65219-pwrbutton - use regmap_set_bits() Input: tps65219-pwrbutton - convert to .remove_new() Input: tests - add test to cover all input_grab_device() function Input: gpio-keys - use input_report_key() Input: xpad - spelling fixes for "Xbox" Input: add HAS_IOPORT dependencies Input: libps2 - do not discard non-ack bytes when controlling LEDs Input: libps2 - introduce common interrupt handler Input: libps2 - fix aborting PS/2 commands Input: libps2 - fix NAK handling Input: libps2 - rework handling of command response Input: libps2 - remove special handling of ACK for command byte Input: libps2 - attach ps2dev instances as serio port's drvdata Input: Switch i2c drivers back to use .probe() dt-bindings: input: cypress,cyapa: convert to dtschema Input: adxl34x - do not hardcode interrupt trigger type Input: pwm-vibra - add support for enable GPIO ...
Diffstat (limited to 'drivers/input/misc/uinput.c')
-rw-r--r--drivers/input/misc/uinput.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index f2593133e524..d98212d55108 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -33,6 +33,7 @@
#define UINPUT_NAME "uinput"
#define UINPUT_BUFFER_SIZE 16
#define UINPUT_NUM_REQUESTS 16
+#define UINPUT_TIMESTAMP_ALLOWED_OFFSET_SECS 10
enum uinput_state { UIST_NEW_DEVICE, UIST_SETUP_COMPLETE, UIST_CREATED };
@@ -569,11 +570,40 @@ static int uinput_setup_device_legacy(struct uinput_device *udev,
return retval;
}
+/*
+ * Returns true if the given timestamp is valid (i.e., if all the following
+ * conditions are satisfied), false otherwise.
+ * 1) given timestamp is positive
+ * 2) it's within the allowed offset before the current time
+ * 3) it's not in the future
+ */
+static bool is_valid_timestamp(const ktime_t timestamp)
+{
+ ktime_t zero_time;
+ ktime_t current_time;
+ ktime_t min_time;
+ ktime_t offset;
+
+ zero_time = ktime_set(0, 0);
+ if (ktime_compare(zero_time, timestamp) >= 0)
+ return false;
+
+ current_time = ktime_get();
+ offset = ktime_set(UINPUT_TIMESTAMP_ALLOWED_OFFSET_SECS, 0);
+ min_time = ktime_sub(current_time, offset);
+
+ if (ktime_after(min_time, timestamp) || ktime_after(timestamp, current_time))
+ return false;
+
+ return true;
+}
+
static ssize_t uinput_inject_events(struct uinput_device *udev,
const char __user *buffer, size_t count)
{
struct input_event ev;
size_t bytes = 0;
+ ktime_t timestamp;
if (count != 0 && count < input_event_size())
return -EINVAL;
@@ -588,6 +618,10 @@ static ssize_t uinput_inject_events(struct uinput_device *udev,
if (input_event_from_user(buffer + bytes, &ev))
return -EFAULT;
+ timestamp = ktime_set(ev.input_event_sec, ev.input_event_usec * NSEC_PER_USEC);
+ if (is_valid_timestamp(timestamp))
+ input_set_timestamp(udev->dev, timestamp);
+
input_event(udev->dev, ev.type, ev.code, ev.value);
bytes += input_event_size();
cond_resched();