From c736a757129a1a2c1e8e11d18daa9742f7ec0d35 Mon Sep 17 00:00:00 2001 From: Oleksandr Tymoshenko Date: Sat, 8 Oct 2016 17:59:53 +0000 Subject: [PATCH] Implement EVDEV_FLAG_MT_AUTOREL flag (autorelease touchpoints) Automaticaly release (send ABS_MT_TRACKING_ID = -1) MT-slots that has not been listed in current MT protocol type B report. Slot is counted as listed if corresponding ABS_MT_SLOT event has been sent regardless of other MT events. Events are sent on SYN_REPORT event. Submitted by: Vladimir Kondratiev --- sys/dev/evdev/evdev.c | 8 +++++--- sys/dev/evdev/evdev.h | 2 ++ sys/dev/evdev/evdev_mt.c | 23 +++++++++++++++++++---- sys/dev/evdev/evdev_private.h | 1 + 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/sys/dev/evdev/evdev.c b/sys/dev/evdev/evdev.c index 7da8eb14182c..63e04966fec9 100644 --- a/sys/dev/evdev/evdev.c +++ b/sys/dev/evdev/evdev.c @@ -686,6 +686,8 @@ evdev_sparse_event(struct evdev_dev *evdev, uint16_t type, uint16_t code, case EV_SYN: if (code == SYN_REPORT) { + /* Count empty reports as well as non empty */ + evdev->ev_report_count++; /* Skip empty reports */ if (!evdev->ev_report_opened) return (EV_SKIP_EVENT); @@ -722,10 +724,7 @@ evdev_propagate_event(struct evdev_dev *evdev, uint16_t type, uint16_t code, EVDEV_CLIENT_UNLOCKQ(client); } - /* Update counters */ evdev->ev_event_count++; - if (type == EV_SYN && code == SYN_REPORT) - evdev->ev_report_count++; } void @@ -765,6 +764,9 @@ evdev_push_event(struct evdev_dev *evdev, uint16_t type, uint16_t code, if (evdev->ev_lock_type == EV_LOCK_INTERNAL) EVDEV_LOCK(evdev); evdev_modify_event(evdev, type, code, &value); + if (type == EV_SYN && code == SYN_REPORT && + bit_test(evdev->ev_flags, EVDEV_FLAG_MT_AUTOREL)) + evdev_send_mt_autorel(evdev); if (type == EV_SYN && code == SYN_REPORT && evdev->ev_report_opened && bit_test(evdev->ev_flags, EVDEV_FLAG_MT_STCOMPAT)) evdev_send_mt_compat(evdev); diff --git a/sys/dev/evdev/evdev.h b/sys/dev/evdev/evdev.h index 2c4aeee1abcf..7287e739e832 100644 --- a/sys/dev/evdev/evdev.h +++ b/sys/dev/evdev/evdev.h @@ -70,6 +70,8 @@ extern int evdev_rcpt_mask; #define EVDEV_FLAG_SOFTREPEAT 0x00 /* use evdev to repeat keys */ #define EVDEV_FLAG_MT_STCOMPAT 0x01 /* autogenerate ST-compatible events * for MT protocol type B reports */ +#define EVDEV_FLAG_MT_AUTOREL 0x02 /* Autorelease MT-slots not listed in + * current MT protocol type B report */ #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 ef36006ddaf6..82f36d8478e2 100644 --- a/sys/dev/evdev/evdev_mt.c +++ b/sys/dev/evdev/evdev_mt.c @@ -112,6 +112,7 @@ void evdev_set_last_mt_slot(struct evdev_dev *evdev, int32_t slot) { + evdev->ev_mt->ev_mt_slots[slot].ev_report = evdev->ev_report_count; evdev->ev_mt->ev_mt_last_reported_slot = slot; } @@ -128,10 +129,6 @@ evdev_set_mt_value(struct evdev_dev *evdev, int32_t slot, int16_t code, int32_t value) { - if (code == ABS_MT_TRACKING_ID && value == -1) - evdev->ev_mt->ev_mt_slots[slot].ev_report = - evdev->ev_report_count; - evdev->ev_mt->ev_mt_slots[slot].ev_mt_states[ABS_MT_INDEX(code)] = value; } @@ -275,3 +272,21 @@ evdev_push_mt_compat(struct evdev_dev *evdev) if (evdev->ev_lock_type == EV_LOCK_INTERNAL) EVDEV_UNLOCK(evdev); } + +void +evdev_send_mt_autorel(struct evdev_dev *evdev) +{ + int32_t slot; + + EVDEV_LOCK_ASSERT(evdev); + + for (slot = 0; slot <= MAXIMAL_MT_SLOT(evdev); slot++) { + if (evdev->ev_mt->ev_mt_slots[slot].ev_report != + evdev->ev_report_count && + evdev_get_mt_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); + } + } +} diff --git a/sys/dev/evdev/evdev_private.h b/sys/dev/evdev/evdev_private.h index 4305c5959587..b3de1bf0fa40 100644 --- a/sys/dev/evdev/evdev_private.h +++ b/sys/dev/evdev/evdev_private.h @@ -192,6 +192,7 @@ void evdev_set_last_mt_slot(struct evdev_dev *, int32_t); int32_t evdev_get_mt_value(struct evdev_dev *, int32_t, int16_t); void evdev_set_mt_value(struct evdev_dev *, int32_t, int16_t, int32_t); void evdev_send_mt_compat(struct evdev_dev *); +void evdev_send_mt_autorel(struct evdev_dev *); /* Utility functions: */ void evdev_client_dumpqueue(struct evdev_client *);