Commit 0fbf87ca authored by Dmitry Torokhov's avatar Dmitry Torokhov

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: default avatarDmitry Torokhov <dtor@mail.ru>
parent 58a00776
...@@ -219,10 +219,24 @@ void input_release_device(struct input_handle *handle) ...@@ -219,10 +219,24 @@ void input_release_device(struct input_handle *handle)
int input_open_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++; handle->open++;
if (handle->dev->open)
return handle->dev->open(handle->dev); if (!dev->users++ && dev->open)
return 0; err = dev->open(dev);
if (err)
handle->open--;
up(&dev->sem);
return err;
} }
int input_flush_device(struct input_handle* handle, struct file* file) 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) ...@@ -235,10 +249,17 @@ int input_flush_device(struct input_handle* handle, struct file* file)
void input_close_device(struct input_handle *handle) void input_close_device(struct input_handle *handle)
{ {
struct input_dev *dev = handle->dev;
input_release_device(handle); 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--; handle->open--;
up(&dev->sem);
} }
static void input_link_handle(struct input_handle *handle) static void input_link_handle(struct input_handle *handle)
...@@ -415,6 +436,8 @@ void input_register_device(struct input_dev *dev) ...@@ -415,6 +436,8 @@ void input_register_device(struct input_dev *dev)
set_bit(EV_SYN, dev->evbit); set_bit(EV_SYN, dev->evbit);
init_MUTEX(&dev->sem);
/* /*
* If delay and period are pre-set by the driver, then autorepeating * 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. * is handled by the driver itself and we don't do it in input.c.
......
...@@ -859,6 +859,10 @@ struct input_dev { ...@@ -859,6 +859,10 @@ struct input_dev {
int (*erase_effect)(struct input_dev *dev, int effect_id); int (*erase_effect)(struct input_dev *dev, int effect_id);
struct input_handle *grab; struct input_handle *grab;
struct semaphore sem; /* serializes open and close operations */
unsigned int users;
struct device *dev; struct device *dev;
struct list_head h_list; struct list_head h_list;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment