aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/joydev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/joydev.c')
-rw-r--r--drivers/input/joydev.c89
1 files changed, 32 insertions, 57 deletions
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 78f323ea1e4b..f362883c94e3 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -27,6 +27,7 @@
27#include <linux/poll.h> 27#include <linux/poll.h>
28#include <linux/init.h> 28#include <linux/init.h>
29#include <linux/device.h> 29#include <linux/device.h>
30#include <linux/cdev.h>
30 31
31MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); 32MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
32MODULE_DESCRIPTION("Joystick device interfaces"); 33MODULE_DESCRIPTION("Joystick device interfaces");
@@ -39,13 +40,13 @@ MODULE_LICENSE("GPL");
39 40
40struct joydev { 41struct joydev {
41 int open; 42 int open;
42 int minor;
43 struct input_handle handle; 43 struct input_handle handle;
44 wait_queue_head_t wait; 44 wait_queue_head_t wait;
45 struct list_head client_list; 45 struct list_head client_list;
46 spinlock_t client_lock; /* protects client_list */ 46 spinlock_t client_lock; /* protects client_list */
47 struct mutex mutex; 47 struct mutex mutex;
48 struct device dev; 48 struct device dev;
49 struct cdev cdev;
49 bool exist; 50 bool exist;
50 51
51 struct js_corr corr[ABS_CNT]; 52 struct js_corr corr[ABS_CNT];
@@ -70,9 +71,6 @@ struct joydev_client {
70 struct list_head node; 71 struct list_head node;
71}; 72};
72 73
73static struct joydev *joydev_table[JOYDEV_MINORS];
74static DEFINE_MUTEX(joydev_table_mutex);
75
76static int joydev_correct(int value, struct js_corr *corr) 74static int joydev_correct(int value, struct js_corr *corr)
77{ 75{
78 switch (corr->type) { 76 switch (corr->type) {
@@ -245,37 +243,20 @@ static int joydev_release(struct inode *inode, struct file *file)
245 kfree(client); 243 kfree(client);
246 244
247 joydev_close_device(joydev); 245 joydev_close_device(joydev);
248 put_device(&joydev->dev);
249 246
250 return 0; 247 return 0;
251} 248}
252 249
253static int joydev_open(struct inode *inode, struct file *file) 250static int joydev_open(struct inode *inode, struct file *file)
254{ 251{
252 struct joydev *joydev =
253 container_of(inode->i_cdev, struct joydev, cdev);
255 struct joydev_client *client; 254 struct joydev_client *client;
256 struct joydev *joydev;
257 int i = iminor(inode) - JOYDEV_MINOR_BASE;
258 int error; 255 int error;
259 256
260 if (i >= JOYDEV_MINORS)
261 return -ENODEV;
262
263 error = mutex_lock_interruptible(&joydev_table_mutex);
264 if (error)
265 return error;
266 joydev = joydev_table[i];
267 if (joydev)
268 get_device(&joydev->dev);
269 mutex_unlock(&joydev_table_mutex);
270
271 if (!joydev)
272 return -ENODEV;
273
274 client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL); 257 client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL);
275 if (!client) { 258 if (!client)
276 error = -ENOMEM; 259 return -ENOMEM;
277 goto err_put_joydev;
278 }
279 260
280 spin_lock_init(&client->buffer_lock); 261 spin_lock_init(&client->buffer_lock);
281 client->joydev = joydev; 262 client->joydev = joydev;
@@ -293,8 +274,6 @@ static int joydev_open(struct inode *inode, struct file *file)
293 err_free_client: 274 err_free_client:
294 joydev_detach_client(joydev, client); 275 joydev_detach_client(joydev, client);
295 kfree(client); 276 kfree(client);
296 err_put_joydev:
297 put_device(&joydev->dev);
298 return error; 277 return error;
299} 278}
300 279
@@ -742,19 +721,6 @@ static const struct file_operations joydev_fops = {
742 .llseek = no_llseek, 721 .llseek = no_llseek,
743}; 722};
744 723
745static int joydev_install_chrdev(struct joydev *joydev)
746{
747 joydev_table[joydev->minor] = joydev;
748 return 0;
749}
750
751static void joydev_remove_chrdev(struct joydev *joydev)
752{
753 mutex_lock(&joydev_table_mutex);
754 joydev_table[joydev->minor] = NULL;
755 mutex_unlock(&joydev_table_mutex);
756}
757
758/* 724/*
759 * Mark device non-existent. This disables writes, ioctls and 725 * Mark device non-existent. This disables writes, ioctls and
760 * prevents new users from opening the device. Already posted 726 * prevents new users from opening the device. Already posted
@@ -773,7 +739,8 @@ static void joydev_cleanup(struct joydev *joydev)
773 739
774 joydev_mark_dead(joydev); 740 joydev_mark_dead(joydev);
775 joydev_hangup(joydev); 741 joydev_hangup(joydev);
776 joydev_remove_chrdev(joydev); 742
743 cdev_del(&joydev->cdev);
777 744
778 /* joydev is marked dead so no one else accesses joydev->open */ 745 /* joydev is marked dead so no one else accesses joydev->open */
779 if (joydev->open) 746 if (joydev->open)
@@ -798,30 +765,33 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
798 const struct input_device_id *id) 765 const struct input_device_id *id)
799{ 766{
800 struct joydev *joydev; 767 struct joydev *joydev;
801 int i, j, t, minor; 768 int i, j, t, minor, dev_no;
802 int error; 769 int error;
803 770
804 for (minor = 0; minor < JOYDEV_MINORS; minor++) 771 minor = input_get_new_minor(JOYDEV_MINOR_BASE, JOYDEV_MINORS, true);
805 if (!joydev_table[minor]) 772 if (minor < 0) {
806 break; 773 error = minor;
807 774 pr_err("failed to reserve new minor: %d\n", error);
808 if (minor == JOYDEV_MINORS) { 775 return error;
809 pr_err("no more free joydev devices\n");
810 return -ENFILE;
811 } 776 }
812 777
813 joydev = kzalloc(sizeof(struct joydev), GFP_KERNEL); 778 joydev = kzalloc(sizeof(struct joydev), GFP_KERNEL);
814 if (!joydev) 779 if (!joydev) {
815 return -ENOMEM; 780 error = -ENOMEM;
781 goto err_free_minor;
782 }
816 783
817 INIT_LIST_HEAD(&joydev->client_list); 784 INIT_LIST_HEAD(&joydev->client_list);
818 spin_lock_init(&joydev->client_lock); 785 spin_lock_init(&joydev->client_lock);
819 mutex_init(&joydev->mutex); 786 mutex_init(&joydev->mutex);
820 init_waitqueue_head(&joydev->wait); 787 init_waitqueue_head(&joydev->wait);
821
822 dev_set_name(&joydev->dev, "js%d", minor);
823 joydev->exist = true; 788 joydev->exist = true;
824 joydev->minor = minor; 789
790 dev_no = minor;
791 /* Normalize device number if it falls into legacy range */
792 if (dev_no < JOYDEV_MINOR_BASE + JOYDEV_MINORS)
793 dev_no -= JOYDEV_MINOR_BASE;
794 dev_set_name(&joydev->dev, "js%d", dev_no);
825 795
826 joydev->handle.dev = input_get_device(dev); 796 joydev->handle.dev = input_get_device(dev);
827 joydev->handle.name = dev_name(&joydev->dev); 797 joydev->handle.name = dev_name(&joydev->dev);
@@ -875,7 +845,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
875 } 845 }
876 } 846 }
877 847
878 joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor); 848 joydev->dev.devt = MKDEV(INPUT_MAJOR, minor);
879 joydev->dev.class = &input_class; 849 joydev->dev.class = &input_class;
880 joydev->dev.parent = &dev->dev; 850 joydev->dev.parent = &dev->dev;
881 joydev->dev.release = joydev_free; 851 joydev->dev.release = joydev_free;
@@ -885,7 +855,9 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
885 if (error) 855 if (error)
886 goto err_free_joydev; 856 goto err_free_joydev;
887 857
888 error = joydev_install_chrdev(joydev); 858 cdev_init(&joydev->cdev, &joydev_fops);
859 joydev->cdev.kobj.parent = &joydev->dev.kobj;
860 error = cdev_add(&joydev->cdev, joydev->dev.devt, 1);
889 if (error) 861 if (error)
890 goto err_unregister_handle; 862 goto err_unregister_handle;
891 863
@@ -901,6 +873,8 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
901 input_unregister_handle(&joydev->handle); 873 input_unregister_handle(&joydev->handle);
902 err_free_joydev: 874 err_free_joydev:
903 put_device(&joydev->dev); 875 put_device(&joydev->dev);
876 err_free_minor:
877 input_free_minor(minor);
904 return error; 878 return error;
905} 879}
906 880
@@ -910,6 +884,7 @@ static void joydev_disconnect(struct input_handle *handle)
910 884
911 device_del(&joydev->dev); 885 device_del(&joydev->dev);
912 joydev_cleanup(joydev); 886 joydev_cleanup(joydev);
887 input_free_minor(MINOR(joydev->dev.devt));
913 input_unregister_handle(handle); 888 input_unregister_handle(handle);
914 put_device(&joydev->dev); 889 put_device(&joydev->dev);
915} 890}
@@ -961,7 +936,7 @@ static struct input_handler joydev_handler = {
961 .match = joydev_match, 936 .match = joydev_match,
962 .connect = joydev_connect, 937 .connect = joydev_connect,
963 .disconnect = joydev_disconnect, 938 .disconnect = joydev_disconnect,
964 .fops = &joydev_fops, 939 .legacy_minors = true,
965 .minor = JOYDEV_MINOR_BASE, 940 .minor = JOYDEV_MINOR_BASE,
966 .name = "joydev", 941 .name = "joydev",
967 .id_table = joydev_ids, 942 .id_table = joydev_ids,