master hovercats/oakiss / pkg / libevdev / patch / 0001-Revert-switch-to-VLAs-for-multitouch-state.patch
  1From 20dd0f459d92805cdd33a7622382f118acf3c07d Mon Sep 17 00:00:00 2001
  2From: Michael Forney <mforney@mforney.org>
  3Date: Tue, 3 Mar 2020 14:17:37 -0800
  4Subject: [PATCH libevdev] Revert switch to VLAs for multitouch state
  5
  6Signed-off-by: Michael Forney <mforney@mforney.org>
  7---
  8 libevdev/libevdev-int.h | 28 +++++++++++++
  9 libevdev/libevdev.c     | 87 +++++++++++++++++++----------------------
 10 2 files changed, 68 insertions(+), 47 deletions(-)
 11
 12diff --git a/libevdev/libevdev-int.h b/libevdev/libevdev-int.h
 13index 8e2518e..bc291ea 100644
 14--- a/libevdev/libevdev-int.h
 15+++ b/libevdev/libevdev-int.h
 16@@ -7,6 +7,7 @@
 17 #define LIBEVDEV_INT_H
 18 
 19 #include "config.h"
 20+#include <stdint.h>
 21 #include <stdio.h>
 22 #include <stdlib.h>
 23 #include <stdbool.h>
 24@@ -38,6 +39,26 @@ enum SyncState {
 25 	SYNC_IN_PROGRESS,
 26 };
 27 
 28+struct mt_sync_state {
 29+	uint32_t code;
 30+	int32_t val[];
 31+};
 32+
 33+/* Keeps a record of touches during SYN_DROPPED  */
 34+enum touch_state {
 35+	TOUCH_OFF,
 36+	TOUCH_STARTED, /* Started during SYN_DROPPED */
 37+	TOUCH_STOPPED, /* Stopped during SYN_DROPPED */
 38+	TOUCH_ONGOING, /* Existed before, still have same tracking ID */
 39+	TOUCH_CHANGED, /* Existed before but have new tracking ID now, so
 40+			  stopped + started in that slot */
 41+};
 42+
 43+struct slot_change_state {
 44+	enum touch_state state;
 45+	unsigned long axes[NLONGS(ABS_CNT)]; /* bitmask for updated axes */
 46+};
 47+
 48 /**
 49  * Internal only: log data used to send messages to the respective log
 50  * handler. We re-use the same struct for a global and inside
 51@@ -90,6 +111,13 @@ struct libevdev {
 52 
 53 	struct timeval last_event_time;
 54 
 55+	struct {
 56+		struct mt_sync_state *mt_state;
 57+		size_t mt_state_sz;		 /* in bytes */
 58+		struct slot_change_state *changes;
 59+		size_t changes_sz;		 /* in bytes */
 60+	} mt_sync;
 61+
 62 	struct logdata log;
 63 };
 64 
 65diff --git a/libevdev/libevdev.c b/libevdev/libevdev.c
 66index b941cfb..1cc912c 100644
 67--- a/libevdev/libevdev.c
 68+++ b/libevdev/libevdev.c
 69@@ -28,23 +28,7 @@ enum event_filter_status {
 70 	EVENT_FILTER_DISCARD,	/**< Discard current event */
 71 };
 72 
 73-/* Keeps a record of touches during SYN_DROPPED  */
 74-enum touch_state {
 75-	TOUCH_OFF,
 76-	TOUCH_STARTED, /* Started during SYN_DROPPED */
 77-	TOUCH_STOPPED, /* Stopped during SYN_DROPPED */
 78-	TOUCH_ONGOING, /* Existed before, still have same tracking ID */
 79-	TOUCH_CHANGED, /* Existed before but have new tracking ID now, so
 80-			  stopped + started in that slot */
 81-};
 82-
 83-struct slot_change_state {
 84-	enum touch_state state;
 85-	unsigned long axes[NLONGS(ABS_CNT)]; /* bitmask for updated axes */
 86-};
 87-
 88-static int sync_mt_state(struct libevdev *dev,
 89-			 struct slot_change_state *changes_out);
 90+static int sync_mt_state(struct libevdev *dev);
 91 static int
 92 update_key_state(struct libevdev *dev, const struct input_event *e);
 93 
 94@@ -203,6 +187,8 @@ libevdev_reset(struct libevdev *dev)
 95 	free(dev->phys);
 96 	free(dev->uniq);
 97 	free(dev->mt_slot_vals);
 98+	free(dev->mt_sync.mt_state);
 99+	free(dev->mt_sync.changes);
