diff options
author | codeworkx <codeworkx@cyanogenmod.com> | 2012-09-22 09:48:20 +0200 |
---|---|---|
committer | codeworkx <codeworkx@cyanogenmod.com> | 2012-09-22 14:02:16 +0200 |
commit | 2489007e7d740ccbc3e0a202914e243ad5178787 (patch) | |
tree | b8e6380ea7b1da63474ad68a5dba997e01146043 /drivers/input/evdev.c | |
parent | 5f67568eb31e3a813c7c52461dcf66ade15fc2e7 (diff) | |
download | kernel_samsung_smdk4412-2489007e7d740ccbc3e0a202914e243ad5178787.zip kernel_samsung_smdk4412-2489007e7d740ccbc3e0a202914e243ad5178787.tar.gz kernel_samsung_smdk4412-2489007e7d740ccbc3e0a202914e243ad5178787.tar.bz2 |
merge opensource jb u5
Change-Id: I1aaec157aa196f3448eff8636134fce89a814cf2
Diffstat (limited to 'drivers/input/evdev.c')
-rw-r--r-- | drivers/input/evdev.c | 57 |
1 files changed, 52 insertions, 5 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 6e7dd68..67dd99a 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -13,7 +13,12 @@ #define EVDEV_MINOR_BASE 64 #define EVDEV_MINORS 32 #define EVDEV_MIN_BUFFER_SIZE 64U + +#ifdef CONFIG_INPUT_WACOM +#define EVDEV_BUF_PACKETS 32 +#else #define EVDEV_BUF_PACKETS 8 +#endif #include <linux/poll.h> #include <linux/sched.h> @@ -45,6 +50,7 @@ struct evdev_client { unsigned int packet_head; /* [future] position of the first element of next packet */ spinlock_t buffer_lock; /* protects access to buffer, head and tail */ struct wake_lock wake_lock; + bool use_wake_lock; char name[28]; struct fasync_struct *fasync; struct evdev *evdev; @@ -62,7 +68,6 @@ static void evdev_pass_event(struct evdev_client *client, /* Interrupts are disabled, just acquire the lock. */ spin_lock(&client->buffer_lock); - wake_lock_timeout(&client->wake_lock, 5 * HZ); client->buffer[client->head++] = *event; client->head &= client->bufsize - 1; @@ -79,10 +84,14 @@ static void evdev_pass_event(struct evdev_client *client, client->buffer[client->tail].value = 0; client->packet_head = client->tail; + if (client->use_wake_lock) + wake_unlock(&client->wake_lock); } if (event->type == EV_SYN && event->code == SYN_REPORT) { client->packet_head = client->head; + if (client->use_wake_lock) + wake_lock(&client->wake_lock); kill_fasync(&client->fasync, SIGIO, POLL_IN); } @@ -262,7 +271,8 @@ static int evdev_release(struct inode *inode, struct file *file) mutex_unlock(&evdev->mutex); evdev_detach_client(evdev, client); - wake_lock_destroy(&client->wake_lock); + if (client->use_wake_lock) + wake_lock_destroy(&client->wake_lock); kfree(client); evdev_close_device(evdev); @@ -316,7 +326,6 @@ static int evdev_open(struct inode *inode, struct file *file) spin_lock_init(&client->buffer_lock); snprintf(client->name, sizeof(client->name), "%s-%d", dev_name(&evdev->dev), task_tgid_vnr(current)); - wake_lock_init(&client->wake_lock, WAKE_LOCK_SUSPEND, client->name); client->evdev = evdev; evdev_attach_client(evdev, client); @@ -331,7 +340,6 @@ static int evdev_open(struct inode *inode, struct file *file) err_free_client: evdev_detach_client(evdev, client); - wake_lock_destroy(&client->wake_lock); kfree(client); err_put_evdev: put_device(&evdev->dev); @@ -385,7 +393,8 @@ static int evdev_fetch_next_event(struct evdev_client *client, if (have_event) { *event = client->buffer[client->tail++]; client->tail &= client->bufsize - 1; - if (client->head == client->tail) + if (client->use_wake_lock && + client->packet_head == client->tail) wake_unlock(&client->wake_lock); } @@ -635,6 +644,35 @@ static int evdev_handle_set_keycode_v2(struct input_dev *dev, void __user *p) return input_set_keycode(dev, &ke); } +static int evdev_enable_suspend_block(struct evdev *evdev, + struct evdev_client *client) +{ + if (client->use_wake_lock) + return 0; + + spin_lock_irq(&client->buffer_lock); + wake_lock_init(&client->wake_lock, WAKE_LOCK_SUSPEND, client->name); + client->use_wake_lock = true; + if (client->packet_head != client->tail) + wake_lock(&client->wake_lock); + spin_unlock_irq(&client->buffer_lock); + return 0; +} + +static int evdev_disable_suspend_block(struct evdev *evdev, + struct evdev_client *client) +{ + if (!client->use_wake_lock) + return 0; + + spin_lock_irq(&client->buffer_lock); + client->use_wake_lock = false; + wake_lock_destroy(&client->wake_lock); + spin_unlock_irq(&client->buffer_lock); + + return 0; +} + static long evdev_do_ioctl(struct file *file, unsigned int cmd, void __user *p, int compat_mode) { @@ -708,6 +746,15 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, case EVIOCSKEYCODE_V2: return evdev_handle_set_keycode_v2(dev, p); + + case EVIOCGSUSPENDBLOCK: + return put_user(client->use_wake_lock, ip); + + case EVIOCSSUSPENDBLOCK: + if (p) + return evdev_enable_suspend_block(evdev, client); + else + return evdev_disable_suspend_block(evdev, client); } size = _IOC_SIZE(cmd); |