Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 8 Sep 2021 00:02:23 GMT
From:      Vladimir Kondratyev <wulf@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: 5bf6cf0fbb2d - stable/13 - evdev: Use bitsets to track active touches and slots changed in current report
Message-ID:  <202109080002.18802NST050237@gitrepo.freebsd.org>

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

URL: https://cgit.FreeBSD.org/src/commit/?id=5bf6cf0fbb2d033b95f0b38ce2c46f07c68480ac

commit 5bf6cf0fbb2d033b95f0b38ce2c46f07c68480ac
Author:     Vladimir Kondratyev <wulf@FreeBSD.org>
AuthorDate: 2021-08-24 22:44:36 +0000
Commit:     Vladimir Kondratyev <wulf@FreeBSD.org>
CommitDate: 2021-09-07 23:55:37 +0000

    evdev: Use bitsets to track active touches and slots changed in current report
    
    Obtained from:  OpenBSD
    
    (cherry picked from commit 2dc7188e532f0147b36a44ce5c033d9f59cbd9f4)
---
 sys/dev/evdev/evdev_mt.c | 94 ++++++++++++++++++++++--------------------------
 1 file changed, 43 insertions(+), 51 deletions(-)

diff --git a/sys/dev/evdev/evdev_mt.c b/sys/dev/evdev/evdev_mt.c
index e8f892e235c0..a28b034884ba 100644
--- a/sys/dev/evdev/evdev_mt.c
+++ b/sys/dev/evdev/evdev_mt.c
@@ -42,6 +42,13 @@
 #define	debugf(fmt, args...)
 #endif
 
+typedef	u_int	slotset_t;
+
+_Static_assert(MAX_MT_SLOTS < sizeof(slotset_t) * 8, "MAX_MT_SLOTS too big");
+
+#define FOREACHBIT(v, i) \
+	for ((i) = ffs(v) - 1; (i) != -1; (i) = ffs((v) & (~1 << (i))) - 1)
+
 static uint16_t evdev_mtstmap[][2] = {
 	{ ABS_MT_POSITION_X, ABS_X },
 	{ ABS_MT_POSITION_Y, ABS_Y },
@@ -50,18 +57,27 @@ static uint16_t evdev_mtstmap[][2] = {
 };
 
 struct evdev_mt_slot {
-	uint64_t	ev_report;
 	int32_t		val[MT_CNT];
 };
 
 struct evdev_mt {
 	int			last_reported_slot;
+	/* the set of slots with active touches */
+	slotset_t		touches;
+	/* the set of slots with unsynchronized state */
+	slotset_t		frame;
 	struct evdev_mt_slot	slots[];
 };
 
 static void	evdev_mt_send_st_compat(struct evdev_dev *);
 static void	evdev_mt_send_autorel(struct evdev_dev *);
 
+static inline int
+ffc_slot(struct evdev_dev *evdev, slotset_t slots)
+{
+	return (ffs(~slots & (2U << MAXIMAL_MT_SLOT(evdev)) - 1) - 1);
+}
+
 void
 evdev_mt_init(struct evdev_dev *evdev)
 {
@@ -73,17 +89,9 @@ evdev_mt_init(struct evdev_dev *evdev)
 	     sizeof(struct evdev_mt_slot) * slots, M_EVDEV, M_WAITOK | M_ZERO);
 
 	/* Initialize multitouch protocol type B states */
-	for (slot = 0; slot < slots; slot++) {
-		/*
-		 * .ev_report should not be initialized to initial value of
-		 * report counter (0) as it brokes free slot detection in
-		 * evdev_get_mt_slot_by_tracking_id. So initialize it to -1
-		 */
-		evdev->ev_mt->slots[slot] = (struct evdev_mt_slot) {
-			.ev_report = 0xFFFFFFFFFFFFFFFFULL,
-			.val[ABS_MT_INDEX(ABS_MT_TRACKING_ID)] = -1,
-		};
-	}
+	for (slot = 0; slot < slots; slot++)
+		evdev->ev_mt->slots[slot].val[ABS_MT_INDEX(ABS_MT_TRACKING_ID)]
+		    = -1;
 
 	if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_STCOMPAT))
 		evdev_support_mt_compat(evdev);
@@ -103,6 +111,7 @@ evdev_mt_sync_frame(struct evdev_dev *evdev)
 	if (evdev->ev_report_opened &&
 	    bit_test(evdev->ev_flags, EVDEV_FLAG_MT_STCOMPAT))
 		evdev_mt_send_st_compat(evdev);
+	evdev->ev_mt->frame = 0;
 }
 
 int
