]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 15 Sep 2013 11:13:39 +0000 (07:13 -0400)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 15 Sep 2013 11:13:39 +0000 (07:13 -0400)
Pull input update from Dmitry Torokhov:
 "The only change is David Hermann's new EVIOCREVOKE evdev ioctl that
  allows safely passing file descriptors to input devices to session
  processes and later being able to stop delivery of events through
  these fds so that inactive sessions will no longer receive user input
  that does not belong to them"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
  Input: evdev - add EVIOCREVOKE ioctl

drivers/input/evdev.c
include/uapi/linux/input.h

index d2b34fbbc42e78ed6b7a59c7ff2a63a6d32b5bf0..b6ded17b3be3adda86ca93bf582f679f837442aa 100644 (file)
@@ -48,6 +48,7 @@ struct evdev_client {
        struct evdev *evdev;
        struct list_head node;
        int clkid;
+       bool revoked;
        unsigned int bufsize;
        struct input_event buffer[];
 };
@@ -164,6 +165,9 @@ static void evdev_pass_values(struct evdev_client *client,
        struct input_event event;
        bool wakeup = false;
 
+       if (client->revoked)
+               return;
+
        event.time = ktime_to_timeval(client->clkid == CLOCK_MONOTONIC ?
                                      mono : real);
 
@@ -240,7 +244,7 @@ static int evdev_flush(struct file *file, fl_owner_t id)
        if (retval)
                return retval;
 
-       if (!evdev->exist)
+       if (!evdev->exist || client->revoked)
                retval = -ENODEV;
        else
                retval = input_flush_device(&evdev->handle, file);
@@ -429,7 +433,7 @@ static ssize_t evdev_write(struct file *file, const char __user *buffer,
        if (retval)
                return retval;
 
-       if (!evdev->exist) {
+       if (!evdev->exist || client->revoked) {
                retval = -ENODEV;
                goto out;
        }
@@ -482,7 +486,7 @@ static ssize_t evdev_read(struct file *file, char __user *buffer,
                return -EINVAL;
 
        for (;;) {
-               if (!evdev->exist)
+               if (!evdev->exist || client->revoked)
                        return -ENODEV;
 
                if (client->packet_head == client->tail &&
@@ -511,7 +515,7 @@ static ssize_t evdev_read(struct file *file, char __user *buffer,
                if (!(file->f_flags & O_NONBLOCK)) {
                        error = wait_event_interruptible(evdev->wait,
                                        client->packet_head != client->tail ||
-                                       !evdev->exist);
+                                       !evdev->exist || client->revoked);
                        if (error)
                                return error;
                }
@@ -529,7 +533,11 @@ static unsigned int evdev_poll(struct file *file, poll_table *wait)
 
        poll_wait(file, &evdev->wait, wait);
 
-       mask = evdev->exist ? POLLOUT | POLLWRNORM : POLLHUP | POLLERR;
+       if (evdev->exist && !client->revoked)
+               mask = POLLOUT | POLLWRNORM;
+       else
+               mask = POLLHUP | POLLERR;
+
        if (client->packet_head != client->tail)
                mask |= POLLIN | POLLRDNORM;
 
@@ -795,6 +803,17 @@ static int evdev_handle_mt_request(struct input_dev *dev,
        return 0;
 }
 
+static int evdev_revoke(struct evdev *evdev, struct evdev_client *client,
+                       struct file *file)
+{
+       client->revoked = true;
+       evdev_ungrab(evdev, client);
+       input_flush_device(&evdev->handle, file);
+       wake_up_interruptible(&evdev->wait);
+
+       return 0;
+}
+
 static long evdev_do_ioctl(struct file *file, unsigned int cmd,
                           void __user *p, int compat_mode)
 {
@@ -857,6 +876,12 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
                else
                        return evdev_ungrab(evdev, client);
 
+       case EVIOCREVOKE:
+               if (p)
+                       return -EINVAL;
+               else
+                       return evdev_revoke(evdev, client, file);
+
        case EVIOCSCLOCKID:
                if (copy_from_user(&i, p, sizeof(unsigned int)))
                        return -EFAULT;
@@ -1002,7 +1027,7 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
        if (retval)
                return retval;
 
-       if (!evdev->exist) {
+       if (!evdev->exist || client->revoked) {
                retval = -ENODEV;
                goto out;
        }
index d08abf9101d2161df16557e97e86b67c969eaa10..a3726275876dc509bfa99a01b8113385c1fb2d2f 100644 (file)
@@ -152,6 +152,7 @@ struct input_keymap_entry {
 #define EVIOCGEFFECTS          _IOR('E', 0x84, int)                    /* Report number of effects playable at the same time */
 
 #define EVIOCGRAB              _IOW('E', 0x90, int)                    /* Grab/Release device */
+#define EVIOCREVOKE            _IOW('E', 0x91, int)                    /* Revoke device access */
 
 #define EVIOCSCLOCKID          _IOW('E', 0xa0, int)                    /* Set clockid to be used for timestamps */