Commit 464b241575f3700e14492e34f26bcd1794280f55

Authored by Dmitry Torokhov
1 parent 6addb1d6de

Input: mousedev - implement proper locking

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>

Showing 1 changed file with 470 additions and 272 deletions Side-by-side Diff

drivers/input/mousedev.c
Changes suppressed. Click to show
... ... @@ -61,9 +61,11 @@
61 61 int open;
62 62 int minor;
63 63 char name[16];
  64 + struct input_handle handle;
64 65 wait_queue_head_t wait;
65 66 struct list_head client_list;
66   - struct input_handle handle;
  67 + spinlock_t client_lock; /* protects client_list */
  68 + struct mutex mutex;
67 69 struct device dev;
68 70  
69 71 struct list_head mixdev_node;
70 72  
71 73  
72 74  
73 75  
74 76  
75 77  
76 78  
77 79  
78 80  
79 81  
80 82  
... ... @@ -113,108 +115,137 @@
113 115 static struct input_handler mousedev_handler;
114 116  
115 117 static struct mousedev *mousedev_table[MOUSEDEV_MINORS];
  118 +static DEFINE_MUTEX(mousedev_table_mutex);
116 119 static struct mousedev *mousedev_mix;
117 120 static LIST_HEAD(mousedev_mix_list);
118 121  
  122 +static void mixdev_open_devices(void);
  123 +static void mixdev_close_devices(void);
  124 +
119 125 #define fx(i) (mousedev->old_x[(mousedev->pkt_count - (i)) & 03])
120 126 #define fy(i) (mousedev->old_y[(mousedev->pkt_count - (i)) & 03])
121 127  
122   -static void mousedev_touchpad_event(struct input_dev *dev, struct mousedev *mousedev, unsigned int code, int value)
  128 +static void mousedev_touchpad_event(struct input_dev *dev,
  129 + struct mousedev *mousedev,
  130 + unsigned int code, int value)
123 131 {
124 132 int size, tmp;
125 133 enum { FRACTION_DENOM = 128 };
126 134  
127 135 switch (code) {
128   - case ABS_X:
129   - fx(0) = value;
130   - if (mousedev->touch && mousedev->pkt_count >= 2) {
131   - size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
132   - if (size == 0)
133   - size = 256 * 2;
134   - tmp = ((value - fx(2)) * (256 * FRACTION_DENOM)) / size;
135   - tmp += mousedev->frac_dx;
136   - mousedev->packet.dx = tmp / FRACTION_DENOM;
137   - mousedev->frac_dx = tmp - mousedev->packet.dx * FRACTION_DENOM;
138   - }
139   - break;
140 136  
141   - case ABS_Y:
142   - fy(0) = value;
143   - if (mousedev->touch && mousedev->pkt_count >= 2) {
144   - /* use X size to keep the same scale */
145   - size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
146   - if (size == 0)
147   - size = 256 * 2;
148   - tmp = -((value - fy(2)) * (256 * FRACTION_DENOM)) / size;
149   - tmp += mousedev->frac_dy;
150   - mousedev->packet.dy = tmp / FRACTION_DENOM;
151   - mousedev->frac_dy = tmp - mousedev->packet.dy * FRACTION_DENOM;
152   - }
153   - break;
  137 + case ABS_X:
  138 + fx(0) = value;
  139 + if (mousedev->touch && mousedev->pkt_count >= 2) {
  140 + size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
  141 + if (size == 0)
  142 + size = 256 * 2;
  143 + tmp = ((value - fx(2)) * 256 * FRACTION_DENOM) / size;
  144 + tmp += mousedev->frac_dx;
  145 + mousedev->packet.dx = tmp / FRACTION_DENOM;
  146 + mousedev->frac_dx =
  147 + tmp - mousedev->packet.dx * FRACTION_DENOM;
  148 + }
  149 + break;
  150 +
  151 + case ABS_Y:
  152 + fy(0) = value;
  153 + if (mousedev->touch && mousedev->pkt_count >= 2) {
  154 + /* use X size to keep the same scale */
  155 + size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
  156 + if (size == 0)
  157 + size = 256 * 2;
  158 + tmp = -((value - fy(2)) * 256 * FRACTION_DENOM) / size;
  159 + tmp += mousedev->frac_dy;
  160 + mousedev->packet.dy = tmp / FRACTION_DENOM;
  161 + mousedev->frac_dy = tmp -
  162 + mousedev->packet.dy * FRACTION_DENOM;
  163 + }
  164 + break;
154 165 }
155 166 }
156 167  
157   -static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev, unsigned int code, int value)
  168 +static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev,
  169 + unsigned int code, int value)
