Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 24 Aug 2021 23:04:17 GMT
From:      Vladimir Kondratyev <wulf@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 66bd52f5e241 - main - evdev: Make MT tracking IDs monotonically increasing sequence.
Message-ID:  <202108242304.17ON4Hhk000851@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by wulf:

URL: https://cgit.FreeBSD.org/src/commit/?id=66bd52f5e241bd2548015f847f12cdff69176c40

commit 66bd52f5e241bd2548015f847f12cdff69176c40
Author:     Vladimir Kondratyev <wulf@FreeBSD.org>
AuthorDate: 2021-08-24 22:48:33 +0000
Commit:     Vladimir Kondratyev <wulf@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;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202108242304.17ON4Hhk000851>