summaryrefslogtreecommitdiffstats
path: root/drivers/usb/input.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-04-19 04:00:00 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-04-19 04:00:00 +0000
commit46e045034336a2cc90c1798cd7cc07af744ddfd6 (patch)
tree3b9b51fc482e729f663d25333e77fbed9aaa939a /drivers/usb/input.c
parent31dc59d503a02e84c4de98826452acaeb56dc15a (diff)
Merge with Linux 2.3.99-pre4.
Diffstat (limited to 'drivers/usb/input.c')
-rw-r--r--drivers/usb/input.c155
1 files changed, 119 insertions, 36 deletions
diff --git a/drivers/usb/input.c b/drivers/usb/input.c
index e370927b3..73f39db7c 100644
--- a/drivers/usb/input.c
+++ b/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 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in
*/
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 @@ static void input_repeat_key(unsigned long data)
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 @@ void input_register_device(struct input_dev *dev)
* 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 @@ void input_unregister_device(struct input_dev *dev)
*/
while (handle) {
+ input_unlink_handle(handle);
handle->handler->disconnect(handle);
handle = handle->dnext;
}
@@ -216,12 +270,22 @@ void input_unregister_device(struct input_dev *dev)
*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 @@ void input_register_handler(struct input_handler *handler)
*/
while (dev) {
- handler->connect(handler, dev);
+ if ((handle = handler->connect(handler, dev)))
+ input_link_handle(handle);
dev = dev->next;
}
}
@@ -250,6 +315,7 @@ void input_unregister_handler(struct input_handler *handler)
*/
while (handle) {
+ input_unlink_handle(handle);
handler->disconnect(handle);
handle = handle->hnext;
}
@@ -263,42 +329,59 @@ void input_unregister_handler(struct input_handler *handler)
*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);