summaryrefslogtreecommitdiffstats
path: root/drivers/input/mousedev.c
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2012-10-08 12:07:24 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2012-10-08 12:37:55 -0400
commit7f8d4cad1e4e11a45d02bd6e024cc2812963c38a (patch)
treeac592d99a390f1aecf9944e10d05abe4ec0f1b76 /drivers/input/mousedev.c
parent0124be49770469cfb258d7df4693e70b4c5fb013 (diff)
Input: extend the number of event (and other) devices
Extend the amount of character devices, such as eventX, mouseX and jsX, from a hard limit of 32 per input handler to about 1024 shared across all handlers. To be compatible with legacy installations input handlers will start creating char devices with minors in their legacy range, however once legacy range is exhausted they will start allocating minors from the dynamic range 256-1024. Reviewed-by: David Herrmann <dh.herrmann@googlemail.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
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