Skip to content

Commit aac8bcf

Browse files
aniroop-mathurdtor
authored andcommitted
Input: evdev - add CLOCK_BOOTTIME support
This patch adds support for CLOCK_BOOTTIME for input event timestamp. CLOCK_BOOTTIME includes suspend time, so it would allow aplications to get correct time difference between two events even when system resumes from suspend state. Signed-off-by: Aniroop Mathur <a.mathur@samsung.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
1 parent 2ba3532 commit aac8bcf

1 file changed

Lines changed: 44 additions & 16 deletions

File tree

drivers/input/evdev.c

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@
2828
#include <linux/cdev.h>
2929
#include "input-compat.h"
3030

31+
enum evdev_clock_type {
32+
EV_CLK_REAL = 0,
33+
EV_CLK_MONO,
34+
EV_CLK_BOOT,
35+
EV_CLK_MAX
36+
};
37+
3138
struct evdev {
3239
int open;
3340
struct input_handle handle;
@@ -49,12 +56,32 @@ struct evdev_client {
4956
struct fasync_struct *fasync;
5057
struct evdev *evdev;
5158
struct list_head node;
52-
int clkid;
59+
int clk_type;
5360
bool revoked;
5461
unsigned int bufsize;
5562
struct input_event buffer[];
5663
};
5764

65+
static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid)
66+
{
67+
switch (clkid) {
68+
69+
case CLOCK_REALTIME:
70+
client->clk_type = EV_CLK_REAL;
71+
break;
72+
case CLOCK_MONOTONIC:
73+
client->clk_type = EV_CLK_MONO;
74+
break;
75+
case CLOCK_BOOTTIME:
76+
client->clk_type = EV_CLK_BOOT;
77+
break;
78+
default:
79+
return -EINVAL;
80+
}
81+
82+
return 0;
83+
}
84+
5885
/* flush queued events of type @type, caller must hold client->buffer_lock */
5986
static void __evdev_flush_queue(struct evdev_client *client, unsigned int type)
6087
{
@@ -108,8 +135,11 @@ static void evdev_queue_syn_dropped(struct evdev_client *client)
108135
struct input_event ev;
109136
ktime_t time;
110137

111-
time = (client->clkid == CLOCK_MONOTONIC) ?
112-
ktime_get() : ktime_get_real();
138+
time = client->clk_type == EV_CLK_REAL ?
139+
ktime_get_real() :
140+
client->clk_type == EV_CLK_MONO ?
141+
ktime_get() :
142+
ktime_get_boottime();
113143

114144
ev.time = ktime_to_timeval(time);
115145
ev.type = EV_SYN;
@@ -159,7 +189,7 @@ static void __pass_event(struct evdev_client *client,
159189

160190
static void evdev_pass_values(struct evdev_client *client,
161191
const struct input_value *vals, unsigned int count,
162-
ktime_t mono, ktime_t real)
192+
ktime_t *ev_time)
163193
{
164194
struct evdev *evdev = client->evdev;
165195
const struct input_value *v;
@@ -169,8 +199,7 @@ static void evdev_pass_values(struct evdev_client *client,
169199
if (client->revoked)
170200
return;
171201

172-
event.time = ktime_to_timeval(client->clkid == CLOCK_MONOTONIC ?
173-
mono : real);
202+
event.time = ktime_to_timeval(ev_time[client->clk_type]);
174203

175204
/* Interrupts are disabled, just acquire the lock. */
176205
spin_lock(&client->buffer_lock);
@@ -198,21 +227,22 @@ static void evdev_events(struct input_handle *handle,
198227
{
199228
struct evdev *evdev = handle->private;
200229
struct evdev_client *client;
201-
ktime_t time_mono, time_real;
230+
ktime_t ev_time[EV_CLK_MAX];
202231

203-
time_mono = ktime_get();
204-
time_real = ktime_mono_to_real(time_mono);
232+
ev_time[EV_CLK_MONO] = ktime_get();
233+
ev_time[EV_CLK_REAL] = ktime_mono_to_real(ev_time[EV_CLK_MONO]);
234+
ev_time[EV_CLK_BOOT] = ktime_mono_to_any(ev_time[EV_CLK_MONO],
235+
TK_OFFS_BOOT);
205236

206237
rcu_read_lock();
207238

208239
client = rcu_dereference(evdev->grab);
209240

210241
if (client)
211-
evdev_pass_values(client, vals, count, time_mono, time_real);
242+
evdev_pass_values(client, vals, count, ev_time);
212243
else
213244
list_for_each_entry_rcu(client, &evdev->client_list, node)
214-
evdev_pass_values(client, vals, count,
215-
time_mono, time_real);
245+
evdev_pass_values(client, vals, count, ev_time);
216246

217247
rcu_read_unlock();
218248
}
@@ -877,10 +907,8 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
877907
case EVIOCSCLOCKID:
878908
if (copy_from_user(&i, p, sizeof(unsigned int)))
879909
return -EFAULT;
880-
if (i != CLOCK_MONOTONIC && i != CLOCK_REALTIME)
881-
return -EINVAL;
882-
client->clkid = i;
883-
return 0;
910+
911+
return evdev_set_clk_type(client, i);
884912

885913
case EVIOCGKEYCODE:
886914
return evdev_handle_get_keycode(dev, p);

0 commit comments

Comments
 (0)