summaryrefslogtreecommitdiffstats
path: root/drivers/usb/joydev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/joydev.c')
-rw-r--r--drivers/usb/joydev.c91
1 files changed, 48 insertions, 43 deletions
diff --git a/drivers/usb/joydev.c b/drivers/usb/joydev.c
index 9b54300e2..585740db9 100644
--- a/drivers/usb/joydev.c
+++ b/drivers/usb/joydev.c
@@ -45,15 +45,18 @@
#include <linux/poll.h>
#include <linux/init.h>
-#define JOYDEV_MAJOR 15
+#define JOYDEV_MINOR_BASE 0
+#define JOYDEV_MINORS 32
#define JOYDEV_BUFFER_SIZE 64
struct joydev {
- char name[32];
int used;
- struct input_handle handle;
+ int open;
int minor;
+ char name[32];
+ struct input_handle handle;
wait_queue_head_t wait;
+ devfs_handle_t devfs;
struct joydev *next;
struct joydev_list *list;
struct js_corr corr[ABS_MAX];
@@ -76,11 +79,10 @@ struct joydev_list {
struct joydev_list *next;
};
-static unsigned long joydev_minors = 0;
-static struct joydev *joydev_base[BITS_PER_LONG];
+static struct joydev *joydev_table[JOYDEV_MINORS];
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_SUPPORTED_DEVICE("js");
+MODULE_SUPPORTED_DEVICE("input/js");
static int joydev_correct(int value, struct js_corr *corr)
{
@@ -164,9 +166,13 @@ static int joydev_release(struct inode * inode, struct file * file)
while (*listptr && (*listptr != list))
listptr = &((*listptr)->next);
*listptr = (*listptr)->next;
+
+ if (!--list->joydev->open)
+ input_close_device(&list->joydev->handle);
if (!--list->joydev->used) {
- clear_bit(list->joydev->minor, &joydev_minors);
+ input_unregister_minor(list->joydev->devfs);
+ joydev_table[list->joydev->minor] = NULL;
kfree(list->joydev);
}
@@ -179,28 +185,30 @@ static int joydev_release(struct inode * inode, struct file * file)
static int joydev_open(struct inode *inode, struct file *file)
{
struct joydev_list *list;
- int i = MINOR(inode->i_rdev);
+ int i = MINOR(inode->i_rdev) - JOYDEV_MINOR_BASE;
- if (MAJOR(inode->i_rdev) != JOYSTICK_MAJOR)
- return -EINVAL;
-
- if (i > BITS_PER_LONG || !test_bit(i, &joydev_minors))
+ if (i > JOYDEV_MINORS || !joydev_table[i])
return -ENODEV;
- if (!(list = kmalloc(sizeof(struct joydev_list), GFP_KERNEL)))
- return -ENOMEM;
+ MOD_INC_USE_COUNT;
+ if (!(list = kmalloc(sizeof(struct joydev_list), GFP_KERNEL))) {
+ MOD_DEC_USE_COUNT;
+ return -ENOMEM;
+ }
memset(list, 0, sizeof(struct joydev_list));
- list->joydev = joydev_base[i];
- list->next = joydev_base[i]->list;
- joydev_base[i]->list = list;
+ list->joydev = joydev_table[i];
+ list->next = joydev_table[i]->list;
+ joydev_table[i]->list = list;
file->private_data = list;
list->joydev->used++;
- MOD_INC_USE_COUNT;
+ if (!list->joydev->open++)
+ input_open_device(&list->joydev->handle);
+
return 0;
}
@@ -370,30 +378,33 @@ static struct file_operations joydev_fops = {
fasync: joydev_fasync,
};
-static int joydev_connect(struct input_handler *handler, struct input_dev *dev)
+static struct input_handle *joydev_connect(struct input_handler *handler, struct input_dev *dev)
{
struct joydev *joydev;
- int i, j;
+ int i, j, minor;
if (!(test_bit(EV_KEY, dev->evbit) && test_bit(EV_ABS, dev->evbit) &&
test_bit(ABS_X, dev->absbit) && test_bit(ABS_Y, dev->absbit) &&
(test_bit(BTN_TRIGGER, dev->keybit) || test_bit(BTN_A, dev->keybit)
- || test_bit(BTN_1, dev->keybit)))) return -1;
+ || test_bit(BTN_1, dev->keybit)))) return NULL;
- if (!(joydev = kmalloc(sizeof(struct joydev), GFP_KERNEL)))
- return -1;
+ for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++);
+ if (joydev_table[minor]) {
+ printk(KERN_ERR "joydev: no more free joydev devices\n");
+ return NULL;
+ }
+ if (!(joydev = kmalloc(sizeof(struct joydev), GFP_KERNEL)))
+ return NULL;
memset(joydev, 0, sizeof(struct joydev));
init_waitqueue_head(&joydev->wait);
- if (joydev_minors == -1) {
- printk("Can't register new joystick - 32 devices already taken.\n");
- return -1;
- }
-
sprintf(joydev->name, "joydev%d", joydev->minor);
+ joydev->minor = minor;
+ joydev_table[minor] = joydev;
+
joydev->handle.dev = dev;
joydev->handle.handler = handler;
joydev->handle.private = joydev;
@@ -421,10 +432,6 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev)
joydev->nkey++;
}
- joydev->minor = ffz(joydev_minors);
- set_bit(joydev->minor, &joydev_minors);
- joydev_base[joydev->minor] = joydev;
-
for (i = 0; i < joydev->nabs; i++) {
j = joydev->abspam[i];
if (dev->absmax[j] == dev->absmin[j]) {
@@ -439,21 +446,23 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev)
joydev->corr[i].coef[3] = (1 << 29) / ((dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j]);
}
- input_open_device(&joydev->handle);
+ joydev->devfs = input_register_minor("js%d", minor, JOYDEV_MINOR_BASE);
- printk("%s: Joystick device for input%d on /dev/js%d\n", joydev->name, dev->number, joydev->minor);
+ printk("js%d: Joystick device for input%d\n", minor, dev->number);
- return 0;
+ return &joydev->handle;
}
static void joydev_disconnect(struct input_handle *handle)
{
struct joydev *joydev = handle->private;
- input_close_device(handle);
+ if (joydev->open)
+ input_close_device(handle);
if (!--joydev->used) {
- clear_bit(joydev->minor, &joydev_minors);
+ input_unregister_minor(joydev->devfs);
+ joydev_table[joydev->minor] = NULL;
kfree(joydev);
}
}
@@ -462,14 +471,12 @@ static struct input_handler joydev_handler = {
event: joydev_event,
connect: joydev_connect,
disconnect: joydev_disconnect,
+ fops: &joydev_fops,
+ minor: JOYDEV_MINOR_BASE,
};
static int __init joydev_init(void)
{
- if (register_chrdev(JOYDEV_MAJOR, "js", &joydev_fops)) {
- printk(KERN_ERR "joydev: unable to get major %d for joystick\n", JOYDEV_MAJOR);
- return -EBUSY;
- }
input_register_handler(&joydev_handler);
return 0;
}
@@ -477,8 +484,6 @@ static int __init joydev_init(void)
static void __exit joydev_exit(void)
{
input_unregister_handler(&joydev_handler);
- if (unregister_chrdev(JOYSTICK_MAJOR, "js"))
- printk(KERN_ERR "js: can't unregister device\n");
}
module_init(joydev_init);