1 /*- 2 * Copyright (c) 2016 Vladimir Kondratyev <[email protected]> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 29 #include <sys/param.h> 30 #include <sys/lock.h> 31 #include <sys/malloc.h> 32 #include <sys/mutex.h> 33 #include <sys/systm.h> 34 35 #include <dev/evdev/evdev.h> 36 #include <dev/evdev/evdev_private.h> 37 #include <dev/evdev/input.h> 38 39 #ifdef DEBUG 40 #define debugf(fmt, args...) printf("evdev: " fmt "\n", ##args) 41 #else 42 #define debugf(fmt, args...) 43 #endif 44 45 typedef u_int slotset_t; 46 47 _Static_assert(MAX_MT_SLOTS < sizeof(slotset_t) * 8, "MAX_MT_SLOTS too big"); 48 49 #define FOREACHBIT(v, i) \ 50 for ((i) = ffs(v) - 1; (i) != -1; (i) = ffs((v) & (~1 << (i))) - 1) 51 52 static uint16_t evdev_mtstmap[][2] = { 53 { ABS_MT_POSITION_X, ABS_X }, 54 { ABS_MT_POSITION_Y, ABS_Y }, 55 { ABS_MT_PRESSURE, ABS_PRESSURE }, 56 { ABS_MT_TOUCH_MAJOR, ABS_TOOL_WIDTH }, 57 }; 58 59 struct evdev_mt_slot { 60 int32_t val[MT_CNT]; 61 }; 62 63 struct evdev_mt { 64 int last_reported_slot; 65 /* the set of slots with active touches */ 66 slotset_t touches; 67 /* the set of slots with unsynchronized state */ 68 slotset_t frame; 69 struct evdev_mt_slot slots[]; 70 }; 71 72 static void evdev_mt_send_st_compat(struct evdev_dev *); 73 static void evdev_mt_send_autorel(struct evdev_dev *); 74 75 static inline int 76 ffc_slot(struct evdev_dev *evdev, slotset_t slots) 77 { 78 return (ffs(~slots & (2U << MAXIMAL_MT_SLOT(evdev)) - 1) - 1); 79 } 80 81 void 82 evdev_mt_init(struct evdev_dev *evdev) 83 { 84 int slot, slots; 85 86 slots = MAXIMAL_MT_SLOT(evdev) + 1; 87 88 evdev->ev_mt = malloc(offsetof(struct evdev_mt, slots) + 89 sizeof(struct evdev_mt_slot) * slots, M_EVDEV, M_WAITOK | M_ZERO); 90 91 /* Initialize multitouch protocol type B states */ 92 for (slot = 0; slot < slots; slot++) 93 evdev->ev_mt->slots[slot].val[ABS_MT_INDEX(ABS_MT_TRACKING_ID)] 94 = -1; 95 96 if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_STCOMPAT)) 97 evdev_support_mt_compat(evdev); 98 } 99 100 void 101 evdev_mt_free(struct evdev_dev *evdev) 102 { 103 free(evdev->ev_mt, M_EVDEV); 104 } 105 106 void 107 evdev_mt_sync_frame(struct evdev_dev *evdev) 108 { 109 if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_AUTOREL)) 110 evdev_mt_send_autorel(evdev); 111 if (evdev->ev_report_opened && 112 bit_test(evdev->ev_flags, EVDEV_FLAG_MT_STCOMPAT)) 113 evdev_mt_send_st_compat(evdev); 114 evdev->ev_mt->frame = 0; 115 } 116 117 int 118 evdev_mt_get_last_slot(struct evdev_dev *evdev) 119 { 120 return (evdev->ev_mt->last_reported_slot); 121 } 122 123 void 124 evdev_mt_set_last_slot(struct evdev_dev *evdev, int slot) 125 { 126 struct evdev_mt *mt = evdev->ev_mt; 127 128 MPASS(slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev)); 129 130 mt->frame |= 1U << slot; 131 mt->last_reported_slot = slot; 132 } 133 134 int32_t 135 evdev_mt_get_value(struct evdev_dev *evdev, int slot, int16_t code) 136 { 137 struct evdev_mt *mt = evdev->ev_mt; 138 139 MPASS(slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev)); 140 141 return (mt->slots[slot].val[ABS_MT_INDEX(code)]); 142 } 143 144 void 145 evdev_mt_set_value(struct evdev_dev *evdev, int slot, int16_t code, 146 int32_t value) 147 { 148 struct evdev_mt *mt = evdev->ev_mt; 149 150 MPASS(slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev)); 151 152 if (code == ABS_MT_TRACKING_ID) { 153 if (value != -1) 154 mt->touches |= 1U << slot; 155 else 156 mt->touches &= ~(1U << slot); 157 } 158 mt->slots[slot].val[ABS_MT_INDEX(code)] = value; 159 } 160 161 int 162 evdev_get_mt_slot_by_tracking_id(struct evdev_dev *evdev, int32_t tracking_id) 163 { 164 struct evdev_mt *mt = evdev->ev_mt; 165 int slot; 166 167 FOREACHBIT(mt->touches, slot) 168 if (evdev_mt_get_value(evdev, slot, ABS_MT_TRACKING_ID) == 169 tracking_id) 170 return (slot); 171 /* 172 * Do not allow allocation of new slot in a place of just 173 * released one within the same report. 174 */ 175 return (ffc_slot(evdev, mt->touches | mt->frame)); 176 } 177 178 void 179 evdev_support_mt_compat(struct evdev_dev *evdev) 180 { 181 int i; 182 183 if (evdev->ev_absinfo == NULL) 184 return; 185 186 evdev_support_event(evdev, EV_KEY); 187 evdev_support_key(evdev, BTN_TOUCH); 188 189 /* Touchscreens should not advertise tap tool capabilities */ 190 if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT)) 191 evdev_support_nfingers(evdev, MAXIMAL_MT_SLOT(evdev) + 1); 192 193 /* Echo 0-th MT-slot as ST-slot */ 194 for (i = 0; i < nitems(evdev_mtstmap); i++) 195 if (bit_test(evdev->ev_abs_flags, evdev_mtstmap[i][0])) 196 evdev_support_abs(evdev, evdev_mtstmap[i][1], 197 evdev->ev_absinfo[evdev_mtstmap[i][0]].minimum, 198 evdev->ev_absinfo[evdev_mtstmap[i][0]].maximum, 199 evdev->ev_absinfo[evdev_mtstmap[i][0]].fuzz, 200 evdev->ev_absinfo[evdev_mtstmap[i][0]].flat, 201 evdev->ev_absinfo[evdev_mtstmap[i][0]].resolution); 202 } 203 204 static void 205 evdev_mt_send_st_compat(struct evdev_dev *evdev) 206 { 207 struct evdev_mt *mt = evdev->ev_mt; 208 int nfingers, i, st_slot; 209 210 EVDEV_LOCK_ASSERT(evdev); 211 212 nfingers = bitcount(mt->touches); 213 evdev_send_event(evdev, EV_KEY, BTN_TOUCH, nfingers > 0); 214 215 /* Send first active MT-slot state as single touch report */ 216 st_slot = ffs(mt->touches) - 1; 217 if (st_slot != -1) 218 for (i = 0; i < nitems(evdev_mtstmap); i++) 219 if (bit_test(evdev->ev_abs_flags, evdev_mtstmap[i][1])) 220 evdev_send_event(evdev, EV_ABS, 221 evdev_mtstmap[i][1], 222 evdev_mt_get_value(evdev, st_slot, 223 evdev_mtstmap[i][0])); 224 225 /* Touchscreens should not report tool taps */ 226 if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT)) 227 evdev_send_nfingers(evdev, nfingers); 228 229 if (nfingers == 0) 230 evdev_send_event(evdev, EV_ABS, ABS_PRESSURE, 0); 231 } 232 233 void 234 evdev_push_mt_compat(struct evdev_dev *evdev) 235 { 236 237 EVDEV_ENTER(evdev); 238 evdev_mt_send_st_compat(evdev); 239 EVDEV_EXIT(evdev); 240 } 241 242 static void 243 evdev_mt_send_autorel(struct evdev_dev *evdev) 244 { 245 struct evdev_mt *mt = evdev->ev_mt; 246 int slot; 247 248 EVDEV_LOCK_ASSERT(evdev); 249 250 FOREACHBIT(mt->touches & ~mt->frame, slot) { 251 evdev_send_event(evdev, EV_ABS, ABS_MT_SLOT, slot); 252 evdev_send_event(evdev, EV_ABS, ABS_MT_TRACKING_ID, -1); 253 } 254 } 255 256 void 257 evdev_mt_push_autorel(struct evdev_dev *evdev) 258 { 259 EVDEV_ENTER(evdev); 260 evdev_mt_send_autorel(evdev); 261 EVDEV_EXIT(evdev); 262 } 263