mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-21 16:29:59 +00:00
Input: evdev - flush pending events on clock type change
When client changes the type of clock used for the time stamps in input events flush pending events from the client's queue (since client would not know which events have old time stamps and which ones have new ones) and and queue SYN_DROPPED event. Signed-off-by: Anshul Garg <anshul.g@samsung.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
This commit is contained in:
parent
34412ba282
commit
0c3e99437a
1 changed files with 32 additions and 23 deletions
|
@ -62,26 +62,6 @@ struct evdev_client {
|
|||
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)
|
||||
{
|
||||
|
@ -128,8 +108,8 @@ static void __evdev_flush_queue(struct evdev_client *client, unsigned int type)
|
|||
client->head = head;
|
||||
}
|
||||
|
||||
/* queue SYN_DROPPED event */
|
||||
static void evdev_queue_syn_dropped(struct evdev_client *client)
|
||||
/* queue SYN_DROPPED event and flush queue if flush parameter is true */
|
||||
static void evdev_queue_syn_dropped(struct evdev_client *client, bool flush)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct input_event ev;
|
||||
|
@ -148,6 +128,9 @@ static void evdev_queue_syn_dropped(struct evdev_client *client)
|
|||
|
||||
spin_lock_irqsave(&client->buffer_lock, flags);
|
||||
|
||||
if (flush)
|
||||
client->packet_head = client->head = client->tail;
|
||||
|
||||
client->buffer[client->head++] = ev;
|
||||
client->head &= client->bufsize - 1;
|
||||
|
||||
|
@ -160,6 +143,32 @@ static void evdev_queue_syn_dropped(struct evdev_client *client)
|
|||
spin_unlock_irqrestore(&client->buffer_lock, flags);
|
||||
}
|
||||
|
||||
static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid)
|
||||
{
|
||||
if (client->clk_type == clkid)
|
||||
return 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* Flush pending events and queue SYN_DROPPED event.*/
|
||||
evdev_queue_syn_dropped(client, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __pass_event(struct evdev_client *client,
|
||||
const struct input_event *event)
|
||||
{
|
||||
|
@ -794,7 +803,7 @@ static int evdev_handle_get_val(struct evdev_client *client,
|
|||
|
||||
ret = bits_to_user(mem, maxbit, maxlen, p, compat);
|
||||
if (ret < 0)
|
||||
evdev_queue_syn_dropped(client);
|
||||
evdev_queue_syn_dropped(client, false);
|
||||
|
||||
kfree(mem);
|
||||
|
||||
|
|
Loading…
Reference in a new issue