aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/mousedev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/mousedev.c')
-rw-r--r--drivers/input/mousedev.c242
1 files changed, 132 insertions, 110 deletions
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index 3f4866d8d18c..9173916b8be5 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -64,6 +64,7 @@ struct mousedev {
64 wait_queue_head_t wait; 64 wait_queue_head_t wait;
65 struct list_head client_list; 65 struct list_head client_list;
66 struct input_handle handle; 66 struct input_handle handle;
67 struct device dev;
67 68
68 struct list_head mixdev_node; 69 struct list_head mixdev_node;
69 int mixdev_open; 70 int mixdev_open;
@@ -112,7 +113,7 @@ static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 };
112static struct input_handler mousedev_handler; 113static struct input_handler mousedev_handler;
113 114
114static struct mousedev *mousedev_table[MOUSEDEV_MINORS]; 115static struct mousedev *mousedev_table[MOUSEDEV_MINORS];
115static struct mousedev mousedev_mix; 116static struct mousedev *mousedev_mix;
116static LIST_HEAD(mousedev_mix_list); 117static LIST_HEAD(mousedev_mix_list);
117 118
118#define fx(i) (mousedev->old_x[(mousedev->pkt_count - (i)) & 03]) 119#define fx(i) (mousedev->old_x[(mousedev->pkt_count - (i)) & 03])
@@ -218,10 +219,10 @@ static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int
218 219
219 if (value) { 220 if (value) {
220 set_bit(index, &mousedev->packet.buttons); 221 set_bit(index, &mousedev->packet.buttons);
221 set_bit(index, &mousedev_mix.packet.buttons); 222 set_bit(index, &mousedev_mix->packet.buttons);
222 } else { 223 } else {
223 clear_bit(index, &mousedev->packet.buttons); 224 clear_bit(index, &mousedev->packet.buttons);
224 clear_bit(index, &mousedev_mix.packet.buttons); 225 clear_bit(index, &mousedev_mix->packet.buttons);
225 } 226 }
226} 227}
227 228
@@ -287,11 +288,11 @@ static void mousedev_touchpad_touch(struct mousedev *mousedev, int value)
287 * motion packet so we won't mess current position. 288 * motion packet so we won't mess current position.
288 */ 289 */
289 set_bit(0, &mousedev->packet.buttons); 290 set_bit(0, &mousedev->packet.buttons);
290 set_bit(0, &mousedev_mix.packet.buttons); 291 set_bit(0, &mousedev_mix->packet.buttons);
291 mousedev_notify_readers(mousedev, &mousedev_mix.packet); 292 mousedev_notify_readers(mousedev, &mousedev_mix->packet);
292 mousedev_notify_readers(&mousedev_mix, &mousedev_mix.packet); 293 mousedev_notify_readers(mousedev_mix, &mousedev_mix->packet);
293 clear_bit(0, &mousedev->packet.buttons); 294 clear_bit(0, &mousedev->packet.buttons);
294 clear_bit(0, &mousedev_mix.packet.buttons); 295 clear_bit(0, &mousedev_mix->packet.buttons);
295 } 296 }
296 mousedev->touch = mousedev->pkt_count = 0; 297 mousedev->touch = mousedev->pkt_count = 0;
297 mousedev->frac_dx = 0; 298 mousedev->frac_dx = 0;
@@ -343,7 +344,7 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig
343 } 344 }
344 345
345 mousedev_notify_readers(mousedev, &mousedev->packet); 346 mousedev_notify_readers(mousedev, &mousedev->packet);
346 mousedev_notify_readers(&mousedev_mix, &mousedev->packet); 347 mousedev_notify_readers(mousedev_mix, &mousedev->packet);
347 348
348 mousedev->packet.dx = mousedev->packet.dy = mousedev->packet.dz = 0; 349 mousedev->packet.dx = mousedev->packet.dy = mousedev->packet.dz = 0;
349 mousedev->packet.abs_event = 0; 350 mousedev->packet.abs_event = 0;
@@ -362,8 +363,10 @@ static int mousedev_fasync(int fd, struct file *file, int on)
362 return retval < 0 ? retval : 0; 363 return retval < 0 ? retval : 0;
363} 364}
364 365
365static void mousedev_free(struct mousedev *mousedev) 366static void mousedev_free(struct device *dev)
366{ 367{
368 struct mousedev *mousedev = container_of(dev, struct mousedev, dev);
369
367 mousedev_table[mousedev->minor] = NULL; 370 mousedev_table[mousedev->minor] = NULL;
368 kfree(mousedev); 371 kfree(mousedev);
369} 372}
@@ -372,15 +375,16 @@ static int mixdev_add_device(struct mousedev *mousedev)
372{ 375{
373 int error; 376 int error;
374 377
375 if (mousedev_mix.open) { 378 if (mousedev_mix->open) {
376 error = input_open_device(&mousedev->handle); 379 error = input_open_device(&mousedev->handle);
377 if (error) 380 if (error)
378 return error; 381 return error;
379 382
380 mousedev->open++; 383 mousedev->open++;
381 mousedev->mixdev_open++; 384 mousedev->mixdev_open = 1;
382 } 385 }
383 386
387 get_device(&mousedev->dev);
384 list_add_tail(&mousedev->mixdev_node, &mousedev_mix_list); 388 list_add_tail(&mousedev->mixdev_node, &mousedev_mix_list);
385 389
386 return 0; 390 return 0;
@@ -395,36 +399,40 @@ static void mixdev_remove_device(struct mousedev *mousedev)
395 } 399 }
396 400
397 list_del_init(&mousedev->mixdev_node); 401 list_del_init(&mousedev->mixdev_node);
402 put_device(&mousedev->dev);
398} 403}
399 404
400static void mixdev_open_devices(void) 405static void mixdev_open_devices(void)
401{ 406{
402 struct mousedev *mousedev; 407 struct mousedev *mousedev;
403 408
409 if (mousedev_mix->open++)
410 return;
411
404 list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) { 412 list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
405 if (mousedev->exist && !mousedev->open) { 413 if (!mousedev->mixdev_open) {
406 if (input_open_device(&mousedev->handle)) 414 if (!mousedev->open && mousedev->exist)
407 continue; 415 if (input_open_device(&mousedev->handle))
416 continue;
408 417
409 mousedev->open++; 418 mousedev->open++;
410 mousedev->mixdev_open++; 419 mousedev->mixdev_open = 1;
411 } 420 }
412 } 421 }
413} 422}
414 423
415static void mixdev_close_devices(void) 424static void mixdev_close_devices(void)
416{ 425{
417 struct mousedev *mousedev, *next; 426 struct mousedev *mousedev;
418 427
419 list_for_each_entry_safe(mousedev, next, &mousedev_mix_list, mixdev_node) { 428 if (--mousedev_mix->open)
429 return;
430
431 list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
420 if (mousedev->mixdev_open) { 432 if (mousedev->mixdev_open) {
421 mousedev->mixdev_open = 0; 433 mousedev->mixdev_open = 0;
422 if (!--mousedev->open) { 434 if (!--mousedev->open && mousedev->exist)
423 if (mousedev->exist) 435 input_close_device(&mousedev->handle);
424 input_close_device(&mousedev->handle);
425 else
426 mousedev_free(mousedev);
427 }
428 } 436 }
429 } 437 }
430} 438}
@@ -439,14 +447,12 @@ static int mousedev_release(struct inode *inode, struct file *file)
439 list_del(&client->node); 447 list_del(&client->node);
440 kfree(client); 448 kfree(client);
441 449
442 if (!--mousedev->open) { 450 if (mousedev->minor == MOUSEDEV_MIX)
443 if (mousedev->minor == MOUSEDEV_MIX) 451 mixdev_close_devices();
444 mixdev_close_devices(); 452 else if (!--mousedev->open && mousedev->exist)
445 else if (mousedev->exist) 453 input_close_device(&mousedev->handle);
446 input_close_device(&mousedev->handle); 454
447 else 455 put_device(&mousedev->dev);
448 mousedev_free(mousedev);
449 }
450 456
451 return 0; 457 return 0;
452} 458}
@@ -473,9 +479,13 @@ static int mousedev_open(struct inode *inode, struct file *file)
473 if (!mousedev) 479 if (!mousedev)
474 return -ENODEV; 480 return -ENODEV;
475 481
482 get_device(&mousedev->dev);
483
476 client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL); 484 client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL);
477 if (!client) 485 if (!client) {
478 return -ENOMEM; 486 error = -ENOMEM;
487 goto err_put_mousedev;
488 }
479 489
480 spin_lock_init(&client->packet_lock); 490 spin_lock_init(&client->packet_lock);
481 client->pos_x = xres / 2; 491 client->pos_x = xres / 2;
@@ -483,21 +493,23 @@ static int mousedev_open(struct inode *inode, struct file *file)
483 client->mousedev = mousedev; 493 client->mousedev = mousedev;
484 list_add_tail(&client->node, &mousedev->client_list); 494 list_add_tail(&client->node, &mousedev->client_list);
485 495
486 if (!mousedev->open++) { 496 if (mousedev->minor == MOUSEDEV_MIX)
487 if (mousedev->minor == MOUSEDEV_MIX) 497 mixdev_open_devices();
488 mixdev_open_devices(); 498 else if (!mousedev->open++ && mousedev->exist) {
489 else if (mousedev->exist) { 499 error = input_open_device(&mousedev->handle);
490 error = input_open_device(&mousedev->handle); 500 if (error)
491 if (error) { 501 goto err_free_client;
492 list_del(&client->node);
493 kfree(client);
494 return error;
495 }
496 }
497 } 502 }
498 503
499 file->private_data = client; 504 file->private_data = client;
500 return 0; 505 return 0;
506
507 err_free_client:
508 list_del(&client->node);
509 kfree(client);
510 err_put_mousedev:
511 put_device(&mousedev->dev);
512 return error;
501} 513}
502 514
503static inline int mousedev_limit_delta(int delta, int limit) 515static inline int mousedev_limit_delta(int delta, int limit)
@@ -680,57 +692,96 @@ static const struct file_operations mousedev_fops = {
680 .fasync = mousedev_fasync, 692 .fasync = mousedev_fasync,
681}; 693};
682 694
683static int mousedev_connect(struct input_handler *handler, struct input_dev *dev, 695static struct mousedev *mousedev_create(struct input_dev *dev,
684 const struct input_device_id *id) 696 struct input_handler *handler,
697 int minor)
685{ 698{
686 struct mousedev *mousedev; 699 struct mousedev *mousedev;
687 struct class_device *cdev;
688 dev_t devt;
689 int minor;
690 int error; 700 int error;
691 701
692 for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++);
693 if (minor == MOUSEDEV_MINORS) {
694 printk(KERN_ERR "mousedev: no more free mousedev devices\n");
695 return -ENFILE;
696 }
697
698 mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL); 702 mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL);
699 if (!mousedev) 703 if (!mousedev) {
700 return -ENOMEM; 704 error = -ENOMEM;
705 goto err_out;
706 }
701 707
702 INIT_LIST_HEAD(&mousedev->client_list); 708 INIT_LIST_HEAD(&mousedev->client_list);
703 INIT_LIST_HEAD(&mousedev->mixdev_node); 709 INIT_LIST_HEAD(&mousedev->mixdev_node);
704 init_waitqueue_head(&mousedev->wait); 710 init_waitqueue_head(&mousedev->wait);
705 711
712 if (minor == MOUSEDEV_MIX)
713 strlcpy(mousedev->name, "mice", sizeof(mousedev->name));
714 else
715 snprintf(mousedev->name, sizeof(mousedev->name),
716 "mouse%d", minor);
717
706 mousedev->minor = minor; 718 mousedev->minor = minor;
707 mousedev->exist = 1; 719 mousedev->exist = 1;
708 mousedev->handle.dev = dev; 720 mousedev->handle.dev = dev;
709 mousedev->handle.name = mousedev->name; 721 mousedev->handle.name = mousedev->name;
710 mousedev->handle.handler = handler; 722 mousedev->handle.handler = handler;
711 mousedev->handle.private = mousedev; 723 mousedev->handle.private = mousedev;
712 sprintf(mousedev->name, "mouse%d", minor);
713 724
714 mousedev_table[minor] = mousedev; 725 strlcpy(mousedev->dev.bus_id, mousedev->name,
726 sizeof(mousedev->dev.bus_id));
727 mousedev->dev.class = &input_class;
728 if (dev)
729 mousedev->dev.parent = &dev->dev;
730 mousedev->dev.devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor);
731 mousedev->dev.release = mousedev_free;
732 device_initialize(&mousedev->dev);
715 733
716 devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor), 734 mousedev_table[minor] = mousedev;
717 735
718 cdev = class_device_create(&input_class, &dev->cdev, devt, 736 error = device_add(&mousedev->dev);
719 dev->cdev.dev, mousedev->name); 737 if (error)
720 if (IS_ERR(cdev)) {
721 error = PTR_ERR(cdev);
722 goto err_free_mousedev; 738 goto err_free_mousedev;
739
740 return mousedev;
741
742 err_free_mousedev:
743 put_device(&mousedev->dev);
744 err_out:
745 return ERR_PTR(error);
746}
747
748static void mousedev_destroy(struct mousedev *mousedev)
749{
750 struct mousedev_client *client;
751
752 device_del(&mousedev->dev);
753 mousedev->exist = 0;
754
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);
723 } 760 }
724 761
725 /* temporary symlink to keep userspace happy */ 762 put_device(&mousedev->dev);
726 error = sysfs_create_link(&input_class.subsys.kobj, 763}
727 &cdev->kobj, mousedev->name); 764
728 if (error) 765static int mousedev_connect(struct input_handler *handler, struct input_dev *dev,
729 goto err_cdev_destroy; 766 const struct input_device_id *id)
767{
768 struct mousedev *mousedev;
769 int minor;
770 int error;
771
772 for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++);
773 if (minor == MOUSEDEV_MINORS) {
774 printk(KERN_ERR "mousedev: no more free mousedev devices\n");
775 return -ENFILE;
776 }
777
778 mousedev = mousedev_create(dev, handler, minor);
779 if (IS_ERR(mousedev))
780 return PTR_ERR(mousedev);
730 781
731 error = input_register_handle(&mousedev->handle); 782 error = input_register_handle(&mousedev->handle);
732 if (error) 783 if (error)
733 goto err_remove_link; 784 goto err_delete_mousedev;
734 785
735 error = mixdev_add_device(mousedev); 786 error = mixdev_add_device(mousedev);
736 if (error) 787 if (error)
@@ -740,37 +791,18 @@ static int mousedev_connect(struct input_handler *handler, struct input_dev *dev
740 791
741 err_unregister_handle: 792 err_unregister_handle:
742 input_unregister_handle(&mousedev->handle); 793 input_unregister_handle(&mousedev->handle);
743 err_remove_link: 794 err_delete_mousedev:
744 sysfs_remove_link(&input_class.subsys.kobj, mousedev->name); 795 device_unregister(&mousedev->dev);
745 err_cdev_destroy:
746 class_device_destroy(&input_class, devt);
747 err_free_mousedev:
748 mousedev_table[minor] = NULL;
749 kfree(mousedev);
750 return error; 796 return error;
751} 797}
752 798
753static void mousedev_disconnect(struct input_handle *handle) 799static void mousedev_disconnect(struct input_handle *handle)
754{ 800{
755 struct mousedev *mousedev = handle->private; 801 struct mousedev *mousedev = handle->private;
756 struct mousedev_client *client;
757
758 input_unregister_handle(handle);
759
760 sysfs_remove_link(&input_class.subsys.kobj, mousedev->name);
761 class_device_destroy(&input_class,
762 MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor));
763 mousedev->exist = 0;
764 802
765 mixdev_remove_device(mousedev); 803 mixdev_remove_device(mousedev);
766 804 input_unregister_handle(handle);
767 if (mousedev->open) { 805 mousedev_destroy(mousedev);
768 input_close_device(handle);
769 list_for_each_entry(client, &mousedev->client_list, node)
770 kill_fasync(&client->fasync, SIGIO, POLL_HUP);
771 wake_up_interruptible(&mousedev->wait);
772 } else
773 mousedev_free(mousedev);
774} 806}
775 807
776static const struct input_device_id mousedev_ids[] = { 808static const struct input_device_id mousedev_ids[] = {
@@ -822,25 +854,16 @@ static int psaux_registered;
822 854
823static int __init mousedev_init(void) 855static int __init mousedev_init(void)
824{ 856{
825 struct class_device *cdev;
826 int error; 857 int error;
827 858
859 mousedev_mix = mousedev_create(NULL, &mousedev_handler, MOUSEDEV_MIX);
860 if (IS_ERR(mousedev_mix))
861 return PTR_ERR(mousedev_mix);
862
828 error = input_register_handler(&mousedev_handler); 863 error = input_register_handler(&mousedev_handler);
829 if (error) 864 if (error) {
865 mousedev_destroy(mousedev_mix);
830 return error; 866 return error;
831
832 memset(&mousedev_mix, 0, sizeof(struct mousedev));
833 INIT_LIST_HEAD(&mousedev_mix.client_list);
834 init_waitqueue_head(&mousedev_mix.wait);
835 mousedev_table[MOUSEDEV_MIX] = &mousedev_mix;
836 mousedev_mix.exist = 1;
837 mousedev_mix.minor = MOUSEDEV_MIX;
838
839 cdev = class_device_create(&input_class, NULL,
840 MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX), NULL, "mice");
841 if (IS_ERR(cdev)) {
842 input_unregister_handler(&mousedev_handler);
843 return PTR_ERR(cdev);
844 } 867 }
845 868
846#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX 869#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
@@ -863,9 +886,8 @@ static void __exit mousedev_exit(void)
863 if (psaux_registered) 886 if (psaux_registered)
864 misc_deregister(&psaux_mouse); 887 misc_deregister(&psaux_mouse);
865#endif 888#endif
866 class_device_destroy(&input_class,
867 MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX));
868 input_unregister_handler(&mousedev_handler); 889 input_unregister_handler(&mousedev_handler);
890 mousedev_destroy(mousedev_mix);
869} 891}
870 892
871module_init(mousedev_init); 893module_init(mousedev_init);