summaryrefslogtreecommitdiff
path: root/target/linux/s3c24xx/patches-2.6.26/1050-fix-EVIOCGRAB-semantics.patch.patch
blob: 5ef328b2f0404ff0c1c844a600f9d1ccfa5eacbe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
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