@@ -118,7 +127,7 @@ evdev_mt_set_last_slot(struct evdev_dev *evdev, int slot)
 
 	MPASS(slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev));
 
-	mt->slots[slot].ev_report = evdev->ev_report_count;
+	mt->frame |= 1U << slot;
 	mt->last_reported_slot = slot;
 }
 
@@ -140,6 +149,12 @@ evdev_mt_set_value(struct evdev_dev *evdev, int slot, int16_t code,
 
 	MPASS(slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev));
 
+	if (code == ABS_MT_TRACKING_ID) {
+		if (value != -1)
+			mt->touches |= 1U << slot;
+		else
+			mt->touches &= ~(1U << slot);
+	}
 	mt->slots[slot].val[ABS_MT_INDEX(code)] = value;
 }
 
@@ -147,25 +162,17 @@ int
 evdev_get_mt_slot_by_tracking_id(struct evdev_dev *evdev, int32_t tracking_id)
 {
 	struct evdev_mt *mt = evdev->ev_mt;
-	int32_t tr_id;
-	int slot, free_slot = -1;
+	int slot;
 
-	for (slot = 0; slot <= MAXIMAL_MT_SLOT(evdev); slot++) {
-		tr_id = evdev_mt_get_value(evdev, slot, ABS_MT_TRACKING_ID);
-		if (tr_id == tracking_id)
+	FOREACHBIT(mt->touches, slot)
+		if (evdev_mt_get_value(evdev, slot, ABS_MT_TRACKING_ID) ==
+		    tracking_id)
 			return (slot);
-		/*
-		 * Its possible that slot will be reassigned in a place of just
-		 * released one within the same report. To avoid this compare
-		 * report counter with slot`s report number updated with each
-		 * ABS_MT_TRACKING_ID change.
-		 */
-		if (free_slot == -1 && tr_id == -1 &&
-		    mt->slots[slot].ev_report != evdev->ev_report_count)
-			free_slot = slot;
-	}
-
-	return (free_slot);
+	/*
+	 * Do not allow allocation of new slot in a place of just
+	 * released one within the same report.
+	 */
+	return (ffc_slot(evdev, mt->touches | mt->frame));
 }
 
 void
@@ -194,29 +201,18 @@ evdev_support_mt_compat(struct evdev_dev *evdev)
 			    evdev->ev_absinfo[evdev_mtstmap[i][0]].resolution);
 }
 
-static int32_t
-evdev_count_fingers(struct evdev_dev *evdev)
-{
-	int nfingers = 0, i;
-
-	for (i = 0; i <= MAXIMAL_MT_SLOT(evdev); i++)
-		if (evdev_mt_get_value(evdev, i, ABS_MT_TRACKING_ID) != -1)
-			nfingers++;
-
-	return (nfingers);
-}
-
 static void
 evdev_mt_send_st_compat(struct evdev_dev *evdev)
 {
+	struct evdev_mt *mt = evdev->ev_mt;
 	int nfingers, i;
 
 	EVDEV_LOCK_ASSERT(evdev);
 
-	nfingers = evdev_count_fingers(evdev);
+	nfingers = bitcount(mt->touches);
 	evdev_send_event(evdev, EV_KEY, BTN_TOUCH, nfingers > 0);
 
-	if (evdev_mt_get_value(evdev, 0, ABS_MT_TRACKING_ID) != -1)
+	if ((mt->touches & 1U << 0) != 0)
 		/* Echo 0-th MT-slot as ST-slot */
 		for (i = 0; i < nitems(evdev_mtstmap); i++)
 			if (bit_test(evdev->ev_abs_flags, evdev_mtstmap[i][1]))
@@ -250,13 +246,9 @@ evdev_mt_send_autorel(struct evdev_dev *evdev)
 
 	EVDEV_LOCK_ASSERT(evdev);
 
-	for (slot = 0; slot <= MAXIMAL_MT_SLOT(evdev); slot++) {
-		if (mt->slots[slot].ev_report != evdev->ev_report_count &&
-		    evdev_mt_get_value(evdev, slot, ABS_MT_TRACKING_ID) != -1){
-			evdev_send_event(evdev, EV_ABS, ABS_MT_SLOT, slot);
-			evdev_send_event(evdev, EV_ABS, ABS_MT_TRACKING_ID,
-			    -1);
-		}
+	FOREACHBIT(mt->touches & ~mt->frame, slot) {
+		evdev_send_event(evdev, EV_ABS, ABS_MT_SLOT, slot);
+		evdev_send_event(evdev, EV_ABS, ABS_MT_TRACKING_ID, -1);
 	}
 }
 



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