aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorJP Abgrall <jpa@google.com>2012-02-06 13:07:39 -0800
committerJP Abgrall <jpa@google.com>2012-02-06 13:07:39 -0800
commit66b1fe9916260621f3decf5b61142f4010e6cd12 (patch)
treef5ca3444102f737dbdd72d97dc1b94bf62338633 /drivers/input
parent47771afc77173e4d87f67cd11c792b92e8578e72 (diff)
parent1f8c5cecfe44994cd617ba2803f41fb56d53e91c (diff)
downloadkernel_samsung_crespo-66b1fe9916260621f3decf5b61142f4010e6cd12.zip
kernel_samsung_crespo-66b1fe9916260621f3decf5b61142f4010e6cd12.tar.gz
kernel_samsung_crespo-66b1fe9916260621f3decf5b61142f4010e6cd12.tar.bz2
Merge remote-tracking branch 'common/android-3.0' into android-samsung-30-wip-mergedown
* common/android-3.0: Input: evdev - fix variable initialisation Input: evdev - Add ioctl to block suspend while event queue is not empty. Input: evdev - Don't hold wakelock when no data is available to user-space net: wireless: bcmdhd: Increase pm_notify callback priority net: wireless: bcmdhd: Fix crash on dhdsdio_probe_attach() failure net: wireless: bcmdhd: Daemonize wl_event_handler net: wireless: bcmdhd: Update to Version 5.90.195.23 net: wireless: bcmdhd: Update to Version 5.90.195.22 net: wireless: bcmdhd: Update to Version 5.90.195.19 net: wireless: bcmdhd: Update to Version 5.90.195.15 net: wireless: bcmdhd: Add WIPHY_FLAG_SUPPORTS_FW_ROAM flag net: wireless: bcmdhd: Fake PNO event to wake up the wpa_supplicant usb: gadget: android: Honor CONFIG_USB_GADGET_VBUS_DRAW usb: gadget: Fix usb string id allocation nl80211/cfg80211: Make addition of new sinfo fields safer cfg80211/nl80211: Send AssocReq IEs to user space in AP mode misc: remove android pmem driver, it's obsolete. Revert "proc: enable writing to /proc/pid/mem" ram_console: set CON_ANYTIME console flag Conflicts: drivers/misc/Kconfig Change-Id: I7d64300b228a0fc05e700f283a02f830bcadd371
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/evdev.c54
1 files changed, 48 insertions, 6 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 5c5f9db..6288d7d 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -45,6 +45,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 +63,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 +79,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 +266,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 +321,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 +335,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 +388,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);
}
@@ -400,7 +404,7 @@ static ssize_t evdev_read(struct file *file, char __user *buffer,
struct evdev_client *client = file->private_data;
struct evdev *evdev = client->evdev;
struct input_event event;
- int retval;
+ int retval = 0;
if (count < input_event_size())
return -EINVAL;
@@ -635,6 +639,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 +741,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);