Add an ioctl, EVIOCSSUSPENDBLOCK, to enable a suspend_blocker that will blocksuspend while the event queue is not empty. This allows userspace code toprocess input events while the device appears to be asleep. Signed-off-by: Arve Hjønnevåg <arve@xxxxxxxxxxx>--- drivers/input/evdev.c | 22 ++++++++++++++++++++++ include/linux/input.h | 3 +++ 2 files changed, 25 insertions(+), 0 deletions(-) diff --git a/drivers/input/evdev.c b/drivers/input/evdev.cindex ed8baa0..f07ac06 100644--- a/drivers/input/evdev.c+++ b/drivers/input/evdev.c@@ -19,6 +19,7 @@ #include <linux/input.h> #include <linux/major.h> #include <linux/device.h>+#include <linux/suspend_blocker.h> #include "input-compat.h" struct evdev {@@ -43,6 +44,8 @@ struct evdev_client { struct fasync_struct *fasync; struct evdev *evdev; struct list_head node;+ struct suspend_blocker suspend_blocker;+ bool use_suspend_blocker; }; static struct evdev *evdev_table[EVDEV_MINORS];@@ -55,6 +58,8 @@ static void evdev_pass_event(struct evdev_client *client, * Interrupts are disabled, just acquire the lock */ spin_lock(&client->buffer_lock);+ if (client->use_suspend_blocker)+ suspend_block(&client->suspend_blocker); client->buffer[client->head++] = *event; client->head &= EVDEV_BUFFER_SIZE - 1; spin_unlock(&client->buffer_lock);@@ -236,6 +241,8 @@ static int evdev_release(struct inode *inode, struct file *file) mutex_unlock(&evdev->mutex); evdev_detach_client(evdev, client);+ if (client->use_suspend_blocker)+ suspend_blocker_destroy(&client->suspend_blocker); kfree(client); evdev_close_device(evdev);@@ -335,6 +342,8 @@ static int evdev_fetch_next_event(struct evdev_client *client, if (have_event) { *event = client->buffer[client->tail++]; client->tail &= EVDEV_BUFFER_SIZE - 1;+ if (client->use_suspend_blocker && client->head == client->tail)+ suspend_unblock(&client->suspend_blocker); } spin_unlock_irq(&client->buffer_lock);@@ -585,6 +594,19 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, else return evdev_ungrab(evdev, client); + case EVIOCGSUSPENDBLOCK:+ return put_user(client->use_suspend_blocker, ip);++ case EVIOCSSUSPENDBLOCK:+ spin_lock_irq(&client->buffer_lock);+ if (!client->use_suspend_blocker && p)+ suspend_blocker_init(&client->suspend_blocker, "evdev");+ else if (client->use_suspend_blocker && !p)+ suspend_blocker_destroy(&client->suspend_blocker);+ client->use_suspend_blocker = !!p;+ spin_unlock_irq(&client->buffer_lock);+ return 0;+ default: if (_IOC_TYPE(cmd) != 'E')diff --git a/include/linux/input.h b/include/linux/input.hindex 1249a0c..67e2332 100644--- a/include/linux/input.h+++ b/include/linux/input.h@@ -81,6 +81,9 @@ struct input_absinfo { #define EVIOCGRAB _IOW('E', 0x90, int) /* Grab/Release device */ +#define EVIOCGSUSPENDBLOCK _IOR('E', 0x91, int) /* get suspend block enable */+#define EVIOCSSUSPENDBLOCK _IOW('E', 0x91, int) /* set suspend block enable */+ /* * Event types */-- 1.6.1 _______________________________________________linux-pm mailing listlinux-pm@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx://lists.linux-foundation.org/mailman/listinfo/linux-pm