Skip to content

Commit a80b83b

Browse files
johnstultz-workdtor
authored andcommitted
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 <[email protected]> Reviewed-by: Daniel Kurtz <[email protected]> Signed-off-by: Dmitry Torokhov <[email protected]>
1 parent 4065d1e commit a80b83b

File tree

3 files changed

+25
-4
lines changed

3 files changed

+25
-4
lines changed

drivers/input/evdev.c

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ struct evdev_client {
4646
struct fasync_struct *fasync;
4747
struct evdev *evdev;
4848
struct list_head node;
49+
int clkid;
4950
unsigned int bufsize;
5051
struct input_event buffer[];
5152
};
@@ -54,8 +55,12 @@ static struct evdev *evdev_table[EVDEV_MINORS];
5455
static DEFINE_MUTEX(evdev_table_mutex);
5556

5657
static 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)
5860
{
61+
event->time = ktime_to_timeval(client->clkid == CLOCK_MONOTONIC ?
62+
mono : real);
63+
5964
/* Interrupts are disabled, just acquire the lock. */
6065
spin_lock(&client->buffer_lock);
6166

@@ -94,20 +99,24 @@ static void evdev_event(struct input_handle *handle,
9499
struct evdev *evdev = handle->private;
95100
struct evdev_client *client;
96101
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());
97106

98-
do_gettimeofday(&event.time);
99107
event.type = type;
100108
event.code = code;
101109
event.value = value;
102110

103111
rcu_read_lock();
104112

105113
client = rcu_dereference(evdev->grab);
114+
106115
if (client)
107-
evdev_pass_event(client, &event);
116+
evdev_pass_event(client, &event, time_mono, time_real);
108117
else
109118
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);
111120

112121
rcu_read_unlock();
113122

@@ -685,6 +694,14 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
685694
else
686695
return evdev_ungrab(evdev, client);
687696

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+
688705
case EVIOCGKEYCODE:
689706
return evdev_handle_get_keycode(dev, p);
690707

include/linux/input.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ struct input_keymap_entry {
129129

130130
#define EVIOCGRAB _IOW('E', 0x90, int) /* Grab/Release device */
131131

132+
#define EVIOCSCLOCKID _IOW('E', 0xa0, int) /* Set clockid to be used for timestamps */
133+
132134
/*
133135
* Device properties and quirks
134136
*/

kernel/time/timekeeping.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1140,6 +1140,8 @@ ktime_t ktime_get_monotonic_offset(void)
11401140
} while (read_seqretry(&xtime_lock, seq));
11411141
return timespec_to_ktime(wtom);
11421142
}
1143+
EXPORT_SYMBOL_GPL(ktime_get_monotonic_offset);
1144+
11431145

11441146
/**
11451147
* xtime_update() - advances the timekeeping infrastructure

0 commit comments

Comments
 (0)