diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/input/input.c | 64 |
1 files changed, 63 insertions, 1 deletions
diff --git a/drivers/input/input.c b/drivers/input/input.c index 7c237e6ac71..b8ed4294fcc 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -11,6 +11,7 @@ */ #include <linux/init.h> +#include <linux/types.h> #include <linux/input.h> #include <linux/module.h> #include <linux/random.h> @@ -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() */ mutex_lock(&dev->mutex); - dev->going_away = 1; + dev->going_away = true; mutex_unlock(&dev->mutex); spin_lock_irq(&dev->event_lock); @@ -1259,10 +1260,71 @@ static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env) 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 = { .groups = input_dev_attr_groups, .release = input_dev_release, .uevent = input_dev_uevent, +#ifdef CONFIG_PM + .pm = &input_dev_pm_ops, +#endif }; static char *input_nodename(struct device *dev) |