From 0fbf87caf70acec0c435233fbc39c7bd0aca3ca6 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 29 May 2005 02:29:25 -0500 Subject: Input: add semaphore and user count to input_dev structure; serialize open and close calls and ensure that device's open and close methods are only called when first user opens it or last user closes it. Signed-off-by: Dmitry Torokhov --- drivers/input/input.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) (limited to 'drivers/input/input.c') diff --git a/drivers/input/input.c b/drivers/input/input.c index 3385dd03abfc..1885f369e3e2 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -219,10 +219,24 @@ void input_release_device(struct input_handle *handle) int input_open_device(struct input_handle *handle) { + struct input_dev *dev = handle->dev; + int err; + + err = down_interruptible(&dev->sem); + if (err) + return err; + handle->open++; - if (handle->dev->open) - return handle->dev->open(handle->dev); - return 0; + + if (!dev->users++ && dev->open) + err = dev->open(dev); + + if (err) + handle->open--; + + up(&dev->sem); + + return err; } int input_flush_device(struct input_handle* handle, struct file* file) @@ -235,10 +249,17 @@ int input_flush_device(struct input_handle* handle, struct file* file) void input_close_device(struct input_handle *handle) { + struct input_dev *dev = handle->dev; + input_release_device(handle); - if (handle->dev->close) - handle->dev->close(handle->dev); + + down(&dev->sem); + + if (!--dev->users && dev->close) + dev->close(dev); handle->open--; + + up(&dev->sem); } static void input_link_handle(struct input_handle *handle) @@ -415,6 +436,8 @@ void input_register_device(struct input_dev *dev) set_bit(EV_SYN, dev->evbit); + init_MUTEX(&dev->sem); + /* * If delay and period are pre-set by the driver, then autorepeating * is handled by the driver itself and we don't do it in input.c. -- cgit v1.2.3 From e334016fc1735e491385e14157a0360cd85c321b Mon Sep 17 00:00:00 2001 From: Luke Kosewski Date: Wed, 1 Jun 2005 02:39:28 -0500 Subject: Input: do not corrupt system-wide procfs fops. entry->proc_fops is a pointer to struct file_operations. When we call create_proc_entry(...), it pointis to proc_file_operations, deep in fs/proc/generic.c. By adding a 'poll' member to this struct we effectively force the 'poll' member on every file in /proc, which is wrong (they all fail select(...) calls). This patch changes a copy of entry->proc_fops and reassigns it rather than changing the original member. Signed-off-by: Dmitry Torokhov --- drivers/input/input.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/input/input.c') diff --git a/drivers/input/input.c b/drivers/input/input.c index 1885f369e3e2..c1dbc04cf54a 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -697,6 +697,8 @@ static int input_handlers_read(char *buf, char **start, off_t pos, int count, in return (count > cnt) ? cnt : count; } +static struct file_operations input_fileops; + static int __init input_proc_init(void) { struct proc_dir_entry *entry; @@ -711,6 +713,8 @@ static int __init input_proc_init(void) return -ENOMEM; } entry->owner = THIS_MODULE; + input_fileops = *entry->proc_fops; + entry->proc_fops = &input_fileops; entry->proc_fops->poll = input_devices_poll; entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL); if (entry == NULL) { -- cgit v1.2.3