diff options
Diffstat (limited to 'drivers/input/input.c')
| -rw-r--r-- | drivers/input/input.c | 98 | 
1 files changed, 71 insertions, 27 deletions
diff --git a/drivers/input/input.c b/drivers/input/input.c index c0446992892..29ca0bb4f56 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -257,9 +257,10 @@ static int input_handle_abs_event(struct input_dev *dev,  }  static int input_get_disposition(struct input_dev *dev, -			  unsigned int type, unsigned int code, int value) +			  unsigned int type, unsigned int code, int *pval)  {  	int disposition = INPUT_IGNORE_EVENT; +	int value = *pval;  	switch (type) { @@ -357,6 +358,7 @@ static int input_get_disposition(struct input_dev *dev,  		break;  	} +	*pval = value;  	return disposition;  } @@ -365,7 +367,7 @@ static void input_handle_event(struct input_dev *dev,  {  	int disposition; -	disposition = input_get_disposition(dev, type, code, value); +	disposition = input_get_disposition(dev, type, code, &value);  	if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event)  		dev->event(dev, type, code, value); @@ -1653,35 +1655,36 @@ static void input_dev_toggle(struct input_dev *dev, bool activate)   */  void input_reset_device(struct input_dev *dev)  { -	mutex_lock(&dev->mutex); +	unsigned long flags; -	if (dev->users) { -		input_dev_toggle(dev, true); +	mutex_lock(&dev->mutex); +	spin_lock_irqsave(&dev->event_lock, flags); -		/* -		 * Keys that have been pressed at suspend time are unlikely -		 * to be still pressed when we resume. -		 */ -		spin_lock_irq(&dev->event_lock); -		input_dev_release_keys(dev); -		spin_unlock_irq(&dev->event_lock); -	} +	input_dev_toggle(dev, true); +	input_dev_release_keys(dev); +	spin_unlock_irqrestore(&dev->event_lock, flags);  	mutex_unlock(&dev->mutex);  }  EXPORT_SYMBOL(input_reset_device); -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int input_dev_suspend(struct device *dev)  {  	struct input_dev *input_dev = to_input_dev(dev); -	mutex_lock(&input_dev->mutex); +	spin_lock_irq(&input_dev->event_lock); + +	/* +	 * Keys that are pressed now are unlikely to be +	 * still pressed when we resume. +	 */ +	input_dev_release_keys(input_dev); -	if (input_dev->users) -		input_dev_toggle(input_dev, false); +	/* Turn off LEDs and sounds, if any are active. */ +	input_dev_toggle(input_dev, false); -	mutex_unlock(&input_dev->mutex); +	spin_unlock_irq(&input_dev->event_lock);  	return 0;  } @@ -1690,7 +1693,43 @@ static int input_dev_resume(struct device *dev)  {  	struct input_dev *input_dev = to_input_dev(dev); -	input_reset_device(input_dev); +	spin_lock_irq(&input_dev->event_lock); + +	/* Restore state of LEDs and sounds, if any were active. */ +	input_dev_toggle(input_dev, true); + +	spin_unlock_irq(&input_dev->event_lock); + +	return 0; +} + +static int input_dev_freeze(struct device *dev) +{ +	struct input_dev *input_dev = to_input_dev(dev); + +	spin_lock_irq(&input_dev->event_lock); + +	/* +	 * Keys that are pressed now are unlikely to be +	 * still pressed when we resume. +	 */ +	input_dev_release_keys(input_dev); + +	spin_unlock_irq(&input_dev->event_lock); + +	return 0; +} + +static int input_dev_poweroff(struct device *dev) +{ +	struct input_dev *input_dev = to_input_dev(dev); + +	spin_lock_irq(&input_dev->event_lock); + +	/* Turn off LEDs and sounds, if any are active. */ +	input_dev_toggle(input_dev, false); + +	spin_unlock_irq(&input_dev->event_lock);  	return 0;  } @@ -1698,7 +1737,8 @@ static int input_dev_resume(struct device *dev)  static const struct dev_pm_ops input_dev_pm_ops = {  	.suspend	= input_dev_suspend,  	.resume		= input_dev_resume, -	.poweroff	= input_dev_suspend, +	.freeze		= input_dev_freeze, +	.poweroff	= input_dev_poweroff,  	.restore	= input_dev_resume,  };  #endif /* CONFIG_PM */ @@ -1707,7 +1747,7 @@ static struct device_type input_dev_type = {  	.groups		= input_dev_attr_groups,  	.release	= input_dev_release,  	.uevent		= input_dev_uevent, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.pm		= &input_dev_pm_ops,  #endif  }; @@ -1734,6 +1774,7 @@ EXPORT_SYMBOL_GPL(input_class);   */  struct input_dev *input_allocate_device(void)  { +	static atomic_t input_no = ATOMIC_INIT(0);  	struct input_dev *dev;  	dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL); @@ -1743,9 +1784,13 @@ struct input_dev *input_allocate_device(void)  		device_initialize(&dev->dev);  		mutex_init(&dev->mutex);  		spin_lock_init(&dev->event_lock); +		init_timer(&dev->timer);  		INIT_LIST_HEAD(&dev->h_list);  		INIT_LIST_HEAD(&dev->node); +		dev_set_name(&dev->dev, "input%ld", +			     (unsigned long) atomic_inc_return(&input_no) - 1); +  		__module_get(THIS_MODULE);  	} @@ -1866,6 +1911,10 @@ void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int  		break;  	case EV_ABS: +		input_alloc_absinfo(dev); +		if (!dev->absinfo) +			return; +  		__set_bit(code, dev->absbit);  		break; @@ -2019,7 +2068,6 @@ static void devm_input_device_unregister(struct device *dev, void *res)   */  int input_register_device(struct input_dev *dev)  { -	static atomic_t input_no = ATOMIC_INIT(0);  	struct input_devres *devres = NULL;  	struct input_handler *handler;  	unsigned int packet_size; @@ -2048,7 +2096,7 @@ int input_register_device(struct input_dev *dev)  	if (dev->hint_events_per_packet < packet_size)  		dev->hint_events_per_packet = packet_size; -	dev->max_vals = max(dev->hint_events_per_packet, packet_size) + 2; +	dev->max_vals = dev->hint_events_per_packet + 2;  	dev->vals = kcalloc(dev->max_vals, sizeof(*dev->vals), GFP_KERNEL);  	if (!dev->vals) {  		error = -ENOMEM; @@ -2059,7 +2107,6 @@ int input_register_device(struct input_dev *dev)  	 * If delay and period are pre-set by the driver, then autorepeating  	 * is handled by the driver itself and we don't do it in input.c.  	 */ -	init_timer(&dev->timer);  	if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {  		dev->timer.data = (long) dev;  		dev->timer.function = input_repeat_key; @@ -2073,9 +2120,6 @@ int input_register_device(struct input_dev *dev)  	if (!dev->setkeycode)  		dev->setkeycode = input_default_setkeycode; -	dev_set_name(&dev->dev, "input%ld", -		     (unsigned long) atomic_inc_return(&input_no) - 1); -  	error = device_add(&dev->dev);  	if (error)  		goto err_free_vals;  | 
