Commit 6addb1d6de1968b84852f54561cc9a999909b5a9
1 parent
8006479c9b
Input: evdev - implement proper locking
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Showing 1 changed file with 473 additions and 240 deletions Side-by-side Diff
drivers/input/evdev.c
Changes suppressed. Click to show
... | ... | @@ -30,6 +30,8 @@ |
30 | 30 | wait_queue_head_t wait; |
31 | 31 | struct evdev_client *grab; |
32 | 32 | struct list_head client_list; |
33 | + spinlock_t client_lock; /* protects client_list */ | |
34 | + struct mutex mutex; | |
33 | 35 | struct device dev; |
34 | 36 | }; |
35 | 37 | |
36 | 38 | |
37 | 39 | |
38 | 40 | |
39 | 41 | |
40 | 42 | |
41 | 43 | |
42 | 44 | |
... | ... | @@ -37,40 +39,54 @@ |
37 | 39 | struct input_event buffer[EVDEV_BUFFER_SIZE]; |
38 | 40 | int head; |
39 | 41 | int tail; |
42 | + spinlock_t buffer_lock; /* protects access to buffer, head and tail */ | |
40 | 43 | struct fasync_struct *fasync; |
41 | 44 | struct evdev *evdev; |
42 | 45 | struct list_head node; |
43 | 46 | }; |
44 | 47 | |
45 | 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) | |
48 | 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) | |
73 | +{ | |
49 | 74 | struct evdev *evdev = handle->private; |
50 | 75 | struct evdev_client *client; |
76 | + struct input_event event; | |
51 | 77 | |
52 | - if (evdev->grab) { | |
53 | - client = evdev->grab; | |
78 | + do_gettimeofday(&event.time); | |
79 | + event.type = type; | |
80 | + event.code = code; | |
81 | + event.value = value; | |
54 | 82 | |
55 | - do_gettimeofday(&client->buffer[client->head].time); | |
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); | |
83 | + client = rcu_dereference(evdev->grab); | |
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); | |
60 | 89 | |
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 | - | |
71 | - kill_fasync(&client->fasync, SIGIO, POLL_IN); | |
72 | - } | |
73 | - | |
74 | 90 | wake_up_interruptible(&evdev->wait); |
75 | 91 | } |
76 | 92 | |
77 | 93 | |
78 | 94 | |
79 | 95 | |
80 | 96 | |
81 | 97 | |
82 | 98 | |
83 | 99 | |
84 | 100 | |
... | ... | @@ -88,38 +104,142 @@ |
88 | 104 | { |
89 | 105 | struct evdev_client *client = file->private_data; |
90 | 106 | struct evdev *evdev = client->evdev; |
107 | + int retval; | |
91 | 108 | |
109 | + retval = mutex_lock_interruptible(&evdev->mutex); | |
110 | + if (retval) | |
111 | + return retval; | |
112 | + | |
92 | 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 | 122 | static void evdev_free(struct device *dev) |
99 | 123 | { |
100 | 124 | struct evdev *evdev = container_of(dev, struct evdev, dev); |
101 | 125 | |
102 | - evdev_table[evdev->minor] = NULL; | |
103 | 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 | 228 | static int evdev_release(struct inode *inode, struct file *file) |
107 | 229 | { |
108 | 230 | struct evdev_client *client = file->private_data; |
109 | 231 | struct evdev *evdev = client->evdev; |
110 | 232 | |
111 | - if (evdev->grab == client) { | |
112 | - input_release_device(&evdev->handle); | |
113 | - evdev->grab = NULL; | |
114 | - } | |
233 | + mutex_lock(&evdev->mutex); | |
234 | + if (evdev->grab == client) | |
235 | + evdev_ungrab(evdev, client); | |
236 | + mutex_unlock(&evdev->mutex); | |
115 | 237 | |
116 | 238 | evdev_fasync(-1, file, 0); |
117 | - list_del(&client->node); | |
239 | + evdev_detach_client(evdev, client); | |
118 | 240 | kfree(client); |
119 | 241 | |
120 | - if (!--evdev->open && evdev->exist) | |
121 | - input_close_device(&evdev->handle); | |
122 | - | |
242 | + evdev_close_device(evdev); | |
123 | 243 | put_device(&evdev->dev); |
124 | 244 | |
125 | 245 | return 0; |
126 | 246 | |
127 | 247 | |
128 | 248 | |
129 | 249 | |
130 | 250 | |
131 | 251 | |
132 | 252 | |
133 | 253 | |
134 | 254 | |
... | ... | @@ -127,41 +247,44 @@ |
127 | 247 | |
128 | 248 | static int evdev_open(struct inode *inode, struct file *file) |
129 | 249 | { |
130 | - struct evdev_client *client; | |
131 | 250 | struct evdev *evdev; |
251 | + struct evdev_client *client; | |
132 | 252 | int i = iminor(inode) - EVDEV_MINOR_BASE; |
133 | 253 | int error; |
134 | 254 | |
135 | 255 | if (i >= EVDEV_MINORS) |
136 | 256 | return -ENODEV; |
137 | 257 | |
258 | + error = mutex_lock_interruptible(&evdev_table_mutex); | |
259 | + if (error) | |
260 | + return error; | |
138 | 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 | 267 | return -ENODEV; |
142 | 268 | |
143 | - get_device(&evdev->dev); | |
144 | - | |
145 | 269 | client = kzalloc(sizeof(struct evdev_client), GFP_KERNEL); |
146 | 270 | if (!client) { |
147 | 271 | error = -ENOMEM; |
148 | 272 | goto err_put_evdev; |
149 | 273 | } |
150 | 274 | |
275 | + spin_lock_init(&client->buffer_lock); | |
151 | 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) { | |
155 | - error = input_open_device(&evdev->handle); | |
156 | - if (error) | |
157 | - goto err_free_client; | |
158 | - } | |
279 | + error = evdev_open_device(evdev); | |
280 | + if (error) | |
281 | + goto err_free_client; | |
159 | 282 | |
160 | 283 | file->private_data = client; |
161 | 284 | return 0; |
162 | 285 | |
163 | 286 | err_free_client: |
164 | - list_del(&client->node); | |
287 | + evdev_detach_client(evdev, client); | |
165 | 288 | kfree(client); |
166 | 289 | err_put_evdev: |
167 | 290 | put_device(&evdev->dev); |
168 | 291 | |
... | ... | @@ -197,12 +320,14 @@ |
197 | 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 | 326 | if (COMPAT_TEST) { |
203 | 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 | 331 | return -EFAULT; |
207 | 332 | |
208 | 333 | event->time.tv_sec = compat_event.time.tv_sec; |
... | ... | @@ -219,7 +344,8 @@ |
219 | 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 | 350 | if (COMPAT_TEST) { |
225 | 351 | struct input_event_compat compat_event; |
... | ... | @@ -230,7 +356,8 @@ |
230 | 356 | compat_event.code = event->code; |
231 | 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 | 361 | return -EFAULT; |
235 | 362 | |
236 | 363 | } else { |
... | ... | @@ -248,7 +375,8 @@ |
248 | 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 | 381 | if (copy_from_user(event, buffer, sizeof(struct input_event))) |
254 | 382 | return -EFAULT; |
... | ... | @@ -256,7 +384,8 @@ |
256 | 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 | 390 | if (copy_to_user(buffer, event, sizeof(struct input_event))) |
262 | 391 | return -EFAULT; |
263 | 392 | |
264 | 393 | |
265 | 394 | |
266 | 395 | |
267 | 396 | |
268 | 397 | |
269 | 398 | |
270 | 399 | |
271 | 400 | |
... | ... | @@ -266,37 +395,71 @@ |
266 | 395 | |
267 | 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 | 401 | struct evdev_client *client = file->private_data; |
272 | 402 | struct evdev *evdev = client->evdev; |
273 | 403 | struct input_event event; |
274 | - int retval = 0; | |
404 | + int retval; | |
275 | 405 | |
276 | - if (!evdev->exist) | |
277 | - return -ENODEV; | |
406 | + retval = mutex_lock_interruptible(&evdev->mutex); | |
407 | + if (retval) | |
408 | + return retval; | |
278 | 409 | |
410 | + if (!evdev->exist) { | |
411 | + retval = -ENODEV; | |
412 | + goto out; | |
413 | + } | |
414 | + | |
279 | 415 | while (retval < count) { |
280 | 416 | |
281 | - if (evdev_event_from_user(buffer + retval, &event)) | |
282 | - return -EFAULT; | |
283 | - input_inject_event(&evdev->handle, event.type, event.code, event.value); | |
417 | + if (evdev_event_from_user(buffer + retval, &event)) { | |
418 | + retval = -EFAULT; | |
419 | + goto out; | |
420 | + } | |
421 | + | |
422 | + input_inject_event(&evdev->handle, | |
423 | + event.type, event.code, event.value); | |
284 | 424 | retval += evdev_event_size(); |
285 | 425 | } |
286 | 426 | |
427 | + out: | |
428 | + mutex_unlock(&evdev->mutex); | |
287 | 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) | |
291 | 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) | |
452 | +{ | |
292 | 453 | struct evdev_client *client = file->private_data; |
293 | 454 | struct evdev *evdev = client->evdev; |
455 | + struct input_event event; | |
294 | 456 | int retval; |
295 | 457 | |
296 | 458 | if (count < evdev_event_size()) |
297 | 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 | 463 | return -EAGAIN; |
301 | 464 | |
302 | 465 | retval = wait_event_interruptible(evdev->wait, |
303 | 466 | |
304 | 467 | |
... | ... | @@ -307,14 +470,12 @@ |
307 | 470 | if (!evdev->exist) |
308 | 471 | return -ENODEV; |
309 | 472 | |
310 | - while (client->head != client->tail && retval + evdev_event_size() <= count) { | |
473 | + while (retval + evdev_event_size() <= count && | |
474 | + evdev_fetch_next_event(client, &event)) { | |
311 | 475 | |
312 | - struct input_event *event = (struct input_event *) client->buffer + client->tail; | |
313 | - | |
314 | - if (evdev_event_to_user(buffer + retval, event)) | |
476 | + if (evdev_event_to_user(buffer + retval, &event)) | |
315 | 477 | return -EFAULT; |
316 | 478 | |
317 | - client->tail = (client->tail + 1) & (EVDEV_BUFFER_SIZE - 1); | |
318 | 479 | retval += evdev_event_size(); |
319 | 480 | } |
320 | 481 | |
... | ... | @@ -409,8 +570,8 @@ |
409 | 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, | |
413 | - void __user *p, int compat_mode) | |
573 | +static long evdev_do_ioctl(struct file *file, unsigned int cmd, | |
574 | + void __user *p, int compat_mode) | |
414 | 575 | { |
415 | 576 | struct evdev_client *client = file->private_data; |
416 | 577 | struct evdev *evdev = client->evdev; |
417 | 578 | |
418 | 579 | |
419 | 580 | |
420 | 581 | |
421 | 582 | |
422 | 583 | |
423 | 584 | |
424 | 585 | |
425 | 586 | |
426 | 587 | |
427 | 588 | |
428 | 589 | |
429 | 590 | |
430 | 591 | |
431 | 592 | |
432 | 593 | |
433 | 594 | |
434 | 595 | |
435 | 596 | |
436 | 597 | |
437 | 598 | |
438 | 599 | |
439 | 600 | |
440 | 601 | |
441 | 602 | |
442 | 603 | |
443 | 604 | |
444 | 605 | |
445 | 606 | |
446 | 607 | |
447 | 608 | |
448 | 609 | |
449 | 610 | |
450 | 611 | |
451 | 612 | |
452 | 613 | |
453 | 614 | |
454 | 615 | |
455 | 616 | |
456 | 617 | |
457 | 618 | |
458 | 619 | |
459 | 620 | |
460 | 621 | |
461 | 622 | |
462 | 623 | |
463 | 624 | |
464 | 625 | |
465 | 626 | |
466 | 627 | |
467 | 628 | |
... | ... | @@ -421,215 +582,289 @@ |
421 | 582 | int i, t, u, v; |
422 | 583 | int error; |
423 | 584 | |
424 | - if (!evdev->exist) | |
425 | - return -ENODEV; | |
426 | - | |
427 | 585 | switch (cmd) { |
428 | 586 | |
429 | - case EVIOCGVERSION: | |
430 | - return put_user(EV_VERSION, ip); | |
587 | + case EVIOCGVERSION: | |
588 | + return put_user(EV_VERSION, ip); | |
431 | 589 | |
432 | - case EVIOCGID: | |
433 | - if (copy_to_user(p, &dev->id, sizeof(struct input_id))) | |
434 | - return -EFAULT; | |
435 | - return 0; | |
590 | + case EVIOCGID: | |
591 | + if (copy_to_user(p, &dev->id, sizeof(struct input_id))) | |
592 | + return -EFAULT; | |
593 | + return 0; | |
436 | 594 | |
437 | - case EVIOCGREP: | |
438 | - if (!test_bit(EV_REP, dev->evbit)) | |
439 | - return -ENOSYS; | |
440 | - if (put_user(dev->rep[REP_DELAY], ip)) | |
441 | - return -EFAULT; | |
442 | - if (put_user(dev->rep[REP_PERIOD], ip + 1)) | |
443 | - return -EFAULT; | |
444 | - return 0; | |
595 | + case EVIOCGREP: | |
596 | + if (!test_bit(EV_REP, dev->evbit)) | |
597 | + return -ENOSYS; | |
598 | + if (put_user(dev->rep[REP_DELAY], ip)) | |
599 | + return -EFAULT; | |
600 | + if (put_user(dev->rep[REP_PERIOD], ip + 1)) | |
601 | + return -EFAULT; | |
602 | + return 0; | |
445 | 603 | |
446 | - case EVIOCSREP: | |
447 | - if (!test_bit(EV_REP, dev->evbit)) | |
448 | - return -ENOSYS; | |
449 | - if (get_user(u, ip)) | |
450 | - return -EFAULT; | |
451 | - if (get_user(v, ip + 1)) | |
452 | - return -EFAULT; | |
604 | + case EVIOCSREP: | |
605 | + if (!test_bit(EV_REP, dev->evbit)) | |
606 | + return -ENOSYS; | |
607 | + if (get_user(u, ip)) | |
608 | + return -EFAULT; | |
609 | + if (get_user(v, ip + 1)) | |
610 | + return -EFAULT; | |
453 | 611 | |
454 | - input_inject_event(&evdev->handle, EV_REP, REP_DELAY, u); | |
455 | - input_inject_event(&evdev->handle, EV_REP, REP_PERIOD, v); | |
612 | + input_inject_event(&evdev->handle, EV_REP, REP_DELAY, u); | |
613 | + input_inject_event(&evdev->handle, EV_REP, REP_PERIOD, v); | |
456 | 614 | |
457 | - return 0; | |
615 | + return 0; | |
458 | 616 | |
459 | - case EVIOCGKEYCODE: | |
460 | - if (get_user(t, ip)) | |
461 | - return -EFAULT; | |
617 | + case EVIOCGKEYCODE: | |
618 | + if (get_user(t, ip)) | |
619 | + return -EFAULT; | |
462 | 620 | |
463 | - error = dev->getkeycode(dev, t, &v); | |
464 | - if (error) | |
465 | - return error; | |
621 | + error = dev->getkeycode(dev, t, &v); | |
622 | + if (error) | |
623 | + return error; | |
466 | 624 | |
467 | - if (put_user(v, ip + 1)) | |
468 | - return -EFAULT; | |
625 | + if (put_user(v, ip + 1)) | |
626 | + return -EFAULT; | |
469 | 627 | |
470 | - return 0; | |
628 | + return 0; | |
471 | 629 | |
472 | - case EVIOCSKEYCODE: | |
473 | - if (get_user(t, ip) || get_user(v, ip + 1)) | |
474 | - return -EFAULT; | |
630 | + case EVIOCSKEYCODE: | |
631 | + if (get_user(t, ip) || get_user(v, ip + 1)) | |
632 | + return -EFAULT; | |
475 | 633 | |
476 | - return dev->setkeycode(dev, t, v); | |
634 | + return dev->setkeycode(dev, t, v); | |
477 | 635 | |
478 | - case EVIOCSFF: | |
479 | - if (copy_from_user(&effect, p, sizeof(effect))) | |
480 | - return -EFAULT; | |
636 | + case EVIOCSFF: | |
637 | + if (copy_from_user(&effect, p, sizeof(effect))) | |
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))) | |
485 | - return -EFAULT; | |
642 | + if (put_user(effect.id, &(((struct ff_effect __user *)p)->id))) | |
643 | + return -EFAULT; | |
486 | 644 | |
487 | - return error; | |
645 | + return error; | |
488 | 646 | |
489 | - case EVIOCRMFF: | |
490 | - return input_ff_erase(dev, (int)(unsigned long) p, file); | |
647 | + case EVIOCRMFF: | |
648 | + return input_ff_erase(dev, (int)(unsigned long) p, file); | |
491 | 649 | |
492 | - case EVIOCGEFFECTS: | |
493 | - i = test_bit(EV_FF, dev->evbit) ? dev->ff->max_effects : 0; | |
494 | - if (put_user(i, ip)) | |
495 | - return -EFAULT; | |
496 | - return 0; | |
650 | + case EVIOCGEFFECTS: | |
651 | + i = test_bit(EV_FF, dev->evbit) ? | |
652 | + dev->ff->max_effects : 0; | |
653 | + if (put_user(i, ip)) | |
654 | + return -EFAULT; | |
655 | + return 0; | |
497 | 656 | |
498 | - case EVIOCGRAB: | |
499 | - if (p) { | |
500 | - if (evdev->grab) | |
501 | - return -EBUSY; | |
502 | - if (input_grab_device(&evdev->handle)) | |
503 | - return -EBUSY; | |
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 | - } | |
657 | + case EVIOCGRAB: | |
658 | + if (p) | |
659 | + return evdev_grab(evdev, client); | |
660 | + else | |
661 | + return evdev_ungrab(evdev, client); | |
513 | 662 | |
514 | - default: | |
663 | + default: | |
515 | 664 | |
516 | - if (_IOC_TYPE(cmd) != 'E') | |
517 | - return -EINVAL; | |
665 | + if (_IOC_TYPE(cmd) != 'E') | |
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; | |
524 | - int len; | |
672 | + unsigned long *bits; | |
673 | + int len; | |
525 | 674 | |
526 | - 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 | - } | |
675 | + switch (_IOC_NR(cmd) & EV_MAX) { | |
540 | 676 | |
541 | - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) | |
542 | - return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd), | |
543 | - p, compat_mode); | |
677 | + case 0: bits = dev->evbit; len = EV_MAX; break; | |
678 | + case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; | |
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))) | |
546 | - return bits_to_user(dev->led, LED_MAX, _IOC_SIZE(cmd), | |
547 | - p, compat_mode); | |
691 | + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) | |
692 | + return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd), | |
693 | + p, compat_mode); | |
548 | 694 | |
549 | - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) | |
550 | - return bits_to_user(dev->snd, SND_MAX, _IOC_SIZE(cmd), | |
551 | - p, compat_mode); | |
695 | + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) | |
696 | + return bits_to_user(dev->led, LED_MAX, _IOC_SIZE(cmd), | |
697 | + p, compat_mode); | |
552 | 698 | |
553 | - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0))) | |
554 | - return bits_to_user(dev->sw, SW_MAX, _IOC_SIZE(cmd), | |
555 | - p, compat_mode); | |
699 | + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) | |
700 | + return bits_to_user(dev->snd, SND_MAX, _IOC_SIZE(cmd), | |
701 | + p, compat_mode); | |
556 | 702 | |
557 | - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) | |
558 | - return str_to_user(dev->name, _IOC_SIZE(cmd), p); | |
703 | + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0))) | |
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))) | |
561 | - return str_to_user(dev->phys, _IOC_SIZE(cmd), p); | |
707 | + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) | |
708 | + return str_to_user(dev->name, _IOC_SIZE(cmd), p); | |
562 | 709 | |
563 | - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) | |
564 | - return str_to_user(dev->uniq, _IOC_SIZE(cmd), p); | |
710 | + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) | |
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]; | |
571 | - abs.minimum = dev->absmin[t]; | |
572 | - abs.maximum = dev->absmax[t]; | |
573 | - abs.fuzz = dev->absfuzz[t]; | |
574 | - abs.flat = dev->absflat[t]; | |
718 | + t = _IOC_NR(cmd) & ABS_MAX; | |
575 | 719 | |
576 | - if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) | |
577 | - return -EFAULT; | |
720 | + abs.value = dev->abs[t]; | |
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; | |
580 | - } | |
726 | + if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) | |
727 | + return -EFAULT; | |
581 | 728 | |
729 | + return 0; | |
582 | 730 | } |
583 | 731 | |
584 | - if (_IOC_DIR(cmd) == _IOC_WRITE) { | |
732 | + } | |
585 | 733 | |
586 | - if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { | |
734 | + if (_IOC_DIR(cmd) == _IOC_WRITE) { | |
587 | 735 | |
588 | - t = _IOC_NR(cmd) & ABS_MAX; | |
736 | + if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { | |
589 | 737 | |
590 | - if (copy_from_user(&abs, p, sizeof(struct input_absinfo))) | |
591 | - return -EFAULT; | |
738 | + t = _IOC_NR(cmd) & ABS_MAX; | |
592 | 739 | |
593 | - dev->abs[t] = abs.value; | |
594 | - dev->absmin[t] = abs.minimum; | |
595 | - dev->absmax[t] = abs.maximum; | |
596 | - dev->absfuzz[t] = abs.fuzz; | |
597 | - dev->absflat[t] = abs.flat; | |
740 | + if (copy_from_user(&abs, p, | |
741 | + sizeof(struct input_absinfo))) | |
742 | + return -EFAULT; | |
598 | 743 | |
599 | - return 0; | |
600 | - } | |
744 | + /* | |
745 | + * Take event lock to ensure that we are not | |
746 | + * changing device parameters in the middle | |
747 | + * of event. | |
748 | + */ | |
749 | + spin_lock_irq(&dev->event_lock); | |
750 | + | |
751 | + dev->abs[t] = abs.value; | |
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 | 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 | 789 | static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
607 | 790 | { |
608 | 791 | return evdev_ioctl_handler(file, cmd, (void __user *)arg, 0); |
609 | 792 | } |
610 | 793 | |
611 | 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 | 798 | return evdev_ioctl_handler(file, cmd, compat_ptr(arg), 1); |
615 | 799 | } |
616 | 800 | #endif |
617 | 801 | |
618 | 802 | static const struct file_operations evdev_fops = { |
619 | - .owner = THIS_MODULE, | |
620 | - .read = evdev_read, | |
621 | - .write = evdev_write, | |
622 | - .poll = evdev_poll, | |
623 | - .open = evdev_open, | |
624 | - .release = evdev_release, | |
625 | - .unlocked_ioctl = evdev_ioctl, | |
803 | + .owner = THIS_MODULE, | |
804 | + .read = evdev_read, | |
805 | + .write = evdev_write, | |
806 | + .poll = evdev_poll, | |
807 | + .open = evdev_open, | |
808 | + .release = evdev_release, | |
809 | + .unlocked_ioctl = evdev_ioctl, | |
626 | 810 | #ifdef CONFIG_COMPAT |
627 | - .compat_ioctl = evdev_ioctl_compat, | |
811 | + .compat_ioctl = evdev_ioctl_compat, | |
628 | 812 | #endif |
629 | - .fasync = evdev_fasync, | |
630 | - .flush = evdev_flush | |
813 | + .fasync = evdev_fasync, | |
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 | 868 | static int evdev_connect(struct input_handler *handler, struct input_dev *dev, |
634 | 869 | const struct input_device_id *id) |
635 | 870 | { |
... | ... | @@ -637,7 +872,10 @@ |
637 | 872 | int minor; |
638 | 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 | 879 | if (minor == EVDEV_MINORS) { |
642 | 880 | printk(KERN_ERR "evdev: no more free evdev devices\n"); |
643 | 881 | return -ENFILE; |
644 | 882 | |
645 | 883 | |
646 | 884 | |
647 | 885 | |
648 | 886 | |
649 | 887 | |
650 | 888 | |
651 | 889 | |
652 | 890 | |
653 | 891 | |
... | ... | @@ -648,38 +886,44 @@ |
648 | 886 | return -ENOMEM; |
649 | 887 | |
650 | 888 | INIT_LIST_HEAD(&evdev->client_list); |
889 | + spin_lock_init(&evdev->client_lock); | |
890 | + mutex_init(&evdev->mutex); | |
651 | 891 | init_waitqueue_head(&evdev->wait); |
652 | 892 | |
893 | + snprintf(evdev->name, sizeof(evdev->name), "event%d", minor); | |
653 | 894 | evdev->exist = 1; |
654 | 895 | evdev->minor = minor; |
896 | + | |
655 | 897 | evdev->handle.dev = dev; |
656 | 898 | evdev->handle.name = evdev->name; |
657 | 899 | evdev->handle.handler = handler; |
658 | 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), | |
662 | - "event%d", minor); | |
902 | + strlcpy(evdev->dev.bus_id, evdev->name, sizeof(evdev->dev.bus_id)); | |
903 | + evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor); | |
663 | 904 | evdev->dev.class = &input_class; |
664 | 905 | evdev->dev.parent = &dev->dev; |
665 | - evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor); | |
666 | 906 | evdev->dev.release = evdev_free; |
667 | 907 | device_initialize(&evdev->dev); |
668 | 908 | |
669 | - evdev_table[minor] = evdev; | |
670 | - | |
671 | - error = device_add(&evdev->dev); | |
909 | + error = input_register_handle(&evdev->handle); | |
672 | 910 | if (error) |
673 | 911 | goto err_free_evdev; |
674 | 912 | |
675 | - error = input_register_handle(&evdev->handle); | |
913 | + error = evdev_install_chrdev(evdev); | |
676 | 914 | if (error) |
677 | - goto err_delete_evdev; | |
915 | + goto err_unregister_handle; | |
678 | 916 | |
917 | + error = device_add(&evdev->dev); | |
918 | + if (error) | |
919 | + goto err_cleanup_evdev; | |
920 | + | |
679 | 921 | return 0; |
680 | 922 | |
681 | - err_delete_evdev: | |
682 | - device_del(&evdev->dev); | |
923 | + err_cleanup_evdev: | |
924 | + evdev_cleanup(evdev); | |
925 | + err_unregister_handle: | |
926 | + input_unregister_handle(&evdev->handle); | |
683 | 927 | err_free_evdev: |
684 | 928 | put_device(&evdev->dev); |
685 | 929 | return error; |
686 | 930 | |
687 | 931 | |
... | ... | @@ -688,21 +932,10 @@ |
688 | 932 | static void evdev_disconnect(struct input_handle *handle) |
689 | 933 | { |
690 | 934 | struct evdev *evdev = handle->private; |
691 | - struct evdev_client *client; | |
692 | 935 | |
693 | - input_unregister_handle(handle); | |
694 | 936 | device_del(&evdev->dev); |
695 | - | |
696 | - evdev->exist = 0; | |
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 | - | |
937 | + evdev_cleanup(evdev); | |
938 | + input_unregister_handle(handle); | |
706 | 939 | put_device(&evdev->dev); |
707 | 940 | } |
708 | 941 | |
... | ... | @@ -714,13 +947,13 @@ |
714 | 947 | MODULE_DEVICE_TABLE(input, evdev_ids); |
715 | 948 | |
716 | 949 | static struct input_handler evdev_handler = { |
717 | - .event = evdev_event, | |
718 | - .connect = evdev_connect, | |
719 | - .disconnect = evdev_disconnect, | |
720 | - .fops = &evdev_fops, | |
721 | - .minor = EVDEV_MINOR_BASE, | |
722 | - .name = "evdev", | |
723 | - .id_table = evdev_ids, | |
950 | + .event = evdev_event, | |
951 | + .connect = evdev_connect, | |
952 | + .disconnect = evdev_disconnect, | |
953 | + .fops = &evdev_fops, | |
954 | + .minor = EVDEV_MINOR_BASE, | |
955 | + .name = "evdev", | |
956 | + .id_table = evdev_ids, | |
724 | 957 | }; |
725 | 958 | |
726 | 959 | static int __init evdev_init(void) |