Skip to content

Commit 3b51c44

Browse files
Atif Niyazdtor
authored andcommitted
Input: allow drivers specify timestamp for input events
Currently, evdev stamps events with timestamps acquired in evdev_events() However, this timestamping may not be accurate in terms of measuring when the actual event happened. Let's allow individual drivers specify timestamp in order to provide a more accurate sense of time for the event. It is expected that drivers will set the timestamp in their hard interrupt routine. Signed-off-by: Atif Niyaz <[email protected]> Signed-off-by: Dmitry Torokhov <[email protected]>
1 parent c243382 commit 3b51c44

File tree

3 files changed

+62
-27
lines changed

3 files changed

+62
-27
lines changed

drivers/input/evdev.c

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,6 @@
2525
#include <linux/cdev.h>
2626
#include "input-compat.h"
2727

28-
enum evdev_clock_type {
29-
EV_CLK_REAL = 0,
30-
EV_CLK_MONO,
31-
EV_CLK_BOOT,
32-
EV_CLK_MAX
33-
};
34-
3528
struct evdev {
3629
int open;
3730
struct input_handle handle;
@@ -53,7 +46,7 @@ struct evdev_client {
5346
struct fasync_struct *fasync;
5447
struct evdev *evdev;
5548
struct list_head node;
56-
unsigned int clk_type;
49+
enum input_clock_type clk_type;
5750
bool revoked;
5851
unsigned long *evmasks[EV_CNT];
5952
unsigned int bufsize;
@@ -149,17 +142,10 @@ static void __evdev_flush_queue(struct evdev_client *client, unsigned int type)
149142

150143
static void __evdev_queue_syn_dropped(struct evdev_client *client)
151144
{
145+
ktime_t *ev_time = input_get_timestamp(client->evdev->handle.dev);
146+
struct timespec64 ts = ktime_to_timespec64(ev_time[client->clk_type]);
152147
struct input_event ev;
153-
ktime_t time;
154-
struct timespec64 ts;
155148

156-
time = client->clk_type == EV_CLK_REAL ?
157-
ktime_get_real() :
158-
client->clk_type == EV_CLK_MONO ?
159-
ktime_get() :
160-
ktime_get_boottime();
161-
162-
ts = ktime_to_timespec64(time);
163149
ev.input_event_sec = ts.tv_sec;
164150
ev.input_event_usec = ts.tv_nsec / NSEC_PER_USEC;
165151
ev.type = EV_SYN;
@@ -188,18 +174,18 @@ static void evdev_queue_syn_dropped(struct evdev_client *client)
188174
static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid)
189175
{
190176
unsigned long flags;
191-
unsigned int clk_type;
177+
enum input_clock_type clk_type;
192178

193179
switch (clkid) {
194180

195181
case CLOCK_REALTIME:
196-
clk_type = EV_CLK_REAL;
182+
clk_type = INPUT_CLK_REAL;
197183
break;
198184
case CLOCK_MONOTONIC:
199-
clk_type = EV_CLK_MONO;
185+
clk_type = INPUT_CLK_MONO;
200186
break;
201187
case CLOCK_BOOTTIME:
202-
clk_type = EV_CLK_BOOT;
188+
clk_type = INPUT_CLK_BOOT;
203189
break;
204190
default:
205191
return -EINVAL;
@@ -307,12 +293,7 @@ static void evdev_events(struct input_handle *handle,
307293
{
308294
struct evdev *evdev = handle->private;
309295
struct evdev_client *client;
310-
ktime_t ev_time[EV_CLK_MAX];
311-
312-
ev_time[EV_CLK_MONO] = ktime_get();
313-
ev_time[EV_CLK_REAL] = ktime_mono_to_real(ev_time[EV_CLK_MONO]);
314-
ev_time[EV_CLK_BOOT] = ktime_mono_to_any(ev_time[EV_CLK_MONO],
315-
TK_OFFS_BOOT);
296+
ktime_t *ev_time = input_get_timestamp(handle->dev);
316297

317298
rcu_read_lock();
318299

drivers/input/input.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1894,6 +1894,46 @@ void input_free_device(struct input_dev *dev)
18941894
}
18951895
EXPORT_SYMBOL(input_free_device);
18961896

1897+
/**
1898+
* input_set_timestamp - set timestamp for input events
1899+
* @dev: input device to set timestamp for
1900+
* @timestamp: the time at which the event has occurred
1901+
* in CLOCK_MONOTONIC
1902+
*
1903+
* This function is intended to provide to the input system a more
1904+
* accurate time of when an event actually occurred. The driver should
1905+
* call this function as soon as a timestamp is acquired ensuring
1906+
* clock conversions in input_set_timestamp are done correctly.
1907+
*
1908+
* The system entering suspend state between timestamp acquisition and
1909+
* calling input_set_timestamp can result in inaccurate conversions.
1910+
*/
1911+
void input_set_timestamp(struct input_dev *dev, ktime_t timestamp)
1912+
{
1913+
dev->timestamp[INPUT_CLK_MONO] = timestamp;
1914+
dev->timestamp[INPUT_CLK_REAL] = ktime_mono_to_real(timestamp);
1915+
dev->timestamp[INPUT_CLK_BOOT] = ktime_mono_to_any(timestamp,
1916+
TK_OFFS_BOOT);
1917+
}
1918+
EXPORT_SYMBOL(input_set_timestamp);
1919+
1920+
/**
1921+
* input_get_timestamp - get timestamp for input events
1922+
* @dev: input device to get timestamp from
1923+
*
1924+
* A valid timestamp is a timestamp of non-zero value.
1925+
*/
1926+
ktime_t *input_get_timestamp(struct input_dev *dev)
1927+
{
1928+
const ktime_t invalid_timestamp = ktime_set(0, 0);
1929+
1930+
if (!ktime_compare(dev->timestamp[INPUT_CLK_MONO], invalid_timestamp))
1931+
input_set_timestamp(dev, ktime_get());
1932+
1933+
return dev->timestamp;
1934+
}
1935+
EXPORT_SYMBOL(input_get_timestamp);
1936+
18971937
/**
18981938
* input_set_capability - mark device as capable of a certain event
18991939
* @dev: device that is capable of emitting or accepting event

include/linux/input.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ struct input_value {
3333
__s32 value;
3434
};
3535

36+
enum input_clock_type {
37+
INPUT_CLK_REAL = 0,
38+
INPUT_CLK_MONO,
39+
INPUT_CLK_BOOT,
40+
INPUT_CLK_MAX
41+
};
42+
3643
/**
3744
* struct input_dev - represents an input device
3845
* @name: name of the device
@@ -114,6 +121,8 @@ struct input_value {
114121
* @vals: array of values queued in the current frame
115122
* @devres_managed: indicates that devices is managed with devres framework
116123
* and needs not be explicitly unregistered or freed.
124+
* @timestamp: storage for a timestamp set by input_set_timestamp called
125+
* by a driver
117126
*/
118127
struct input_dev {
119128
const char *name;
@@ -184,6 +193,8 @@ struct input_dev {
184193
struct input_value *vals;
185194

186195
bool devres_managed;
196+
197+
ktime_t timestamp[INPUT_CLK_MAX];
187198
};
188199
#define to_input_dev(d) container_of(d, struct input_dev, dev)
189200

@@ -382,6 +393,9 @@ void input_close_device(struct input_handle *);
382393

383394
int input_flush_device(struct input_handle *handle, struct file *file);
384395

396+
void input_set_timestamp(struct input_dev *dev, ktime_t timestamp);
397+
ktime_t *input_get_timestamp(struct input_dev *dev);
398+
385399
void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);
386400
void input_inject_event(struct input_handle *handle, unsigned int type, unsigned int code, int value);
387401

0 commit comments

Comments
 (0)