12b3f6d66SOleksandr Tymoshenko /*- 2e6502802SVladimir Kondratyev * Copyright (c) 2016 Vladimir Kondratyev <wulf@FreeBSD.org> 32b3f6d66SOleksandr Tymoshenko * All rights reserved. 42b3f6d66SOleksandr Tymoshenko * 52b3f6d66SOleksandr Tymoshenko * Redistribution and use in source and binary forms, with or without 62b3f6d66SOleksandr Tymoshenko * modification, are permitted provided that the following conditions 72b3f6d66SOleksandr Tymoshenko * are met: 82b3f6d66SOleksandr Tymoshenko * 1. Redistributions of source code must retain the above copyright 92b3f6d66SOleksandr Tymoshenko * notice, this list of conditions and the following disclaimer. 102b3f6d66SOleksandr Tymoshenko * 2. Redistributions in binary form must reproduce the above copyright 112b3f6d66SOleksandr Tymoshenko * notice, this list of conditions and the following disclaimer in the 122b3f6d66SOleksandr Tymoshenko * documentation and/or other materials provided with the distribution. 132b3f6d66SOleksandr Tymoshenko * 142b3f6d66SOleksandr Tymoshenko * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 152b3f6d66SOleksandr Tymoshenko * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 162b3f6d66SOleksandr Tymoshenko * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 172b3f6d66SOleksandr Tymoshenko * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 182b3f6d66SOleksandr Tymoshenko * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 192b3f6d66SOleksandr Tymoshenko * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 202b3f6d66SOleksandr Tymoshenko * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 212b3f6d66SOleksandr Tymoshenko * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 222b3f6d66SOleksandr Tymoshenko * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 232b3f6d66SOleksandr Tymoshenko * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 242b3f6d66SOleksandr Tymoshenko * SUCH DAMAGE. 252b3f6d66SOleksandr Tymoshenko * 262b3f6d66SOleksandr Tymoshenko * $FreeBSD$ 272b3f6d66SOleksandr Tymoshenko */ 282b3f6d66SOleksandr Tymoshenko 292b3f6d66SOleksandr Tymoshenko #include <sys/param.h> 302b3f6d66SOleksandr Tymoshenko #include <sys/lock.h> 31ea2e26b1SVladimir Kondratyev #include <sys/malloc.h> 322b3f6d66SOleksandr Tymoshenko #include <sys/mutex.h> 332b3f6d66SOleksandr Tymoshenko #include <sys/systm.h> 342b3f6d66SOleksandr Tymoshenko 352b3f6d66SOleksandr Tymoshenko #include <dev/evdev/evdev.h> 362b3f6d66SOleksandr Tymoshenko #include <dev/evdev/evdev_private.h> 37ea2e26b1SVladimir Kondratyev #include <dev/evdev/input.h> 382b3f6d66SOleksandr Tymoshenko 392b3f6d66SOleksandr Tymoshenko #ifdef DEBUG 402b3f6d66SOleksandr Tymoshenko #define debugf(fmt, args...) printf("evdev: " fmt "\n", ##args) 412b3f6d66SOleksandr Tymoshenko #else 422b3f6d66SOleksandr Tymoshenko #define debugf(fmt, args...) 432b3f6d66SOleksandr Tymoshenko #endif 442b3f6d66SOleksandr Tymoshenko 452dc7188eSVladimir Kondratyev typedef u_int slotset_t; 462dc7188eSVladimir Kondratyev 472dc7188eSVladimir Kondratyev _Static_assert(MAX_MT_SLOTS < sizeof(slotset_t) * 8, "MAX_MT_SLOTS too big"); 482dc7188eSVladimir Kondratyev 492dc7188eSVladimir Kondratyev #define FOREACHBIT(v, i) \ 502dc7188eSVladimir Kondratyev for ((i) = ffs(v) - 1; (i) != -1; (i) = ffs((v) & (~1 << (i))) - 1) 512dc7188eSVladimir Kondratyev 52127e54deSVladimir Kondratyev struct { 53127e54deSVladimir Kondratyev uint16_t mt; 54127e54deSVladimir Kondratyev uint16_t st; 55127e54deSVladimir Kondratyev int32_t max; 56127e54deSVladimir Kondratyev } static evdev_mtstmap[] = { 57127e54deSVladimir Kondratyev { ABS_MT_POSITION_X, ABS_X, 0 }, 58127e54deSVladimir Kondratyev { ABS_MT_POSITION_Y, ABS_Y, 0 }, 59127e54deSVladimir Kondratyev { ABS_MT_PRESSURE, ABS_PRESSURE, 255 }, 60127e54deSVladimir Kondratyev { ABS_MT_TOUCH_MAJOR, ABS_TOOL_WIDTH, 15 }, 612b3f6d66SOleksandr Tymoshenko }; 622b3f6d66SOleksandr Tymoshenko 632b3f6d66SOleksandr Tymoshenko struct evdev_mt { 6498a7606bSVladimir Kondratyev int last_reported_slot; 65*66bd52f5SVladimir Kondratyev uint16_t tracking_id; 66*66bd52f5SVladimir Kondratyev int32_t tracking_ids[MAX_MT_SLOTS]; 67127e54deSVladimir Kondratyev u_int mtst_events; 682dc7188eSVladimir Kondratyev /* the set of slots with active touches */ 692dc7188eSVladimir Kondratyev slotset_t touches; 702dc7188eSVladimir Kondratyev /* the set of slots with unsynchronized state */ 712dc7188eSVladimir Kondratyev slotset_t frame; 7205936028SVladimir Kondratyev union evdev_mt_slot slots[]; 732b3f6d66SOleksandr Tymoshenko }; 742b3f6d66SOleksandr Tymoshenko 7598a7606bSVladimir Kondratyev static void evdev_mt_send_st_compat(struct evdev_dev *); 7698a7606bSVladimir Kondratyev static void evdev_mt_send_autorel(struct evdev_dev *); 7798a7606bSVladimir Kondratyev 782dc7188eSVladimir Kondratyev static inline int 792dc7188eSVladimir Kondratyev ffc_slot(struct evdev_dev *evdev, slotset_t slots) 802dc7188eSVladimir Kondratyev { 812dc7188eSVladimir Kondratyev return (ffs(~slots & (2U << MAXIMAL_MT_SLOT(evdev)) - 1) - 1); 822dc7188eSVladimir Kondratyev } 832dc7188eSVladimir Kondratyev 842b3f6d66SOleksandr Tymoshenko void 852b3f6d66SOleksandr Tymoshenko evdev_mt_init(struct evdev_dev *evdev) 862b3f6d66SOleksandr Tymoshenko { 8798a7606bSVladimir Kondratyev int slot, slots; 882b3f6d66SOleksandr Tymoshenko 892b3f6d66SOleksandr Tymoshenko slots = MAXIMAL_MT_SLOT(evdev) + 1; 902b3f6d66SOleksandr Tymoshenko 9198a7606bSVladimir Kondratyev evdev->ev_mt = malloc(offsetof(struct evdev_mt, slots) + 9205936028SVladimir Kondratyev sizeof(union evdev_mt_slot) * slots, M_EVDEV, M_WAITOK | M_ZERO); 932b3f6d66SOleksandr Tymoshenko 942b3f6d66SOleksandr Tymoshenko /* Initialize multitouch protocol type B states */ 952dc7188eSVladimir Kondratyev for (slot = 0; slot < slots; slot++) 9605936028SVladimir Kondratyev evdev->ev_mt->slots[slot].id = -1; 972b3f6d66SOleksandr Tymoshenko 98*66bd52f5SVladimir Kondratyev if (!bit_test(evdev->ev_flags, EVDEV_FLAG_MT_KEEPID)) 99*66bd52f5SVladimir Kondratyev evdev_support_abs(evdev, 100*66bd52f5SVladimir Kondratyev ABS_MT_TRACKING_ID, -1, UINT16_MAX, 0, 0, 0); 1012b3f6d66SOleksandr Tymoshenko if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_STCOMPAT)) 1022b3f6d66SOleksandr Tymoshenko evdev_support_mt_compat(evdev); 1032b3f6d66SOleksandr Tymoshenko } 1042b3f6d66SOleksandr Tymoshenko 1052b3f6d66SOleksandr Tymoshenko void 1062b3f6d66SOleksandr Tymoshenko evdev_mt_free(struct evdev_dev *evdev) 1072b3f6d66SOleksandr Tymoshenko { 1082b3f6d66SOleksandr Tymoshenko free(evdev->ev_mt, M_EVDEV); 1092b3f6d66SOleksandr Tymoshenko } 1102b3f6d66SOleksandr Tymoshenko 11198a7606bSVladimir Kondratyev void 11298a7606bSVladimir Kondratyev evdev_mt_sync_frame(struct evdev_dev *evdev) 1132b3f6d66SOleksandr Tymoshenko { 11498a7606bSVladimir Kondratyev if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_AUTOREL)) 11598a7606bSVladimir Kondratyev evdev_mt_send_autorel(evdev); 11698a7606bSVladimir Kondratyev if (evdev->ev_report_opened && 11798a7606bSVladimir Kondratyev bit_test(evdev->ev_flags, EVDEV_FLAG_MT_STCOMPAT)) 11898a7606bSVladimir Kondratyev evdev_mt_send_st_compat(evdev); 1192dc7188eSVladimir Kondratyev evdev->ev_mt->frame = 0; 12098a7606bSVladimir Kondratyev } 1212b3f6d66SOleksandr Tymoshenko 12205936028SVladimir Kondratyev static void 12305936028SVladimir Kondratyev evdev_mt_send_slot(struct evdev_dev *evdev, int slot, 12405936028SVladimir Kondratyev union evdev_mt_slot *state) 12505936028SVladimir Kondratyev { 12605936028SVladimir Kondratyev int i; 12705936028SVladimir Kondratyev bool type_a = !bit_test(evdev->ev_abs_flags, ABS_MT_SLOT); 12805936028SVladimir Kondratyev 12905936028SVladimir Kondratyev EVDEV_LOCK_ASSERT(evdev); 13005936028SVladimir Kondratyev MPASS(type_a || (slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev))); 13105936028SVladimir Kondratyev MPASS(!type_a || state != NULL); 13205936028SVladimir Kondratyev 13305936028SVladimir Kondratyev if (!type_a) { 13405936028SVladimir Kondratyev evdev_send_event(evdev, EV_ABS, ABS_MT_SLOT, slot); 13505936028SVladimir Kondratyev if (state == NULL) { 13605936028SVladimir Kondratyev evdev_send_event(evdev, EV_ABS, ABS_MT_TRACKING_ID, -1); 13705936028SVladimir Kondratyev return; 13805936028SVladimir Kondratyev } 13905936028SVladimir Kondratyev } 14005936028SVladimir Kondratyev bit_foreach_at(evdev->ev_abs_flags, ABS_MT_FIRST, ABS_MT_LAST + 1, i) 14105936028SVladimir Kondratyev evdev_send_event(evdev, EV_ABS, i, 14205936028SVladimir Kondratyev state->val[ABS_MT_INDEX(i)]); 14305936028SVladimir Kondratyev if (type_a) 14405936028SVladimir Kondratyev evdev_send_event(evdev, EV_SYN, SYN_MT_REPORT, 1); 14505936028SVladimir Kondratyev } 14605936028SVladimir Kondratyev 14705936028SVladimir Kondratyev int 14805936028SVladimir Kondratyev evdev_mt_push_slot(struct evdev_dev *evdev, int slot, 14905936028SVladimir Kondratyev union evdev_mt_slot *state) 15005936028SVladimir Kondratyev { 15105936028SVladimir Kondratyev bool type_a = !bit_test(evdev->ev_abs_flags, ABS_MT_SLOT); 15205936028SVladimir Kondratyev 15305936028SVladimir Kondratyev if (type_a && state == NULL) 15405936028SVladimir Kondratyev return (EINVAL); 15505936028SVladimir Kondratyev if (!type_a && (slot < 0 || slot > MAXIMAL_MT_SLOT(evdev))) 15605936028SVladimir Kondratyev return (EINVAL); 15705936028SVladimir Kondratyev 15805936028SVladimir Kondratyev EVDEV_ENTER(evdev); 15905936028SVladimir Kondratyev evdev_mt_send_slot(evdev, slot, state); 16005936028SVladimir Kondratyev EVDEV_EXIT(evdev); 16105936028SVladimir Kondratyev 16205936028SVladimir Kondratyev return (0); 16305936028SVladimir Kondratyev } 16405936028SVladimir Kondratyev 16598a7606bSVladimir Kondratyev int 16698a7606bSVladimir Kondratyev evdev_mt_get_last_slot(struct evdev_dev *evdev) 16798a7606bSVladimir Kondratyev { 16898a7606bSVladimir Kondratyev return (evdev->ev_mt->last_reported_slot); 1692b3f6d66SOleksandr Tymoshenko } 1702b3f6d66SOleksandr Tymoshenko 1712b3f6d66SOleksandr Tymoshenko void 17298a7606bSVladimir Kondratyev evdev_mt_set_last_slot(struct evdev_dev *evdev, int slot) 1732b3f6d66SOleksandr Tymoshenko { 17498a7606bSVladimir Kondratyev struct evdev_mt *mt = evdev->ev_mt; 1752b3f6d66SOleksandr Tymoshenko 17698a7606bSVladimir Kondratyev MPASS(slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev)); 1772b3f6d66SOleksandr Tymoshenko 1782dc7188eSVladimir Kondratyev mt->frame |= 1U << slot; 17998a7606bSVladimir Kondratyev mt->last_reported_slot = slot; 1802b3f6d66SOleksandr Tymoshenko } 1812b3f6d66SOleksandr Tymoshenko 1822b3f6d66SOleksandr Tymoshenko int32_t 18398a7606bSVladimir Kondratyev evdev_mt_get_value(struct evdev_dev *evdev, int slot, int16_t code) 18498a7606bSVladimir Kondratyev { 18598a7606bSVladimir Kondratyev struct evdev_mt *mt = evdev->ev_mt; 18698a7606bSVladimir Kondratyev 18798a7606bSVladimir Kondratyev MPASS(slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev)); 18898a7606bSVladimir Kondratyev 18998a7606bSVladimir Kondratyev return (mt->slots[slot].val[ABS_MT_INDEX(code)]); 19098a7606bSVladimir Kondratyev } 19198a7606bSVladimir Kondratyev 19298a7606bSVladimir Kondratyev void 19398a7606bSVladimir Kondratyev evdev_mt_set_value(struct evdev_dev *evdev, int slot, int16_t code, 19498a7606bSVladimir Kondratyev int32_t value) 19598a7606bSVladimir Kondratyev { 19698a7606bSVladimir Kondratyev struct evdev_mt *mt = evdev->ev_mt; 19798a7606bSVladimir Kondratyev 19898a7606bSVladimir Kondratyev MPASS(slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev)); 19998a7606bSVladimir Kondratyev 2002dc7188eSVladimir Kondratyev if (code == ABS_MT_TRACKING_ID) { 2012dc7188eSVladimir Kondratyev if (value != -1) 2022dc7188eSVladimir Kondratyev mt->touches |= 1U << slot; 2032dc7188eSVladimir Kondratyev else 2042dc7188eSVladimir Kondratyev mt->touches &= ~(1U << slot); 2052dc7188eSVladimir Kondratyev } 20698a7606bSVladimir Kondratyev mt->slots[slot].val[ABS_MT_INDEX(code)] = value; 20798a7606bSVladimir Kondratyev } 20898a7606bSVladimir Kondratyev 20998a7606bSVladimir Kondratyev int 2102b3f6d66SOleksandr Tymoshenko evdev_get_mt_slot_by_tracking_id(struct evdev_dev *evdev, int32_t tracking_id) 2112b3f6d66SOleksandr Tymoshenko { 21298a7606bSVladimir Kondratyev struct evdev_mt *mt = evdev->ev_mt; 2132dc7188eSVladimir Kondratyev int slot; 2142b3f6d66SOleksandr Tymoshenko 2152dc7188eSVladimir Kondratyev FOREACHBIT(mt->touches, slot) 216*66bd52f5SVladimir Kondratyev if (mt->tracking_ids[slot] == tracking_id) 2172b3f6d66SOleksandr Tymoshenko return (slot); 2182b3f6d66SOleksandr Tymoshenko /* 2192dc7188eSVladimir Kondratyev * Do not allow allocation of new slot in a place of just 2202dc7188eSVladimir Kondratyev * released one within the same report. 2212b3f6d66SOleksandr Tymoshenko */ 2222dc7188eSVladimir Kondratyev return (ffc_slot(evdev, mt->touches | mt->frame)); 2232b3f6d66SOleksandr Tymoshenko } 2242b3f6d66SOleksandr Tymoshenko 225*66bd52f5SVladimir Kondratyev int32_t 226*66bd52f5SVladimir Kondratyev evdev_mt_reassign_id(struct evdev_dev *evdev, int slot, int32_t id) 227*66bd52f5SVladimir Kondratyev { 228*66bd52f5SVladimir Kondratyev struct evdev_mt *mt = evdev->ev_mt; 229*66bd52f5SVladimir Kondratyev int32_t nid; 230*66bd52f5SVladimir Kondratyev 231*66bd52f5SVladimir Kondratyev if (id == -1 || bit_test(evdev->ev_flags, EVDEV_FLAG_MT_KEEPID)) { 232*66bd52f5SVladimir Kondratyev mt->tracking_ids[slot] = id; 233*66bd52f5SVladimir Kondratyev return (id); 234*66bd52f5SVladimir Kondratyev } 235*66bd52f5SVladimir Kondratyev 236*66bd52f5SVladimir Kondratyev nid = evdev_mt_get_value(evdev, slot, ABS_MT_TRACKING_ID); 237*66bd52f5SVladimir Kondratyev if (nid != -1) { 238*66bd52f5SVladimir Kondratyev KASSERT(id == mt->tracking_ids[slot], 239*66bd52f5SVladimir Kondratyev ("MT-slot tracking id has changed")); 240*66bd52f5SVladimir Kondratyev return (nid); 241*66bd52f5SVladimir Kondratyev } 242*66bd52f5SVladimir Kondratyev 243*66bd52f5SVladimir Kondratyev mt->tracking_ids[slot] = id; 244*66bd52f5SVladimir Kondratyev again: 245*66bd52f5SVladimir Kondratyev nid = mt->tracking_id++; 246*66bd52f5SVladimir Kondratyev FOREACHBIT(mt->touches, slot) 247*66bd52f5SVladimir Kondratyev if (evdev_mt_get_value(evdev, slot, ABS_MT_TRACKING_ID) == nid) 248*66bd52f5SVladimir Kondratyev goto again; 249*66bd52f5SVladimir Kondratyev 250*66bd52f5SVladimir Kondratyev return (nid); 251*66bd52f5SVladimir Kondratyev } 252*66bd52f5SVladimir Kondratyev 253127e54deSVladimir Kondratyev static inline int32_t 254127e54deSVladimir Kondratyev evdev_mt_normalize(int32_t value, int32_t mtmin, int32_t mtmax, int32_t stmax) 255127e54deSVladimir Kondratyev { 256127e54deSVladimir Kondratyev if (stmax != 0 && mtmax != mtmin) { 257127e54deSVladimir Kondratyev value = (value - mtmin) * stmax / (mtmax - mtmin); 258127e54deSVladimir Kondratyev value = MAX(MIN(value, stmax), 0); 259127e54deSVladimir Kondratyev } 260127e54deSVladimir Kondratyev return (value); 261127e54deSVladimir Kondratyev } 262127e54deSVladimir Kondratyev 2632b3f6d66SOleksandr Tymoshenko void 2642b3f6d66SOleksandr Tymoshenko evdev_support_mt_compat(struct evdev_dev *evdev) 2652b3f6d66SOleksandr Tymoshenko { 266127e54deSVladimir Kondratyev struct input_absinfo *ai; 26798a7606bSVladimir Kondratyev int i; 2682b3f6d66SOleksandr Tymoshenko 2692b3f6d66SOleksandr Tymoshenko if (evdev->ev_absinfo == NULL) 2702b3f6d66SOleksandr Tymoshenko return; 2712b3f6d66SOleksandr Tymoshenko 2722b3f6d66SOleksandr Tymoshenko evdev_support_event(evdev, EV_KEY); 2732b3f6d66SOleksandr Tymoshenko evdev_support_key(evdev, BTN_TOUCH); 2742b3f6d66SOleksandr Tymoshenko 2752b3f6d66SOleksandr Tymoshenko /* Touchscreens should not advertise tap tool capabilities */ 2762b3f6d66SOleksandr Tymoshenko if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT)) 2772b3f6d66SOleksandr Tymoshenko evdev_support_nfingers(evdev, MAXIMAL_MT_SLOT(evdev) + 1); 2782b3f6d66SOleksandr Tymoshenko 2792b3f6d66SOleksandr Tymoshenko /* Echo 0-th MT-slot as ST-slot */ 280127e54deSVladimir Kondratyev for (i = 0; i < nitems(evdev_mtstmap); i++) { 281127e54deSVladimir Kondratyev if (!bit_test(evdev->ev_abs_flags, evdev_mtstmap[i].mt) || 282127e54deSVladimir Kondratyev bit_test(evdev->ev_abs_flags, evdev_mtstmap[i].st)) 283127e54deSVladimir Kondratyev continue; 284127e54deSVladimir Kondratyev ai = evdev->ev_absinfo + evdev_mtstmap[i].mt; 285127e54deSVladimir Kondratyev evdev->ev_mt->mtst_events |= 1U << i; 286127e54deSVladimir Kondratyev if (evdev_mtstmap[i].max != 0) 287127e54deSVladimir Kondratyev evdev_support_abs(evdev, evdev_mtstmap[i].st, 288314913edSVladimir Kondratyev 0, 289127e54deSVladimir Kondratyev evdev_mtstmap[i].max, 290127e54deSVladimir Kondratyev 0, 291127e54deSVladimir Kondratyev evdev_mt_normalize( 292127e54deSVladimir Kondratyev ai->flat, 0, ai->maximum, evdev_mtstmap[i].max), 293127e54deSVladimir Kondratyev 0); 294127e54deSVladimir Kondratyev else 295127e54deSVladimir Kondratyev evdev_support_abs(evdev, evdev_mtstmap[i].st, 296127e54deSVladimir Kondratyev ai->minimum, 297127e54deSVladimir Kondratyev ai->maximum, 298127e54deSVladimir Kondratyev 0, 299127e54deSVladimir Kondratyev ai->flat, 300127e54deSVladimir Kondratyev ai->resolution); 301127e54deSVladimir Kondratyev } 3022b3f6d66SOleksandr Tymoshenko } 3032b3f6d66SOleksandr Tymoshenko 3042b3f6d66SOleksandr Tymoshenko static void 30598a7606bSVladimir Kondratyev evdev_mt_send_st_compat(struct evdev_dev *evdev) 3062b3f6d66SOleksandr Tymoshenko { 3072dc7188eSVladimir Kondratyev struct evdev_mt *mt = evdev->ev_mt; 308fbe17f90SVladimir Kondratyev int nfingers, i, st_slot; 3092b3f6d66SOleksandr Tymoshenko 3102b3f6d66SOleksandr Tymoshenko EVDEV_LOCK_ASSERT(evdev); 3112b3f6d66SOleksandr Tymoshenko 3122dc7188eSVladimir Kondratyev nfingers = bitcount(mt->touches); 3132b3f6d66SOleksandr Tymoshenko evdev_send_event(evdev, EV_KEY, BTN_TOUCH, nfingers > 0); 3142b3f6d66SOleksandr Tymoshenko 315fbe17f90SVladimir Kondratyev /* Send first active MT-slot state as single touch report */ 316fbe17f90SVladimir Kondratyev st_slot = ffs(mt->touches) - 1; 317fbe17f90SVladimir Kondratyev if (st_slot != -1) 318127e54deSVladimir Kondratyev FOREACHBIT(mt->mtst_events, i) 319127e54deSVladimir Kondratyev evdev_send_event(evdev, EV_ABS, evdev_mtstmap[i].st, 320127e54deSVladimir Kondratyev evdev_mt_normalize(evdev_mt_get_value(evdev, 321127e54deSVladimir Kondratyev st_slot, evdev_mtstmap[i].mt), 322127e54deSVladimir Kondratyev evdev->ev_absinfo[evdev_mtstmap[i].mt].minimum, 323127e54deSVladimir Kondratyev evdev->ev_absinfo[evdev_mtstmap[i].mt].maximum, 324127e54deSVladimir Kondratyev evdev_mtstmap[i].max)); 3252b3f6d66SOleksandr Tymoshenko 3262b3f6d66SOleksandr Tymoshenko /* Touchscreens should not report tool taps */ 3272b3f6d66SOleksandr Tymoshenko if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT)) 3282b3f6d66SOleksandr Tymoshenko evdev_send_nfingers(evdev, nfingers); 3292b3f6d66SOleksandr Tymoshenko 3302b3f6d66SOleksandr Tymoshenko if (nfingers == 0) 3312b3f6d66SOleksandr Tymoshenko evdev_send_event(evdev, EV_ABS, ABS_PRESSURE, 0); 3322b3f6d66SOleksandr Tymoshenko } 3332b3f6d66SOleksandr Tymoshenko 3342b3f6d66SOleksandr Tymoshenko void 3352b3f6d66SOleksandr Tymoshenko evdev_push_mt_compat(struct evdev_dev *evdev) 3362b3f6d66SOleksandr Tymoshenko { 3372b3f6d66SOleksandr Tymoshenko 3384c0a4665SVladimir Kondratyev EVDEV_ENTER(evdev); 33998a7606bSVladimir Kondratyev evdev_mt_send_st_compat(evdev); 3404c0a4665SVladimir Kondratyev EVDEV_EXIT(evdev); 3412b3f6d66SOleksandr Tymoshenko } 342c736a757SOleksandr Tymoshenko 34398a7606bSVladimir Kondratyev static void 34498a7606bSVladimir Kondratyev evdev_mt_send_autorel(struct evdev_dev *evdev) 345c736a757SOleksandr Tymoshenko { 34698a7606bSVladimir Kondratyev struct evdev_mt *mt = evdev->ev_mt; 34798a7606bSVladimir Kondratyev int slot; 348c736a757SOleksandr Tymoshenko 349c736a757SOleksandr Tymoshenko EVDEV_LOCK_ASSERT(evdev); 350c736a757SOleksandr Tymoshenko 35105936028SVladimir Kondratyev FOREACHBIT(mt->touches & ~mt->frame, slot) 35205936028SVladimir Kondratyev evdev_mt_send_slot(evdev, slot, NULL); 353c736a757SOleksandr Tymoshenko } 35498a7606bSVladimir Kondratyev 35598a7606bSVladimir Kondratyev void 35698a7606bSVladimir Kondratyev evdev_mt_push_autorel(struct evdev_dev *evdev) 35798a7606bSVladimir Kondratyev { 35898a7606bSVladimir Kondratyev EVDEV_ENTER(evdev); 35998a7606bSVladimir Kondratyev evdev_mt_send_autorel(evdev); 36098a7606bSVladimir Kondratyev EVDEV_EXIT(evdev); 36198a7606bSVladimir Kondratyev } 362