diff options
Diffstat (limited to 'drivers/input/evdev.c')
-rw-r--r-- | drivers/input/evdev.c | 52 |
1 files changed, 47 insertions, 5 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 7df5bfef2624..4b2e10d5d641 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/input.h> | 23 | #include <linux/input/mt.h> |
24 | #include <linux/major.h> | 24 | #include <linux/major.h> |
25 | #include <linux/device.h> | 25 | #include <linux/device.h> |
26 | #include "input-compat.h" | 26 | #include "input-compat.h" |
@@ -46,6 +46,7 @@ struct evdev_client { | |||
46 | struct fasync_struct *fasync; | 46 | struct fasync_struct *fasync; |
47 | struct evdev *evdev; | 47 | struct evdev *evdev; |
48 | struct list_head node; | 48 | struct list_head node; |
49 | int clkid; | ||
49 | unsigned int bufsize; | 50 | unsigned int bufsize; |
50 | struct input_event buffer[]; | 51 | struct input_event buffer[]; |
51 | }; | 52 | }; |
@@ -54,8 +55,12 @@ static struct evdev *evdev_table[EVDEV_MINORS]; | |||
54 | static DEFINE_MUTEX(evdev_table_mutex); | 55 | static DEFINE_MUTEX(evdev_table_mutex); |
55 | 56 | ||
56 | static void evdev_pass_event(struct evdev_client *client, | 57 | 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) | ||
58 | { | 60 | { |
61 | event->time = ktime_to_timeval(client->clkid == CLOCK_MONOTONIC ? | ||
62 | mono : real); | ||
63 | |||
59 | /* Interrupts are disabled, just acquire the lock. */ | 64 | /* Interrupts are disabled, just acquire the lock. */ |
60 | spin_lock(&client->buffer_lock); | 65 | spin_lock(&client->buffer_lock); |
61 | 66 | ||
@@ -94,8 +99,11 @@ static void evdev_event(struct input_handle *handle, | |||
94 | struct evdev *evdev = handle->private; | 99 | struct evdev *evdev = handle->private; |
95 | struct evdev_client *client; | 100 | struct evdev_client *client; |
96 | struct input_event event; | 101 | 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()); | ||
97 | 106 | ||
98 | do_gettimeofday(&event.time); | ||
99 | event.type = type; | 107 | event.type = type; |
100 | event.code = code; | 108 | event.code = code; |
101 | event.value = value; | 109 | event.value = value; |
@@ -103,11 +111,12 @@ static void evdev_event(struct input_handle *handle, | |||
103 | rcu_read_lock(); | 111 | rcu_read_lock(); |
104 | 112 | ||
105 | client = rcu_dereference(evdev->grab); | 113 | client = rcu_dereference(evdev->grab); |
114 | |||
106 | if (client) | 115 | if (client) |
107 | evdev_pass_event(client, &event); | 116 | evdev_pass_event(client, &event, time_mono, time_real); |
108 | else | 117 | else |
109 | list_for_each_entry_rcu(client, &evdev->client_list, node) | 118 | 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); |
111 | 120 | ||
112 | rcu_read_unlock(); | 121 | rcu_read_unlock(); |
113 | 122 | ||
@@ -623,6 +632,28 @@ static int evdev_handle_set_keycode_v2(struct input_dev *dev, void __user *p) | |||
623 | return input_set_keycode(dev, &ke); | 632 | return input_set_keycode(dev, &ke); |
624 | } | 633 | } |
625 | 634 | ||
635 | static int evdev_handle_mt_request(struct input_dev *dev, | ||
636 | unsigned int size, | ||
637 | int __user *ip) | ||
638 | { | ||
639 | const struct input_mt_slot *mt = dev->mt; | ||
640 | unsigned int code; | ||
641 | int max_slots; | ||
642 | int i; | ||
643 | |||
644 | if (get_user(code, &ip[0])) | ||
645 | return -EFAULT; | ||
646 | if (!input_is_mt_value(code)) | ||
647 | return -EINVAL; | ||
648 | |||
649 | max_slots = (size - sizeof(__u32)) / sizeof(__s32); | ||
650 | for (i = 0; i < dev->mtsize && i < max_slots; i++) | ||
651 | if (put_user(input_mt_get_value(&mt[i], code), &ip[1 + i])) | ||
652 | return -EFAULT; | ||
653 | |||
654 | return 0; | ||
655 | } | ||
656 | |||
626 | static long evdev_do_ioctl(struct file *file, unsigned int cmd, | 657 | static long evdev_do_ioctl(struct file *file, unsigned int cmd, |
627 | void __user *p, int compat_mode) | 658 | void __user *p, int compat_mode) |
628 | { | 659 | { |
@@ -685,6 +716,14 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, | |||
685 | else | 716 | else |
686 | return evdev_ungrab(evdev, client); | 717 | return evdev_ungrab(evdev, client); |
687 | 718 | ||
719 | case EVIOCSCLOCKID: | ||
720 | if (copy_from_user(&i, p, sizeof(unsigned int))) | ||
721 | return -EFAULT; | ||
722 | if (i != CLOCK_MONOTONIC && i != CLOCK_REALTIME) | ||
723 | return -EINVAL; | ||
724 | client->clkid = i; | ||
725 | return 0; | ||
726 | |||
688 | case EVIOCGKEYCODE: | 727 | case EVIOCGKEYCODE: |
689 | return evdev_handle_get_keycode(dev, p); | 728 | return evdev_handle_get_keycode(dev, p); |
690 | 729 | ||
@@ -708,6 +747,9 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, | |||
708 | return bits_to_user(dev->propbit, INPUT_PROP_MAX, | 747 | return bits_to_user(dev->propbit, INPUT_PROP_MAX, |
709 | size, p, compat_mode); | 748 | size, p, compat_mode); |
710 | 749 | ||
750 | case EVIOCGMTSLOTS(0): | ||
751 | return evdev_handle_mt_request(dev, size, ip); | ||
752 | |||
711 | case EVIOCGKEY(0): | 753 | case EVIOCGKEY(0): |
712 | return bits_to_user(dev->key, KEY_MAX, size, p, compat_mode); | 754 | return bits_to_user(dev->key, KEY_MAX, size, p, compat_mode); |
713 | 755 | ||