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

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

diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/input.c linux/drivers/usb/input.c
@@ -35,20 +35,25 @@
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
 
-#ifndef MODULE
 EXPORT_SYMBOL(input_register_device);
 EXPORT_SYMBOL(input_unregister_device);
 EXPORT_SYMBOL(input_register_handler);
 EXPORT_SYMBOL(input_unregister_handler);
+EXPORT_SYMBOL(input_register_minor);
+EXPORT_SYMBOL(input_unregister_minor);
 EXPORT_SYMBOL(input_open_device);
 EXPORT_SYMBOL(input_close_device);
 EXPORT_SYMBOL(input_event);
-#endif
+
+#define INPUT_MAJOR	13
+#define INPUT_DEVICES	256
 
 static struct input_dev *input_dev = NULL;
 static struct input_handler *input_handler = NULL;
-
+static struct input_handler *input_table[8] = { NULL, /* ... */ };
+static devfs_handle_t input_devfs_handle = NULL;
 static int input_number = 0;
+static long input_devices[NBITS(INPUT_DEVICES)] = { 0, /* ... */ };
 
 void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
@@ -142,7 +147,8 @@
  */
 
 	while (handle) {
-		handle->handler->event(handle, type, code, value);
+		if (handle->open)
+			handle->handler->event(handle, type, code, value);
 		handle = handle->dnext;
 	}
 }
@@ -154,9 +160,48 @@
 	mod_timer(&dev->timer, jiffies + dev->rep[REP_PERIOD]);
 }
 
+int input_open_device(struct input_handle *handle)
+{
+	handle->open++;
+	if (handle->dev->open)
+		return handle->dev->open(handle->dev);
+	return 0;
+}
+
+void input_close_device(struct input_handle *handle)
+{
+	if (handle->dev->close)
+		handle->dev->close(handle->dev);
+	handle->open--;
+}
+
+static void input_link_handle(struct input_handle *handle)
+{
+	handle->dnext = handle->dev->handle;
+	handle->hnext = handle->handler->handle;
+	handle->dev->handle = handle;
+	handle->handler->handle = handle;
+}
+
+static void input_unlink_handle(struct input_handle *handle)
+{
+	struct input_handle **handleptr;
+
+	handleptr = &handle->dev->handle;
+	while (*handleptr && (*handleptr != handle))
+		handleptr = &((*handleptr)->dnext);
+	*handleptr = (*handleptr)->dnext;
+
+	handleptr = &handle->handler->handle;
+	while (*handleptr && (*handleptr != handle))
+		handleptr = &((*handleptr)->hnext);
+	*handleptr = (*handleptr)->hnext;
+}
+
 void input_register_device(struct input_dev *dev)
 {
 	struct input_handler *handler = input_handler;
+	struct input_handle *handle;
 
 /*
  * Initialize repeat timer to default values.
@@ -172,17 +217,25 @@
  * Add the device.
  */
 
-	MOD_INC_USE_COUNT;
-	dev->number = input_number++;
+	if (input_number >= INPUT_DEVICES) {
+		printk(KERN_WARNING "input: ran out of input device numbers!\n");
+		dev->number = input_number;
+	} else {
+		dev->number = find_first_zero_bit(input_devices, INPUT_DEVICES);
+		set_bit(dev->number, input_devices);
+	}
+		
 	dev->next = input_dev;	
 	input_dev = dev;
+	input_number++;
 
 /*
  * Notify handlers.
  */
 
 	while (handler) {
-		handler->connect(handler, dev);
+		if ((handle = handler->connect(handler, dev)))
+			input_link_handle(handle);
 		handler = handler->next;
 	}
 }
@@ -203,6 +256,7 @@
  */
 
 	while (handle) {
+		input_unlink_handle(handle);
 		handle->handler->disconnect(handle);
 		handle = handle->dnext;
 	}
