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+
3138struct 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 */
5986static 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
160190static 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