summaryrefslogtreecommitdiff
path: root/packages/linux/linux-openmoko/fix-EVIOCGRAB-semantics.patch
blob: 3c96faa271655f524034bb43f7d9b6570027d759 (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
96
97
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 12c7ab8..c7e741b 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -29,7 +29,7 @@ struct evdev {
 	char name[16];
 	struct input_handle handle;
 	wait_queue_head_t wait;
-	struct evdev_list *grab;
+	int grab;
 	struct list_head list;
 };
 
@@ -37,6 +37,7 @@ struct evdev_list {
 	struct input_event buffer[EVDEV_BUFFER_SIZE];
 	int head;
 	int tail;
+	int grab;
 	struct fasync_struct *fasync;
 	struct evdev *evdev;
 	struct list_head node;
@@ -49,8 +50,7 @@ static void evdev_event(struct input_han
 	struct evdev *evdev = handle->private;
 	struct evdev_list *list;
 
-	if (evdev->grab) {
-		list = evdev->grab;
+	list_for_each_entry(list, &evdev->list, node) {
 
 		do_gettimeofday(&list->buffer[list->head].time);
 		list->buffer[list->head].type = type;
@@ -59,17 +59,7 @@ static void evdev_event(struct input_han
 		list->head = (list->head + 1) & (EVDEV_BUFFER_SIZE - 1);
 
 		kill_fasync(&list->fasync, SIGIO, POLL_IN);
-	} else
-		list_for_each_entry(list, &evdev->list, node) {
-
-			do_gettimeofday(&list->buffer[list->head].time);
-			list->buffer[list->head].type = type;
-			list->buffer[list->head].code = code;
-			list->buffer[list->head].value = value;
-			list->head = (list->head + 1) & (EVDEV_BUFFER_SIZE - 1);
-
-			kill_fasync(&list->fasync, SIGIO, POLL_IN);
-		}
+	}
 
 	wake_up_interruptible(&evdev->wait);
 }
@@ -104,9 +94,10 @@ static int evdev_release(struct inode * 
 {
 	struct evdev_list *list = file->private_data;
 
-	if (list->evdev->grab == list) {
-		input_release_device(&list->evdev->handle);
-		list->evdev->grab = NULL;
+	if (list->grab) {
+		if(!--list->evdev->grab && list->evdev->exist)
+			input_release_device(&list->evdev->handle);
+		list->grab = 0;
 	}
 
 	evdev_fasync(-1, file, 0);
@@ -483,17 +474,19 @@ static long evdev_ioctl_handler(struct f
 
 		case EVIOCGRAB:
 			if (p) {
-				if (evdev->grab)
-					return -EBUSY;
-				if (input_grab_device(&evdev->handle))
+				if (list->grab)
 					return -EBUSY;
-				evdev->grab = list;
+				if (!evdev->grab++)
+					if (input_grab_device(&evdev->handle))
+						return -EBUSY;
+				list->grab = 0;
 				return 0;
 			} else {
-				if (evdev->grab != list)
+				if (!list->grab)
 					return -EINVAL;
-				input_release_device(&evdev->handle);
-				evdev->grab = NULL;
+				if (!--evdev->grab)
+					input_release_device(&evdev->handle);
+				list->grab = 0;
 				return 0;
 			}
 
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/