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