git: 45fd5fe9e973 - stable/13 - evdev: Add support for automatic MT protocol type A to type B conversion.

Vladimir Kondratyev wulf at FreeBSD.org
Wed Sep 8 00:02:37 UTC 2021


The branch stable/13 has been updated by wulf:

URL: https://cgit.FreeBSD.org/src/commit/?id=45fd5fe9e97396f3dfdf399b8f84301db599b517

commit 45fd5fe9e97396f3dfdf399b8f84301db599b517
Author:     Vladimir Kondratyev <wulf at FreeBSD.org>
AuthorDate: 2021-08-24 22:53:56 +0000
Commit:     Vladimir Kondratyev <wulf at FreeBSD.org>
CommitDate: 2021-09-07 23:59:57 +0000

    evdev: Add support for automatic MT protocol type A to type B conversion.
    
    (cherry picked from commit d056693d7bc6c1b5f2c1612e5b34807f173e21c7)
---
 sys/dev/evdev/evdev.c    |  5 +++--
 sys/dev/evdev/evdev_mt.c | 32 ++++++++++++++++++++++++++++++--
 2 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/sys/dev/evdev/evdev.c b/sys/dev/evdev/evdev.c
index 74335b6f40b1..2fd7c2e201ea 100644
--- a/sys/dev/evdev/evdev.c
+++ b/sys/dev/evdev/evdev.c
@@ -306,8 +306,9 @@ evdev_register_common(struct evdev_dev *evdev)
 		}
 	}
 
-	/* Initialize multitouch protocol type B states */
-	if (bit_test(evdev->ev_abs_flags, ABS_MT_SLOT))
+	/* Initialize multitouch protocol type B states or A to B converter */
+	if (bit_test(evdev->ev_abs_flags, ABS_MT_SLOT) ||
+	    bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK))
 		evdev_mt_init(evdev);
 
 	/* Estimate maximum report size */
diff --git a/sys/dev/evdev/evdev_mt.c b/sys/dev/evdev/evdev_mt.c
index d5bf4affea1b..3030a60e098a 100644
--- a/sys/dev/evdev/evdev_mt.c
+++ b/sys/dev/evdev/evdev_mt.c
@@ -79,6 +79,7 @@ struct evdev_mt {
 	int			last_reported_slot;
 	uint16_t		tracking_id;
 	int32_t			tracking_ids[MAX_MT_SLOTS];
+	bool			type_a;
 	u_int			mtst_events;
 	/* the set of slots with active touches */
 	slotset_t		touches;
@@ -108,6 +109,16 @@ evdev_mt_init(struct evdev_dev *evdev)
 	struct evdev_mt *mt;
 	size_t size = offsetof(struct evdev_mt, slots);
 	int slot, slots;
+	bool type_a;
+
+	type_a = !bit_test(evdev->ev_abs_flags, ABS_MT_SLOT);
+	if (type_a) {
+		/* Add events produced by MT type A to type B converter */
+		evdev_support_abs(evdev,
+		    ABS_MT_SLOT, 0, MAX_MT_SLOTS - 1, 0, 0, 0);
+		evdev_support_abs(evdev,
+		    ABS_MT_TRACKING_ID, -1, MAX_MT_SLOTS - 1, 0, 0, 0);
+	}
 
 	slots = MAXIMAL_MT_SLOT(evdev) + 1;
 	size += sizeof(mt->slots[0]) * slots;
@@ -118,6 +129,7 @@ evdev_mt_init(struct evdev_dev *evdev)
 
 	mt = malloc(size, M_EVDEV, M_WAITOK | M_ZERO);
 	evdev->ev_mt = mt;
+	mt->type_a = type_a;
 
 	if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK)) {
 		mt->match_slots = mt->slots + slots;
@@ -186,13 +198,16 @@ evdev_mt_push_slot(struct evdev_dev *evdev, int slot,
 	struct evdev_mt *mt = evdev->ev_mt;
 	bool type_a = !bit_test(evdev->ev_abs_flags, ABS_MT_SLOT);
 
-	if (type_a && state == NULL)
+	if ((type_a || (mt != NULL && mt->type_a)) && state == NULL)
 		return (EINVAL);
 	if (!type_a && (slot < 0 || slot > MAXIMAL_MT_SLOT(evdev)))
 		return (EINVAL);
 
 	EVDEV_ENTER(evdev);
-	if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK)) {
+	if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK) && mt->type_a) {
+		mt->match_slots[mt->match_slot] = *state;
+		evdev_mt_record_event(evdev, EV_SYN, SYN_MT_REPORT, 1);
+	} else if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK)) {
 		evdev_mt_record_event(evdev, EV_ABS, ABS_MT_SLOT, slot);
 		if (state != NULL)
 			mt->match_slots[mt->match_slot] = *state;
@@ -394,14 +409,25 @@ evdev_mt_record_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
 	EVDEV_LOCK_ASSERT(evdev);
 
 	switch (type) {
+	case EV_SYN:
+		if (code == SYN_MT_REPORT) {
+			/* MT protocol type A support */
+			KASSERT(mt->type_a, ("Not a MT type A protocol"));
+			mt->match_frame |= 1U << mt->match_slot;
+			mt->match_slot++;
+			return (true);
+		}
+		break;
 	case EV_ABS:
 		if (code == ABS_MT_SLOT) {
 			/* MT protocol type B support */
+			KASSERT(!mt->type_a, ("Not a MT type B protocol"));
 			KASSERT(value >= 0, ("Negative slot number"));
 			mt->match_slot = value;
 			mt->match_frame |= 1U << mt->match_slot;
 			return (true);
 		} else if (code == ABS_MT_TRACKING_ID) {
+			KASSERT(!mt->type_a, ("Not a MT type B protocol"));
 			if (value == -1)
 				mt->match_frame &= ~(1U << mt->match_slot);
 			return (true);
@@ -496,6 +522,8 @@ evdev_get_mt_slot_by_tracking_id(struct evdev_dev *evdev, int32_t tracking_id)
 	struct evdev_mt *mt = evdev->ev_mt;
 	int slot;
 
+	KASSERT(!mt->type_a, ("Not a MT type B protocol"));
+
 	/*
 	 * Ignore tracking_id if slot assignment is performed by evdev.
 	 * Events are written sequentially to temporary matching buffer.


More information about the dev-commits-src-branches mailing list