]> Pileus Git - ~andy/linux/commitdiff
Input: add infrastructure for selecting clockid for event time stamps
authorJohn Stultz <john.stultz@linaro.org>
Fri, 3 Feb 2012 08:19:07 +0000 (00:19 -0800)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Fri, 3 Feb 2012 08:24:58 +0000 (00:24 -0800)
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>
drivers/input/evdev.c
include/linux/input.h
kernel/time/timekeeping.c

index 76457d50bc3493e351c40fbe5b667d1b2e33ff6a..c17409742999e9376e4b3334306d10b056c79bd6 100644 (file)
@@ -46,6 +46,7 @@ struct evdev_client {
        struct fasync_struct *fasync;
        struct evdev *evdev;
        struct list_head node;
+       int clkid;
        unsigned int bufsize;
        struct input_event buffer[];
 };
@@ -54,8 +55,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);
 
@@ -94,8 +99,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;
@@ -103,11 +111,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();
 
@@ -685,6 +694,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);
 
index 3862e32c4eeb38076d4768c70a958a7b58dd6cf8..177261ea6f5216b3c228c804e18f5e1101df5e4e 100644 (file)
@@ -129,6 +129,8 @@ struct input_keymap_entry {
 
 #define EVIOCGRAB              _IOW('E', 0x90, int)                    /* Grab/Release device */
 
+#define EVIOCSCLOCKID          _IOW('E', 0xa0, int)                    /* Set clockid to be used for timestamps */
+
 /*
  * Device properties and quirks
  */
index 2b021b0e8507e7e4f9951780c88877bb2d4d56bd..16947999475505e47895beebd7b290ea873bfc26 100644 (file)
@@ -1140,6 +1140,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