mirror of https://github.com/hak5/openwrt.git
96 lines
2.5 KiB
Diff
96 lines
2.5 KiB
Diff
|
From 6294c84872b0d26111bdd1b9e5fec41c8a087443 Mon Sep 17 00:00:00 2001
|
||
|
From: mokopatches <mokopatches@openmoko.org>
|
||
|
Date: Fri, 25 Jul 2008 22:21:23 +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 b32984b..499ffe1 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();
|
||
|
|
||
|
@@ -136,14 +133,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;
|
||
|
@@ -151,12 +149,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;
|
||
|
}
|
||
|
@@ -231,7 +229,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.3
|
||
|
|