aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladimir Kondratyev <wulf@FreeBSD.org>2021-08-24 22:53:56 +0000
committerVladimir Kondratyev <wulf@FreeBSD.org>2021-09-07 23:59:57 +0000
commit45fd5fe9e97396f3dfdf399b8f84301db599b517 (patch)
tree066e69bdc987b38816038c673a8bfd584d4b8df2
parent4174302b4a85fc048b10dd93183231e13c99ec56 (diff)
downloadsrc-45fd5fe9e97396f3dfdf399b8f84301db599b517.tar.gz
src-45fd5fe9e97396f3dfdf399b8f84301db599b517.zip
evdev: Add support for automatic MT protocol type A to type B conversion.
(cherry picked from commit d056693d7bc6c1b5f2c1612e5b34807f173e21c7)
-rw-r--r--sys/dev/evdev/evdev.c5
-rw-r--r--sys/dev/evdev/evdev_mt.c32
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.