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.c132
1 files changed, 62 insertions, 70 deletions
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index 88b962aeef13..a1b4c37956b2 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -24,6 +24,7 @@
24#include <linux/random.h> 24#include <linux/random.h>
25#include <linux/major.h> 25#include <linux/major.h>
26#include <linux/device.h> 26#include <linux/device.h>
27#include <linux/cdev.h>
27#include <linux/kernel.h> 28#include <linux/kernel.h>
28 29
29MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); 30MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
@@ -58,14 +59,15 @@ struct mousedev_hw_data {
58 59
59struct mousedev { 60struct mousedev {
60 int open; 61 int open;
61 int minor;
62 struct input_handle handle; 62 struct input_handle handle;
63 wait_queue_head_t wait; 63 wait_queue_head_t wait;
64 struct list_head client_list; 64 struct list_head client_list;
65 spinlock_t client_lock; /* protects client_list */ 65 spinlock_t client_lock; /* protects client_list */
66 struct mutex mutex; 66 struct mutex mutex;
67 struct device dev; 67 struct device dev;
68 struct cdev cdev;
68 bool exist; 69 bool exist;
70 bool is_mixdev;
69 71
70 struct list_head mixdev_node; 72 struct list_head mixdev_node;
71 bool opened_by_mixdev; 73 bool opened_by_mixdev;
@@ -111,10 +113,6 @@ struct mousedev_client {
111static unsigned char mousedev_imps_seq[] = { 0xf3, 200, 0xf3, 100, 0xf3, 80 }; 113static unsigned char mousedev_imps_seq[] = { 0xf3, 200, 0xf3, 100, 0xf3, 80 };
112static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 }; 114static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 };
113 115
114static struct input_handler mousedev_handler;
115
116static struct mousedev *mousedev_table[MOUSEDEV_MINORS];
117static DEFINE_MUTEX(mousedev_table_mutex);
118static struct mousedev *mousedev_mix; 116static struct mousedev *mousedev_mix;
119static LIST_HEAD(mousedev_mix_list); 117static LIST_HEAD(mousedev_mix_list);
120 118
@@ -430,7 +428,7 @@ static int mousedev_open_device(struct mousedev *mousedev)
430 if (retval) 428 if (retval)
431 return retval; 429 return retval;
432 430
433 if (mousedev->minor == MOUSEDEV_MIX) 431 if (mousedev->is_mixdev)
434 mixdev_open_devices(); 432 mixdev_open_devices();
435 else if (!mousedev->exist) 433 else if (!mousedev->exist)
436 retval = -ENODEV; 434 retval = -ENODEV;
@@ -448,7 +446,7 @@ static void mousedev_close_device(struct mousedev *mousedev)
448{ 446{
449 mutex_lock(&mousedev->mutex); 447 mutex_lock(&mousedev->mutex);
450 448
451 if (mousedev->minor == MOUSEDEV_MIX) 449 if (mousedev->is_mixdev)
452 mixdev_close_devices(); 450 mixdev_close_devices();
453 else if (mousedev->exist && !--mousedev->open) 451 else if (mousedev->exist && !--mousedev->open)
454 input_close_device(&mousedev->handle); 452 input_close_device(&mousedev->handle);
@@ -535,35 +533,17 @@ static int mousedev_open(struct inode *inode, struct file *file)
535 struct mousedev_client *client; 533 struct mousedev_client *client;
536 struct mousedev *mousedev; 534 struct mousedev *mousedev;
537 int error; 535 int error;
538 int i;
539 536
540#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX 537#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
541 if (imajor(inode) == MISC_MAJOR) 538 if (imajor(inode) == MISC_MAJOR)
542 i = MOUSEDEV_MIX; 539 mousedev = mousedev_mix;
543 else 540 else
544#endif 541#endif
545 i = iminor(inode) - MOUSEDEV_MINOR_BASE; 542 mousedev = container_of(inode->i_cdev, struct mousedev, cdev);
546
547 if (i >= MOUSEDEV_MINORS)
548 return -ENODEV;
549
550 error = mutex_lock_interruptible(&mousedev_table_mutex);
551 if (error)
552 return error;
553
554 mousedev = mousedev_table[i];
555 if (mousedev)
556 get_device(&mousedev->dev);
557 mutex_unlock(&mousedev_table_mutex);
558
559 if (!mousedev)
560 return -ENODEV;
561 543
562 client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL); 544 client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL);
563 if (!client) { 545 if (!client)
564 error = -ENOMEM; 546 return -ENOMEM;
565 goto err_put_mousedev;
566 }
567 547
568 spin_lock_init(&client->packet_lock); 548 spin_lock_init(&client->packet_lock);
569 client->pos_x = xres / 2; 549 client->pos_x = xres / 2;
@@ -577,13 +557,13 @@ static int mousedev_open(struct inode *inode, struct file *file)
577 557
578 file->private_data = client; 558 file->private_data = client;
579 nonseekable_open(inode, file); 559 nonseekable_open(inode, file);
560
561 get_device(&mousedev->dev);
580 return 0; 562 return 0;
581 563
582 err_free_client: 564 err_free_client:
583 mousedev_detach_client(mousedev, client); 565 mousedev_detach_client(mousedev, client);
584 kfree(client); 566 kfree(client);
585 err_put_mousedev:
586 put_device(&mousedev->dev);
587 return error; 567 return error;
588} 568}
589 569
@@ -793,19 +773,6 @@ static const struct file_operations mousedev_fops = {
793 .llseek = noop_llseek, 773 .llseek = noop_llseek,
794}; 774};
795 775
796static int mousedev_install_chrdev(struct mousedev *mousedev)
797{
798 mousedev_table[mousedev->minor] = mousedev;
799 return 0;
800}
801
802static void mousedev_remove_chrdev(struct mousedev *mousedev)
803{
804 mutex_lock(&mousedev_table_mutex);
805 mousedev_table[mousedev->minor] = NULL;
806 mutex_unlock(&mousedev_table_mutex);
807}
808
809/* 776/*
810 * Mark device non-existent. This disables writes, ioctls and 777 * Mark device non-existent. This disables writes, ioctls and
811 * prevents new users from opening the device. Already posted 778 * prevents new users from opening the device. Already posted
@@ -840,24 +807,50 @@ static void mousedev_cleanup(struct mousedev *mousedev)
840 807
841 mousedev_mark_dead(mousedev); 808 mousedev_mark_dead(mousedev);
842 mousedev_hangup(mousedev); 809 mousedev_hangup(mousedev);
843 mousedev_remove_chrdev(mousedev); 810
811 cdev_del(&mousedev->cdev);
844 812
845 /* mousedev is marked dead so no one else accesses mousedev->open */ 813 /* mousedev is marked dead so no one else accesses mousedev->open */
846 if (mousedev->open) 814 if (mousedev->open)
847 input_close_device(handle); 815 input_close_device(handle);
848} 816}
849 817
818static int mousedev_reserve_minor(bool mixdev)
819{
820 int minor;
821
822 if (mixdev) {
823 minor = input_get_new_minor(MOUSEDEV_MIX, 1, false);
824 if (minor < 0)
825 pr_err("failed to reserve mixdev minor: %d\n", minor);
826 } else {
827 minor = input_get_new_minor(MOUSEDEV_MINOR_BASE,
828 MOUSEDEV_MINORS, true);
829 if (minor < 0)
830 pr_err("failed to reserve new minor: %d\n", minor);
831 }
832
833 return minor;
834}
835
850static struct mousedev *mousedev_create(struct input_dev *dev, 836static struct mousedev *mousedev_create(struct input_dev *dev,
851 struct input_handler *handler, 837 struct input_handler *handler,
852 int minor) 838 bool mixdev)
853{ 839{
854 struct mousedev *mousedev; 840 struct mousedev *mousedev;
841 int minor;
855 int error; 842 int error;
856 843
844 minor = mousedev_reserve_minor(mixdev);
845 if (minor < 0) {
846 error = minor;
847 goto err_out;
848 }
849
857 mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL); 850 mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL);
858 if (!mousedev) { 851 if (!mousedev) {
859 error = -ENOMEM; 852 error = -ENOMEM;
860 goto err_out; 853 goto err_free_minor;
861 } 854 }
862 855
863 INIT_LIST_HEAD(&mousedev->client_list); 856 INIT_LIST_HEAD(&mousedev->client_list);
@@ -865,16 +858,21 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
865 spin_lock_init(&mousedev->client_lock); 858 spin_lock_init(&mousedev->client_lock);
866 mutex_init(&mousedev->mutex); 859 mutex_init(&mousedev->mutex);
867 lockdep_set_subclass(&mousedev->mutex, 860 lockdep_set_subclass(&mousedev->mutex,
868 minor == MOUSEDEV_MIX ? SINGLE_DEPTH_NESTING : 0); 861 mixdev ? SINGLE_DEPTH_NESTING : 0);
869 init_waitqueue_head(&mousedev->wait); 862 init_waitqueue_head(&mousedev->wait);
870 863
871 if (minor == MOUSEDEV_MIX) 864 if (mixdev) {
872 dev_set_name(&mousedev->dev, "mice"); 865 dev_set_name(&mousedev->dev, "mice");
873 else 866 } else {
874 dev_set_name(&mousedev->dev, "mouse%d", minor); 867 int dev_no = minor;
868 /* Normalize device number if it falls into legacy range */
869 if (dev_no < MOUSEDEV_MINOR_BASE + MOUSEDEV_MINORS)
870 dev_no -= MOUSEDEV_MINOR_BASE;
871 dev_set_name(&mousedev->dev, "mouse%d", dev_no);
872 }
875 873
876 mousedev->minor = minor;
877 mousedev->exist = true; 874 mousedev->exist = true;
875 mousedev->is_mixdev = mixdev;
878 mousedev->handle.dev = input_get_device(dev); 876 mousedev->handle.dev = input_get_device(dev);
879 mousedev->handle.name = dev_name(&mousedev->dev); 877 mousedev->handle.name = dev_name(&mousedev->dev);
880 mousedev->handle.handler = handler; 878 mousedev->handle.handler = handler;
@@ -883,17 +881,18 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
883 mousedev->dev.class = &input_class; 881 mousedev->dev.class = &input_class;
884 if (dev) 882 if (dev)
885 mousedev->dev.parent = &dev->dev; 883 mousedev->dev.parent = &dev->dev;
886 mousedev->dev.devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor); 884 mousedev->dev.devt = MKDEV(INPUT_MAJOR, minor);
887 mousedev->dev.release = mousedev_free; 885 mousedev->dev.release = mousedev_free;
888 device_initialize(&mousedev->dev); 886 device_initialize(&mousedev->dev);
889 887
890 if (minor != MOUSEDEV_MIX) { 888 if (!mixdev) {
891 error = input_register_handle(&mousedev->handle); 889 error = input_register_handle(&mousedev->handle);
892 if (error) 890 if (error)
893 goto err_free_mousedev; 891 goto err_free_mousedev;
894 } 892 }
895 893
896 error = mousedev_install_chrdev(mousedev); 894 cdev_init(&mousedev->cdev, &mousedev_fops);
895 error = cdev_add(&mousedev->cdev, mousedev->dev.devt, 1);
897 if (error) 896 if (error)
898 goto err_unregister_handle; 897 goto err_unregister_handle;
899 898
@@ -906,10 +905,12 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
906 err_cleanup_mousedev: 905 err_cleanup_mousedev:
907 mousedev_cleanup(mousedev); 906 mousedev_cleanup(mousedev);
908 err_unregister_handle: 907 err_unregister_handle:
909 if (minor != MOUSEDEV_MIX) 908 if (!mixdev)
910 input_unregister_handle(&mousedev->handle); 909 input_unregister_handle(&mousedev->handle);
911 err_free_mousedev: 910 err_free_mousedev:
912 put_device(&mousedev->dev); 911 put_device(&mousedev->dev);
912 err_free_minor:
913 input_free_minor(minor);
913 err_out: 914 err_out:
914 return ERR_PTR(error); 915 return ERR_PTR(error);
915} 916}
@@ -918,7 +919,8 @@ static void mousedev_destroy(struct mousedev *mousedev)
918{ 919{
919 device_del(&mousedev->dev); 920 device_del(&mousedev->dev);
920 mousedev_cleanup(mousedev); 921 mousedev_cleanup(mousedev);
921 if (mousedev->minor != MOUSEDEV_MIX) 922 input_free_minor(MINOR(mousedev->dev.devt));
923 if (!mousedev->is_mixdev)
922 input_unregister_handle(&mousedev->handle); 924 input_unregister_handle(&mousedev->handle);
923 put_device(&mousedev->dev); 925 put_device(&mousedev->dev);
924} 926}
@@ -967,19 +969,9 @@ static int mousedev_connect(struct input_handler *handler,
967 const struct input_device_id *id) 969 const struct input_device_id *id)
968{ 970{
969 struct mousedev *mousedev; 971 struct mousedev *mousedev;
970 int minor;
971 int error; 972 int error;
972 973
973 for (minor = 0; minor < MOUSEDEV_MINORS; minor++) 974 mousedev = mousedev_create(dev, handler, false);
974 if (!mousedev_table[minor])
975 break;
976
977 if (minor == MOUSEDEV_MINORS) {
978 pr_err("no more free mousedev devices\n");
979 return -ENFILE;
980 }
981
982 mousedev = mousedev_create(dev, handler, minor);
983 if (IS_ERR(mousedev)) 975 if (IS_ERR(mousedev))
984 return PTR_ERR(mousedev); 976 return PTR_ERR(mousedev);
985 977
@@ -1055,7 +1047,7 @@ static struct input_handler mousedev_handler = {
1055 .event = mousedev_event, 1047 .event = mousedev_event,
1056 .connect = mousedev_connect, 1048 .connect = mousedev_connect,
1057 .disconnect = mousedev_disconnect, 1049 .disconnect = mousedev_disconnect,
1058 .fops = &mousedev_fops, 1050 .legacy_minors = true,
1059 .minor = MOUSEDEV_MINOR_BASE, 1051 .minor = MOUSEDEV_MINOR_BASE,
1060 .name = "mousedev", 1052 .name = "mousedev",
1061 .id_table = mousedev_ids, 1053 .id_table = mousedev_ids,
@@ -1098,7 +1090,7 @@ static int __init mousedev_init(void)
1098{ 1090{
1099 int error; 1091 int error;
1100 1092
1101 mousedev_mix = mousedev_create(NULL, &mousedev_handler, MOUSEDEV_MIX); 1093 mousedev_mix = mousedev_create(NULL, &mousedev_handler, true);
1102 if (IS_ERR(mousedev_mix)) 1094 if (IS_ERR(mousedev_mix))
1103 return PTR_ERR(mousedev_mix); 1095 return PTR_ERR(mousedev_mix);
1104 1096