patch-2.3.99-pre4 linux/drivers/usb/joydev.c

Next file: linux/drivers/usb/keybdev.c
Previous file: linux/drivers/usb/input.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/joydev.c linux/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 *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 @@
 	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_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 @@
 	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 @@
 			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 @@
 		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 @@
 	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 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);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)