Commit ffd0db97 authored by Dmitry Torokhov's avatar Dmitry Torokhov

Input: add generic suspend and resume for input devices

Automatically turn off leds and sound effects as part of suspend
process and restore led state, sounds and repeat rate at resume.
Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
parent 181d683d
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
*/ */
#include <linux/init.h> #include <linux/init.h>
#include <linux/types.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/random.h> #include <linux/random.h>
...@@ -514,7 +515,7 @@ static void input_disconnect_device(struct input_dev *dev) ...@@ -514,7 +515,7 @@ static void input_disconnect_device(struct input_dev *dev)
* that there are no threads in the middle of input_open_device() * that there are no threads in the middle of input_open_device()
*/ */
mutex_lock(&dev->mutex); mutex_lock(&dev->mutex);
dev->going_away = 1; dev->going_away = true;
mutex_unlock(&dev->mutex); mutex_unlock(&dev->mutex);
spin_lock_irq(&dev->event_lock); spin_lock_irq(&dev->event_lock);
...@@ -1259,10 +1260,71 @@ static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env) ...@@ -1259,10 +1260,71 @@ static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env)
return 0; return 0;
} }
#define INPUT_DO_TOGGLE(dev, type, bits, on) \
do { \
int i; \
if (!test_bit(EV_##type, dev->evbit)) \
break; \
for (i = 0; i < type##_MAX; i++) { \
if (!test_bit(i, dev->bits##bit) || \
!test_bit(i, dev->bits)) \
continue; \
dev->event(dev, EV_##type, i, on); \
} \
} while (0)
static void input_dev_reset(struct input_dev *dev, bool activate)
{
if (!dev->event)
return;
INPUT_DO_TOGGLE(dev, LED, led, activate);
INPUT_DO_TOGGLE(dev, SND, snd, activate);
if (activate && test_bit(EV_REP, dev->evbit)) {
dev->event(dev, EV_REP, REP_PERIOD, dev->rep[REP_PERIOD]);
dev->event(dev, EV_REP, REP_DELAY, dev->rep[REP_DELAY]);
}
}
#ifdef CONFIG_PM
static int input_dev_suspend(struct device *dev)
{
struct input_dev *input_dev = to_input_dev(dev);
mutex_lock(&input_dev->mutex);
input_dev_reset(input_dev, false);
mutex_unlock(&input_dev->mutex);
return 0;
}
static int input_dev_resume(struct device *dev)
{
struct input_dev *input_dev = to_input_dev(dev);
mutex_lock(&input_dev->mutex);
input_dev_reset(input_dev, true);
mutex_unlock(&input_dev->mutex);
return 0;
}
static const struct dev_pm_ops input_dev_pm_ops = {
.suspend = input_dev_suspend,
.resume = input_dev_resume,
.poweroff = input_dev_suspend,
.restore = input_dev_resume,
};
#endif /* CONFIG_PM */
static struct device_type input_dev_type = { static struct device_type input_dev_type = {
.groups = input_dev_attr_groups, .groups = input_dev_attr_groups,
.release = input_dev_release, .release = input_dev_release,
.uevent = input_dev_uevent, .uevent = input_dev_uevent,
#ifdef CONFIG_PM
.pm = &input_dev_pm_ops,
#endif
}; };
static char *input_nodename(struct device *dev) static char *input_nodename(struct device *dev)
......
...@@ -1123,7 +1123,7 @@ struct input_dev { ...@@ -1123,7 +1123,7 @@ struct input_dev {
struct mutex mutex; struct mutex mutex;
unsigned int users; unsigned int users;
int going_away; bool going_away;
struct device dev; struct device dev;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment