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>
This commit is contained in:
parent
58a007765b
commit
0fbf87caf7
@ -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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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 {
|
|||||||
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;
|
||||||
|
Loading…
Reference in New Issue
Block a user