158 170 {
159 171 int size;
160 172  
161 173 switch (code) {
162   - case ABS_X:
163   - size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
164   - if (size == 0)
165   - size = xres ? : 1;
166   - if (value > dev->absmax[ABS_X])
167   - value = dev->absmax[ABS_X];
168   - if (value < dev->absmin[ABS_X])
169   - value = dev->absmin[ABS_X];
170   - mousedev->packet.x = ((value - dev->absmin[ABS_X]) * xres) / size;
171   - mousedev->packet.abs_event = 1;
172   - break;
173 174  
174   - case ABS_Y:
175   - size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y];
176   - if (size == 0)
177   - size = yres ? : 1;
178   - if (value > dev->absmax[ABS_Y])
179   - value = dev->absmax[ABS_Y];
180   - if (value < dev->absmin[ABS_Y])
181   - value = dev->absmin[ABS_Y];
182   - mousedev->packet.y = yres - ((value - dev->absmin[ABS_Y]) * yres) / size;
183   - mousedev->packet.abs_event = 1;
184   - break;
  175 + case ABS_X:
  176 + size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
  177 + if (size == 0)
  178 + size = xres ? : 1;
  179 + if (value > dev->absmax[ABS_X])
  180 + value = dev->absmax[ABS_X];
  181 + if (value < dev->absmin[ABS_X])
  182 + value = dev->absmin[ABS_X];
  183 + mousedev->packet.x =
  184 + ((value - dev->absmin[ABS_X]) * xres) / size;
  185 + mousedev->packet.abs_event = 1;
  186 + break;
  187 +
  188 + case ABS_Y:
  189 + size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y];
  190 + if (size == 0)
  191 + size = yres ? : 1;
  192 + if (value > dev->absmax[ABS_Y])
  193 + value = dev->absmax[ABS_Y];
  194 + if (value < dev->absmin[ABS_Y])
  195 + value = dev->absmin[ABS_Y];
  196 + mousedev->packet.y = yres -
  197 + ((value - dev->absmin[ABS_Y]) * yres) / size;
  198 + mousedev->packet.abs_event = 1;
  199 + break;
185 200 }
186 201 }
187 202  
188   -static void mousedev_rel_event(struct mousedev *mousedev, unsigned int code, int value)
  203 +static void mousedev_rel_event(struct mousedev *mousedev,
  204 + unsigned int code, int value)
189 205 {
190 206 switch (code) {
191   - case REL_X: mousedev->packet.dx += value; break;
192   - case REL_Y: mousedev->packet.dy -= value; break;
193   - case REL_WHEEL: mousedev->packet.dz -= value; break;
  207 + case REL_X:
  208 + mousedev->packet.dx += value;
  209 + break;
  210 +
  211 + case REL_Y:
  212 + mousedev->packet.dy -= value;
  213 + break;
  214 +
  215 + case REL_WHEEL:
  216 + mousedev->packet.dz -= value;
  217 + break;
194 218 }
195 219 }
196 220  
197   -static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int value)
  221 +static void mousedev_key_event(struct mousedev *mousedev,
  222 + unsigned int code, int value)
198 223 {
199 224 int index;
200 225  
201 226 switch (code) {
202   - case BTN_TOUCH:
203   - case BTN_0:
204   - case BTN_LEFT: index = 0; break;
205   - case BTN_STYLUS:
206   - case BTN_1:
207   - case BTN_RIGHT: index = 1; break;
208   - case BTN_2:
209   - case BTN_FORWARD:
210   - case BTN_STYLUS2:
211   - case BTN_MIDDLE: index = 2; break;
212   - case BTN_3:
213   - case BTN_BACK:
214   - case BTN_SIDE: index = 3; break;
215   - case BTN_4:
216   - case BTN_EXTRA: index = 4; break;
217   - default: return;
  227 +
  228 + case BTN_TOUCH:
  229 + case BTN_0:
  230 + case BTN_LEFT: index = 0; break;
  231 +
  232 + case BTN_STYLUS:
  233 + case BTN_1:
  234 + case BTN_RIGHT: index = 1; break;
  235 +
  236 + case BTN_2:
  237 + case BTN_FORWARD:
  238 + case BTN_STYLUS2:
  239 + case BTN_MIDDLE: index = 2; break;
  240 +
  241 + case BTN_3:
  242 + case BTN_BACK:
  243 + case BTN_SIDE: index = 3; break;
  244 +
  245 + case BTN_4:
  246 + case BTN_EXTRA: index = 4; break;
  247 +
  248 + default: return;
218 249 }
219 250  
220 251 if (value) {
221 252  
222 253  
223 254  
224 255  
... ... @@ -226,19 +257,22 @@
226 257 }
227 258 }
228 259  
229   -static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_hw_data *packet)
  260 +static void mousedev_notify_readers(struct mousedev *mousedev,
  261 + struct mousedev_hw_data *packet)
