]> err.no Git - linux-2.6/commitdiff
Input: add semaphore and user count to input_dev structure;
authorDmitry Torokhov <dtor_core@ameritech.net>
Sun, 29 May 2005 07:29:25 +0000 (02:29 -0500)
committerDmitry Torokhov <dtor_core@ameritech.net>
Sun, 29 May 2005 07:29:25 +0000 (02:29 -0500)
       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 <dtor@mail.ru>
drivers/input/input.c
include/linux/input.h

index 3385dd03abfc17be819ce992eb8bc314eb64abc5..1885f369e3e2c4022e8f968c7445848704d99718 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.
index 72731d7d189ee2be0f223e77d75799e18d5eb26c..43e8ecec602b23d52dca5221939a92c0e4eb9a70 100644 (file)
@@ -859,6 +859,10 @@ struct input_dev {
        int (*erase_effect)(struct input_dev *dev, int effect_id);
 
        struct input_handle *grab;
+
+       struct semaphore sem;   /* serializes open and close operations */
+       unsigned int users;
+
        struct device *dev;
 
        struct list_head        h_list;