100 	memset(dev, 0, sizeof(*dev));
101 	dev->fd = -1;
102 	dev->initialized = false;
103@@ -331,7 +317,11 @@ free_slots(struct libevdev *dev)
104 {
105 	dev->num_slots = -1;
106 	free(dev->mt_slot_vals);
107+	free(dev->mt_sync.changes);
108+	free(dev->mt_sync.mt_state);
109 	dev->mt_slot_vals = NULL;
110+	dev->mt_sync.changes = NULL;
111+	dev->mt_sync.mt_state = NULL;
112 }
113 
114 static int
115@@ -341,7 +331,11 @@ init_slots(struct libevdev *dev)
116 	int rc = 0;
117 
118 	free(dev->mt_slot_vals);
119+	free(dev->mt_sync.changes);
120+	free(dev->mt_sync.mt_state);
121 	dev->mt_slot_vals = NULL;
122+	dev->mt_sync.changes = NULL;
123+	dev->mt_sync.mt_state = NULL;
124 
125 	/* devices with ABS_RESERVED aren't MT devices,
126 	   see the documentation for multitouch-related
127@@ -365,6 +359,19 @@ init_slots(struct libevdev *dev)
128 	}
129 	dev->current_slot = abs_info->value;
130 
131+	dev->mt_sync.mt_state_sz = sizeof(*dev->mt_sync.mt_state) +
132+				   dev->num_slots * sizeof(int32_t);
133+	dev->mt_sync.mt_state = calloc(1, dev->mt_sync.mt_state_sz);
134+
135+	dev->mt_sync.changes_sz = dev->num_slots *
136+				  sizeof(dev->mt_sync.changes[0]);
137+	dev->mt_sync.changes = malloc(dev->mt_sync.changes_sz);
138+
139+	if (!dev->mt_sync.changes || !dev->mt_sync.mt_state) {
140+		rc = -ENOMEM;
141+		goto out;
142+	}
143+
144 	reset_tracking_ids(dev);
145 out:
146 	return rc;
147@@ -523,10 +530,8 @@ libevdev_set_fd(struct libevdev* dev, int fd)
148 	if (rc != 0)
149 		goto out;
150 
151-	if (dev->num_slots != -1) {
152-		struct slot_change_state unused[dev->num_slots];
153-		sync_mt_state(dev, unused);
154-	}
155+	if (dev->num_slots != -1)
156+		sync_mt_state(dev);
157 
158 	rc = init_event_queue(dev);
159 	if (rc < 0) {
160@@ -661,33 +666,27 @@ out:
161 }
162 
163 static int
164-sync_mt_state(struct libevdev *dev,
165-	      struct slot_change_state changes_out[dev->num_slots])
166+sync_mt_state(struct libevdev *dev)
167 {
168-#define MAX_SLOTS 256
169 	int rc = 0;
170-	struct slot_change_state changes[MAX_SLOTS] = {0};
171-	unsigned int nslots = min(MAX_SLOTS, dev->num_slots);
172+	struct mt_sync_state *mt_state = dev->mt_sync.mt_state;
173+	struct slot_change_state *changes = dev->mt_sync.changes;
174 
175-	for (int axis = ABS_MT_MIN; axis <= ABS_MT_MAX; axis++) {
176-		/* EVIOCGMTSLOTS required format */
177-		struct mt_sync_state {
178-			uint32_t code;
179-			int32_t val[MAX_SLOTS];
180-		} mt_state;
181+	memset(dev->mt_sync.changes, 0, dev->mt_sync.changes_sz);
182 
183+	for (int axis = ABS_MT_MIN; axis <= ABS_MT_MAX; axis++) {
184 		if (axis == ABS_MT_SLOT ||
185 		    !libevdev_has_event_code(dev, EV_ABS, axis))
186 			continue;
187 
188-		mt_state.code = axis;
189-		rc = ioctl(dev->fd, EVIOCGMTSLOTS(sizeof(mt_state)), &mt_state);
190+		mt_state->code = axis;
191+		rc = ioctl(dev->fd, EVIOCGMTSLOTS(dev->mt_sync.mt_state_sz), mt_state);
192 		if (rc < 0)
193 			goto out;
194 
195-		for (unsigned int slot = 0; slot < nslots; slot++) {
196+		for (int slot = 0; slot < dev->num_slots; slot++) {
197 			int val_before = *slot_value(dev, slot, axis),
198-			    val_after = mt_state.val[slot];
199+			    val_after = mt_state->val[slot];
200 
201 			if (axis == ABS_MT_TRACKING_ID) {
202 				if (val_before == -1 && val_after != -1) {
203@@ -716,17 +715,12 @@ sync_mt_state(struct libevdev *dev,
204 		}
205 	}
206 
207-	if (dev->num_slots > MAX_SLOTS)
208-		memset(changes_out, 0, sizeof(*changes) * dev->num_slots);
209-
210-	memcpy(changes_out, changes, sizeof(*changes) * nslots);
211 out:
212 	return rc;
213 }
214 
215 static void
216 terminate_slots(struct libevdev *dev,
217-		const struct slot_change_state changes[dev->num_slots],
218 		int *last_reported_slot)
219 {
220 	const unsigned int map[] = {BTN_TOOL_FINGER, BTN_TOOL_DOUBLETAP,
221@@ -734,6 +728,7 @@ terminate_slots(struct libevdev *dev,
222 				    BTN_TOOL_QUINTTAP};
223 	bool touches_stopped = false;
224 	int ntouches_before = 0, ntouches_after = 0;
225+	struct slot_change_state *changes = dev->mt_sync.changes;
226 
227 	/* For BTN_TOOL_* emulation, we need to know how many touches we had
228 	 * before and how many we have left once we terminate all the ones
229@@ -797,10 +792,10 @@ terminate_slots(struct libevdev *dev,
230 
231 static int
232 push_mt_sync_events(struct libevdev *dev,
233-		    const struct slot_change_state changes[dev->num_slots],
234 		    int last_reported_slot)
235 {
236 	struct input_absinfo abs_info;
237+	struct slot_change_state *changes = dev->mt_sync.changes;
238 	int rc;
239 
240 	for (int slot = 0; slot < dev->num_slots;  slot++) {
241@@ -909,8 +904,6 @@ sync_state(struct libevdev *dev)
242 	int rc = 0;
243 	bool want_mt_sync = false;
244 	int last_reported_slot = 0;
245-	struct slot_change_state changes[dev->num_slots > 0 ? dev->num_slots : 1];
246-		memset(changes, 0, sizeof(changes));
247 
248 	 /* see section "Discarding events before synchronizing" in
249 	  * libevdev/libevdev.h */
250@@ -928,9 +921,9 @@ sync_state(struct libevdev *dev)
251 	if (dev->num_slots > -1 &&
252 	    libevdev_has_event_code(dev, EV_ABS, ABS_MT_SLOT)) {
253 		want_mt_sync = true;
254-		rc = sync_mt_state(dev, changes);
255+		rc = sync_mt_state(dev);
256 		if (rc == 0)
257-			terminate_slots(dev, changes, &last_reported_slot);
258+			terminate_slots(dev, &last_reported_slot);
259 		else
260 			want_mt_sync = false;
261 	}
262@@ -944,7 +937,7 @@ sync_state(struct libevdev *dev)
263 	if (rc == 0 && libevdev_has_event_type(dev, EV_ABS))
264 		rc = sync_abs_state(dev);
265 	if (rc == 0 && want_mt_sync)
266-		push_mt_sync_events(dev, changes, last_reported_slot);
267+		push_mt_sync_events(dev, last_reported_slot);
268 
269 	dev->queue_nsync = queue_num_elements(dev);
270 
271-- 
2722.30.0
273