mirror of https://github.com/hak5/openwrt.git
96 lines
2.5 KiB
Diff
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
|
|
|