From a6b37451a52ae7d30c2493b9cc14b8604e81587d Mon Sep 17 00:00:00 2001 From: mokopatches Date: Sun, 13 Apr 2008 07:23:53 +0100 Subject: [PATCH] fix-EVIOCGRAB-semantics.patch --- drivers/input/evdev.c | 32 +++++++++++++++----------------- 1 files changed, 15 insertions(+), 17 deletions(-) diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index e5b4e9b..2f3d825 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -28,7 +28,7 @@ struct evdev { char name[16]; struct input_handle handle; wait_queue_head_t wait; - struct evdev_client *grab; + int *grab; struct list_head client_list; spinlock_t client_lock; /* protects client_list */ struct mutex mutex; @@ -39,6 +39,7 @@ struct evdev_client { struct input_event buffer[EVDEV_BUFFER_SIZE]; int head; int tail; + int grab; spinlock_t buffer_lock; /* protects access to buffer, head and tail */ struct fasync_struct *fasync; struct evdev *evdev; @@ -79,12 +80,8 @@ static void evdev_event(struct input_handle *handle, rcu_read_lock(); - client = rcu_dereference(evdev->grab); - if (client) + list_for_each_entry_rcu(client, &evdev->client_list, node) evdev_pass_event(client, &event); - else - list_for_each_entry_rcu(client, &evdev->client_list, node) - evdev_pass_event(client, &event); rcu_read_unlock(); @@ -135,14 +132,15 @@ static int evdev_grab(struct evdev *evdev, struct evdev_client *client) { int error; - if (evdev->grab) + if (client->grab) return -EBUSY; - error = input_grab_device(&evdev->handle); - if (error) - return error; - - rcu_assign_pointer(evdev->grab, client); + if (!evdev->grab++) { + error = input_grab_device(&evdev->handle); + if (error) + return error; + } + client->grab = 1; synchronize_rcu(); return 0; @@ -150,12 +148,12 @@ static int evdev_grab(struct evdev *evdev, struct evdev_client *client) static int evdev_ungrab(struct evdev *evdev, struct evdev_client *client) { - if (evdev->grab != client) + if (!client->grab) return -EINVAL; - rcu_assign_pointer(evdev->grab, NULL); - synchronize_rcu(); - input_release_device(&evdev->handle); + if (!--evdev->grab && evdev->exist) + input_release_device(&evdev->handle); + client->grab = 0; return 0; } @@ -230,7 +228,7 @@ static int evdev_release(struct inode *inode, struct file *file) struct evdev *evdev = client->evdev; mutex_lock(&evdev->mutex); - if (evdev->grab == client) + if (client->grab) evdev_ungrab(evdev, client); mutex_unlock(&evdev->mutex); -- 1.5.6.5