The branch stable/13 has been updated by wulf:

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

commit f160aa0d3de33df408a70a33d2af00b5d3545dce
Author:     Vladimir Kondratyev <[email protected]>
AuthorDate: 2021-08-24 22:48:33 +0000
Commit:     Vladimir Kondratyev <[email protected]>
CommitDate: 2021-09-07 23:58:47 +0000

    evdev: Make MT tracking IDs monotonically increasing sequence.
    
    (cherry picked from commit 66bd52f5e241bd2548015f847f12cdff69176c40)
---
 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;
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to