diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2007-08-30 00:22:18 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2007-08-30 00:22:18 -0400 |
commit | 6addb1d6de1968b84852f54561cc9a999909b5a9 (patch) | |
tree | 568526cfdd11abb953cd69db2f7059c582ebe9d4 /drivers/input/evdev.c | |
parent | 8006479c9b75fb6594a7b746af3d7f1fbb68f18f (diff) |
Input: evdev - implement proper locking
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/evdev.c')
-rw-r--r-- | drivers/input/evdev.c | 713 |
1 files changed, 473 insertions, 240 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index ab4b2d9b5327..bfee4f9a7715 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
@@ -30,6 +30,8 @@ struct evdev { | |||
30 | wait_queue_head_t wait; | 30 | wait_queue_head_t wait; |
31 | struct evdev_client *grab; | 31 | struct evdev_client *grab; |
32 | struct list_head client_list; | 32 | struct list_head client_list; |
33 | spinlock_t client_lock; /* protects client_list */ | ||
34 | struct mutex mutex; | ||
33 | struct device dev; | 35 | struct device dev; |
34 | }; | 36 | }; |
35 | 37 | ||
@@ -37,39 +39,53 @@ struct evdev_client { | |||
37 | struct input_event buffer[EVDEV_BUFFER_SIZE]; | 39 | struct input_event buffer[EVDEV_BUFFER_SIZE]; |
38 | int head; | 40 | int head; |
39 | int tail; | 41 | int tail; |
42 | spinlock_t buffer_lock; /* protects access to buffer, head and tail */ | ||
40 | struct fasync_struct *fasync; | 43 | struct fasync_struct *fasync; |
41 | struct evdev *evdev; | 44 | struct evdev *evdev; |
42 | struct list_head node; | 45 | struct list_head node; |
43 | }; | 46 | }; |
44 | 47 | ||
45 | static struct evdev *evdev_table[EVDEV_MINORS]; | 48 | static struct evdev *evdev_table[EVDEV_MINORS]; |
49 | static DEFINE_MUTEX(evdev_table_mutex); | ||
46 | 50 | ||
47 | static void evdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) | 51 | static void evdev_pass_event(struct evdev_client *client, |
52 | struct input_event *event) | ||
53 | { | ||
54 | /* | ||
55 | * Interrupts are disabled, just acquire the lock | ||
56 | */ | ||
57 | spin_lock(&client->buffer_lock); | ||
58 | client->buffer[client->head++] = *event; | ||
59 | client->head &= EVDEV_BUFFER_SIZE - 1; | ||
60 | spin_unlock(&client->buffer_lock); | ||
61 | |||
62 | kill_fasync(&client->fasync, SIGIO, POLL_IN); | ||
63 | } | ||
64 | |||
65 | /* | ||
66 | * Pass incoming event to all connected clients. Note that we are | ||
67 | * caleld under a spinlock with interrupts off so we don't need | ||
68 | * to use rcu_read_lock() here. Writers will be using syncronize_sched() | ||
69 | * instead of synchrnoize_rcu(). | ||
70 | */ | ||
71 | static void evdev_event(struct input_handle *handle, | ||
72 | unsigned int type, unsigned int code, int value) | ||
48 | { | 73 | { |
49 | struct evdev *evdev = handle->private; | 74 | struct evdev *evdev = handle->private; |
50 | struct evdev_client *client; | 75 | struct evdev_client *client; |
76 | struct input_event event; | ||
51 | 77 | ||
52 | if (evdev->grab) { | 78 | do_gettimeofday(&event.time); |
53 | client = evdev->grab; | 79 | event.type = type; |
54 | 80 | event.code = code; | |
55 | do_gettimeofday(&client->buffer[client->head].time); | 81 | event.value = value; |
56 | client->buffer[client->head].type = type; | ||
57 | client->buffer[client->head].code = code; | ||
58 | client->buffer[client->head].value = value; | ||
59 | client->head = (client->head + 1) & (EVDEV_BUFFER_SIZE - 1); | ||
60 | |||
61 | kill_fasync(&client->fasync, SIGIO, POLL_IN); | ||
62 | } else | ||
63 | list_for_each_entry(client, &evdev->client_list, node) { | ||
64 | |||
65 | do_gettimeofday(&client->buffer[client->head].time); | ||
66 | client->buffer[client->head].type = type; | ||
67 | client->buffer[client->head].code = code; | ||
68 | client->buffer[client->head].value = value; | ||
69 | client->head = (client->head + 1) & (EVDEV_BUFFER_SIZE - 1); | ||
70 | 82 | ||
71 | kill_fasync(&client->fasync, SIGIO, POLL_IN); | 83 | client = rcu_dereference(evdev->grab); |
72 | } | 84 | if (client) |
85 | evdev_pass_event(client, &event); | ||
86 | else | ||
87 | list_for_each_entry_rcu(client, &evdev->client_list, node) | ||
88 | evdev_pass_event(client, &event); | ||
73 | 89 | ||
74 | wake_up_interruptible(&evdev->wait); | 90 | wake_up_interruptible(&evdev->wait); |
75 | } | 91 | } |
@@ -88,38 +104,142 @@ static int evdev_flush(struct file *file, fl_owner_t id) | |||
88 | { | 104 | { |
89 | struct evdev_client *client = file->private_data; | 105 | struct evdev_client *client = file->private_data; |
90 | struct evdev *evdev = client->evdev; | 106 | struct evdev *evdev = client->evdev; |
107 | int retval; | ||
108 | |||
109 | retval = mutex_lock_interruptible(&evdev->mutex); | ||
110 | if (retval) | ||
111 | return retval; | ||
91 | 112 | ||
92 | if (!evdev->exist) | 113 | if (!evdev->exist) |
93 | return -ENODEV; | 114 | retval = -ENODEV; |
115 | else | ||
116 | retval = input_flush_device(&evdev->handle, file); | ||
94 | 117 | ||
95 | return input_flush_device(&evdev->handle, file); | 118 | mutex_unlock(&evdev->mutex); |
119 | return retval; | ||
96 | } | 120 | } |
97 | 121 | ||
98 | static void evdev_free(struct device *dev) | 122 | static void evdev_free(struct device *dev) |
99 | { | 123 | { |
100 | struct evdev *evdev = container_of(dev, struct evdev, dev); | 124 | struct evdev *evdev = container_of(dev, struct evdev, dev); |
101 | 125 | ||
102 | evdev_table[evdev->minor] = NULL; | ||
103 | kfree(evdev); | 126 | kfree(evdev); |
104 | } | 127 | } |
105 | 128 | ||
129 | /* | ||
130 | * Grabs an event device (along with underlying input device). | ||
131 | * This function is called with evdev->mutex taken. | ||
132 | */ | ||
133 | static int evdev_grab(struct evdev *evdev, struct evdev_client *client) | ||
134 | { | ||
135 | int error; | ||
136 | |||
137 | if (evdev->grab) | ||
138 | return -EBUSY; | ||
139 | |||
140 | error = input_grab_device(&evdev->handle); | ||
141 | if (error) | ||
142 | return error; | ||
143 | |||
144 | rcu_assign_pointer(evdev->grab, client); | ||
145 | /* | ||
146 | * We don't use synchronize_rcu() here because read-side | ||
147 | * critical section is protected by a spinlock instead | ||
148 | * of rcu_read_lock(). | ||
149 | */ | ||
150 | synchronize_sched(); | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static int evdev_ungrab(struct evdev *evdev, struct evdev_client *client) | ||
156 | { | ||
157 | if (evdev->grab != client) | ||
158 | return -EINVAL; | ||
159 | |||
160 | rcu_assign_pointer(evdev->grab, NULL); | ||
161 | synchronize_sched(); | ||
162 | input_release_device(&evdev->handle); | ||
163 | |||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | static void evdev_attach_client(struct evdev *evdev, | ||
168 | struct evdev_client *client) | ||
169 | { | ||
170 | spin_lock(&evdev->client_lock); | ||
171 | list_add_tail_rcu(&client->node, &evdev->client_list); | ||
172 | spin_unlock(&evdev->client_lock); | ||
173 | synchronize_sched(); | ||
174 | } | ||
175 | |||
176 | static void evdev_detach_client(struct evdev *evdev, | ||
177 | struct evdev_client *client) | ||
178 | { | ||
179 | spin_lock(&evdev->client_lock); | ||
180 | list_del_rcu(&client->node); | ||
181 | spin_unlock(&evdev->client_lock); | ||
182 | synchronize_sched(); | ||
183 | } | ||
184 | |||
185 | static int evdev_open_device(struct evdev *evdev) | ||
186 | { | ||
187 | int retval; | ||
188 | |||
189 | retval = mutex_lock_interruptible(&evdev->mutex); | ||
190 | if (retval) | ||
191 | return retval; | ||
192 | |||
193 | if (!evdev->exist) | ||
194 | retval = -ENODEV; | ||
195 | else if (!evdev->open++) | ||
196 | retval = input_open_device(&evdev->handle); | ||
197 | |||
198 | mutex_unlock(&evdev->mutex); | ||
199 | return retval; | ||
200 | } | ||
201 | |||
202 | static void evdev_close_device(struct evdev *evdev) | ||
203 | { | ||
204 | mutex_lock(&evdev->mutex); | ||
205 | |||
206 | if (evdev->exist && !--evdev->open) | ||
207 | input_close_device(&evdev->handle); | ||
208 | |||
209 | mutex_unlock(&evdev->mutex); | ||
210 | } | ||
211 | |||
212 | /* | ||
213 | * Wake up users waiting for IO so they can disconnect from | ||
214 | * dead device. | ||
215 | */ | ||
216 | static void evdev_hangup(struct evdev *evdev) | ||
217 | { | ||
218 | struct evdev_client *client; | ||
219 | |||
220 | spin_lock(&evdev->client_lock); | ||
221 | list_for_each_entry(client, &evdev->client_list, node) | ||
222 | kill_fasync(&client->fasync, SIGIO, POLL_HUP); | ||
223 | spin_unlock(&evdev->client_lock); | ||
224 | |||
225 | wake_up_interruptible(&evdev->wait); | ||
226 | } | ||
227 | |||
106 | static int evdev_release(struct inode *inode, struct file *file) | 228 | static int evdev_release(struct inode *inode, struct file *file) |
107 | { | 229 | { |
108 | struct evdev_client *client = file->private_data; | 230 | struct evdev_client *client = file->private_data; |
109 | struct evdev *evdev = client->evdev; | 231 | struct evdev *evdev = client->evdev; |
110 | 232 | ||
111 | if (evdev->grab == client) { | 233 | mutex_lock(&evdev->mutex); |
112 | input_release_device(&evdev->handle); | 234 | if (evdev->grab == client) |
113 | evdev->grab = NULL; | 235 | evdev_ungrab(evdev, client); |
114 | } | 236 | mutex_unlock(&evdev->mutex); |
115 | 237 | ||
116 | evdev_fasync(-1, file, 0); | 238 | evdev_fasync(-1, file, 0); |
117 | list_del(&client->node); | 239 | evdev_detach_client(evdev, client); |
118 | kfree(client); | 240 | kfree(client); |
119 | 241 | ||
120 | if (!--evdev->open && evdev->exist) | 242 | evdev_close_device(evdev); |
121 | input_close_device(&evdev->handle); | ||
122 | |||
123 | put_device(&evdev->dev); | 243 | put_device(&evdev->dev); |
124 | 244 | ||
125 | return 0; | 245 | return 0; |
@@ -127,41 +247,44 @@ static int evdev_release(struct inode *inode, struct file *file) | |||
127 | 247 | ||
128 | static int evdev_open(struct inode *inode, struct file *file) | 248 | static int evdev_open(struct inode *inode, struct file *file) |
129 | { | 249 | { |
130 | struct evdev_client *client; | ||
131 | struct evdev *evdev; | 250 | struct evdev *evdev; |
251 | struct evdev_client *client; | ||
132 | int i = iminor(inode) - EVDEV_MINOR_BASE; | 252 | int i = iminor(inode) - EVDEV_MINOR_BASE; |
133 | int error; | 253 | int error; |
134 | 254 | ||
135 | if (i >= EVDEV_MINORS) | 255 | if (i >= EVDEV_MINORS) |
136 | return -ENODEV; | 256 | return -ENODEV; |
137 | 257 | ||
258 | error = mutex_lock_interruptible(&evdev_table_mutex); | ||
259 | if (error) | ||
260 | return error; | ||
138 | evdev = evdev_table[i]; | 261 | evdev = evdev_table[i]; |
262 | if (evdev) | ||
263 | get_device(&evdev->dev); | ||
264 | mutex_unlock(&evdev_table_mutex); | ||
139 | 265 | ||
140 | if (!evdev || !evdev->exist) | 266 | if (!evdev) |
141 | return -ENODEV; | 267 | return -ENODEV; |
142 | 268 | ||
143 | get_device(&evdev->dev); | ||
144 | |||
145 | client = kzalloc(sizeof(struct evdev_client), GFP_KERNEL); | 269 | client = kzalloc(sizeof(struct evdev_client), GFP_KERNEL); |
146 | if (!client) { | 270 | if (!client) { |
147 | error = -ENOMEM; | 271 | error = -ENOMEM; |
148 | goto err_put_evdev; | 272 | goto err_put_evdev; |
149 | } | 273 | } |
150 | 274 | ||
275 | spin_lock_init(&client->buffer_lock); | ||
151 | client->evdev = evdev; | 276 | client->evdev = evdev; |
152 | list_add_tail(&client->node, &evdev->client_list); | 277 | evdev_attach_client(evdev, client); |
153 | 278 | ||
154 | if (!evdev->open++ && evdev->exist) { | 279 | error = evdev_open_device(evdev); |
155 | error = input_open_device(&evdev->handle); | 280 | if (error) |
156 | if (error) | 281 | goto err_free_client; |
157 | goto err_free_client; | ||
158 | } | ||
159 | 282 | ||
160 | file->private_data = client; | 283 | file->private_data = client; |
161 | return 0; | 284 | return 0; |
162 | 285 | ||
163 | err_free_client: | 286 | err_free_client: |
164 | list_del(&client->node); | 287 | evdev_detach_client(evdev, client); |
165 | kfree(client); | 288 | kfree(client); |
166 | err_put_evdev: | 289 | err_put_evdev: |
167 | put_device(&evdev->dev); | 290 | put_device(&evdev->dev); |
@@ -197,12 +320,14 @@ static inline size_t evdev_event_size(void) | |||
197 | sizeof(struct input_event_compat) : sizeof(struct input_event); | 320 | sizeof(struct input_event_compat) : sizeof(struct input_event); |
198 | } | 321 | } |
199 | 322 | ||
200 | static int evdev_event_from_user(const char __user *buffer, struct input_event *event) | 323 | static int evdev_event_from_user(const char __user *buffer, |
324 | struct input_event *event) | ||
201 | { | 325 | { |
202 | if (COMPAT_TEST) { | 326 | if (COMPAT_TEST) { |
203 | struct input_event_compat compat_event; | 327 | struct input_event_compat compat_event; |
204 | 328 | ||
205 | if (copy_from_user(&compat_event, buffer, sizeof(struct input_event_compat))) | 329 | if (copy_from_user(&compat_event, buffer, |
330 | sizeof(struct input_event_compat))) | ||
206 | return -EFAULT; | 331 | return -EFAULT; |
207 | 332 | ||
208 | event->time.tv_sec = compat_event.time.tv_sec; | 333 | event->time.tv_sec = compat_event.time.tv_sec; |
@@ -219,7 +344,8 @@ static int evdev_event_from_user(const char __user *buffer, struct input_event * | |||
219 | return 0; | 344 | return 0; |
220 | } | 345 | } |
221 | 346 | ||
222 | static int evdev_event_to_user(char __user *buffer, const struct input_event *event) | 347 | static int evdev_event_to_user(char __user *buffer, |
348 | const struct input_event *event) | ||
223 | { | 349 | { |
224 | if (COMPAT_TEST) { | 350 | if (COMPAT_TEST) { |
225 | struct input_event_compat compat_event; | 351 | struct input_event_compat compat_event; |
@@ -230,7 +356,8 @@ static int evdev_event_to_user(char __user *buffer, const struct input_event *ev | |||
230 | compat_event.code = event->code; | 356 | compat_event.code = event->code; |
231 | compat_event.value = event->value; | 357 | compat_event.value = event->value; |
232 | 358 | ||
233 | if (copy_to_user(buffer, &compat_event, sizeof(struct input_event_compat))) | 359 | if (copy_to_user(buffer, &compat_event, |
360 | sizeof(struct input_event_compat))) | ||
234 | return -EFAULT; | 361 | return -EFAULT; |
235 | 362 | ||
236 | } else { | 363 | } else { |
@@ -248,7 +375,8 @@ static inline size_t evdev_event_size(void) | |||
248 | return sizeof(struct input_event); | 375 | return sizeof(struct input_event); |
249 | } | 376 | } |
250 | 377 | ||
251 | static int evdev_event_from_user(const char __user *buffer, struct input_event *event) | 378 | static int evdev_event_from_user(const char __user *buffer, |
379 | struct input_event *event) | ||
252 | { | 380 | { |
253 | if (copy_from_user(event, buffer, sizeof(struct input_event))) | 381 | if (copy_from_user(event, buffer, sizeof(struct input_event))) |
254 | return -EFAULT; | 382 | return -EFAULT; |
@@ -256,7 +384,8 @@ static int evdev_event_from_user(const char __user *buffer, struct input_event * | |||
256 | return 0; | 384 | return 0; |
257 | } | 385 | } |
258 | 386 | ||
259 | static int evdev_event_to_user(char __user *buffer, const struct input_event *event) | 387 | static int evdev_event_to_user(char __user *buffer, |
388 | const struct input_event *event) | ||
260 | { | 389 | { |
261 | if (copy_to_user(buffer, event, sizeof(struct input_event))) | 390 | if (copy_to_user(buffer, event, sizeof(struct input_event))) |
262 | return -EFAULT; | 391 | return -EFAULT; |
@@ -266,37 +395,71 @@ static int evdev_event_to_user(char __user *buffer, const struct input_event *ev | |||
266 | 395 | ||
267 | #endif /* CONFIG_COMPAT */ | 396 | #endif /* CONFIG_COMPAT */ |
268 | 397 | ||
269 | static ssize_t evdev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) | 398 | static ssize_t evdev_write(struct file *file, const char __user *buffer, |
399 | size_t count, loff_t *ppos) | ||
270 | { | 400 | { |
271 | struct evdev_client *client = file->private_data; | 401 | struct evdev_client *client = file->private_data; |
272 | struct evdev *evdev = client->evdev; | 402 | struct evdev *evdev = client->evdev; |
273 | struct input_event event; | 403 | struct input_event event; |
274 | int retval = 0; | 404 | int retval; |
275 | 405 | ||
276 | if (!evdev->exist) | 406 | retval = mutex_lock_interruptible(&evdev->mutex); |
277 | return -ENODEV; | 407 | if (retval) |
408 | return retval; | ||
409 | |||
410 | if (!evdev->exist) { | ||
411 | retval = -ENODEV; | ||
412 | goto out; | ||
413 | } | ||
278 | 414 | ||
279 | while (retval < count) { | 415 | while (retval < count) { |
280 | 416 | ||
281 | if (evdev_event_from_user(buffer + retval, &event)) | 417 | if (evdev_event_from_user(buffer + retval, &event)) { |
282 | return -EFAULT; | 418 | retval = -EFAULT; |
283 | input_inject_event(&evdev->handle, event.type, event.code, event.value); | 419 | goto out; |
420 | } | ||
421 | |||
422 | input_inject_event(&evdev->handle, | ||
423 | event.type, event.code, event.value); | ||
284 | retval += evdev_event_size(); | 424 | retval += evdev_event_size(); |
285 | } | 425 | } |
286 | 426 | ||
427 | out: | ||
428 | mutex_unlock(&evdev->mutex); | ||
287 | return retval; | 429 | return retval; |
288 | } | 430 | } |
289 | 431 | ||
290 | static ssize_t evdev_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) | 432 | static int evdev_fetch_next_event(struct evdev_client *client, |
433 | struct input_event *event) | ||
434 | { | ||
435 | int have_event; | ||
436 | |||
437 | spin_lock_irq(&client->buffer_lock); | ||
438 | |||
439 | have_event = client->head != client->tail; | ||
440 | if (have_event) { | ||
441 | *event = client->buffer[client->tail++]; | ||
442 | client->tail &= EVDEV_BUFFER_SIZE - 1; | ||
443 | } | ||
444 | |||
445 | spin_unlock_irq(&client->buffer_lock); | ||
446 | |||
447 | return have_event; | ||
448 | } | ||
449 | |||
450 | static ssize_t evdev_read(struct file *file, char __user *buffer, | ||
451 | size_t count, loff_t *ppos) | ||
291 | { | 452 | { |
292 | struct evdev_client *client = file->private_data; | 453 | struct evdev_client *client = file->private_data; |
293 | struct evdev *evdev = client->evdev; | 454 | struct evdev *evdev = client->evdev; |
455 | struct input_event event; | ||
294 | int retval; | 456 | int retval; |
295 | 457 | ||
296 | if (count < evdev_event_size()) | 458 | if (count < evdev_event_size()) |
297 | return -EINVAL; | 459 | return -EINVAL; |
298 | 460 | ||
299 | if (client->head == client->tail && evdev->exist && (file->f_flags & O_NONBLOCK)) | 461 | if (client->head == client->tail && evdev->exist && |
462 | (file->f_flags & O_NONBLOCK)) | ||
300 | return -EAGAIN; | 463 | return -EAGAIN; |
301 | 464 | ||
302 | retval = wait_event_interruptible(evdev->wait, | 465 | retval = wait_event_interruptible(evdev->wait, |
@@ -307,14 +470,12 @@ static ssize_t evdev_read(struct file *file, char __user *buffer, size_t count, | |||
307 | if (!evdev->exist) | 470 | if (!evdev->exist) |
308 | return -ENODEV; | 471 | return -ENODEV; |
309 | 472 | ||
310 | while (client->head != client->tail && retval + evdev_event_size() <= count) { | 473 | while (retval + evdev_event_size() <= count && |
311 | 474 | evdev_fetch_next_event(client, &event)) { | |
312 | struct input_event *event = (struct input_event *) client->buffer + client->tail; | ||
313 | 475 | ||
314 | if (evdev_event_to_user(buffer + retval, event)) | 476 | if (evdev_event_to_user(buffer + retval, &event)) |
315 | return -EFAULT; | 477 | return -EFAULT; |
316 | 478 | ||
317 | client->tail = (client->tail + 1) & (EVDEV_BUFFER_SIZE - 1); | ||
318 | retval += evdev_event_size(); | 479 | retval += evdev_event_size(); |
319 | } | 480 | } |
320 | 481 | ||
@@ -409,8 +570,8 @@ static int str_to_user(const char *str, unsigned int maxlen, void __user *p) | |||
409 | return copy_to_user(p, str, len) ? -EFAULT : len; | 570 | return copy_to_user(p, str, len) ? -EFAULT : len; |
410 | } | 571 | } |
411 | 572 | ||
412 | static long evdev_ioctl_handler(struct file *file, unsigned int cmd, | 573 | static long evdev_do_ioctl(struct file *file, unsigned int cmd, |
413 | void __user *p, int compat_mode) | 574 | void __user *p, int compat_mode) |
414 | { | 575 | { |
415 | struct evdev_client *client = file->private_data; | 576 | struct evdev_client *client = file->private_data; |
416 | struct evdev *evdev = client->evdev; | 577 | struct evdev *evdev = client->evdev; |
@@ -421,215 +582,289 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd, | |||
421 | int i, t, u, v; | 582 | int i, t, u, v; |
422 | int error; | 583 | int error; |
423 | 584 | ||
424 | if (!evdev->exist) | ||
425 | return -ENODEV; | ||
426 | |||
427 | switch (cmd) { | 585 | switch (cmd) { |
428 | 586 | ||
429 | case EVIOCGVERSION: | 587 | case EVIOCGVERSION: |
430 | return put_user(EV_VERSION, ip); | 588 | return put_user(EV_VERSION, ip); |
431 | 589 | ||
432 | case EVIOCGID: | 590 | case EVIOCGID: |
433 | if (copy_to_user(p, &dev->id, sizeof(struct input_id))) | 591 | if (copy_to_user(p, &dev->id, sizeof(struct input_id))) |
434 | return -EFAULT; | 592 | return -EFAULT; |
435 | return 0; | 593 | return 0; |
436 | 594 | ||
437 | case EVIOCGREP: | 595 | case EVIOCGREP: |
438 | if (!test_bit(EV_REP, dev->evbit)) | 596 | if (!test_bit(EV_REP, dev->evbit)) |
439 | return -ENOSYS; | 597 | return -ENOSYS; |
440 | if (put_user(dev->rep[REP_DELAY], ip)) | 598 | if (put_user(dev->rep[REP_DELAY], ip)) |
441 | return -EFAULT; | 599 | return -EFAULT; |
442 | if (put_user(dev->rep[REP_PERIOD], ip + 1)) | 600 | if (put_user(dev->rep[REP_PERIOD], ip + 1)) |
443 | return -EFAULT; | 601 | return -EFAULT; |
444 | return 0; | 602 | return 0; |
445 | 603 | ||
446 | case EVIOCSREP: | 604 | case EVIOCSREP: |
447 | if (!test_bit(EV_REP, dev->evbit)) | 605 | if (!test_bit(EV_REP, dev->evbit)) |
448 | return -ENOSYS; | 606 | return -ENOSYS; |
449 | if (get_user(u, ip)) | 607 | if (get_user(u, ip)) |
450 | return -EFAULT; | 608 | return -EFAULT; |
451 | if (get_user(v, ip + 1)) | 609 | if (get_user(v, ip + 1)) |
452 | return -EFAULT; | 610 | return -EFAULT; |
453 | 611 | ||
454 | input_inject_event(&evdev->handle, EV_REP, REP_DELAY, u); | 612 | input_inject_event(&evdev->handle, EV_REP, REP_DELAY, u); |
455 | input_inject_event(&evdev->handle, EV_REP, REP_PERIOD, v); | 613 | input_inject_event(&evdev->handle, EV_REP, REP_PERIOD, v); |
456 | 614 | ||
457 | return 0; | 615 | return 0; |
458 | 616 | ||
459 | case EVIOCGKEYCODE: | 617 | case EVIOCGKEYCODE: |
460 | if (get_user(t, ip)) | 618 | if (get_user(t, ip)) |
461 | return -EFAULT; | 619 | return -EFAULT; |
462 | 620 | ||
463 | error = dev->getkeycode(dev, t, &v); | 621 | error = dev->getkeycode(dev, t, &v); |
464 | if (error) | 622 | if (error) |
465 | return error; | 623 | return error; |
466 | 624 | ||
467 | if (put_user(v, ip + 1)) | 625 | if (put_user(v, ip + 1)) |
468 | return -EFAULT; | 626 | return -EFAULT; |
469 | 627 | ||
470 | return 0; | 628 | return 0; |
471 | 629 | ||
472 | case EVIOCSKEYCODE: | 630 | case EVIOCSKEYCODE: |
473 | if (get_user(t, ip) || get_user(v, ip + 1)) | 631 | if (get_user(t, ip) || get_user(v, ip + 1)) |
474 | return -EFAULT; | 632 | return -EFAULT; |
475 | 633 | ||
476 | return dev->setkeycode(dev, t, v); | 634 | return dev->setkeycode(dev, t, v); |
477 | 635 | ||
478 | case EVIOCSFF: | 636 | case EVIOCSFF: |
479 | if (copy_from_user(&effect, p, sizeof(effect))) | 637 | if (copy_from_user(&effect, p, sizeof(effect))) |
480 | return -EFAULT; | 638 | return -EFAULT; |
481 | 639 | ||
482 | error = input_ff_upload(dev, &effect, file); | 640 | error = input_ff_upload(dev, &effect, file); |
483 | 641 | ||
484 | if (put_user(effect.id, &(((struct ff_effect __user *)p)->id))) | 642 | if (put_user(effect.id, &(((struct ff_effect __user *)p)->id))) |
485 | return -EFAULT; | 643 | return -EFAULT; |
486 | 644 | ||
487 | return error; | 645 | return error; |
488 | 646 | ||
489 | case EVIOCRMFF: | 647 | case EVIOCRMFF: |
490 | return input_ff_erase(dev, (int)(unsigned long) p, file); | 648 | return input_ff_erase(dev, (int)(unsigned long) p, file); |
491 | 649 | ||
492 | case EVIOCGEFFECTS: | 650 | case EVIOCGEFFECTS: |
493 | i = test_bit(EV_FF, dev->evbit) ? dev->ff->max_effects : 0; | 651 | i = test_bit(EV_FF, dev->evbit) ? |
494 | if (put_user(i, ip)) | 652 | dev->ff->max_effects : 0; |
495 | return -EFAULT; | 653 | if (put_user(i, ip)) |
496 | return 0; | 654 | return -EFAULT; |
497 | 655 | return 0; | |
498 | case EVIOCGRAB: | 656 | |
499 | if (p) { | 657 | case EVIOCGRAB: |
500 | if (evdev->grab) | 658 | if (p) |
501 | return -EBUSY; | 659 | return evdev_grab(evdev, client); |
502 | if (input_grab_device(&evdev->handle)) | 660 | else |
503 | return -EBUSY; | 661 | return evdev_ungrab(evdev, client); |
504 | evdev->grab = client; | ||
505 | return 0; | ||
506 | } else { | ||
507 | if (evdev->grab != client) | ||
508 | return -EINVAL; | ||
509 | input_release_device(&evdev->handle); | ||
510 | evdev->grab = NULL; | ||
511 | return 0; | ||
512 | } | ||
513 | 662 | ||
514 | default: | 663 | default: |
515 | 664 | ||
516 | if (_IOC_TYPE(cmd) != 'E') | 665 | if (_IOC_TYPE(cmd) != 'E') |
517 | return -EINVAL; | 666 | return -EINVAL; |
518 | 667 | ||
519 | if (_IOC_DIR(cmd) == _IOC_READ) { | 668 | if (_IOC_DIR(cmd) == _IOC_READ) { |
520 | 669 | ||
521 | if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) { | 670 | if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0))) { |
522 | 671 | ||
523 | unsigned long *bits; | 672 | unsigned long *bits; |
524 | int len; | 673 | int len; |
525 | 674 | ||
526 | switch (_IOC_NR(cmd) & EV_MAX) { | 675 | switch (_IOC_NR(cmd) & EV_MAX) { |
527 | case 0: bits = dev->evbit; len = EV_MAX; break; | ||
528 | case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; | ||
529 | case EV_REL: bits = dev->relbit; len = REL_MAX; break; | ||
530 | case EV_ABS: bits = dev->absbit; len = ABS_MAX; break; | ||
531 | case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break; | ||
532 | case EV_LED: bits = dev->ledbit; len = LED_MAX; break; | ||
533 | case EV_SND: bits = dev->sndbit; len = SND_MAX; break; | ||
534 | case EV_FF: bits = dev->ffbit; len = FF_MAX; break; | ||
535 | case EV_SW: bits = dev->swbit; len = SW_MAX; break; | ||
536 | default: return -EINVAL; | ||
537 | } | ||
538 | return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode); | ||
539 | } | ||
540 | 676 | ||
541 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) | 677 | case 0: bits = dev->evbit; len = EV_MAX; break; |
542 | return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd), | 678 | case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; |
543 | p, compat_mode); | 679 | case EV_REL: bits = dev->relbit; len = REL_MAX; break; |
680 | case EV_ABS: bits = dev->absbit; len = ABS_MAX; break; | ||
681 | case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break; | ||
682 | case EV_LED: bits = dev->ledbit; len = LED_MAX; break; | ||
683 | case EV_SND: bits = dev->sndbit; len = SND_MAX; break; | ||
684 | case EV_FF: bits = dev->ffbit; len = FF_MAX; break; | ||
685 | case EV_SW: bits = dev->swbit; len = SW_MAX; break; | ||
686 | default: return -EINVAL; | ||
687 | } | ||
688 | return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode); | ||
689 | } | ||
544 | 690 | ||
545 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) | 691 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) |
546 | return bits_to_user(dev->led, LED_MAX, _IOC_SIZE(cmd), | 692 | return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd), |
547 | p, compat_mode); | 693 | p, compat_mode); |
548 | 694 | ||
549 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) | 695 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) |
550 | return bits_to_user(dev->snd, SND_MAX, _IOC_SIZE(cmd), | 696 | return bits_to_user(dev->led, LED_MAX, _IOC_SIZE(cmd), |
551 | p, compat_mode); | 697 | p, compat_mode); |
552 | 698 | ||
553 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0))) | 699 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) |
554 | return bits_to_user(dev->sw, SW_MAX, _IOC_SIZE(cmd), | 700 | return bits_to_user(dev->snd, SND_MAX, _IOC_SIZE(cmd), |
555 | p, compat_mode); | 701 | p, compat_mode); |
556 | 702 | ||
557 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) | 703 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0))) |
558 | return str_to_user(dev->name, _IOC_SIZE(cmd), p); | 704 | return bits_to_user(dev->sw, SW_MAX, _IOC_SIZE(cmd), |
705 | p, compat_mode); | ||
559 | 706 | ||
560 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) | 707 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) |
561 | return str_to_user(dev->phys, _IOC_SIZE(cmd), p); | 708 | return str_to_user(dev->name, _IOC_SIZE(cmd), p); |
562 | 709 | ||
563 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) | 710 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) |
564 | return str_to_user(dev->uniq, _IOC_SIZE(cmd), p); | 711 | return str_to_user(dev->phys, _IOC_SIZE(cmd), p); |
565 | 712 | ||
566 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { | 713 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) |
714 | return str_to_user(dev->uniq, _IOC_SIZE(cmd), p); | ||
567 | 715 | ||
568 | t = _IOC_NR(cmd) & ABS_MAX; | 716 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { |
569 | 717 | ||
570 | abs.value = dev->abs[t]; | 718 | t = _IOC_NR(cmd) & ABS_MAX; |
571 | abs.minimum = dev->absmin[t]; | ||
572 | abs.maximum = dev->absmax[t]; | ||
573 | abs.fuzz = dev->absfuzz[t]; | ||
574 | abs.flat = dev->absflat[t]; | ||
575 | 719 | ||
576 | if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) | 720 | abs.value = dev->abs[t]; |
577 | return -EFAULT; | 721 | abs.minimum = dev->absmin[t]; |
722 | abs.maximum = dev->absmax[t]; | ||
723 | abs.fuzz = dev->absfuzz[t]; | ||
724 | abs.flat = dev->absflat[t]; | ||
578 | 725 | ||
579 | return 0; | 726 | if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) |
580 | } | 727 | return -EFAULT; |
581 | 728 | ||
729 | return 0; | ||
582 | } | 730 | } |
583 | 731 | ||
584 | if (_IOC_DIR(cmd) == _IOC_WRITE) { | 732 | } |
733 | |||
734 | if (_IOC_DIR(cmd) == _IOC_WRITE) { | ||
585 | 735 | ||
586 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { | 736 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { |
587 | 737 | ||
588 | t = _IOC_NR(cmd) & ABS_MAX; | 738 | t = _IOC_NR(cmd) & ABS_MAX; |
589 | 739 | ||
590 | if (copy_from_user(&abs, p, sizeof(struct input_absinfo))) | 740 | if (copy_from_user(&abs, p, |
591 | return -EFAULT; | 741 | sizeof(struct input_absinfo))) |
742 | return -EFAULT; | ||
592 | 743 | ||
593 | dev->abs[t] = abs.value; | 744 | /* |
594 | dev->absmin[t] = abs.minimum; | 745 | * Take event lock to ensure that we are not |
595 | dev->absmax[t] = abs.maximum; | 746 | * changing device parameters in the middle |
596 | dev->absfuzz[t] = abs.fuzz; | 747 | * of event. |
597 | dev->absflat[t] = abs.flat; | 748 | */ |
749 | spin_lock_irq(&dev->event_lock); | ||
598 | 750 | ||
599 | return 0; | 751 | dev->abs[t] = abs.value; |
600 | } | 752 | dev->absmin[t] = abs.minimum; |
753 | dev->absmax[t] = abs.maximum; | ||
754 | dev->absfuzz[t] = abs.fuzz; | ||
755 | dev->absflat[t] = abs.flat; | ||
756 | |||
757 | spin_unlock_irq(&dev->event_lock); | ||
758 | |||
759 | return 0; | ||
601 | } | 760 | } |
761 | } | ||
602 | } | 762 | } |
603 | return -EINVAL; | 763 | return -EINVAL; |
604 | } | 764 | } |
605 | 765 | ||
766 | static long evdev_ioctl_handler(struct file *file, unsigned int cmd, | ||
767 | void __user *p, int compat_mode) | ||
768 | { | ||
769 | struct evdev_client *client = file->private_data; | ||
770 | struct evdev *evdev = client->evdev; | ||
771 | int retval; | ||
772 | |||
773 | retval = mutex_lock_interruptible(&evdev->mutex); | ||
774 | if (retval) | ||
775 | return retval; | ||
776 | |||
777 | if (!evdev->exist) { | ||
778 | retval = -ENODEV; | ||
779 | goto out; | ||
780 | } | ||
781 | |||
782 | retval = evdev_do_ioctl(file, cmd, p, compat_mode); | ||
783 | |||
784 | out: | ||
785 | mutex_unlock(&evdev->mutex); | ||
786 | return retval; | ||
787 | } | ||
788 | |||
606 | static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 789 | static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
607 | { | 790 | { |
608 | return evdev_ioctl_handler(file, cmd, (void __user *)arg, 0); | 791 | return evdev_ioctl_handler(file, cmd, (void __user *)arg, 0); |
609 | } | 792 | } |
610 | 793 | ||
611 | #ifdef CONFIG_COMPAT | 794 | #ifdef CONFIG_COMPAT |
612 | static long evdev_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) | 795 | static long evdev_ioctl_compat(struct file *file, |
796 | unsigned int cmd, unsigned long arg) | ||
613 | { | 797 | { |
614 | return evdev_ioctl_handler(file, cmd, compat_ptr(arg), 1); | 798 | return evdev_ioctl_handler(file, cmd, compat_ptr(arg), 1); |
615 | } | 799 | } |
616 | #endif | 800 | #endif |
617 | 801 | ||
618 | static const struct file_operations evdev_fops = { | 802 | static const struct file_operations evdev_fops = { |
619 | .owner = THIS_MODULE, | 803 | .owner = THIS_MODULE, |
620 | .read = evdev_read, | 804 | .read = evdev_read, |
621 | .write = evdev_write, | 805 | .write = evdev_write, |
622 | .poll = evdev_poll, | 806 | .poll = evdev_poll, |
623 | .open = evdev_open, | 807 | .open = evdev_open, |
624 | .release = evdev_release, | 808 | .release = evdev_release, |
625 | .unlocked_ioctl = evdev_ioctl, | 809 | .unlocked_ioctl = evdev_ioctl, |
626 | #ifdef CONFIG_COMPAT | 810 | #ifdef CONFIG_COMPAT |
627 | .compat_ioctl = evdev_ioctl_compat, | 811 | .compat_ioctl = evdev_ioctl_compat, |
628 | #endif | 812 | #endif |
629 | .fasync = evdev_fasync, | 813 | .fasync = evdev_fasync, |
630 | .flush = evdev_flush | 814 | .flush = evdev_flush |
631 | }; | 815 | }; |
632 | 816 | ||
817 | static int evdev_install_chrdev(struct evdev *evdev) | ||
818 | { | ||
819 | /* | ||
820 | * No need to do any locking here as calls to connect and | ||
821 | * disconnect are serialized by the input core | ||
822 | */ | ||
823 | evdev_table[evdev->minor] = evdev; | ||
824 | return 0; | ||
825 | } | ||
826 | |||
827 | static void evdev_remove_chrdev(struct evdev *evdev) | ||
828 | { | ||
829 | /* | ||
830 | * Lock evdev table to prevent race with evdev_open() | ||
831 | */ | ||
832 | mutex_lock(&evdev_table_mutex); | ||
833 | evdev_table[evdev->minor] = NULL; | ||
834 | mutex_unlock(&evdev_table_mutex); | ||
835 | } | ||
836 | |||
837 | /* | ||
838 | * Mark device non-existent. This disables writes, ioctls and | ||
839 | * prevents new users from opening the device. Already posted | ||
840 | * blocking reads will stay, however new ones will fail. | ||
841 | */ | ||
842 | static void evdev_mark_dead(struct evdev *evdev) | ||
843 | { | ||
844 | mutex_lock(&evdev->mutex); | ||
845 | evdev->exist = 0; | ||
846 | mutex_unlock(&evdev->mutex); | ||
847 | } | ||
848 | |||
849 | static void evdev_cleanup(struct evdev *evdev) | ||
850 | { | ||
851 | struct input_handle *handle = &evdev->handle; | ||
852 | |||
853 | evdev_mark_dead(evdev); | ||
854 | evdev_hangup(evdev); | ||
855 | evdev_remove_chrdev(evdev); | ||
856 | |||
857 | /* evdev is marked dead so no one else accesses evdev->open */ | ||
858 | if (evdev->open) { | ||
859 | input_flush_device(handle, NULL); | ||
860 | input_close_device(handle); | ||
861 | } | ||
862 | } | ||
863 | |||
864 | /* | ||
865 | * Create new evdev device. Note that input core serializes calls | ||
866 | * to connect and disconnect so we don't need to lock evdev_table here. | ||
867 | */ | ||
633 | static int evdev_connect(struct input_handler *handler, struct input_dev *dev, | 868 | static int evdev_connect(struct input_handler *handler, struct input_dev *dev, |
634 | const struct input_device_id *id) | 869 | const struct input_device_id *id) |
635 | { | 870 | { |
@@ -637,7 +872,10 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, | |||
637 | int minor; | 872 | int minor; |
638 | int error; | 873 | int error; |
639 | 874 | ||
640 | for (minor = 0; minor < EVDEV_MINORS && evdev_table[minor]; minor++); | 875 | for (minor = 0; minor < EVDEV_MINORS; minor++) |
876 | if (!evdev_table[minor]) | ||
877 | break; | ||
878 | |||
641 | if (minor == EVDEV_MINORS) { | 879 | if (minor == EVDEV_MINORS) { |
642 | printk(KERN_ERR "evdev: no more free evdev devices\n"); | 880 | printk(KERN_ERR "evdev: no more free evdev devices\n"); |
643 | return -ENFILE; | 881 | return -ENFILE; |
@@ -648,38 +886,44 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, | |||
648 | return -ENOMEM; | 886 | return -ENOMEM; |
649 | 887 | ||
650 | INIT_LIST_HEAD(&evdev->client_list); | 888 | INIT_LIST_HEAD(&evdev->client_list); |
889 | spin_lock_init(&evdev->client_lock); | ||
890 | mutex_init(&evdev->mutex); | ||
651 | init_waitqueue_head(&evdev->wait); | 891 | init_waitqueue_head(&evdev->wait); |
652 | 892 | ||
893 | snprintf(evdev->name, sizeof(evdev->name), "event%d", minor); | ||
653 | evdev->exist = 1; | 894 | evdev->exist = 1; |
654 | evdev->minor = minor; | 895 | evdev->minor = minor; |
896 | |||
655 | evdev->handle.dev = dev; | 897 | evdev->handle.dev = dev; |
656 | evdev->handle.name = evdev->name; | 898 | evdev->handle.name = evdev->name; |
657 | evdev->handle.handler = handler; | 899 | evdev->handle.handler = handler; |
658 | evdev->handle.private = evdev; | 900 | evdev->handle.private = evdev; |
659 | snprintf(evdev->name, sizeof(evdev->name), "event%d", minor); | ||
660 | 901 | ||
661 | snprintf(evdev->dev.bus_id, sizeof(evdev->dev.bus_id), | 902 | strlcpy(evdev->dev.bus_id, evdev->name, sizeof(evdev->dev.bus_id)); |
662 | "event%d", minor); | 903 | evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor); |
663 | evdev->dev.class = &input_class; | 904 | evdev->dev.class = &input_class; |
664 | evdev->dev.parent = &dev->dev; | 905 | evdev->dev.parent = &dev->dev; |
665 | evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor); | ||
666 | evdev->dev.release = evdev_free; | 906 | evdev->dev.release = evdev_free; |
667 | device_initialize(&evdev->dev); | 907 | device_initialize(&evdev->dev); |
668 | 908 | ||
669 | evdev_table[minor] = evdev; | 909 | error = input_register_handle(&evdev->handle); |
670 | |||
671 | error = device_add(&evdev->dev); | ||
672 | if (error) | 910 | if (error) |
673 | goto err_free_evdev; | 911 | goto err_free_evdev; |
674 | 912 | ||
675 | error = input_register_handle(&evdev->handle); | 913 | error = evdev_install_chrdev(evdev); |
914 | if (error) | ||
915 | goto err_unregister_handle; | ||
916 | |||
917 | error = device_add(&evdev->dev); | ||
676 | if (error) | 918 | if (error) |
677 | goto err_delete_evdev; | 919 | goto err_cleanup_evdev; |
678 | 920 | ||
679 | return 0; | 921 | return 0; |
680 | 922 | ||
681 | err_delete_evdev: | 923 | err_cleanup_evdev: |
682 | device_del(&evdev->dev); | 924 | evdev_cleanup(evdev); |
925 | err_unregister_handle: | ||
926 | input_unregister_handle(&evdev->handle); | ||
683 | err_free_evdev: | 927 | err_free_evdev: |
684 | put_device(&evdev->dev); | 928 | put_device(&evdev->dev); |
685 | return error; | 929 | return error; |
@@ -688,21 +932,10 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, | |||
688 | static void evdev_disconnect(struct input_handle *handle) | 932 | static void evdev_disconnect(struct input_handle *handle) |
689 | { | 933 | { |
690 | struct evdev *evdev = handle->private; | 934 | struct evdev *evdev = handle->private; |
691 | struct evdev_client *client; | ||
692 | 935 | ||
693 | input_unregister_handle(handle); | ||
694 | device_del(&evdev->dev); | 936 | device_del(&evdev->dev); |
695 | 937 | evdev_cleanup(evdev); | |
696 | evdev->exist = 0; | 938 | input_unregister_handle(handle); |
697 | |||
698 | if (evdev->open) { | ||
699 | input_flush_device(handle, NULL); | ||
700 | input_close_device(handle); | ||
701 | list_for_each_entry(client, &evdev->client_list, node) | ||
702 | kill_fasync(&client->fasync, SIGIO, POLL_HUP); | ||
703 | wake_up_interruptible(&evdev->wait); | ||
704 | } | ||
705 | |||
706 | put_device(&evdev->dev); | 939 | put_device(&evdev->dev); |
707 | } | 940 | } |
708 | 941 | ||
@@ -714,13 +947,13 @@ static const struct input_device_id evdev_ids[] = { | |||
714 | MODULE_DEVICE_TABLE(input, evdev_ids); | 947 | MODULE_DEVICE_TABLE(input, evdev_ids); |
715 | 948 | ||
716 | static struct input_handler evdev_handler = { | 949 | static struct input_handler evdev_handler = { |
717 | .event = evdev_event, | 950 | .event = evdev_event, |
718 | .connect = evdev_connect, | 951 | .connect = evdev_connect, |
719 | .disconnect = evdev_disconnect, | 952 | .disconnect = evdev_disconnect, |
720 | .fops = &evdev_fops, | 953 | .fops = &evdev_fops, |
721 | .minor = EVDEV_MINOR_BASE, | 954 | .minor = EVDEV_MINOR_BASE, |
722 | .name = "evdev", | 955 | .name = "evdev", |
723 | .id_table = evdev_ids, | 956 | .id_table = evdev_ids, |
724 | }; | 957 | }; |
725 | 958 | ||
726 | static int __init evdev_init(void) | 959 | static int __init evdev_init(void) |