aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/evdev.c
diff options
context:
space:
mode:
authorJohn Stultz <john.stultz@linaro.org>2012-02-03 03:19:07 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2012-02-03 03:24:58 -0500
commita80b83b7b8456e9b475346c2e01d7e210883208c (patch)
treefb05acce28923e0e62b1b13cd39b9e1eee9bd0ae /drivers/input/evdev.c
parent4065d1e7b2164cff4af57b58fac887df2fe75d2a (diff)
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>
Diffstat (limited to 'drivers/input/evdev.c')
-rw-r--r--drivers/input/evdev.c25
1 files changed, 21 insertions, 4 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 76457d50bc34..c17409742999 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -46,6 +46,7 @@ struct evdev_client {
46 struct fasync_struct *fasync; 46 struct fasync_struct *fasync;
47 struct evdev *evdev; 47 struct evdev *evdev;
48 struct list_head node; 48 struct list_head node;
49 int clkid;
49 unsigned int bufsize; 50 unsigned int bufsize;
50 struct input_event buffer[]; 51 struct input_event buffer[];
51}; 52};
@@ -54,8 +55,12 @@ static struct evdev *evdev_table[EVDEV_MINORS];
54static DEFINE_MUTEX(evdev_table_mutex); 55static DEFINE_MUTEX(evdev_table_mutex);
55 56
56static void evdev_pass_event(struct evdev_client *client, 57static void evdev_pass_event(struct evdev_client *client,
57 struct input_event *event) 58 struct input_event *event,
59 ktime_t mono, ktime_t real)
58{ 60{
61 event->time = ktime_to_timeval(client->clkid == CLOCK_MONOTONIC ?
62 mono : real);
63
59 /* Interrupts are disabled, just acquire the lock. */ 64 /* Interrupts are disabled, just acquire the lock. */
60 spin_lock(&client->buffer_lock); 65 spin_lock(&client->buffer_lock);
61 66
@@ -94,8 +99,11 @@ static void evdev_event(struct input_handle *handle,
94 struct evdev *evdev = handle->private; 99 struct evdev *evdev = handle->private;
95 struct evdev_client *client; 100 struct evdev_client *client;
96 struct input_event event; 101 struct input_event event;
102 ktime_t time_mono, time_real;
103
104 time_mono = ktime_get();
105 time_real = ktime_sub(time_mono, ktime_get_monotonic_offset());
97 106
98 do_gettimeofday(&event.time);
99 event.type = type; 107 event.type = type;
100 event.code = code; 108 event.code = code;
101 event.value = value; 109 event.value = value;
@@ -103,11 +111,12 @@ static void evdev_event(struct input_handle *handle,
103 rcu_read_lock(); 111 rcu_read_lock();
104 112
105 client = rcu_dereference(evdev->grab); 113 client = rcu_dereference(evdev->grab);
114
106 if (client) 115 if (client)
107 evdev_pass_event(client, &event); 116 evdev_pass_event(client, &event, time_mono, time_real);
108 else 117 else
109 list_for_each_entry_rcu(client, &evdev->client_list, node) 118 list_for_each_entry_rcu(client, &evdev->client_list, node)
110 evdev_pass_event(client, &event); 119 evdev_pass_event(client, &event, time_mono, time_real);
111 120
112 rcu_read_unlock(); 121 rcu_read_unlock();
113 122
@@ -685,6 +694,14 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
685 else 694 else
686 return evdev_ungrab(evdev, client); 695 return evdev_ungrab(evdev, client);
687 696
697 case EVIOCSCLOCKID:
698 if (copy_from_user(&i, p, sizeof(unsigned int)))
699 return -EFAULT;
700 if (i != CLOCK_MONOTONIC && i != CLOCK_REALTIME)
701 return -EINVAL;
702 client->clkid = i;
703 return 0;
704
688 case EVIOCGKEYCODE: 705 case EVIOCGKEYCODE:
689 return evdev_handle_get_keycode(dev, p); 706 return evdev_handle_get_keycode(dev, p);
690 707