diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-04-19 04:00:00 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-04-19 04:00:00 +0000 |
commit | 46e045034336a2cc90c1798cd7cc07af744ddfd6 (patch) | |
tree | 3b9b51fc482e729f663d25333e77fbed9aaa939a /drivers/usb/input.c | |
parent | 31dc59d503a02e84c4de98826452acaeb56dc15a (diff) |
Merge with Linux 2.3.99-pre4.
Diffstat (limited to 'drivers/usb/input.c')
-rw-r--r-- | drivers/usb/input.c | 155 |
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); |