@@ -216,12 +270,22 @@
 	*devptr = (*devptr)->next;
 
 	input_number--;
-	MOD_DEC_USE_COUNT;
+
+	if (dev->number < INPUT_DEVICES)
+		clear_bit(dev->number, input_devices);
 }
 
 void input_register_handler(struct input_handler *handler)
 {
 	struct input_dev *dev = input_dev;
+	struct input_handle *handle;
+
+/*
+ * Add minors if needed.
+ */
+
+	if (handler->fops != NULL)
+		input_table[handler->minor >> 5] = handler;
 
 /*
  * Add the handler.
@@ -235,7 +299,8 @@
  */
 
 	while (dev) {
-		handler->connect(handler, dev);
+		if ((handle = handler->connect(handler, dev)))
+			input_link_handle(handle);
 		dev = dev->next;
 	}
 }
@@ -250,6 +315,7 @@
  */
 
 	while (handle) {
+		input_unlink_handle(handle);
 		handler->disconnect(handle);
 		handle = handle->hnext;
 	}
@@ -263,42 +329,59 @@
 
 	*handlerptr = (*handlerptr)->next;
 
+/*
+ * Remove minors.
+ */
+
+	if (handler->fops != NULL)
+		input_table[handler->minor >> 5] = NULL;
 }
 
-void input_open_device(struct input_handle *handle)
+static int input_open_file(struct inode *inode, struct file *file)
 {
-	handle->dnext = handle->dev->handle;
-	handle->hnext = handle->handler->handle;
-	handle->dev->handle = handle;
-	handle->handler->handle = handle;
+	struct input_handler *handler = input_table[MINOR(inode->i_rdev) >> 5];
 
-	if (handle->dev->open)
-		handle->dev->open(handle->dev);
-}
+	if (!handler || !handler->fops || !handler->fops->open)
+		return -ENODEV;
 
-void input_close_device(struct input_handle *handle)
-{
-	struct input_handle **handleptr;
+	file->f_op = handler->fops;
 
-	if (handle->dev->close)
-		handle->dev->close(handle->dev);
-/*
- * Remove from device list of handles.
- */
+	return handler->fops->open(inode, file);
+}
 
-	handleptr = &handle->dev->handle;
+static struct file_operations input_fops = {
+	open: input_open_file,
+};
 
-	while (*handleptr && (*handleptr != handle))
-		handleptr = &((*handleptr)->dnext);
-	*handleptr = (*handleptr)->dnext;
+devfs_handle_t input_register_minor(char *name, int minor, int minor_base)
+{
+	char devfs_name[16];
+	sprintf(devfs_name, name, minor);
+	return devfs_register(input_devfs_handle, devfs_name, 0, DEVFS_FL_DEFAULT, INPUT_MAJOR, minor + minor_base,
+		S_IFCHR | S_IRUGO | S_IWUSR, 0, 0, &input_fops, NULL);
+}
 
-/*
- * Remove from handler list of handles.
- */
+void input_unregister_minor(devfs_handle_t handle)
+{
+	devfs_unregister(handle);
+}
 
-	handleptr = &handle->handler->handle;
+static int __init input_init(void)
+{
+	if (devfs_register_chrdev(INPUT_MAJOR, "input", &input_fops)) {
+		printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR);
+		return -EBUSY;
+	}
+	input_devfs_handle = devfs_mk_dir(NULL, "input", 5, NULL);
+	return 0;
+}
 
-	while (*handleptr && (*handleptr != handle))
-		handleptr = &((*handleptr)->hnext);
-	*handleptr = (*handleptr)->hnext;
+static void __exit input_exit(void)
+{
+	devfs_unregister(input_devfs_handle);
+        if (devfs_unregister_chrdev(INPUT_MAJOR, "input"))
+                printk(KERN_ERR "input: can't unregister char major %d", INPUT_MAJOR);
 }
+
+module_init(input_init);
+module_exit(input_exit);

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