282 lines
8.1 KiB
Diff
282 lines
8.1 KiB
Diff
|
From 3bf2649a9874b5d63e178d2d61ea822901ff991f Mon Sep 17 00:00:00 2001
|
||
|
From: Michael Forney <mforney@mforney.org>
|
||
|
Date: Tue, 3 Mar 2020 14:17:37 -0800
|
||
|
Subject: [PATCH libevdev] Revert switch to VLAs for multitouch state
|
||
|
|
||
|
Signed-off-by: Michael Forney <mforney@mforney.org>
|
||
|
---
|
||
|
libevdev/libevdev-int.h | 28 +++++++++++++
|
||
|
libevdev/libevdev.c | 88 +++++++++++++++++++----------------------
|
||
|
2 files changed, 68 insertions(+), 48 deletions(-)
|
||
|
|
||
|
diff --git a/libevdev/libevdev-int.h b/libevdev/libevdev-int.h
|
||
|
index 7da5cf0..2743e50 100644
|
||
|
--- a/libevdev/libevdev-int.h
|
||
|
+++ b/libevdev/libevdev-int.h
|
||
|
@@ -24,6 +24,7 @@
|
||
|
#define LIBEVDEV_INT_H
|
||
|
|
||
|
#include "config.h"
|
||
|
+#include <stdint.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdbool.h>
|
||
|
@@ -55,6 +56,26 @@ enum SyncState {
|
||
|
SYNC_IN_PROGRESS,
|
||
|
};
|
||
|
|
||
|
+struct mt_sync_state {
|
||
|
+ uint32_t code;
|
||
|
+ int32_t val[];
|
||
|
+};
|
||
|
+
|
||
|
+/* Keeps a record of touches during SYN_DROPPED */
|
||
|
+enum touch_state {
|
||
|
+ TOUCH_OFF,
|
||
|
+ TOUCH_STARTED, /* Started during SYN_DROPPED */
|
||
|
+ TOUCH_STOPPED, /* Stopped during SYN_DROPPED */
|
||
|
+ TOUCH_ONGOING, /* Existed before, still have same tracking ID */
|
||
|
+ TOUCH_CHANGED, /* Existed before but have new tracking ID now, so
|
||
|
+ stopped + started in that slot */
|
||
|
+};
|
||
|
+
|
||
|
+struct slot_change_state {
|
||
|
+ enum touch_state state;
|
||
|
+ unsigned long axes[NLONGS(ABS_CNT)]; /* bitmask for updated axes */
|
||
|
+};
|
||
|
+
|
||
|
/**
|
||
|
* Internal only: log data used to send messages to the respective log
|
||
|
* handler. We re-use the same struct for a global and inside
|
||
|
@@ -107,6 +128,13 @@ struct libevdev {
|
||
|
|
||
|
struct timeval last_event_time;
|
||
|
|
||
|
+ struct {
|
||
|
+ struct mt_sync_state *mt_state;
|
||
|
+ size_t mt_state_sz; /* in bytes */
|
||
|
+ struct slot_change_state *changes;
|
||
|
+ size_t changes_sz; /* in bytes */
|
||
|
+ } mt_sync;
|
||
|
+
|
||
|
struct logdata log;
|
||
|
};
|
||
|
|
||
|
diff --git a/libevdev/libevdev.c b/libevdev/libevdev.c
|
||
|
index c4729b5..ff967d0 100644
|
||
|
--- a/libevdev/libevdev.c
|
||
|
+++ b/libevdev/libevdev.c
|
||
|
@@ -28,7 +28,6 @@
|
||
|
#include <limits.h>
|
||
|
#include <unistd.h>
|
||
|
#include <stdarg.h>
|
||
|
-#include <stdint.h>
|
||
|
#include <stdbool.h>
|
||
|
|
||
|
#include "libevdev.h"
|
||
|
@@ -44,23 +43,7 @@ enum event_filter_status {
|
||
|
EVENT_FILTER_DISCARD, /**< Discard current event */
|
||
|
};
|
||
|
|
||
|
-/* Keeps a record of touches during SYN_DROPPED */
|
||
|
-enum touch_state {
|
||
|
- TOUCH_OFF,
|
||
|
- TOUCH_STARTED, /* Started during SYN_DROPPED */
|
||
|
- TOUCH_STOPPED, /* Stopped during SYN_DROPPED */
|
||
|
- TOUCH_ONGOING, /* Existed before, still have same tracking ID */
|
||
|
- TOUCH_CHANGED, /* Existed before but have new tracking ID now, so
|
||
|
- stopped + started in that slot */
|
||
|
-};
|
||
|
-
|
||
|
-struct slot_change_state {
|
||
|
- enum touch_state state;
|
||
|
- unsigned long axes[NLONGS(ABS_CNT)]; /* bitmask for updated axes */
|
||
|
-};
|
||
|
-
|
||
|
-static int sync_mt_state(struct libevdev *dev,
|
||
|
- struct slot_change_state *changes_out);
|
||
|
+static int sync_mt_state(struct libevdev *dev);
|
||
|
static int
|
||
|
update_key_state(struct libevdev *dev, const struct input_event *e);
|
||
|
|
||
|
@@ -219,6 +202,8 @@ libevdev_reset(struct libevdev *dev)
|
||
|
free(dev->phys);
|
||
|
free(dev->uniq);
|
||
|
free(dev->mt_slot_vals);
|
||
|
+ free(dev->mt_sync.mt_state);
|
||
|
+ free(dev->mt_sync.changes);
|
||
|
memset(dev, 0, sizeof(*dev));
|
||
|
dev->fd = -1;
|
||
|
dev->initialized = false;
|
||
|
@@ -348,7 +333,11 @@ free_slots(struct libevdev *dev)
|
||
|
{
|
||
|
dev->num_slots = -1;
|
||
|
free(dev->mt_slot_vals);
|
||
|
+ free(dev->mt_sync.changes);
|
||
|
+ free(dev->mt_sync.mt_state);
|
||
|
dev->mt_slot_vals = NULL;
|
||
|
+ dev->mt_sync.changes = NULL;
|
||
|
+ dev->mt_sync.mt_state = NULL;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
@@ -358,7 +347,11 @@ init_slots(struct libevdev *dev)
|
||
|
int rc = 0;
|
||
|
|
||
|
free(dev->mt_slot_vals);
|
||
|
+ free(dev->mt_sync.changes);
|
||
|
+ free(dev->mt_sync.mt_state);
|
||
|
dev->mt_slot_vals = NULL;
|
||
|
+ dev->mt_sync.changes = NULL;
|
||
|
+ dev->mt_sync.mt_state = NULL;
|
||
|
|
||
|
/* devices with ABS_RESERVED aren't MT devices,
|
||
|
see the documentation for multitouch-related
|
||
|
@@ -382,6 +375,19 @@ init_slots(struct libevdev *dev)
|
||
|
}
|
||
|
dev->current_slot = abs_info->value;
|
||
|
|
||
|
+ dev->mt_sync.mt_state_sz = sizeof(*dev->mt_sync.mt_state) +
|
||
|
+ dev->num_slots * sizeof(int32_t);
|
||
|
+ dev->mt_sync.mt_state = calloc(1, dev->mt_sync.mt_state_sz);
|
||
|
+
|
||
|
+ dev->mt_sync.changes_sz = dev->num_slots *
|
||
|
+ sizeof(dev->mt_sync.changes[0]);
|
||
|
+ dev->mt_sync.changes = malloc(dev->mt_sync.changes_sz);
|
||
|
+
|
||
|
+ if (!dev->mt_sync.changes || !dev->mt_sync.mt_state) {
|
||
|
+ rc = -ENOMEM;
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+
|
||
|
reset_tracking_ids(dev);
|
||
|
out:
|
||
|
return rc;
|
||
|
@@ -538,10 +544,8 @@ libevdev_set_fd(struct libevdev* dev, int fd)
|
||
|
if (rc != 0)
|
||
|
goto out;
|
||
|
|
||
|
- if (dev->num_slots != -1) {
|
||
|
- struct slot_change_state unused[dev->num_slots];
|
||
|
- sync_mt_state(dev, unused);
|
||
|
- }
|
||
|
+ if (dev->num_slots != -1)
|
||
|
+ sync_mt_state(dev);
|
||
|
|
||
|
rc = init_event_queue(dev);
|
||
|
if (rc < 0) {
|
||
|
@@ -676,33 +680,27 @@ out:
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
-sync_mt_state(struct libevdev *dev,
|
||
|
- struct slot_change_state changes_out[dev->num_slots])
|
||
|
+sync_mt_state(struct libevdev *dev)
|
||
|
{
|
||
|
-#define MAX_SLOTS 256
|
||
|
int rc = 0;
|
||
|
- struct slot_change_state changes[MAX_SLOTS] = {0};
|
||
|
- unsigned int nslots = min(MAX_SLOTS, dev->num_slots);
|
||
|
+ struct mt_sync_state *mt_state = dev->mt_sync.mt_state;
|
||
|
+ struct slot_change_state *changes = dev->mt_sync.changes;
|
||
|
|
||
|
- for (int axis = ABS_MT_MIN; axis <= ABS_MT_MAX; axis++) {
|
||
|
- /* EVIOCGMTSLOTS required format */
|
||
|
- struct mt_sync_state {
|
||
|
- uint32_t code;
|
||
|
- int32_t val[MAX_SLOTS];
|
||
|
- } mt_state;
|
||
|
+ memset(dev->mt_sync.changes, 0, dev->mt_sync.changes_sz);
|
||
|
|
||
|
+ for (int axis = ABS_MT_MIN; axis <= ABS_MT_MAX; axis++) {
|
||
|
if (axis == ABS_MT_SLOT ||
|
||
|
!libevdev_has_event_code(dev, EV_ABS, axis))
|
||
|
continue;
|
||
|
|
||
|
- mt_state.code = axis;
|
||
|
- rc = ioctl(dev->fd, EVIOCGMTSLOTS(sizeof(mt_state)), &mt_state);
|
||
|
+ mt_state->code = axis;
|
||
|
+ rc = ioctl(dev->fd, EVIOCGMTSLOTS(dev->mt_sync.mt_state_sz), mt_state);
|
||
|
if (rc < 0)
|
||
|
goto out;
|
||
|
|
||
|
- for (unsigned int slot = 0; slot < nslots; slot++) {
|
||
|
+ for (int slot = 0; slot < dev->num_slots; slot++) {
|
||
|
int val_before = *slot_value(dev, slot, axis),
|
||
|
- val_after = mt_state.val[slot];
|
||
|
+ val_after = mt_state->val[slot];
|
||
|
|
||
|
if (axis == ABS_MT_TRACKING_ID) {
|
||
|
if (val_before == -1 && val_after != -1) {
|
||
|
@@ -731,17 +729,12 @@ sync_mt_state(struct libevdev *dev,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- if (dev->num_slots > MAX_SLOTS)
|
||
|
- memset(changes_out, 0, sizeof(*changes) * dev->num_slots);
|
||
|
-
|
||
|
- memcpy(changes_out, changes, sizeof(*changes) * nslots);
|
||
|
out:
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
terminate_slots(struct libevdev *dev,
|
||
|
- const struct slot_change_state changes[dev->num_slots],
|
||
|
int *last_reported_slot)
|
||
|
{
|
||
|
const unsigned int map[] = {BTN_TOOL_FINGER, BTN_TOOL_DOUBLETAP,
|
||
|
@@ -749,6 +742,7 @@ terminate_slots(struct libevdev *dev,
|
||
|
BTN_TOOL_QUINTTAP};
|
||
|
bool touches_stopped = false;
|
||
|
int ntouches_before = 0, ntouches_after = 0;
|
||
|
+ struct slot_change_state *changes = dev->mt_sync.changes;
|
||
|
|
||
|
/* For BTN_TOOL_* emulation, we need to know how many touches we had
|
||
|
* before and how many we have left once we terminate all the ones
|
||
|
@@ -812,10 +806,10 @@ terminate_slots(struct libevdev *dev,
|
||
|
|
||
|
static int
|
||
|
push_mt_sync_events(struct libevdev *dev,
|
||
|
- const struct slot_change_state changes[dev->num_slots],
|
||
|
int last_reported_slot)
|
||
|
{
|
||
|
struct input_absinfo abs_info;
|
||
|
+ struct slot_change_state *changes = dev->mt_sync.changes;
|
||
|
int rc;
|
||
|
|
||
|
for (int slot = 0; slot < dev->num_slots; slot++) {
|
||
|
@@ -922,8 +916,6 @@ sync_state(struct libevdev *dev)
|
||
|
int rc = 0;
|
||
|
bool want_mt_sync = false;
|
||
|
int last_reported_slot = 0;
|
||
|
- struct slot_change_state changes[dev->num_slots > 0 ? dev->num_slots : 1];
|
||
|
- memset(changes, 0, sizeof(changes));
|
||
|
|
||
|
/* see section "Discarding events before synchronizing" in
|
||
|
* libevdev/libevdev.h */
|
||
|
@@ -941,9 +933,9 @@ sync_state(struct libevdev *dev)
|
||
|
if (dev->num_slots > -1 &&
|
||
|
libevdev_has_event_code(dev, EV_ABS, ABS_MT_SLOT)) {
|
||
|
want_mt_sync = true;
|
||
|
- rc = sync_mt_state(dev, changes);
|
||
|
+ rc = sync_mt_state(dev);
|
||
|
if (rc == 0)
|
||
|
- terminate_slots(dev, changes, &last_reported_slot);
|
||
|
+ terminate_slots(dev, &last_reported_slot);
|
||
|
else
|
||
|
want_mt_sync = false;
|
||
|
}
|
||
|
@@ -957,7 +949,7 @@ sync_state(struct libevdev *dev)
|
||
|
if (rc == 0 && libevdev_has_event_type(dev, EV_ABS))
|
||
|
rc = sync_abs_state(dev);
|
||
|
if (rc == 0 && want_mt_sync)
|
||
|
- push_mt_sync_events(dev, changes, last_reported_slot);
|
||
|
+ push_mt_sync_events(dev, last_reported_slot);
|
||
|
|
||
|
dev->queue_nsync = queue_num_elements(dev);
|
||
|
|
||
|
--
|
||
|
2.27.0
|
||
|
|