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