diff options
Diffstat (limited to 'drivers/input/evdev.c')
| -rw-r--r-- | drivers/input/evdev.c | 60 |
1 files changed, 44 insertions, 16 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 8afa28e4570e..18d4b2c8fe55 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
| @@ -28,6 +28,13 @@ | |||
| 28 | #include <linux/cdev.h> | 28 | #include <linux/cdev.h> |
| 29 | #include "input-compat.h" | 29 | #include "input-compat.h" |
| 30 | 30 | ||
| 31 | enum evdev_clock_type { | ||
| 32 | EV_CLK_REAL = 0, | ||
| 33 | EV_CLK_MONO, | ||
| 34 | EV_CLK_BOOT, | ||
| 35 | EV_CLK_MAX | ||
| 36 | }; | ||
| 37 | |||
| 31 | struct evdev { | 38 | struct evdev { |
| 32 | int open; | 39 | int open; |
| 33 | struct input_handle handle; | 40 | struct input_handle handle; |
| @@ -49,12 +56,32 @@ struct evdev_client { | |||
| 49 | struct fasync_struct *fasync; | 56 | struct fasync_struct *fasync; |
| 50 | struct evdev *evdev; | 57 | struct evdev *evdev; |
| 51 | struct list_head node; | 58 | struct list_head node; |
| 52 | int clkid; | 59 | int clk_type; |
| 53 | bool revoked; | 60 | bool revoked; |
| 54 | unsigned int bufsize; | 61 | unsigned int bufsize; |
| 55 | struct input_event buffer[]; | 62 | struct input_event buffer[]; |
| 56 | }; | 63 | }; |
| 57 | 64 | ||
| 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 | |||
| 58 | /* flush queued events of type @type, caller must hold client->buffer_lock */ | 85 | /* flush queued events of type @type, caller must hold client->buffer_lock */ |
| 59 | static void __evdev_flush_queue(struct evdev_client *client, unsigned int type) | 86 | static void __evdev_flush_queue(struct evdev_client *client, unsigned int type) |
| 60 | { | 87 | { |
| @@ -108,8 +135,11 @@ static void evdev_queue_syn_dropped(struct evdev_client *client) | |||
| 108 | struct input_event ev; | 135 | struct input_event ev; |
| 109 | ktime_t time; | 136 | ktime_t time; |
| 110 | 137 | ||
| 111 | time = (client->clkid == CLOCK_MONOTONIC) ? | 138 | time = client->clk_type == EV_CLK_REAL ? |
| 112 | ktime_get() : ktime_get_real(); | 139 | ktime_get_real() : |
| 140 | client->clk_type == EV_CLK_MONO ? | ||
| 141 | ktime_get() : | ||
| 142 | ktime_get_boottime(); | ||
| 113 | 143 | ||
| 114 | ev.time = ktime_to_timeval(time); | 144 | ev.time = ktime_to_timeval(time); |
| 115 | ev.type = EV_SYN; | 145 | ev.type = EV_SYN; |
| @@ -159,7 +189,7 @@ static void __pass_event(struct evdev_client *client, | |||
| 159 | 189 | ||
| 160 | static void evdev_pass_values(struct evdev_client *client, | 190 | static void evdev_pass_values(struct evdev_client *client, |
| 161 | const struct input_value *vals, unsigned int count, | 191 | const struct input_value *vals, unsigned int count, |
| 162 | ktime_t mono, ktime_t real) | 192 | ktime_t *ev_time) |
| 163 | { | 193 | { |
| 164 | struct evdev *evdev = client->evdev; | 194 | struct evdev *evdev = client->evdev; |
| 165 | const struct input_value *v; | 195 | const struct input_value *v; |
| @@ -169,8 +199,7 @@ static void evdev_pass_values(struct evdev_client *client, | |||
| 169 | if (client->revoked) | 199 | if (client->revoked) |
| 170 | return; | 200 | return; |
| 171 | 201 | ||
| 172 | event.time = ktime_to_timeval(client->clkid == CLOCK_MONOTONIC ? | 202 | event.time = ktime_to_timeval(ev_time[client->clk_type]); |
| 173 | mono : real); | ||
| 174 | 203 | ||
| 175 | /* Interrupts are disabled, just acquire the lock. */ | 204 | /* Interrupts are disabled, just acquire the lock. */ |
| 176 | spin_lock(&client->buffer_lock); | 205 | spin_lock(&client->buffer_lock); |
| @@ -198,21 +227,22 @@ static void evdev_events(struct input_handle *handle, | |||
| 198 | { | 227 | { |
| 199 | struct evdev *evdev = handle->private; | 228 | struct evdev *evdev = handle->private; |
| 200 | struct evdev_client *client; | 229 | struct evdev_client *client; |
| 201 | ktime_t time_mono, time_real; | 230 | ktime_t ev_time[EV_CLK_MAX]; |
| 202 | 231 | ||
| 203 | time_mono = ktime_get(); | 232 | ev_time[EV_CLK_MONO] = ktime_get(); |
| 204 | time_real = ktime_mono_to_real(time_mono); | 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); | ||
| 205 | 236 | ||
| 206 | rcu_read_lock(); | 237 | rcu_read_lock(); |
| 207 | 238 | ||
| 208 | client = rcu_dereference(evdev->grab); | 239 | client = rcu_dereference(evdev->grab); |
| 209 | 240 | ||
| 210 | if (client) | 241 | if (client) |
| 211 | evdev_pass_values(client, vals, count, time_mono, time_real); | 242 | evdev_pass_values(client, vals, count, ev_time); |
| 212 | else | 243 | else |
| 213 | list_for_each_entry_rcu(client, &evdev->client_list, node) | 244 | list_for_each_entry_rcu(client, &evdev->client_list, node) |
| 214 | evdev_pass_values(client, vals, count, | 245 | evdev_pass_values(client, vals, count, ev_time); |
| 215 | time_mono, time_real); | ||
| 216 | 246 | ||
| 217 | rcu_read_unlock(); | 247 | rcu_read_unlock(); |
| 218 | } | 248 | } |
| @@ -877,10 +907,8 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, | |||
| 877 | case EVIOCSCLOCKID: | 907 | case EVIOCSCLOCKID: |
| 878 | if (copy_from_user(&i, p, sizeof(unsigned int))) | 908 | if (copy_from_user(&i, p, sizeof(unsigned int))) |
| 879 | return -EFAULT; | 909 | return -EFAULT; |
| 880 | if (i != CLOCK_MONOTONIC && i != CLOCK_REALTIME) | 910 | |
| 881 | return -EINVAL; | 911 | return evdev_set_clk_type(client, i); |
| 882 | client->clkid = i; | ||
| 883 | return 0; | ||
| 884 | 912 | ||
| 885 | case EVIOCGKEYCODE: | 913 | case EVIOCGKEYCODE: |
| 886 | return evdev_handle_get_keycode(dev, p); | 914 | return evdev_handle_get_keycode(dev, p); |
