aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Stultz <john.stultz@linaro.org>2012-02-03 00:19:07 -0800
committerWolfgang Wiedmeyer <wolfgit@wiedmeyer.de>2016-03-18 01:51:05 +0100
commit2b47842438d0d84c1f06be2c0c227048ca8e6e5d (patch)
tree7a403136cb1624400e308a45564c5b7e514d1771
parente8d223bdbb059fd8850c220e984501d4628f57d3 (diff)
downloadkernel_samsung_smdk4412-2b47842438d0d84c1f06be2c0c227048ca8e6e5d.zip
kernel_samsung_smdk4412-2b47842438d0d84c1f06be2c0c227048ca8e6e5d.tar.gz
kernel_samsung_smdk4412-2b47842438d0d84c1f06be2c0c227048ca8e6e5d.tar.bz2
Input: add infrastructure for selecting clockid for event time stamps
As noted by Arve and others, since wall time can jump backwards, it is difficult to use for input because one cannot determine if one event occurred before another or for how long a key was pressed. However, the timestamp field is part of the kernel ABI, and cannot be changed without possibly breaking existing users. This patch adds a new IOCTL that allows a clockid to be set in the evdev_client struct that will specify which time base to use for event timestamps (ie: CLOCK_MONOTONIC instead of CLOCK_REALTIME). For now we only support CLOCK_MONOTONIC and CLOCK_REALTIME, but in the future we could support other clockids if appropriate. The default remains CLOCK_REALTIME, so we don't change the ABI. Signed-off-by: John Stultz <john.stultz@linaro.org> Reviewed-by: Daniel Kurtz <djkurtz@google.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru> Conflicts: include/linux/input.h Change-Id: I7b9b442dcd7930a1e72c688327e6fb7275107128
-rw-r--r--drivers/input/evdev.c25
-rw-r--r--include/linux/input.h2
-rw-r--r--kernel/time/timekeeping.c2
3 files changed, 25 insertions, 4 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 97046dd..dd719fd 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -55,6 +55,7 @@ struct evdev_client {
struct fasync_struct *fasync;
struct evdev *evdev;
struct list_head node;
+ int clkid;
unsigned int bufsize;
struct input_event buffer[];
};
@@ -63,8 +64,12 @@ static struct evdev *evdev_table[EVDEV_MINORS];
static DEFINE_MUTEX(evdev_table_mutex);
static void evdev_pass_event(struct evdev_client *client,
- struct input_event *event)
+ struct input_event *event,
+ ktime_t mono, ktime_t real)
{
+ event->time = ktime_to_timeval(client->clkid == CLOCK_MONOTONIC ?
+ mono : real);
+
/* Interrupts are disabled, just acquire the lock. */
spin_lock(&client->buffer_lock);
@@ -107,8 +112,11 @@ static void evdev_event(struct input_handle *handle,
struct evdev *evdev = handle->private;
struct evdev_client *client;
struct input_event event;
+ ktime_t time_mono, time_real;
+
+ time_mono = ktime_get();
+ time_real = ktime_sub(time_mono, ktime_get_monotonic_offset());
- do_gettimeofday(&event.time);
event.type = type;
event.code = code;
event.value = value;
@@ -116,11 +124,12 @@ static void evdev_event(struct input_handle *handle,
rcu_read_lock();
client = rcu_dereference(evdev->grab);
+
if (client)
- evdev_pass_event(client, &event);
+ evdev_pass_event(client, &event, time_mono, time_real);
else
list_for_each_entry_rcu(client, &evdev->client_list, node)
- evdev_pass_event(client, &event);
+ evdev_pass_event(client, &event, time_mono, time_real);
rcu_read_unlock();
@@ -732,6 +741,14 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
else
return evdev_ungrab(evdev, client);
+ case EVIOCSCLOCKID:
+ if (copy_from_user(&i, p, sizeof(unsigned int)))
+ return -EFAULT;
+ if (i != CLOCK_MONOTONIC && i != CLOCK_REALTIME)
+ return -EINVAL;
+ client->clkid = i;
+ return 0;
+
case EVIOCGKEYCODE:
return evdev_handle_get_keycode(dev, p);
diff --git a/include/linux/input.h b/include/linux/input.h
index 5694583..af73bfd 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -132,6 +132,8 @@ struct input_keymap_entry {
#define EVIOCGSUSPENDBLOCK _IOR('E', 0x91, int) /* get suspend block enable */
#define EVIOCSSUSPENDBLOCK _IOW('E', 0x91, int) /* set suspend block enable */
+#define EVIOCSCLOCKID _IOW('E', 0xa0, int) /* Set clockid to be used for timestamps */
+
/*
* Device properties and quirks
*/
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 7aa8c3d..91e88d2 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -1214,6 +1214,8 @@ ktime_t ktime_get_monotonic_offset(void)
} while (read_seqretry(&xtime_lock, seq));
return timespec_to_ktime(wtom);
}
+EXPORT_SYMBOL_GPL(ktime_get_monotonic_offset);
+
/**
* xtime_update() - advances the timekeeping infrastructure