git: 66bd52f5e241 - main - evdev: Make MT tracking IDs monotonically increasing sequence.
Vladimir Kondratyev
wulf at FreeBSD.org
Tue Aug 24 23:04:20 UTC 2021
The branch main has been updated by wulf:
URL: https://cgit.FreeBSD.org/src/commit/?id=66bd52f5e241bd2548015f847f12cdff69176c40
commit 66bd52f5e241bd2548015f847f12cdff69176c40
Author: Vladimir Kondratyev <wulf at FreeBSD.org>
AuthorDate: 2021-08-24 22:48:33 +0000
Commit: Vladimir Kondratyev <wulf at FreeBSD.org>
CommitDate: 2021-08-24 22:48:33 +0000
evdev: Make MT tracking IDs monotonically increasing sequence.
MFC after: 2 weeks
---
sys/dev/evdev/evdev.c | 16 ++++++++++++----
sys/dev/evdev/evdev.h | 1 +
sys/dev/evdev/evdev_mt.c | 35 ++++++++++++++++++++++++++++++++++-
sys/dev/evdev/evdev_private.h | 1 +
sys/dev/evdev/uinput.c | 1 +
5 files changed, 49 insertions(+), 5 deletions(-)
diff --git a/sys/dev/evdev/evdev.c b/sys/dev/evdev/evdev.c
index d6f6cc2e003f..b5eed0e5f02f 100644
--- a/sys/dev/evdev/evdev.c
+++ b/sys/dev/evdev/evdev.c
@@ -701,15 +701,23 @@ evdev_modify_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
break;
case EV_ABS:
- fuzz = evdev->ev_absinfo[code].fuzz;
- if (fuzz == 0 || code == ABS_MT_SLOT)
+ if (code == ABS_MT_SLOT)
break;
else if (!ABS_IS_MT(code))
old_value = evdev->ev_absinfo[code].value;
- else if (bit_test(evdev->ev_abs_flags, ABS_MT_SLOT))
+ else if (!bit_test(evdev->ev_abs_flags, ABS_MT_SLOT))
+ /* Pass MT protocol type A events as is */
+ break;
+ else if (code == ABS_MT_TRACKING_ID) {
+ *value = evdev_mt_reassign_id(evdev,
+ evdev_mt_get_last_slot(evdev), *value);
+ break;
+ } else
old_value = evdev_mt_get_value(evdev,
evdev_mt_get_last_slot(evdev), code);
- else /* Pass MT protocol type A events as is */
+
+ fuzz = evdev->ev_absinfo[code].fuzz;
+ if (fuzz == 0)
break;
abs_change = abs(*value - old_value);
diff --git a/sys/dev/evdev/evdev.h b/sys/dev/evdev/evdev.h
index 64bf75f04efd..e1c5aedb029c 100644
--- a/sys/dev/evdev/evdev.h
+++ b/sys/dev/evdev/evdev.h
@@ -90,6 +90,7 @@ extern int evdev_sysmouse_t_axis;
* current MT protocol type B report */
#define EVDEV_FLAG_EXT_EPOCH 0x03 /* evdev_push_* is allways called with
* input (global) epoch entered */
+#define EVDEV_FLAG_MT_KEEPID 0x04 /* Do not reassign tracking ID */
#define EVDEV_FLAG_MAX 0x1F
#define EVDEV_FLAG_CNT (EVDEV_FLAG_MAX + 1)
diff --git a/sys/dev/evdev/evdev_mt.c b/sys/dev/evdev/evdev_mt.c
index 6f5cce4a008d..1a600fe3480d 100644
--- a/sys/dev/evdev/evdev_mt.c
+++ b/sys/dev/evdev/evdev_mt.c
@@ -62,6 +62,8 @@ struct {
struct evdev_mt {
int last_reported_slot;
+ uint16_t tracking_id;
+ int32_t tracking_ids[MAX_MT_SLOTS];
u_int mtst_events;
/* the set of slots with active touches */
slotset_t touches;
@@ -93,6 +95,9 @@ evdev_mt_init(struct evdev_dev *evdev)
for (slot = 0; slot < slots; slot++)
evdev->ev_mt->slots[slot].id = -1;
+ if (!bit_test(evdev->ev_flags, EVDEV_FLAG_MT_KEEPID))
+ evdev_support_abs(evdev,
+ ABS_MT_TRACKING_ID, -1, UINT16_MAX, 0, 0, 0);
if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_STCOMPAT))
evdev_support_mt_compat(evdev);
}
@@ -208,7 +213,7 @@ evdev_get_mt_slot_by_tracking_id(struct evdev_dev *evdev, int32_t tracking_id)
int slot;
FOREACHBIT(mt->touches, slot)
- if (mt->slots[slot].id == tracking_id)
+ if (mt->tracking_ids[slot] == tracking_id)
return (slot);
/*
* Do not allow allocation of new slot in a place of just
@@ -217,6 +222,34 @@ evdev_get_mt_slot_by_tracking_id(struct evdev_dev *evdev, int32_t tracking_id)
return (ffc_slot(evdev, mt->touches | mt->frame));
}
+int32_t
+evdev_mt_reassign_id(struct evdev_dev *evdev, int slot, int32_t id)
+{
+ struct evdev_mt *mt = evdev->ev_mt;
+ int32_t nid;
+
+ if (id == -1 || bit_test(evdev->ev_flags, EVDEV_FLAG_MT_KEEPID)) {
+ mt->tracking_ids[slot] = id;
+ return (id);
+ }
+
+ nid = evdev_mt_get_value(evdev, slot, ABS_MT_TRACKING_ID);
+ if (nid != -1) {
+ KASSERT(id == mt->tracking_ids[slot],
+ ("MT-slot tracking id has changed"));
+ return (nid);
+ }
+
+ mt->tracking_ids[slot] = id;
+again:
+ nid = mt->tracking_id++;
+ FOREACHBIT(mt->touches, slot)
+ if (evdev_mt_get_value(evdev, slot, ABS_MT_TRACKING_ID) == nid)
+ goto again;
+
+ return (nid);
+}
+
static inline int32_t
evdev_mt_normalize(int32_t value, int32_t mtmin, int32_t mtmax, int32_t stmax)
{
diff --git a/sys/dev/evdev/evdev_private.h b/sys/dev/evdev/evdev_private.h
index fc079a324ba4..3fb2d61d091a 100644
--- a/sys/dev/evdev/evdev_private.h
+++ b/sys/dev/evdev/evdev_private.h
@@ -284,6 +284,7 @@ int evdev_mt_get_last_slot(struct evdev_dev *);
void evdev_mt_set_last_slot(struct evdev_dev *, int);
int32_t evdev_mt_get_value(struct evdev_dev *, int, int16_t);
void evdev_mt_set_value(struct evdev_dev *, int, int16_t, int32_t);
+int32_t evdev_mt_reassign_id(struct evdev_dev *, int, int32_t);
/* Utility functions: */
void evdev_client_dumpqueue(struct evdev_client *);
diff --git a/sys/dev/evdev/uinput.c b/sys/dev/evdev/uinput.c
index ceecee652ac3..e7854e89f645 100644
--- a/sys/dev/evdev/uinput.c
+++ b/sys/dev/evdev/uinput.c
@@ -495,6 +495,7 @@ uinput_ioctl_sub(struct uinput_cdev_state *state, u_long cmd, caddr_t data)
evdev_set_methods(state->ucs_evdev, state, &uinput_ev_methods);
evdev_set_flag(state->ucs_evdev, EVDEV_FLAG_SOFTREPEAT);
+ evdev_set_flag(state->ucs_evdev, EVDEV_FLAG_MT_KEEPID);
ret = evdev_register(state->ucs_evdev);
if (ret == 0)
state->ucs_state = UINPUT_RUNNING;
More information about the dev-commits-src-all
mailing list