Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9fb0f14e authored by Jeff Brown's avatar Jeff Brown Committed by Dmitry Torokhov
Browse files

Input: evdev - indicate buffer overrun with SYN_DROPPED



Add a new EV_SYN code, SYN_DROPPED, to inform the client when input
events have been dropped from the evdev input buffer due to a
buffer overrun.  The client should use this event as a hint to
reset its state or ignore all following events until the next
packet begins.

Signed-off-by: default avatarJeff Brown <jeffbrown@android.com>
[dtor@mail.ru: Implement Henrik's suggestion and drop old events in
 case of overflow.]
Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
parent b1e064b8
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -85,6 +85,12 @@ sent in the evdev event stream.
  - Used to synchronize and separate touch events. See the
    multi-touch-protocol.txt document for more information.

* SYN_DROPPED:
  - Used to indicate buffer overrun in the evdev client's event queue.
    Client should ignore all events up to and including next SYN_REPORT
    event and query the device (using EVIOCG* ioctls) to obtain its
    current state.

EV_KEY:
----------
EV_KEY events take the form KEY_<name> or BTN_<name>. For example, KEY_A is used
+21 −12
Original line number Diff line number Diff line
@@ -39,13 +39,13 @@ struct evdev {
};

struct evdev_client {
	int head;
	int tail;
	unsigned int head;
	unsigned int tail;
	spinlock_t buffer_lock; /* protects access to buffer, head and tail */
	struct fasync_struct *fasync;
	struct evdev *evdev;
	struct list_head node;
	int bufsize;
	unsigned int bufsize;
	struct input_event buffer[];
};

@@ -55,16 +55,25 @@ static DEFINE_MUTEX(evdev_table_mutex);
static void evdev_pass_event(struct evdev_client *client,
			     struct input_event *event)
{
	/*
	 * Interrupts are disabled, just acquire the lock.
	 * Make sure we don't leave with the client buffer
	 * "empty" by having client->head == client->tail.
	 */
	/* Interrupts are disabled, just acquire the lock. */
	spin_lock(&client->buffer_lock);
	do {

	client->buffer[client->head++] = *event;
	client->head &= client->bufsize - 1;
	} while (client->head == client->tail);

	if (unlikely(client->head == client->tail)) {
		/*
		 * This effectively "drops" all unconsumed events, leaving
		 * EV_SYN/SYN_DROPPED plus the newest event in the queue.
		 */
		client->tail = (client->head - 2) & (client->bufsize - 1);

		client->buffer[client->tail].time = event->time;
		client->buffer[client->tail].type = EV_SYN;
		client->buffer[client->tail].code = SYN_DROPPED;
		client->buffer[client->tail].value = 0;
	}

	spin_unlock(&client->buffer_lock);

	if (event->type == EV_SYN)
+1 −0
Original line number Diff line number Diff line
@@ -167,6 +167,7 @@ struct input_keymap_entry {
#define SYN_REPORT		0
#define SYN_CONFIG		1
#define SYN_MT_REPORT		2
#define SYN_DROPPED		3

/*
 * Keys and buttons