diff options
Diffstat (limited to 'drivers/input/input.c')
-rw-r--r-- | drivers/input/input.c | 37 |
1 files changed, 32 insertions, 5 deletions
diff --git a/drivers/input/input.c b/drivers/input/input.c index 83c77c990dda..7c4b4d37b3e6 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
@@ -219,10 +219,24 @@ void input_release_device(struct input_handle *handle) | |||
219 | 219 | ||
220 | int input_open_device(struct input_handle *handle) | 220 | int input_open_device(struct input_handle *handle) |
221 | { | 221 | { |
222 | struct input_dev *dev = handle->dev; | ||
223 | int err; | ||
224 | |||
225 | err = down_interruptible(&dev->sem); | ||
226 | if (err) | ||
227 | return err; | ||
228 | |||
222 | handle->open++; | 229 | handle->open++; |
223 | if (handle->dev->open) | 230 | |
224 | return handle->dev->open(handle->dev); | 231 | if (!dev->users++ && dev->open) |
225 | return 0; | 232 | err = dev->open(dev); |
233 | |||
234 | if (err) | ||
235 | handle->open--; | ||
236 | |||
237 | up(&dev->sem); | ||
238 | |||
239 | return err; | ||
226 | } | 240 | } |
227 | 241 | ||
228 | int input_flush_device(struct input_handle* handle, struct file* file) | 242 | 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 | 249 | ||
236 | void input_close_device(struct input_handle *handle) | 250 | void input_close_device(struct input_handle *handle) |
237 | { | 251 | { |
252 | struct input_dev *dev = handle->dev; | ||
253 | |||
238 | input_release_device(handle); | 254 | input_release_device(handle); |
239 | if (handle->dev->close) | 255 | |
240 | handle->dev->close(handle->dev); | 256 | down(&dev->sem); |
257 | |||
258 | if (!--dev->users && dev->close) | ||
259 | dev->close(dev); | ||
241 | handle->open--; | 260 | handle->open--; |
261 | |||
262 | up(&dev->sem); | ||
242 | } | 263 | } |
243 | 264 | ||
244 | static void input_link_handle(struct input_handle *handle) | 265 | static void input_link_handle(struct input_handle *handle) |
@@ -415,6 +436,8 @@ void input_register_device(struct input_dev *dev) | |||
415 | 436 | ||
416 | set_bit(EV_SYN, dev->evbit); | 437 | set_bit(EV_SYN, dev->evbit); |
417 | 438 | ||
439 | init_MUTEX(&dev->sem); | ||
440 | |||
418 | /* | 441 | /* |
419 | * If delay and period are pre-set by the driver, then autorepeating | 442 | * If delay and period are pre-set by the driver, then autorepeating |
420 | * is handled by the driver itself and we don't do it in input.c. | 443 | * is handled by the driver itself and we don't do it in input.c. |
@@ -674,6 +697,8 @@ static int input_handlers_read(char *buf, char **start, off_t pos, int count, in | |||
674 | return (count > cnt) ? cnt : count; | 697 | return (count > cnt) ? cnt : count; |
675 | } | 698 | } |
676 | 699 | ||
700 | static struct file_operations input_fileops; | ||
701 | |||
677 | static int __init input_proc_init(void) | 702 | static int __init input_proc_init(void) |
678 | { | 703 | { |
679 | struct proc_dir_entry *entry; | 704 | struct proc_dir_entry *entry; |
@@ -688,6 +713,8 @@ static int __init input_proc_init(void) | |||
688 | return -ENOMEM; | 713 | return -ENOMEM; |
689 | } | 714 | } |
690 | entry->owner = THIS_MODULE; | 715 | entry->owner = THIS_MODULE; |
716 | input_fileops = *entry->proc_fops; | ||
717 | entry->proc_fops = &input_fileops; | ||
691 | entry->proc_fops->poll = input_devices_poll; | 718 | entry->proc_fops->poll = input_devices_poll; |
692 | entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL); | 719 | entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL); |
693 | if (entry == NULL) { | 720 | if (entry == NULL) { |