|
@@ -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.
|