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
|
Index: linux-2.6.22.5/drivers/input/evdev.c
===================================================================
--- linux-2.6.22.5.orig/drivers/input/evdev.c
+++ linux-2.6.22.5/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;
};
@@ -36,6 +36,7 @@ struct evdev_client {
struct input_event buffer[EVDEV_BUFFER_SIZE];
int head;
int tail;
+ int grab;
struct fasync_struct *fasync;
struct evdev *evdev;
struct list_head node;
@@ -48,8 +49,7 @@ static void evdev_event(struct input_han
struct evdev *evdev = handle->private;
struct evdev_client *client;
- if (evdev->grab) {
- client = evdev->grab;
+ list_for_each_entry(client, &evdev->client_list, node) {
do_gettimeofday(&client->buffer[client->head].time);
client->buffer[client->head].type = type;
@@ -58,17 +58,7 @@ static void evdev_event(struct input_han
client->head = (client->head + 1) & (EVDEV_BUFFER_SIZE - 1);
kill_fasync(&client->fasync, SIGIO, POLL_IN);
- } else
- list_for_each_entry(client, &evdev->client_list, node) {
-
- do_gettimeofday(&client->buffer[client->head].time);
- client->buffer[client->head].type = type;
- client->buffer[client->head].code = code;
- client->buffer[client->head].value = value;
- client->head = (client->head + 1) & (EVDEV_BUFFER_SIZE - 1);
-
- kill_fasync(&client->fasync, SIGIO, POLL_IN);
- }
+ }
wake_up_interruptible(&evdev->wait);
}
@@ -105,9 +95,10 @@ static int evdev_release(struct inode *i
struct evdev_client *client = file->private_data;
struct evdev *evdev = client->evdev;
- if (evdev->grab == client) {
- input_release_device(&evdev->handle);
- evdev->grab = NULL;
+ if (client->grab) {
+ if(!--evdev->grab && evdev->exist)
+ input_release_device(&evdev->handle);
+ client->grab = 0;
}
evdev_fasync(-1, file, 0);
@@ -488,17 +479,19 @@ static long evdev_ioctl_handler(struct f
case EVIOCGRAB:
if (p) {
- if (evdev->grab)
- return -EBUSY;
- if (input_grab_device(&evdev->handle))
+ if (client->grab)
return -EBUSY;
- evdev->grab = client;
+ if (!evdev->grab++)
+ if (input_grab_device(&evdev->handle))
+ return -EBUSY;
+ client->grab = 0;
return 0;
} else {
- if (evdev->grab != client)
+ if (!client->grab)
return -EINVAL;
- input_release_device(&evdev->handle);
- evdev->grab = NULL;
+ if (!--evdev->grab)
+ input_release_device(&evdev->handle);
+ client->grab = 0;
return 0;
}
|