]> err.no Git - linux-2.6/blobdiff - drivers/input/input.c
Merge master.kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6
[linux-2.6] / drivers / input / input.c
index 83c77c990ddab8b8e6a6e17e4f360d3d2d0b40d1..7c4b4d37b3e657698808baf1e8366f056bc64065 100644 (file)
@@ -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.
@@ -674,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;
@@ -688,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) {