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 * Copyright (c) 2015, 2016 Ulf Brosziewski 30 * 31 * Permission to use, copy, modify, and distribute this software for any 32 * purpose with or without fee is hereby granted, provided that the above 33 * copyright notice and this permission notice appear in all copies. 34 * 35 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 36 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 37 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 38 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 39 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 40 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 41 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 42 */ 43 44 #include <sys/param.h> 45 #include <sys/lock.h> 46 #include <sys/malloc.h> 47 #include <sys/mutex.h> 48 #include <sys/systm.h> 49 50 #include <dev/evdev/evdev.h> 51 #include <dev/evdev/evdev_private.h> 52 #include <dev/evdev/input.h> 53 54 #ifdef DEBUG 55 #define debugf(fmt, args...) printf("evdev: " fmt "\n", ##args) 56 #else 57 #define debugf(fmt, args...) 58 #endif 59 60 typedef u_int slotset_t; 61 62 _Static_assert(MAX_MT_SLOTS < sizeof(slotset_t) * 8, "MAX_MT_SLOTS too big"); 63 64 #define FOREACHBIT(v, i) \ 65 for ((i) = ffs(v) - 1; (i) != -1; (i) = ffs((v) & (~1 << (i))) - 1) 66 67 struct { 68 uint16_t mt; 69 uint16_t st; 70 int32_t max; 71 } static evdev_mtstmap[] = { 72 { ABS_MT_POSITION_X, ABS_X, 0 }, 73 { ABS_MT_POSITION_Y, ABS_Y, 0 }, 74 { ABS_MT_PRESSURE, ABS_PRESSURE, 255 }, 75 { ABS_MT_TOUCH_MAJOR, ABS_TOOL_WIDTH, 15 }, 76 }; 77 78 struct evdev_mt { 79 int last_reported_slot; 80 uint16_t tracking_id; 81 int32_t tracking_ids[MAX_MT_SLOTS]; 82 u_int mtst_events; 83 /* the set of slots with active touches */ 84 slotset_t touches; 85 /* the set of slots with unsynchronized state */ 86 slotset_t frame; 87 int *matrix; 88 union evdev_mt_slot slots[]; 89 }; 90 91 static void evdev_mt_send_st_compat(struct evdev_dev *); 92 static void evdev_mt_send_autorel(struct evdev_dev *); 93 94 static inline int 95 ffc_slot(struct evdev_dev *evdev, slotset_t slots) 96 { 97 return (ffs(~slots & (2U << MAXIMAL_MT_SLOT(evdev)) - 1) - 1); 98 } 99 100 void 101 evdev_mt_init(struct evdev_dev *evdev) 102 { 103 struct evdev_mt *mt; 104 size_t size = offsetof(struct evdev_mt, slots); 105 int slot, slots; 106 107 slots = MAXIMAL_MT_SLOT(evdev) + 1; 108 size += sizeof(mt->slots[0]) * slots; 109 if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK)) { 110 size += sizeof(mt->matrix[0]) * (slots + 6) * slots; 111 } 112 113 mt = malloc(size, M_EVDEV, M_WAITOK | M_ZERO); 114 evdev->ev_mt = mt; 115 116 if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK)) { 117 evdev_support_abs(evdev, 118 ABS_MT_TRACKING_ID, -1, slots - 1, 0, 0, 0); 119 mt->matrix = (int *)(mt->slots + slots); 120 } 121 122 /* Initialize multitouch protocol type B states */ 123 for (slot = 0; slot < slots; slot++) 124 evdev->ev_mt->slots[slot].id = -1; 125 126 if (!bit_test(evdev->ev_flags, EVDEV_FLAG_MT_KEEPID)) 127 evdev_support_abs(evdev, 128 ABS_MT_TRACKING_ID, -1, UINT16_MAX, 0, 0, 0); 129 if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_STCOMPAT)) 130 evdev_support_mt_compat(evdev); 131 } 132 133 void 134 evdev_mt_free(struct evdev_dev *evdev) 135 { 136 free(evdev->ev_mt, M_EVDEV); 137 } 138 139 void 140 evdev_mt_sync_frame(struct evdev_dev *evdev) 141 { 142 if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_AUTOREL)) 143 evdev_mt_send_autorel(evdev); 144 if (evdev->ev_report_opened && 145 bit_test(evdev->ev_flags, EVDEV_FLAG_MT_STCOMPAT)) 146 evdev_mt_send_st_compat(evdev); 147 evdev->ev_mt->frame = 0; 148 } 149 150 static void 151 evdev_mt_send_slot(struct evdev_dev *evdev, int slot, 152 union evdev_mt_slot *state) 153 { 154 int i; 155 bool type_a = !bit_test(evdev->ev_abs_flags, ABS_MT_SLOT); 156 157 EVDEV_LOCK_ASSERT(evdev); 158 MPASS(type_a || (slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev))); 159 MPASS(!type_a || state != NULL); 160 161 if (!type_a) { 162 evdev_send_event(evdev, EV_ABS, ABS_MT_SLOT, slot); 163 if (state == NULL) { 164 evdev_send_event(evdev, EV_ABS, ABS_MT_TRACKING_ID, -1); 165 return; 166 } 167 } 168 bit_foreach_at(evdev->ev_abs_flags, ABS_MT_FIRST, ABS_MT_LAST + 1, i) 169 evdev_send_event(evdev, EV_ABS, i, 170 state->val[ABS_MT_INDEX(i)]); 171 if (type_a) 172 evdev_send_event(evdev, EV_SYN, SYN_MT_REPORT, 1); 173 } 174 175 int 176 evdev_mt_push_slot(struct evdev_dev *evdev, int slot, 177 union evdev_mt_slot *state) 178 { 179 bool type_a = !bit_test(evdev->ev_abs_flags, ABS_MT_SLOT); 180 181 if (type_a && state == NULL) 182 return (EINVAL); 183 if (!type_a && (slot < 0 || slot > MAXIMAL_MT_SLOT(evdev))) 184 return (EINVAL); 185 186 EVDEV_ENTER(evdev); 187 evdev_mt_send_slot(evdev, slot, state); 188 EVDEV_EXIT(evdev); 189 190 return (0); 191 } 192 193 /* 194 * Find a minimum-weight matching for an m-by-n matrix. 195 * 196 * m must be greater than or equal to n. The size of the buffer must be 197 * at least 3m + 3n. 198 * 199 * On return, the first m elements of the buffer contain the row-to- 200 * column mappings, i.e., buffer[i] is the column index for row i, or -1 201 * if there is no assignment for that row (which may happen if n < m). 202 * 203 * Wrong results because of overflows will not occur with input values 204 * in the range of 0 to INT_MAX / 2 inclusive. 205 * 206 * The function applies the Dinic-Kronrod algorithm. It is not modern or 207 * popular, but it seems to be a good choice for small matrices at least. 208 * The original form of the algorithm is modified as follows: There is no 209 * initial search for row minima, the initial assignments are in a 210 * "virtual" column with the index -1 and zero values. This permits inputs 211 * with n < m, and it simplifies the reassignments. 212 */ 213 static void 214 evdev_mt_matching(int *matrix, int m, int n, int *buffer) 215 { 216 int i, j, k, d, e, row, col, delta; 217 int *p; 218 int *r2c = buffer; /* row-to-column assignments */ 219 int *red = r2c + m; /* reduced values of the assignments */ 220 int *mc = red + m; /* row-wise minimal elements of cs */ 221 int *cs = mc + m; /* the column set */ 222 int *c2r = cs + n; /* column-to-row assignments in cs */ 223 int *cd = c2r + n; /* column deltas (reduction) */ 224 225 for (p = r2c; p < red; *p++ = -1) {} 226 for (; p < mc; *p++ = 0) {} 227 for (col = 0; col < n; col++) { 228 delta = INT_MAX; 229 for (i = 0, p = matrix + col; i < m; i++, p += n) { 230 d = *p - red[i]; 231 if (d < delta || (d == delta && r2c[i] < 0)) { 232 delta = d; 233 row = i; 234 } 235 } 236 cd[col] = delta; 237 if (r2c[row] < 0) { 238 r2c[row] = col; 239 continue; 240 } 241 for (p = mc; p < cs; *p++ = col) {} 242 for (k = 0; (j = r2c[row]) >= 0;) { 243 cs[k++] = j; 244 c2r[j] = row; 245 mc[row] -= n; 246 delta = INT_MAX; 247 for (i = 0, p = matrix; i < m; i++, p += n) 248 if (mc[i] >= 0) { 249 d = p[mc[i]] - cd[mc[i]]; 250 e = p[j] - cd[j]; 251 if (e < d) { 252 d = e; 253 mc[i] = j; 254 } 255 d -= red[i]; 256 if (d < delta || (d == delta 257 && r2c[i] < 0)) { 258 delta = d; 259 row = i; 260 } 261 } 262 cd[col] += delta; 263 for (i = 0; i < k; i++) { 264 cd[cs[i]] += delta; 265 red[c2r[cs[i]]] -= delta; 266 } 267 } 268 for (j = mc[row]; (r2c[row] = j) != col;) { 269 row = c2r[j]; 270 j = mc[row] + n; 271 } 272 } 273 } 274 275 /* 276 * Assign tracking IDs to the points in the pt array. The tracking ID 277 * assignment pairs the points with points of the previous frame in 278 * such a way that the sum of the squared distances is minimal. Using 279 * squares instead of simple distances favours assignments with more uniform 280 * distances, and it is faster. 281 * Set tracking id to -1 for unassigned (new) points. 282 */ 283 void 284 evdev_mt_match_frame(struct evdev_dev *evdev, union evdev_mt_slot *pt, 285 int size) 286 { 287 struct evdev_mt *mt = evdev->ev_mt; 288 int i, j, m, n, dx, dy, slot, num_touches; 289 int *p, *r2c, *c2r; 290 291 EVDEV_LOCK_ASSERT(evdev); 292 MPASS(mt->matrix != NULL); 293 MPASS(size >= 0 && size <= MAXIMAL_MT_SLOT(evdev) + 1); 294 295 if (size == 0) 296 return; 297 298 p = mt->matrix; 299 num_touches = bitcount(mt->touches); 300 if (num_touches >= size) { 301 FOREACHBIT(mt->touches, slot) 302 for (i = 0; i < size; i++) { 303 dx = pt[i].x - mt->slots[slot].x; 304 dy = pt[i].y - mt->slots[slot].y; 305 *p++ = dx * dx + dy * dy; 306 } 307 m = num_touches; 308 n = size; 309 } else { 310 for (i = 0; i < size; i++) 311 FOREACHBIT(mt->touches, slot) { 312 dx = pt[i].x - mt->slots[slot].x; 313 dy = pt[i].y - mt->slots[slot].y; 314 *p++ = dx * dx + dy * dy; 315 } 316 m = size; 317 n = num_touches; 318 } 319 evdev_mt_matching(mt->matrix, m, n, p); 320 321 r2c = p; 322 c2r = p + m; 323 for (i = 0; i < m; i++) 324 if ((j = r2c[i]) >= 0) 325 c2r[j] = i; 326 327 p = (n == size ? c2r : r2c); 328 for (i = 0; i < size; i++) 329 if (*p++ < 0) 330 pt[i].id = -1; 331 332 p = (n == size ? r2c : c2r); 333 FOREACHBIT(mt->touches, slot) 334 if ((i = *p++) >= 0) 335 pt[i].id = mt->tracking_ids[slot]; 336 } 337 338 static void 339 evdev_mt_send_frame(struct evdev_dev *evdev, union evdev_mt_slot *pt, int size) 340 { 341 struct evdev_mt *mt = evdev->ev_mt; 342 union evdev_mt_slot *slot; 343 344 EVDEV_LOCK_ASSERT(evdev); 345 MPASS(size >= 0 && size <= MAXIMAL_MT_SLOT(evdev) + 1); 346 347 /* 348 * While MT-matching assign tracking IDs of new contacts to be equal 349 * to a slot number to make things simpler. 350 */ 351 for (slot = pt; slot < pt + size; slot++) { 352 if (slot->id < 0) 353 slot->id = ffc_slot(evdev, mt->touches | mt->frame); 354 if (slot->id >= 0) 355 evdev_mt_send_slot(evdev, slot->id, slot); 356 } 357 } 358 359 int 360 evdev_mt_push_frame(struct evdev_dev *evdev, union evdev_mt_slot *pt, int size) 361 { 362 if (size < 0 || size > MAXIMAL_MT_SLOT(evdev) + 1) 363 return (EINVAL); 364 365 EVDEV_ENTER(evdev); 366 evdev_mt_send_frame(evdev, pt, size); 367 EVDEV_EXIT(evdev); 368 369 return (0); 370 } 371 372 int 373 evdev_mt_get_last_slot(struct evdev_dev *evdev) 374 { 375 return (evdev->ev_mt->last_reported_slot); 376 } 377 378 void 379 evdev_mt_set_last_slot(struct evdev_dev *evdev, int slot) 380 { 381 struct evdev_mt *mt = evdev->ev_mt; 382 383 MPASS(slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev)); 384 385 mt->frame |= 1U << slot; 386 mt->last_reported_slot = slot; 387 } 388 389 int32_t 390 evdev_mt_get_value(struct evdev_dev *evdev, int slot, int16_t code) 391 { 392 struct evdev_mt *mt = evdev->ev_mt; 393 394 MPASS(slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev)); 395 396 return (mt->slots[slot].val[ABS_MT_INDEX(code)]); 397 } 398 399 void 400 evdev_mt_set_value(struct evdev_dev *evdev, int slot, int16_t code, 401 int32_t value) 402 { 403 struct evdev_mt *mt = evdev->ev_mt; 404 405 MPASS(slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev)); 406 407 if (code == ABS_MT_TRACKING_ID) { 408 if (value != -1) 409 mt->touches |= 1U << slot; 410 else 411 mt->touches &= ~(1U << slot); 412 } 413 mt->slots[slot].val[ABS_MT_INDEX(code)] = value; 414 } 415 416 int 417 evdev_get_mt_slot_by_tracking_id(struct evdev_dev *evdev, int32_t tracking_id) 418 { 419 struct evdev_mt *mt = evdev->ev_mt; 420 int slot; 421 422 FOREACHBIT(mt->touches, slot) 423 if (mt->tracking_ids[slot] == tracking_id) 424 return (slot); 425 /* 426 * Do not allow allocation of new slot in a place of just 427 * released one within the same report. 428 */ 429 return (ffc_slot(evdev, mt->touches | mt->frame)); 430 } 431 432 int32_t 433 evdev_mt_reassign_id(struct evdev_dev *evdev, int slot, int32_t id) 434 { 435 struct evdev_mt *mt = evdev->ev_mt; 436 int32_t nid; 437 438 if (id == -1 || bit_test(evdev->ev_flags, EVDEV_FLAG_MT_KEEPID)) { 439 mt->tracking_ids[slot] = id; 440 return (id); 441 } 442 443 nid = evdev_mt_get_value(evdev, slot, ABS_MT_TRACKING_ID); 444 if (nid != -1) { 445 KASSERT(id == mt->tracking_ids[slot], 446 ("MT-slot tracking id has changed")); 447 return (nid); 448 } 449 450 mt->tracking_ids[slot] = id; 451 again: 452 nid = mt->tracking_id++; 453 FOREACHBIT(mt->touches, slot) 454 if (evdev_mt_get_value(evdev, slot, ABS_MT_TRACKING_ID) == nid) 455 goto again; 456 457 return (nid); 458 } 459 460 static inline int32_t 461 evdev_mt_normalize(int32_t value, int32_t mtmin, int32_t mtmax, int32_t stmax) 462 { 463 if (stmax != 0 && mtmax != mtmin) { 464 value = (value - mtmin) * stmax / (mtmax - mtmin); 465 value = MAX(MIN(value, stmax), 0); 466 } 467 return (value); 468 } 469 470 void 471 evdev_support_mt_compat(struct evdev_dev *evdev) 472 { 473 struct input_absinfo *ai; 474 int i; 475 476 if (evdev->ev_absinfo == NULL) 477 return; 478 479 evdev_support_event(evdev, EV_KEY); 480 evdev_support_key(evdev, BTN_TOUCH); 481 482 /* Touchscreens should not advertise tap tool capabilities */ 483 if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT)) 484 evdev_support_nfingers(evdev, MAXIMAL_MT_SLOT(evdev) + 1); 485 486 /* Echo 0-th MT-slot as ST-slot */ 487 for (i = 0; i < nitems(evdev_mtstmap); i++) { 488 if (!bit_test(evdev->ev_abs_flags, evdev_mtstmap[i].mt) || 489 bit_test(evdev->ev_abs_flags, evdev_mtstmap[i].st)) 490 continue; 491 ai = evdev->ev_absinfo + evdev_mtstmap[i].mt; 492 evdev->ev_mt->mtst_events |= 1U << i; 493 if (evdev_mtstmap[i].max != 0) 494 evdev_support_abs(evdev, evdev_mtstmap[i].st, 495 0, 496 evdev_mtstmap[i].max, 497 0, 498 evdev_mt_normalize( 499 ai->flat, 0, ai->maximum, evdev_mtstmap[i].max), 500 0); 501 else 502 evdev_support_abs(evdev, evdev_mtstmap[i].st, 503 ai->minimum, 504 ai->maximum, 505 0, 506 ai->flat, 507 ai->resolution); 508 } 509 } 510 511 static void 512 evdev_mt_send_st_compat(struct evdev_dev *evdev) 513 { 514 struct evdev_mt *mt = evdev->ev_mt; 515 int nfingers, i, st_slot; 516 517 EVDEV_LOCK_ASSERT(evdev); 518 519 nfingers = bitcount(mt->touches); 520 evdev_send_event(evdev, EV_KEY, BTN_TOUCH, nfingers > 0); 521 522 /* Send first active MT-slot state as single touch report */ 523 st_slot = ffs(mt->touches) - 1; 524 if (st_slot != -1) 525 FOREACHBIT(mt->mtst_events, i) 526 evdev_send_event(evdev, EV_ABS, evdev_mtstmap[i].st, 527 evdev_mt_normalize(evdev_mt_get_value(evdev, 528 st_slot, evdev_mtstmap[i].mt), 529 evdev->ev_absinfo[evdev_mtstmap[i].mt].minimum, 530 evdev->ev_absinfo[evdev_mtstmap[i].mt].maximum, 531 evdev_mtstmap[i].max)); 532 533 /* Touchscreens should not report tool taps */ 534 if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT)) 535 evdev_send_nfingers(evdev, nfingers); 536 537 if (nfingers == 0) 538 evdev_send_event(evdev, EV_ABS, ABS_PRESSURE, 0); 539 } 540 541 void 542 evdev_push_mt_compat(struct evdev_dev *evdev) 543 { 544 545 EVDEV_ENTER(evdev); 546 evdev_mt_send_st_compat(evdev); 547 EVDEV_EXIT(evdev); 548 } 549 550 static void 551 evdev_mt_send_autorel(struct evdev_dev *evdev) 552 { 553 struct evdev_mt *mt = evdev->ev_mt; 554 int slot; 555 556 EVDEV_LOCK_ASSERT(evdev); 557 558 FOREACHBIT(mt->touches & ~mt->frame, slot) 559 evdev_mt_send_slot(evdev, slot, NULL); 560 } 561 562 void 563 evdev_mt_push_autorel(struct evdev_dev *evdev) 564 { 565 EVDEV_ENTER(evdev); 566 evdev_mt_send_autorel(evdev); 567 EVDEV_EXIT(evdev); 568 } 569