summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor_core@ameritech.net>2005-05-29 02:29:25 -0500
committerDmitry Torokhov <dtor_core@ameritech.net>2005-05-29 02:29:25 -0500
commit0fbf87caf70acec0c435233fbc39c7bd0aca3ca6 (patch)
tree65fa9bdde1f04a1359c3599d351199f834eb01ec
parent58a007765bb5f16020e6000ecbdc5bcc6e54a147 (diff)
downloadop-kernel-dev-0fbf87caf70acec0c435233fbc39c7bd0aca3ca6.zip
op-kernel-dev-0fbf87caf70acec0c435233fbc39c7bd0aca3ca6.tar.gz
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 <dtor@mail.ru>
-rw-r--r--drivers/input/input.c33
-rw-r--r--include/linux/input.h4
2 files changed, 32 insertions, 5 deletions
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 3385dd0..1885f36 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.
diff --git a/include/linux/input.h b/include/linux/input.h
index 72731d7..43e8ece 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -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;
OpenPOWER on IntegriCloud