diff options
| author | Russell King <rmk+kernel@arm.linux.org.uk> | 2015-02-10 10:26:38 +0000 | 
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2015-02-10 10:26:38 +0000 | 
| commit | df9ab9771c64f5229843bfe2a20fe0ee6ac59fc1 (patch) | |
| tree | a091be1024bd76627f78e791e377126e47703b7b /drivers/input/evdev.c | |
| parent | ed8f8ce38d0f7b505d7da2d79522972e962457c2 (diff) | |
| parent | 4e1c0664de11e4b5861957ab4ddff2aeeffd042f (diff) | |
Merge branch 'devel-stable' into for-next
Diffstat (limited to 'drivers/input/evdev.c')
| -rw-r--r-- | drivers/input/evdev.c | 60 | 
1 files changed, 44 insertions, 16 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 8afa28e4570e..18d4b2c8fe55 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -28,6 +28,13 @@  #include <linux/cdev.h>  #include "input-compat.h" +enum evdev_clock_type { +	EV_CLK_REAL = 0, +	EV_CLK_MONO, +	EV_CLK_BOOT, +	EV_CLK_MAX +}; +  struct evdev {  	int open;  	struct input_handle handle; @@ -49,12 +56,32 @@ struct evdev_client {  	struct fasync_struct *fasync;  	struct evdev *evdev;  	struct list_head node; -	int clkid; +	int clk_type;  	bool revoked;  	unsigned int bufsize;  	struct input_event buffer[];  }; +static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid) +{ +	switch (clkid) { + +	case CLOCK_REALTIME: +		client->clk_type = EV_CLK_REAL; +		break; +	case CLOCK_MONOTONIC: +		client->clk_type = EV_CLK_MONO; +		break; +	case CLOCK_BOOTTIME: +		client->clk_type = EV_CLK_BOOT; +		break; +	default: +		return -EINVAL; +	} + +	return 0; +} +  /* flush queued events of type @type, caller must hold client->buffer_lock */  static void __evdev_flush_queue(struct evdev_client *client, unsigned int type)  { @@ -108,8 +135,11 @@ static void evdev_queue_syn_dropped(struct evdev_client *client)  	struct input_event ev;  	ktime_t time; -	time = (client->clkid == CLOCK_MONOTONIC) ? -		ktime_get() : ktime_get_real(); +	time = client->clk_type == EV_CLK_REAL ? +			ktime_get_real() : +			client->clk_type == EV_CLK_MONO ? +				ktime_get() : +				ktime_get_boottime();  	ev.time = ktime_to_timeval(time);  	ev.type = EV_SYN; @@ -159,7 +189,7 @@ static void __pass_event(struct evdev_client *client,  static void evdev_pass_values(struct evdev_client *client,  			const struct input_value *vals, unsigned int count, -			ktime_t mono, ktime_t real) +			ktime_t *ev_time)  {  	struct evdev *evdev = client->evdev;  	const struct input_value *v; @@ -169,8 +199,7 @@ static void evdev_pass_values(struct evdev_client *client,  	if (client->revoked)  		return; -	event.time = ktime_to_timeval(client->clkid == CLOCK_MONOTONIC ? -				      mono : real); +	event.time = ktime_to_timeval(ev_time[client->clk_type]);  	/* Interrupts are disabled, just acquire the lock. */  	spin_lock(&client->buffer_lock); @@ -198,21 +227,22 @@ static void evdev_events(struct input_handle *handle,  {  	struct evdev *evdev = handle->private;  	struct evdev_client *client; -	ktime_t time_mono, time_real; +	ktime_t ev_time[EV_CLK_MAX]; -	time_mono = ktime_get(); -	time_real = ktime_mono_to_real(time_mono); +	ev_time[EV_CLK_MONO] = ktime_get(); +	ev_time[EV_CLK_REAL] = ktime_mono_to_real(ev_time[EV_CLK_MONO]); +	ev_time[EV_CLK_BOOT] = ktime_mono_to_any(ev_time[EV_CLK_MONO], +						 TK_OFFS_BOOT);  	rcu_read_lock();  	client = rcu_dereference(evdev->grab);  	if (client) -		evdev_pass_values(client, vals, count, time_mono, time_real); +		evdev_pass_values(client, vals, count, ev_time);  	else  		list_for_each_entry_rcu(client, &evdev->client_list, node) -			evdev_pass_values(client, vals, count, -					  time_mono, time_real); +			evdev_pass_values(client, vals, count, ev_time);  	rcu_read_unlock();  } @@ -877,10 +907,8 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,  	case EVIOCSCLOCKID:  		if (copy_from_user(&i, p, sizeof(unsigned int)))  			return -EFAULT; -		if (i != CLOCK_MONOTONIC && i != CLOCK_REALTIME) -			return -EINVAL; -		client->clkid = i; -		return 0; + +		return evdev_set_clk_type(client, i);  	case EVIOCGKEYCODE:  		return evdev_handle_get_keycode(dev, p);  | 
