openwrt/target/linux/s3c24xx/patches-2.6.24/1058-fix-EVIOCGRAB-semantic...

96 lines
2.5 KiB
Diff

From a6b37451a52ae7d30c2493b9cc14b8604e81587d Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
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