]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/input/evdev.c
Merge branch 'for-next' of github.com:rydberg/linux into next
[karo-tx-linux.git] / drivers / input / evdev.c
index e4cad161be9d832d5baeaabe047024c2dbe4332e..cfe78597eb68d7be98472f7d86f2661d60e3f8d7 100644 (file)
@@ -46,6 +46,7 @@ struct evdev_client {
        struct fasync_struct *fasync;
        struct evdev *evdev;
        struct list_head node;
+       int clkid;
        unsigned int bufsize;
        struct input_event buffer[];
 };
@@ -54,8 +55,12 @@ static struct evdev *evdev_table[EVDEV_MINORS];
 static DEFINE_MUTEX(evdev_table_mutex);
 
 static void evdev_pass_event(struct evdev_client *client,
-                            struct input_event *event)
+                            struct input_event *event,
+                            ktime_t mono, ktime_t real)
 {
+       event->time = ktime_to_timeval(client->clkid == CLOCK_MONOTONIC ?
+                                       mono : real);
+
        /* Interrupts are disabled, just acquire the lock. */
        spin_lock(&client->buffer_lock);
 
@@ -94,8 +99,11 @@ static void evdev_event(struct input_handle *handle,
        struct evdev *evdev = handle->private;
        struct evdev_client *client;
        struct input_event event;
+       ktime_t time_mono, time_real;
+
+       time_mono = ktime_get();
+       time_real = ktime_sub(time_mono, ktime_get_monotonic_offset());
 
-       do_gettimeofday(&event.time);
        event.type = type;
        event.code = code;
        event.value = value;
@@ -103,11 +111,12 @@ static void evdev_event(struct input_handle *handle,
        rcu_read_lock();
 
        client = rcu_dereference(evdev->grab);
+
        if (client)
-               evdev_pass_event(client, &event);
+               evdev_pass_event(client, &event, time_mono, time_real);
        else
                list_for_each_entry_rcu(client, &evdev->client_list, node)
-                       evdev_pass_event(client, &event);
+                       evdev_pass_event(client, &event, time_mono, time_real);
 
        rcu_read_unlock();
 
@@ -386,7 +395,7 @@ static ssize_t evdev_read(struct file *file, char __user *buffer,
        struct evdev_client *client = file->private_data;
        struct evdev *evdev = client->evdev;
        struct input_event event;
-       int retval;
+       int retval = 0;
 
        if (count < input_event_size())
                return -EINVAL;
@@ -707,6 +716,14 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
                else
                        return evdev_ungrab(evdev, client);
 
+       case EVIOCSCLOCKID:
+               if (copy_from_user(&i, p, sizeof(unsigned int)))
+                       return -EFAULT;
+               if (i != CLOCK_MONOTONIC && i != CLOCK_REALTIME)
+                       return -EINVAL;
+               client->clkid = i;
+               return 0;
+
        case EVIOCGKEYCODE:
                return evdev_handle_get_keycode(dev, p);