230 262 {
231 263 struct mousedev_client *client;
232 264 struct mousedev_motion *p;
233   - unsigned long flags;
  265 + unsigned int new_head;
234 266 int wake_readers = 0;
235 267  
236   - list_for_each_entry(client, &mousedev->client_list, node) {
237   - spin_lock_irqsave(&client->packet_lock, flags);
  268 + list_for_each_entry_rcu(client, &mousedev->client_list, node) {
238 269  
  270 + /* Just acquire the lock, interrupts already disabled */
  271 + spin_lock(&client->packet_lock);
  272 +
239 273 p = &client->packets[client->head];
240 274 if (client->ready && p->buttons != mousedev->packet.buttons) {
241   - unsigned int new_head = (client->head + 1) % PACKET_QUEUE_LEN;
  275 + new_head = (client->head + 1) % PACKET_QUEUE_LEN;
242 276 if (new_head != client->tail) {
243 277 p = &client->packets[client->head = new_head];
244 278 memset(p, 0, sizeof(struct mousedev_motion));
245 279  
246 280  
247 281  
... ... @@ -253,19 +287,22 @@
253 287 }
254 288  
255 289 client->pos_x += packet->dx;
256   - client->pos_x = client->pos_x < 0 ? 0 : (client->pos_x >= xres ? xres : client->pos_x);
  290 + client->pos_x = client->pos_x < 0 ?
  291 + 0 : (client->pos_x >= xres ? xres : client->pos_x);
257 292 client->pos_y += packet->dy;
258   - client->pos_y = client->pos_y < 0 ? 0 : (client->pos_y >= yres ? yres : client->pos_y);
  293 + client->pos_y = client->pos_y < 0 ?
  294 + 0 : (client->pos_y >= yres ? yres : client->pos_y);
259 295  
260 296 p->dx += packet->dx;
261 297 p->dy += packet->dy;
262 298 p->dz += packet->dz;
263 299 p->buttons = mousedev->packet.buttons;
264 300  
265   - if (p->dx || p->dy || p->dz || p->buttons != client->last_buttons)
  301 + if (p->dx || p->dy || p->dz ||
  302 + p->buttons != client->last_buttons)
266 303 client->ready = 1;
267 304  
268   - spin_unlock_irqrestore(&client->packet_lock, flags);
  305 + spin_unlock(&client->packet_lock);
269 306  
270 307 if (client->ready) {
271 308 kill_fasync(&client->fasync, SIGIO, POLL_IN);
... ... @@ -281,7 +318,8 @@
281 318 {
282 319 if (!value) {
283 320 if (mousedev->touch &&
284   - time_before(jiffies, mousedev->touch + msecs_to_jiffies(tap_time))) {
  321 + time_before(jiffies,
  322 + mousedev->touch + msecs_to_jiffies(tap_time))) {
285 323 /*
286 324 * Toggle left button to emulate tap.
287 325 * We rely on the fact that mousedev_mix always has 0
... ... @@ -290,7 +328,8 @@
290 328 set_bit(0, &mousedev->packet.buttons);
291 329 set_bit(0, &mousedev_mix->packet.buttons);
292 330 mousedev_notify_readers(mousedev, &mousedev_mix->packet);
293   - mousedev_notify_readers(mousedev_mix, &mousedev_mix->packet);
  331 + mousedev_notify_readers(mousedev_mix,
  332 + &mousedev_mix->packet);
294 333 clear_bit(0, &mousedev->packet.buttons);
295 334 clear_bit(0, &mousedev_mix->packet.buttons);
296 335 }
297 336  
298 337  
299 338  
300 339  
301 340  
302 341  
303 342  
304 343  
... ... @@ -302,54 +341,61 @@
302 341 mousedev->touch = jiffies;
303 342 }
304 343  
305   -static void mousedev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
  344 +static void mousedev_event(struct input_handle *handle,
  345 + unsigned int type, unsigned int code, int value)
306 346 {
307 347 struct mousedev *mousedev = handle->private;
308 348  
309 349 switch (type) {
310   - case EV_ABS:
311   - /* Ignore joysticks */
312   - if (test_bit(BTN_TRIGGER, handle->dev->keybit))
313   - return;
314 350  
315   - if (test_bit(BTN_TOOL_FINGER, handle->dev->keybit))
316   - mousedev_touchpad_event(handle->dev, mousedev, code, value);
317   - else
318   - mousedev_abs_event(handle->dev, mousedev, code, value);
  351 + case EV_ABS:
  352 + /* Ignore joysticks */
  353 + if (test_bit(BTN_TRIGGER, handle->dev->keybit))
  354 + return;
319 355  
320   - break;
  356 + if (test_bit(BTN_TOOL_FINGER, handle->dev->keybit))
  357 + mousedev_touchpad_event(handle->dev,
  358 + mousedev, code, value);
  359 + else
  360 + mousedev_abs_event(handle->dev, mousedev, code, value);
321 361  
322   - case EV_REL:
323   - mousedev_rel_event(mousedev, code, value);
324   - break;
  362 + break;
325 363  
326   - case EV_KEY:
327   - if (value != 2) {
328   - if (code == BTN_TOUCH && test_bit(BTN_TOOL_FINGER, handle->dev->keybit))
329   - mousedev_touchpad_touch(mousedev, value);
330   - else
331   - mousedev_key_event(mousedev, code, value);
332   - }
333   - break;
  364 + case EV_REL:
  365 + mousedev_rel_event(mousedev, code, value);
  366 + break;
334 367  
335   - case EV_SYN:
336   - if (code == SYN_REPORT) {
337   - if (mousedev->touch) {
338   - mousedev->pkt_count++;
339   - /* Input system eats duplicate events, but we need all of them
340   - * to do correct averaging so apply present one forward
341   - */
342   - fx(0) = fx(1);
343   - fy(0) = fy(1);
344   - }
  368 + case EV_KEY:
  369 + if (value != 2) {
  370 + if (code == BTN_TOUCH &&
  371 + test_bit(BTN_TOOL_FINGER, handle->dev->keybit))
  372 + mousedev_touchpad_touch(mousedev, value);
  373 + else
  374 + mousedev_key_event(mousedev, code, value);
  375 + }
  376 + break;
345 377  
346   - mousedev_notify_readers(mousedev, &mousedev->packet);
347   - mousedev_notify_readers(mousedev_mix, &mousedev->packet);
348   -
349   - mousedev->packet.dx = mousedev->packet.dy = mousedev->packet.dz = 0;
350   - mousedev->packet.abs_event = 0;
  378 + case EV_SYN:
  379 + if (code == SYN_REPORT) {
  380 + if (mousedev->touch) {
  381 + mousedev->pkt_count++;
  382 + /*
  383 + * Input system eats duplicate events,
  384 + * but we need all of them to do correct
  385 + * averaging so apply present one forward
  386 + */
  387 + fx(0) = fx(1);
  388 + fy(0) = fy(1);
351 389 }
352   - break;
  390 +
  391 + mousedev_notify_readers(mousedev, &mousedev->packet);
  392 + mousedev_notify_readers(mousedev_mix, &mousedev->packet);
  393 +
  394 + mousedev->packet.dx = mousedev->packet.dy =
  395 + mousedev->packet.dz = 0;
  396 + mousedev->packet.abs_event = 0;
  397 + }
  398 + break;
353 399 }
354 400 }
355 401  
356 402  
357 403  
358 404  
359 405  
360 406  
361 407  
362 408  
363 409  
364 410  
... ... @@ -367,41 +413,45 @@
367 413 {
368 414 struct mousedev *mousedev = container_of(dev, struct mousedev, dev);
369 415  
370   - mousedev_table[mousedev->minor] = NULL;
371 416 kfree(mousedev);
372 417 }
373 418  
374   -static int mixdev_add_device(struct mousedev *mousedev)
  419 +static int mousedev_open_device(struct mousedev *mousedev)
375 420 {
376   - int error;
  421 + int retval;
377 422  
378   - if (mousedev_mix->open) {
379   - error = input_open_device(&mousedev->handle);
380   - if (error)
381   - return error;
  423 + retval = mutex_lock_interruptible(&mousedev->mutex);
  424 + if (retval)
  425 + return retval;
382 426  
383   - mousedev->open++;
384   - mousedev->mixdev_open = 1;
385   - }
  427 + if (mousedev->minor == MOUSEDEV_MIX)
  428 + mixdev_open_devices();
  429 + else if (!mousedev->exist)
  430 + retval = -ENODEV;
  431 + else if (!mousedev->open++)
  432 + retval = input_open_device(&mousedev->handle);
386 433  
387   - get_device(&mousedev->dev);
388   - list_add_tail(&mousedev->mixdev_node, &mousedev_mix_list);
389   -
390   - return 0;
  434 + mutex_unlock(&mousedev->mutex);
  435 + return retval;
391 436 }
392 437  
393   -static void mixdev_remove_device(struct mousedev *mousedev)
  438 +static void mousedev_close_device(struct mousedev *mousedev)
394 439 {
395   - if (mousedev->mixdev_open) {
396   - mousedev->mixdev_open = 0;
397   - if (!--mousedev->open && mousedev->exist)
398   - input_close_device(&mousedev->handle);
399   - }
  440 + mutex_lock(&mousedev->mutex);
400 441  
401   - list_del_init(&mousedev->mixdev_node);
402   - put_device(&mousedev->dev);
  442 + if (mousedev->minor == MOUSEDEV_MIX)
  443 + mixdev_close_devices();
  444 + else if (mousedev->exist && !--mousedev->open)
  445 + input_close_device(&mousedev->handle);
  446 +
  447 + mutex_unlock(&mousedev->mutex);
403 448 }
404 449  
  450 +/*
  451 + * Open all available devices so they can all be multiplexed in one.
  452 + * stream. Note that this function is called with mousedev_mix->mutex
  453 + * held.
  454 + */
405 455 static void mixdev_open_devices(void)
406 456 {
407 457 struct mousedev *mousedev;
408 458  
409 459  
... ... @@ -411,16 +461,19 @@
411 461  
412 462 list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
413 463 if (!mousedev->mixdev_open) {
414   - if (!mousedev->open && mousedev->exist)
415   - if (input_open_device(&mousedev->handle))
416   - continue;
  464 + if (mousedev_open_device(mousedev))
  465 + continue;
417 466  
418   - mousedev->open++;
419 467 mousedev->mixdev_open = 1;
420 468 }
421 469 }
422 470 }
423 471  
  472 +/*
  473 + * Close all devices that were opened as part of multiplexed
  474 + * device. Note that this function is called with mousedev_mix->mutex
  475 + * held.
  476 + */
424 477 static void mixdev_close_devices(void)
425 478 {
426 479 struct mousedev *mousedev;
427 480  
428 481  
429 482  
430 483  
... ... @@ -431,33 +484,50 @@
431 484 list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
432 485 if (mousedev->mixdev_open) {
433 486 mousedev->mixdev_open = 0;
434   - if (!--mousedev->open && mousedev->exist)
435   - input_close_device(&mousedev->handle);
  487 + mousedev_close_device(mousedev);
436 488 }
437 489 }
438 490 }
439 491  
  492 +
  493 +static void mousedev_attach_client(struct mousedev *mousedev,
  494 + struct mousedev_client *client)
  495 +{
  496 + spin_lock(&mousedev->client_lock);
  497 + list_add_tail_rcu(&client->node, &mousedev->client_list);
  498 + spin_unlock(&mousedev->client_lock);
  499 + /*
  500 + * We don't use synchronize_rcu() here because read-side
  501 + * critical section is protected by a spinlock (dev->event_lock)
  502 + * instead of rcu_read_lock().
  503 + */
  504 + synchronize_sched();
  505 +}
  506 +
  507 +static void mousedev_detach_client(struct mousedev *mousedev,
  508 + struct mousedev_client *client)
  509 +{
  510 + spin_lock(&mousedev->client_lock);
  511 + list_del_rcu(&client->node);
  512 + spin_unlock(&mousedev->client_lock);
  513 + synchronize_sched();
  514 +}
  515 +
440 516 static int mousedev_release(struct inode *inode, struct file *file)
441 517 {
442 518 struct mousedev_client *client = file->private_data;
443 519 struct mousedev *mousedev = client->mousedev;
444 520  
445 521 mousedev_fasync(-1, file, 0);
446   -
447   - list_del(&client->node);
  522 + mousedev_detach_client(mousedev, client);
448 523 kfree(client);
449 524  
450   - if (mousedev->minor == MOUSEDEV_MIX)
451   - mixdev_close_devices();
452   - else if (!--mousedev->open && mousedev->exist)
453   - input_close_device(&mousedev->handle);
454   -
  525 + mousedev_close_device(mousedev);
455 526 put_device(&mousedev->dev);
456 527  
457 528 return 0;
458 529 }
459 530  
460   -
461 531 static int mousedev_open(struct inode *inode, struct file *file)
462 532 {
463 533 struct mousedev_client *client;
464 534  
465 535  
... ... @@ -475,12 +545,17 @@
475 545 if (i >= MOUSEDEV_MINORS)
476 546 return -ENODEV;
477 547  
  548 + error = mutex_lock_interruptible(&mousedev_table_mutex);
  549 + if (error)
  550 + return error;
478 551 mousedev = mousedev_table[i];
  552 + if (mousedev)
  553 + get_device(&mousedev->dev);
  554 + mutex_unlock(&mousedev_table_mutex);
  555 +
479 556 if (!mousedev)
480 557 return -ENODEV;
481 558  
482   - get_device(&mousedev->dev);
483   -
484 559 client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL);
485 560 if (!client) {
486 561 error = -ENOMEM;
487 562  
488 563  
... ... @@ -491,21 +566,17 @@
491 566 client->pos_x = xres / 2;
492 567 client->pos_y = yres / 2;
493 568 client->mousedev = mousedev;
494   - list_add_tail(&client->node, &mousedev->client_list);
  569 + mousedev_attach_client(mousedev, client);
495 570  
496   - if (mousedev->minor == MOUSEDEV_MIX)
497   - mixdev_open_devices();
498   - else if (!mousedev->open++ && mousedev->exist) {
499   - error = input_open_device(&mousedev->handle);
500   - if (error)
501   - goto err_free_client;
502   - }
  571 + error = mousedev_open_device(mousedev);
  572 + if (error)
  573 + goto err_free_client;
503 574  
504 575 file->private_data = client;
505 576 return 0;
506 577  
507 578 err_free_client:
508   - list_del(&client->node);
  579 + mousedev_detach_client(mousedev, client);
509 580 kfree(client);
510 581 err_put_mousedev:
511 582 put_device(&mousedev->dev);
512 583  
513 584  
514 585  
515 586  
516 587  
... ... @@ -517,41 +588,41 @@
517 588 return delta > limit ? limit : (delta < -limit ? -limit : delta);
518 589 }
519 590  
520   -static void mousedev_packet(struct mousedev_client *client, signed char *ps2_data)
  591 +static void mousedev_packet(struct mousedev_client *client,
  592 + signed char *ps2_data)
521 593 {
522   - struct mousedev_motion *p;
523   - unsigned long flags;
  594 + struct mousedev_motion *p = &client->packets[client->tail];
524 595  
525   - spin_lock_irqsave(&client->packet_lock, flags);
526   - p = &client->packets[client->tail];
527   -
528   - ps2_data[0] = 0x08 | ((p->dx < 0) << 4) | ((p->dy < 0) << 5) | (p->buttons & 0x07);
  596 + ps2_data[0] = 0x08 |
  597 + ((p->dx < 0) << 4) | ((p->dy < 0) << 5) | (p->buttons & 0x07);
529 598 ps2_data[1] = mousedev_limit_delta(p->dx, 127);
530 599 ps2_data[2] = mousedev_limit_delta(p->dy, 127);
531 600 p->dx -= ps2_data[1];
532 601 p->dy -= ps2_data[2];
533 602  
534 603 switch (client->mode) {
535   - case MOUSEDEV_EMUL_EXPS:
536   - ps2_data[3] = mousedev_limit_delta(p->dz, 7);
537   - p->dz -= ps2_data[3];
538   - ps2_data[3] = (ps2_data[3] & 0x0f) | ((p->buttons & 0x18) << 1);
539   - client->bufsiz = 4;
540   - break;
  604 + case MOUSEDEV_EMUL_EXPS:
  605 + ps2_data[3] = mousedev_limit_delta(p->dz, 7);
  606 + p->dz -= ps2_data[3];
  607 + ps2_data[3] = (ps2_data[3] & 0x0f) | ((p->buttons & 0x18) << 1);
  608 + client->bufsiz = 4;
  609 + break;
541 610  
542   - case MOUSEDEV_EMUL_IMPS:
543   - ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
544   - ps2_data[3] = mousedev_limit_delta(p->dz, 127);
545   - p->dz -= ps2_data[3];
546   - client->bufsiz = 4;
547   - break;
  611 + case MOUSEDEV_EMUL_IMPS:
  612 + ps2_data[0] |=
  613 + ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
  614 + ps2_data[3] = mousedev_limit_delta(p->dz, 127);
  615 + p->dz -= ps2_data[3];
  616 + client->bufsiz = 4;
  617 + break;
548 618  
549   - case MOUSEDEV_EMUL_PS2:
550   - default:
551   - ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
552   - p->dz = 0;
553   - client->bufsiz = 3;
554   - break;
  619 + case MOUSEDEV_EMUL_PS2:
  620 + default:
  621 + ps2_data[0] |=
  622 + ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
  623 + p->dz = 0;
  624 + client->bufsiz = 3;
  625 + break;
555 626 }
556 627  
557 628 if (!p->dx && !p->dy && !p->dz) {
558 629  
559 630  
... ... @@ -561,12 +632,56 @@
561 632 } else
562 633 client->tail = (client->tail + 1) % PACKET_QUEUE_LEN;
563 634 }
564   -
565   - spin_unlock_irqrestore(&client->packet_lock, flags);
566 635 }
567 636  
  637 +static void mousedev_generate_response(struct mousedev_client *client,
  638 + int command)
  639 +{
  640 + client->ps2[0] = 0xfa; /* ACK */
568 641  
569   -static ssize_t mousedev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
  642 + switch (command) {
  643 +
  644 + case 0xeb: /* Poll */
  645 + mousedev_packet(client, &client->ps2[1]);
  646 + client->bufsiz++; /* account for leading ACK */
  647 + break;
  648 +
  649 + case 0xf2: /* Get ID */
  650 + switch (client->mode) {
  651 + case MOUSEDEV_EMUL_PS2:
  652 + client->ps2[1] = 0;
  653 + break;
  654 + case MOUSEDEV_EMUL_IMPS:
  655 + client->ps2[1] = 3;
  656 + break;
  657 + case MOUSEDEV_EMUL_EXPS:
  658 + client->ps2[1] = 4;
  659 + break;
  660 + }
  661 + client->bufsiz = 2;
  662 + break;
  663 +
  664 + case 0xe9: /* Get info */
  665 + client->ps2[1] = 0x60; client->ps2[2] = 3; client->ps2[3] = 200;
  666 + client->bufsiz = 4;
  667 + break;
  668 +
  669 + case 0xff: /* Reset */
  670 + client->impsseq = client->imexseq = 0;
  671 + client->mode = MOUSEDEV_EMUL_PS2;
  672 + client->ps2[1] = 0xaa; client->ps2[2] = 0x00;
  673 + client->bufsiz = 3;
  674 + break;
  675 +
  676 + default:
  677 + client->bufsiz = 1;
  678 + break;
  679 + }
  680 + client->buffer = client->bufsiz;
  681 +}
  682 +
  683 +static ssize_t mousedev_write(struct file *file, const char __user *buffer,
  684 + size_t count, loff_t *ppos)
570 685 {
571 686 struct mousedev_client *client = file->private_data;
572 687 unsigned char c;
... ... @@ -577,6 +692,8 @@
577 692 if (get_user(c, buffer + i))
578 693 return -EFAULT;
579 694  
  695 + spin_lock_irq(&client->packet_lock);
  696 +
580 697 if (c == mousedev_imex_seq[client->imexseq]) {
581 698 if (++client->imexseq == MOUSEDEV_SEQ_LEN) {
582 699 client->imexseq = 0;
583 700  
584 701  
585 702  
586 703  
587 704  
588 705  
589 706  
590 707  
... ... @@ -593,68 +710,39 @@
593 710 } else
594 711 client->impsseq = 0;
595 712  
596   - client->ps2[0] = 0xfa;
  713 + mousedev_generate_response(client, c);
597 714  
598   - switch (c) {
599   -
600   - case 0xeb: /* Poll */
601   - mousedev_packet(client, &client->ps2[1]);
602   - client->bufsiz++; /* account for leading ACK */
603   - break;
604   -
605   - case 0xf2: /* Get ID */
606   - switch (client->mode) {
607   - case MOUSEDEV_EMUL_PS2: client->ps2[1] = 0; break;
608   - case MOUSEDEV_EMUL_IMPS: client->ps2[1] = 3; break;
609   - case MOUSEDEV_EMUL_EXPS: client->ps2[1] = 4; break;
610   - }
611   - client->bufsiz = 2;
612   - break;
613   -
614   - case 0xe9: /* Get info */
615   - client->ps2[1] = 0x60; client->ps2[2] = 3; client->ps2[3] = 200;
616   - client->bufsiz = 4;
617   - break;
618   -
619   - case 0xff: /* Reset */
620   - client->impsseq = client->imexseq = 0;
621   - client->mode = MOUSEDEV_EMUL_PS2;
622   - client->ps2[1] = 0xaa; client->ps2[2] = 0x00;
623   - client->bufsiz = 3;
624   - break;
625   -
626   - default:
627   - client->bufsiz = 1;
628   - break;
629   - }
630   -
631   - client->buffer = client->bufsiz;
  715 + spin_unlock_irq(&client->packet_lock);
632 716 }
633 717  
634 718 kill_fasync(&client->fasync, SIGIO, POLL_IN);
635   -
636 719 wake_up_interruptible(&client->mousedev->wait);
637 720  
638 721 return count;
639 722 }
640 723  
641   -static ssize_t mousedev_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
  724 +static ssize_t mousedev_read(struct file *file, char __user *buffer,
  725 + size_t count, loff_t *ppos)
642 726 {
643 727 struct mousedev_client *client = file->private_data;
  728 + struct mousedev *mousedev = client->mousedev;
  729 + signed char data[sizeof(client->ps2)];
644 730 int retval = 0;
645 731  
646   - if (!client->ready && !client->buffer && (file->f_flags & O_NONBLOCK))
  732 + if (!client->ready && !client->buffer && mousedev->exist &&
  733 + (file->f_flags & O_NONBLOCK))
647 734 return -EAGAIN;
648 735  
649   - retval = wait_event_interruptible(client->mousedev->wait,
650   - !client->mousedev->exist || client->ready || client->buffer);
651   -
  736 + retval = wait_event_interruptible(mousedev->wait,
  737 + !mousedev->exist || client->ready || client->buffer);
652 738 if (retval)
653 739 return retval;
654 740  
655   - if (!client->mousedev->exist)
  741 + if (!mousedev->exist)
656 742 return -ENODEV;
657 743  
  744 + spin_lock_irq(&client->packet_lock);
  745 +
658 746 if (!client->buffer && client->ready) {
659 747 mousedev_packet(client, client->ps2);
660 748 client->buffer = client->bufsiz;
661 749  
... ... @@ -663,9 +751,12 @@
663 751 if (count > client->buffer)
664 752 count = client->buffer;
665 753  
  754 + memcpy(data, client->ps2 + client->bufsiz - client->buffer, count);
666 755 client->buffer -= count;
667 756  
668   - if (copy_to_user(buffer, client->ps2 + client->bufsiz - client->buffer - count, count))
  757 + spin_unlock_irq(&client->packet_lock);
  758 +
  759 + if (copy_to_user(buffer, data, count))
669 760 return -EFAULT;
670 761  
671 762 return count;
... ... @@ -692,6 +783,60 @@
692 783 .fasync = mousedev_fasync,
693 784 };
694 785  
  786 +static int mousedev_install_chrdev(struct mousedev *mousedev)
  787 +{
  788 + mousedev_table[mousedev->minor] = mousedev;
  789 + return 0;
  790 +}
  791 +
  792 +static void mousedev_remove_chrdev(struct mousedev *mousedev)
  793 +{
  794 + mutex_lock(&mousedev_table_mutex);
  795 + mousedev_table[mousedev->minor] = NULL;
  796 + mutex_unlock(&mousedev_table_mutex);
  797 +}
  798 +
  799 +/*
  800 + * Mark device non-existent. This disables writes, ioctls and
  801 + * prevents new users from opening the device. Already posted
  802 + * blocking reads will stay, however new ones will fail.
  803 + */
  804 +static void mousedev_mark_dead(struct mousedev *mousedev)
  805 +{
  806 + mutex_lock(&mousedev->mutex);
  807 + mousedev->exist = 0;
  808 + mutex_unlock(&mousedev->mutex);
  809 +}
  810 +
  811 +/*
  812 + * Wake up users waiting for IO so they can disconnect from
  813 + * dead device.
  814 + */
  815 +static void mousedev_hangup(struct mousedev *mousedev)
  816 +{
  817 + struct mousedev_client *client;
  818 +
  819 + spin_lock(&mousedev->client_lock);
  820 + list_for_each_entry(client, &mousedev->client_list, node)
  821 + kill_fasync(&client->fasync, SIGIO, POLL_HUP);
  822 + spin_unlock(&mousedev->client_lock);
  823 +
  824 + wake_up_interruptible(&mousedev->wait);
  825 +}
  826 +
  827 +static void mousedev_cleanup(struct mousedev *mousedev)
  828 +{
  829 + struct input_handle *handle = &mousedev->handle;
  830 +
  831 + mousedev_mark_dead(mousedev);
  832 + mousedev_hangup(mousedev);
  833 + mousedev_remove_chrdev(mousedev);
  834 +
  835 + /* mousedev is marked dead so no one else accesses mousedev->open */
  836 + if (mousedev->open)
  837 + input_close_device(handle);
  838 +}
  839 +
695 840 static struct mousedev *mousedev_create(struct input_dev *dev,
696 841 struct input_handler *handler,
697 842 int minor)
... ... @@ -707,6 +852,10 @@
707 852  
708 853 INIT_LIST_HEAD(&mousedev->client_list);
709 854 INIT_LIST_HEAD(&mousedev->mixdev_node);
  855 + spin_lock_init(&mousedev->client_lock);
  856 + mutex_init(&mousedev->mutex);
  857 + lockdep_set_subclass(&mousedev->mutex,
  858 + minor == MOUSEDEV_MIX ? MOUSEDEV_MIX : 0);
710 859 init_waitqueue_head(&mousedev->wait);
711 860  
712 861 if (minor == MOUSEDEV_MIX)
713 862  
714 863  
715 864  
... ... @@ -731,14 +880,27 @@
731 880 mousedev->dev.release = mousedev_free;
732 881 device_initialize(&mousedev->dev);
733 882  
734   - mousedev_table[minor] = mousedev;
  883 + if (minor != MOUSEDEV_MIX) {
  884 + error = input_register_handle(&mousedev->handle);
  885 + if (error)
  886 + goto err_free_mousedev;
  887 + }
735 888  
  889 + error = mousedev_install_chrdev(mousedev);
  890 + if (error)
  891 + goto err_unregister_handle;
  892 +
736 893 error = device_add(&mousedev->dev);
737 894 if (error)
738   - goto err_free_mousedev;
  895 + goto err_cleanup_mousedev;
739 896  
740 897 return mousedev;
741 898  
  899 + err_cleanup_mousedev:
  900 + mousedev_cleanup(mousedev);
  901 + err_unregister_handle:
  902 + if (minor != MOUSEDEV_MIX)
  903 + input_unregister_handle(&mousedev->handle);
742 904 err_free_mousedev:
743 905 put_device(&mousedev->dev);
744 906 err_out:
745 907  
746 908  
747 909  
748 910  
749 911  
... ... @@ -747,29 +909,64 @@
747 909  
748 910 static void mousedev_destroy(struct mousedev *mousedev)
749 911 {
750   - struct mousedev_client *client;
751   -
752 912 device_del(&mousedev->dev);
753   - mousedev->exist = 0;
  913 + mousedev_cleanup(mousedev);
  914 + if (mousedev->minor != MOUSEDEV_MIX)
  915 + input_unregister_handle(&mousedev->handle);
  916 + put_device(&mousedev->dev);
  917 +}
754 918  
755   - if (mousedev->open) {
756   - input_close_device(&mousedev->handle);
757   - list_for_each_entry(client, &mousedev->client_list, node)
758   - kill_fasync(&client->fasync, SIGIO, POLL_HUP);
759   - wake_up_interruptible(&mousedev->wait);
  919 +static int mixdev_add_device(struct mousedev *mousedev)
  920 +{
  921 + int retval;
  922 +
  923 + retval = mutex_lock_interruptible(&mousedev_mix->mutex);
  924 + if (retval)
  925 + return retval;
  926 +
  927 + if (mousedev_mix->open) {
  928 + retval = mousedev_open_device(mousedev);
  929 + if (retval)
  930 + goto out;
  931 +
  932 + mousedev->mixdev_open = 1;
760 933 }
761 934  
  935 + get_device(&mousedev->dev);
  936 + list_add_tail(&mousedev->mixdev_node, &mousedev_mix_list);
  937 +
  938 + out:
  939 + mutex_unlock(&mousedev_mix->mutex);
  940 + return retval;
  941 +}
  942 +
  943 +static void mixdev_remove_device(struct mousedev *mousedev)
  944 +{
  945 + mutex_lock(&mousedev_mix->mutex);
  946 +
  947 + if (mousedev->mixdev_open) {
  948 + mousedev->mixdev_open = 0;
  949 + mousedev_close_device(mousedev);
  950 + }
  951 +
  952 + list_del_init(&mousedev->mixdev_node);
  953 + mutex_unlock(&mousedev_mix->mutex);
  954 +
762 955 put_device(&mousedev->dev);
763 956 }
764 957  
765   -static int mousedev_connect(struct input_handler *handler, struct input_dev *dev,
  958 +static int mousedev_connect(struct input_handler *handler,
  959 + struct input_dev *dev,
766 960 const struct input_device_id *id)
767 961 {
768 962 struct mousedev *mousedev;
769 963 int minor;
770 964 int error;
771 965  
772   - for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++);
  966 + for (minor = 0; minor < MOUSEDEV_MINORS; minor++)
  967 + if (!mousedev_table[minor])
  968 + break;
  969 +
773 970 if (minor == MOUSEDEV_MINORS) {
774 971 printk(KERN_ERR "mousedev: no more free mousedev devices\n");
775 972 return -ENFILE;
776 973  
777 974  
... ... @@ -779,21 +976,13 @@
779 976 if (IS_ERR(mousedev))
780 977 return PTR_ERR(mousedev);
781 978  
782   - error = input_register_handle(&mousedev->handle);
783   - if (error)
784   - goto err_delete_mousedev;
785   -
786 979 error = mixdev_add_device(mousedev);
787   - if (error)
788   - goto err_unregister_handle;
  980 + if (error) {
  981 + mousedev_destroy(mousedev);
  982 + return error;
  983 + }
789 984  
790 985 return 0;
791   -
792   - err_unregister_handle:
793   - input_unregister_handle(&mousedev->handle);
794   - err_delete_mousedev:
795   - device_unregister(&mousedev->dev);
796   - return error;
797 986 }
798 987  
799 988 static void mousedev_disconnect(struct input_handle *handle)
800 989  
801 990  
802 991  
803 992  
804 993  
805 994  
806 995  
... ... @@ -801,33 +990,42 @@
801 990 struct mousedev *mousedev = handle->private;
802 991  
803 992 mixdev_remove_device(mousedev);
804   - input_unregister_handle(handle);
805 993 mousedev_destroy(mousedev);
806 994 }
807 995  
808 996 static const struct input_device_id mousedev_ids[] = {
809 997 {
810   - .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_RELBIT,
  998 + .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
  999 + INPUT_DEVICE_ID_MATCH_KEYBIT |
  1000 + INPUT_DEVICE_ID_MATCH_RELBIT,
811 1001 .evbit = { BIT(EV_KEY) | BIT(EV_REL) },
812 1002 .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) },
813 1003 .relbit = { BIT(REL_X) | BIT(REL_Y) },
814   - }, /* A mouse like device, at least one button, two relative axes */
  1004 + }, /* A mouse like device, at least one button,
  1005 + two relative axes */
815 1006 {
816   - .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_RELBIT,
  1007 + .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
  1008 + INPUT_DEVICE_ID_MATCH_RELBIT,
817 1009 .evbit = { BIT(EV_KEY) | BIT(EV_REL) },
818 1010 .relbit = { BIT(REL_WHEEL) },
819 1011 }, /* A separate scrollwheel */
820 1012 {
821   - .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
  1013 + .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
  1014 + INPUT_DEVICE_ID_MATCH_KEYBIT |
  1015 + INPUT_DEVICE_ID_MATCH_ABSBIT,
822 1016 .evbit = { BIT(EV_KEY) | BIT(EV_ABS) },
823 1017 .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) },
824 1018 .absbit = { BIT(ABS_X) | BIT(ABS_Y) },
825   - }, /* A tablet like device, at least touch detection, two absolute axes */
  1019 + }, /* A tablet like device, at least touch detection,
  1020 + two absolute axes */
826 1021 {
827   - .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
  1022 + .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
  1023 + INPUT_DEVICE_ID_MATCH_KEYBIT |
  1024 + INPUT_DEVICE_ID_MATCH_ABSBIT,
828 1025 .evbit = { BIT(EV_KEY) | BIT(EV_ABS) },
829 1026 .keybit = { [LONG(BTN_TOOL_FINGER)] = BIT(BTN_TOOL_FINGER) },
830   - .absbit = { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_TOOL_WIDTH) },
  1027 + .absbit = { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) |
  1028 + BIT(ABS_TOOL_WIDTH) },
831 1029 }, /* A touchpad */
832 1030  
833 1031 { }, /* Terminating entry */