1 /*-
2 * Copyright (c) 2016, 2020 Vladimir Kondratyev <wulf@FreeBSD.org>
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 bool type_a;
83 u_int mtst_events;
84 /* the set of slots with active touches */
85 slotset_t touches;
86 /* the set of slots with unsynchronized state */
87 slotset_t frame;
88 /* the set of slots to match with active touches */
89 slotset_t match_frame;
90 int match_slot;
91 union evdev_mt_slot *match_slots;
92 int *matrix;
93 union evdev_mt_slot slots[];
94 };
95
96 static void evdev_mt_send_st_compat(struct evdev_dev *);
97 static void evdev_mt_send_autorel(struct evdev_dev *);
98 static void evdev_mt_replay_events(struct evdev_dev *);
99
100 static inline int
101 ffc_slot(struct evdev_dev *evdev, slotset_t slots)
102 {
103 return (ffs(~slots & ((2U << MAXIMAL_MT_SLOT(evdev)) - 1)) - 1);
104 }
105
106 void
107 evdev_mt_init(struct evdev_dev *evdev)
108 {
109 struct evdev_mt *mt;
110 size_t size = offsetof(struct evdev_mt, slots);
111 int slot, slots;
112 bool type_a;
113
114 type_a = !bit_test(evdev->ev_abs_flags, ABS_MT_SLOT);
115 if (type_a) {
116 /* Add events produced by MT type A to type B converter */
117 evdev_support_abs(evdev,
118 ABS_MT_SLOT, 0, MAX_MT_SLOTS - 1, 0, 0, 0);
119 evdev_support_abs(evdev,
120 ABS_MT_TRACKING_ID, -1, MAX_MT_SLOTS - 1, 0, 0, 0);
121 }
122
123 slots = MAXIMAL_MT_SLOT(evdev) + 1;
124 size += sizeof(mt->slots[0]) * slots;
125 if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK)) {
126 size += sizeof(mt->match_slots[0]) * slots;
127 size += sizeof(mt->matrix[0]) * (slots + 6) * slots;
128 }
129
130 mt = malloc(size, M_EVDEV, M_WAITOK | M_ZERO);
131 evdev->ev_mt = mt;
132 mt->type_a = type_a;
133
134 if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK)) {
135 mt->match_slots = mt->slots + slots;
136 mt->matrix = (int *)(mt->match_slots + slots);
137 }
138
139 /* Initialize multitouch protocol type B states */
140 for (slot = 0; slot < slots; slot++)
141 mt->slots[slot].id = -1;
142
143 if (!bit_test(evdev->ev_flags, EVDEV_FLAG_MT_KEEPID))
144 evdev_support_abs(evdev,
145 ABS_MT_TRACKING_ID, -1, UINT16_MAX, 0, 0, 0);
146 if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_STCOMPAT))
147 evdev_support_mt_compat(evdev);
148 }
149
150 void
151 evdev_mt_free(struct evdev_dev *evdev)
152 {
153 free(evdev->ev_mt, M_EVDEV);
154 }
155
156 void
157 evdev_mt_sync_frame(struct evdev_dev *evdev)
158 {
159 if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK))
160 evdev_mt_replay_events(evdev);
161 if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_AUTOREL))
162 evdev_mt_send_autorel(evdev);
163 if (evdev->ev_report_opened &&
164 bit_test(evdev->ev_flags, EVDEV_FLAG_MT_STCOMPAT))
165 evdev_mt_send_st_compat(evdev);
166 evdev->ev_mt->frame = 0;
167 }
168
169 static void
170 evdev_mt_send_slot(struct evdev_dev *evdev, int slot,
171 union evdev_mt_slot *state)
172 {
173 int i;
174 bool type_a = !bit_test(evdev->ev_abs_flags, ABS_MT_SLOT);
175
176 EVDEV_LOCK_ASSERT(evdev);
177 MPASS(type_a || (slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev)));
178 MPASS(!type_a || state != NULL);
179
180 if (!type_a) {
181 evdev_send_event(evdev, EV_ABS, ABS_MT_SLOT, slot);
182 if (state == NULL) {
183 evdev_send_event(evdev, EV_ABS, ABS_MT_TRACKING_ID, -1);
184 return;
185 }
186 }
187 bit_foreach_at(evdev->ev_abs_flags, ABS_MT_FIRST, ABS_MT_LAST + 1, i)
188 evdev_send_event(evdev, EV_ABS, i,
189 state->val[ABS_MT_INDEX(i)]);
190 if (type_a)
191 evdev_send_event(evdev, EV_SYN, SYN_MT_REPORT, 1);
192 }
193
194 int
195 evdev_mt_push_slot(struct evdev_dev *evdev, int slot,
196 union evdev_mt_slot *state)
197 {
198 struct evdev_mt *mt = evdev->ev_mt;
199 bool type_a = !bit_test(evdev->ev_abs_flags, ABS_MT_SLOT);
200
201 if ((type_a || (mt != NULL && mt->type_a)) && state == NULL)
202 return (EINVAL);
203 if (!type_a && (slot < 0 || slot > MAXIMAL_MT_SLOT(evdev)))
204 return (EINVAL);
205
206 EVDEV_ENTER(evdev);
207 if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK) && mt->type_a) {
208 mt->match_slots[mt->match_slot] = *state;
209 evdev_mt_record_event(evdev, EV_SYN, SYN_MT_REPORT, 1);
210 } else if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK)) {
211 evdev_mt_record_event(evdev, EV_ABS, ABS_MT_SLOT, slot);
212 if (state != NULL)
213 mt->match_slots[mt->match_slot] = *state;
214 else
215 evdev_mt_record_event(evdev, EV_ABS,
216 ABS_MT_TRACKING_ID, -1);
217 } else
218 evdev_mt_send_slot(evdev, slot, state);
219 EVDEV_EXIT(evdev);
220
221 return (0);
222 }
223
224 /*
225 * Find a minimum-weight matching for an m-by-n matrix.
226 *
227 * m must be greater than or equal to n. The size of the buffer must be
228 * at least 3m + 3n.
229 *
230 * On return, the first m elements of the buffer contain the row-to-
231 * column mappings, i.e., buffer[i] is the column index for row i, or -1
232 * if there is no assignment for that row (which may happen if n < m).
233 *
234 * Wrong results because of overflows will not occur with input values
235 * in the range of 0 to INT_MAX / 2 inclusive.
236 *
237 * The function applies the Dinic-Kronrod algorithm. It is not modern or
238 * popular, but it seems to be a good choice for small matrices at least.
239 * The original form of the algorithm is modified as follows: There is no
240 * initial search for row minima, the initial assignments are in a
241 * "virtual" column with the index -1 and zero values. This permits inputs
242 * with n < m, and it simplifies the reassignments.
243 */
244 static void
245 evdev_mt_matching(int *matrix, int m, int n, int *buffer)
246 {
247 int i, j, k, d, e, row, col, delta;
248 int *p;
249 int *r2c = buffer; /* row-to-column assignments */
250 int *red = r2c + m; /* reduced values of the assignments */
251 int *mc = red + m; /* row-wise minimal elements of cs */
252 int *cs = mc + m; /* the column set */
253 int *c2r = cs + n; /* column-to-row assignments in cs */
254 int *cd = c2r + n; /* column deltas (reduction) */
255
256 for (p = r2c; p < red; *p++ = -1) {}
257 for (; p < mc; *p++ = 0) {}
258 for (col = 0; col < n; col++) {
259 delta = INT_MAX;
260 for (i = 0, p = matrix + col; i < m; i++, p += n) {
261 d = *p - red[i];
262 if (d < delta || (d == delta && r2c[i] < 0)) {
263 delta = d;
264 row = i;
265 }
266 }
267 cd[col] = delta;
268 if (r2c[row] < 0) {
269 r2c[row] = col;
270 continue;
271 }
272 for (p = mc; p < cs; *p++ = col) {}
273 for (k = 0; (j = r2c[row]) >= 0;) {
274 cs[k++] = j;
275 c2r[j] = row;
276 mc[row] -= n;
277 delta = INT_MAX;
278 for (i = 0, p = matrix; i < m; i++, p += n)
279 if (mc[i] >= 0) {
280 d = p[mc[i]] - cd[mc[i]];
281 e = p[j] - cd[j];
282 if (e < d) {
283 d = e;
284 mc[i] = j;
285 }
286 d -= red[i];
287 if (d < delta || (d == delta
288 && r2c[i] < 0)) {
289 delta = d;
290 row = i;
291 }
292 }
293 cd[col] += delta;
294 for (i = 0; i < k; i++) {
295 cd[cs[i]] += delta;
296 red[c2r[cs[i]]] -= delta;
297 }
298 }
299 for (j = mc[row]; (r2c[row] = j) != col;) {
300 row = c2r[j];
301 j = mc[row] + n;
302 }
303 }
304 }
305
306 /*
307 * Assign tracking IDs to the points in the pt array. The tracking ID
308 * assignment pairs the points with points of the previous frame in
309 * such a way that the sum of the squared distances is minimal. Using
310 * squares instead of simple distances favours assignments with more uniform
311 * distances, and it is faster.
312 * Set tracking id to -1 for unassigned (new) points.
313 */
314 void
315 evdev_mt_match_frame(struct evdev_dev *evdev, union evdev_mt_slot *pt,
316 int size)
317 {
318 struct evdev_mt *mt = evdev->ev_mt;
319 int i, j, m, n, dx, dy, slot, num_touches;
320 int *p, *r2c, *c2r;
321
322 EVDEV_LOCK_ASSERT(evdev);
323 MPASS(mt->matrix != NULL);
324 MPASS(size >= 0 && size <= MAXIMAL_MT_SLOT(evdev) + 1);
325
326 if (size == 0)
327 return;
328
329 p = mt->matrix;
330 num_touches = bitcount(mt->touches);
331 if (num_touches >= size) {
332 FOREACHBIT(mt->touches, slot)
333 for (i = 0; i < size; i++) {
334 dx = pt[i].x - mt->slots[slot].x;
335 dy = pt[i].y - mt->slots[slot].y;
336 *p++ = dx * dx + dy * dy;
337 }
338 m = num_touches;
339 n = size;
340 } else {
341 for (i = 0; i < size; i++)
342 FOREACHBIT(mt->touches, slot) {
343 dx = pt[i].x - mt->slots[slot].x;
344 dy = pt[i].y - mt->slots[slot].y;
345 *p++ = dx * dx + dy * dy;
346 }
347 m = size;
348 n = num_touches;
349 }
350 evdev_mt_matching(mt->matrix, m, n, p);
351
352 r2c = p;
353 c2r = p + m;
354 for (i = 0; i < m; i++)
355 if ((j = r2c[i]) >= 0)
356 c2r[j] = i;
357
358 p = (n == size ? c2r : r2c);
359 for (i = 0; i < size; i++)
360 if (*p++ < 0)
361 pt[i].id = -1;
362
363 p = (n == size ? r2c : c2r);
364 FOREACHBIT(mt->touches, slot)
365 if ((i = *p++) >= 0)
366 pt[i].id = mt->tracking_ids[slot];
367 }
368
369 static void
370 evdev_mt_send_frame(struct evdev_dev *evdev, union evdev_mt_slot *pt, int size)
371 {
372 struct evdev_mt *mt = evdev->ev_mt;
373 union evdev_mt_slot *slot;
374
375 EVDEV_LOCK_ASSERT(evdev);
376 MPASS(size >= 0 && size <= MAXIMAL_MT_SLOT(evdev) + 1);
377
378 /*
379 * While MT-matching assign tracking IDs of new contacts to be equal
380 * to a slot number to make things simpler.
381 */
382 for (slot = pt; slot < pt + size; slot++) {
383 if (slot->id < 0)
384 slot->id = ffc_slot(evdev, mt->touches | mt->frame);
385 if (slot->id >= 0)
386 evdev_mt_send_slot(evdev, slot->id, slot);
387 }
388 }
389
390 int
391 evdev_mt_push_frame(struct evdev_dev *evdev, union evdev_mt_slot *pt, int size)
392 {
393 if (size < 0 || size > MAXIMAL_MT_SLOT(evdev) + 1)
394 return (EINVAL);
395
396 EVDEV_ENTER(evdev);
397 evdev_mt_send_frame(evdev, pt, size);
398 EVDEV_EXIT(evdev);
399
400 return (0);
401 }
402
403 bool
404 evdev_mt_record_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
405 int32_t value)
406 {
407 struct evdev_mt *mt = evdev->ev_mt;
408
409 EVDEV_LOCK_ASSERT(evdev);
410
411 switch (type) {
412 case EV_SYN:
413 if (code == SYN_MT_REPORT) {
414 /* MT protocol type A support */
415 KASSERT(mt->type_a, ("Not a MT type A protocol"));
416 mt->match_frame |= 1U << mt->match_slot;
417 mt->match_slot++;
418 return (true);
419 }
420 break;
421 case EV_ABS:
422 if (code == ABS_MT_SLOT) {
423 /* MT protocol type B support */
424 KASSERT(!mt->type_a, ("Not a MT type B protocol"));
425 KASSERT(value >= 0, ("Negative slot number"));
426 mt->match_slot = value;
427 mt->match_frame |= 1U << mt->match_slot;
428 return (true);
429 } else if (code == ABS_MT_TRACKING_ID) {
430 KASSERT(!mt->type_a, ("Not a MT type B protocol"));
431 if (value == -1)
432 mt->match_frame &= ~(1U << mt->match_slot);
433 return (true);
434 } else if (ABS_IS_MT(code)) {
435 KASSERT(mt->match_slot >= 0, ("Negative slot"));
436 KASSERT(mt->match_slot <= MAXIMAL_MT_SLOT(evdev),
437 ("Slot number too big"));
438 mt->match_slots[mt->match_slot].
439 val[ABS_MT_INDEX(code)] = value;
440 return (true);
441 }
442 break;
443 default:
444 break;
445 }
446
447 return (false);
448 }
449
450 static void
451 evdev_mt_replay_events(struct evdev_dev *evdev)
452 {
453 struct evdev_mt *mt = evdev->ev_mt;
454 int slot, size = 0;
455
456 EVDEV_LOCK_ASSERT(evdev);
457
458 FOREACHBIT(mt->match_frame, slot) {
459 if (slot != size)
460 mt->match_slots[size] = mt->match_slots[slot];
461 size++;
462 }
463 evdev_mt_match_frame(evdev, mt->match_slots, size);
464 evdev_mt_send_frame(evdev, mt->match_slots, size);
465 mt->match_slot = 0;
466 mt->match_frame = 0;
467 }
468
469 union evdev_mt_slot *
470 evdev_mt_get_match_slots(struct evdev_dev *evdev)
471 {
472 return (evdev->ev_mt->match_slots);
473 }
474
475 int
476 evdev_mt_get_last_slot(struct evdev_dev *evdev)
477 {
478 return (evdev->ev_mt->last_reported_slot);
479 }
480
481 void
482 evdev_mt_set_last_slot(struct evdev_dev *evdev, int slot)
483 {
484 struct evdev_mt *mt = evdev->ev_mt;
485
486 MPASS(slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev));
487
488 mt->frame |= 1U << slot;
489 mt->last_reported_slot = slot;
490 }
491
492 int32_t
493 evdev_mt_get_value(struct evdev_dev *evdev, int slot, int16_t code)
494 {
495 struct evdev_mt *mt = evdev->ev_mt;
496
497 MPASS(slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev));
498
499 return (mt->slots[slot].val[ABS_MT_INDEX(code)]);
500 }
501
502 void
503 evdev_mt_set_value(struct evdev_dev *evdev, int slot, int16_t code,
504 int32_t value)
505 {
506 struct evdev_mt *mt = evdev->ev_mt;
507
508 MPASS(slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev));
509
510 if (code == ABS_MT_TRACKING_ID) {
511 if (value != -1)
512 mt->touches |= 1U << slot;
513 else
514 mt->touches &= ~(1U << slot);
515 }
516 mt->slots[slot].val[ABS_MT_INDEX(code)] = value;
517 }
518
519 int
520 evdev_get_mt_slot_by_tracking_id(struct evdev_dev *evdev, int32_t tracking_id)
521 {
522 struct evdev_mt *mt = evdev->ev_mt;
523 int slot;
524
525 KASSERT(!mt->type_a, ("Not a MT type B protocol"));
526
527 /*
528 * Ignore tracking_id if slot assignment is performed by evdev.
529 * Events are written sequentially to temporary matching buffer.
530 */
531 if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK))
532 return (ffc_slot(evdev, mt->match_frame));
533
534 FOREACHBIT(mt->touches, slot)
535 if (mt->tracking_ids[slot] == tracking_id)
536 return (slot);
537 /*
538 * Do not allow allocation of new slot in a place of just
539 * released one within the same report.
540 */
541 return (ffc_slot(evdev, mt->touches | mt->frame));
542 }
543
544 int32_t
545 evdev_mt_reassign_id(struct evdev_dev *evdev, int slot, int32_t id)
546 {
547 struct evdev_mt *mt = evdev->ev_mt;
548 int32_t nid;
549
550 if (id == -1 || bit_test(evdev->ev_flags, EVDEV_FLAG_MT_KEEPID)) {
551 mt->tracking_ids[slot] = id;
552 return (id);
553 }
554
555 nid = evdev_mt_get_value(evdev, slot, ABS_MT_TRACKING_ID);
556 if (nid != -1) {
557 KASSERT(id == mt->tracking_ids[slot],
558 ("MT-slot tracking id has changed"));
559 return (nid);
560 }
561
562 mt->tracking_ids[slot] = id;
563 again:
564 nid = mt->tracking_id++;
565 FOREACHBIT(mt->touches, slot)
566 if (evdev_mt_get_value(evdev, slot, ABS_MT_TRACKING_ID) == nid)
567 goto again;
568
569 return (nid);
570 }
571
572 static inline int32_t
573 evdev_mt_normalize(int32_t value, int32_t mtmin, int32_t mtmax, int32_t stmax)
574 {
575 if (stmax != 0 && mtmax != mtmin) {
576 value = (value - mtmin) * stmax / (mtmax - mtmin);
577 value = MAX(MIN(value, stmax), 0);
578 }
579 return (value);
580 }
581
582 void
583 evdev_support_mt_compat(struct evdev_dev *evdev)
584 {
585 struct input_absinfo *ai;
586 int i;
587
588 if (evdev->ev_absinfo == NULL)
589 return;
590
591 evdev_support_event(evdev, EV_KEY);
592 evdev_support_key(evdev, BTN_TOUCH);
593
594 /* Touchscreens should not advertise tap tool capabilities */
595 if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT))
596 evdev_support_nfingers(evdev, MAXIMAL_MT_SLOT(evdev) + 1);
597
598 /* Echo 0-th MT-slot as ST-slot */
599 for (i = 0; i < nitems(evdev_mtstmap); i++) {
600 if (!bit_test(evdev->ev_abs_flags, evdev_mtstmap[i].mt) ||
601 bit_test(evdev->ev_abs_flags, evdev_mtstmap[i].st))
602 continue;
603 ai = evdev->ev_absinfo + evdev_mtstmap[i].mt;
604 evdev->ev_mt->mtst_events |= 1U << i;
605 if (evdev_mtstmap[i].max != 0)
606 evdev_support_abs(evdev, evdev_mtstmap[i].st,
607 0,
608 evdev_mtstmap[i].max,
609 0,
610 evdev_mt_normalize(
611 ai->flat, 0, ai->maximum, evdev_mtstmap[i].max),
612 0);
613 else
614 evdev_support_abs(evdev, evdev_mtstmap[i].st,
615 ai->minimum,
616 ai->maximum,
617 0,
618 ai->flat,
619 ai->resolution);
620 }
621 }
622
623 static void
624 evdev_mt_send_st_compat(struct evdev_dev *evdev)
625 {
626 struct evdev_mt *mt = evdev->ev_mt;
627 int nfingers, i, st_slot;
628
629 EVDEV_LOCK_ASSERT(evdev);
630
631 nfingers = bitcount(mt->touches);
632 evdev_send_event(evdev, EV_KEY, BTN_TOUCH, nfingers > 0);
633
634 /* Send first active MT-slot state as single touch report */
635 st_slot = ffs(mt->touches) - 1;
636 if (st_slot != -1)
637 FOREACHBIT(mt->mtst_events, i)
638 evdev_send_event(evdev, EV_ABS, evdev_mtstmap[i].st,
639 evdev_mt_normalize(evdev_mt_get_value(evdev,
640 st_slot, evdev_mtstmap[i].mt),
641 evdev->ev_absinfo[evdev_mtstmap[i].mt].minimum,
642 evdev->ev_absinfo[evdev_mtstmap[i].mt].maximum,
643 evdev_mtstmap[i].max));
644
645 /* Touchscreens should not report tool taps */
646 if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT))
647 evdev_send_nfingers(evdev, nfingers);
648
649 if (nfingers == 0)
650 evdev_send_event(evdev, EV_ABS, ABS_PRESSURE, 0);
651 }
652
653 void
654 evdev_push_mt_compat(struct evdev_dev *evdev)
655 {
656
657 EVDEV_ENTER(evdev);
658 evdev_mt_send_st_compat(evdev);
659 EVDEV_EXIT(evdev);
660 }
661
662 static void
663 evdev_mt_send_autorel(struct evdev_dev *evdev)
664 {
665 struct evdev_mt *mt = evdev->ev_mt;
666 int slot;
667
668 EVDEV_LOCK_ASSERT(evdev);
669 KASSERT(mt->match_frame == 0, ("Unmatched events exist"));
670
671 FOREACHBIT(mt->touches & ~mt->frame, slot)
672 evdev_mt_send_slot(evdev, slot, NULL);
673 }
674
675 void
676 evdev_mt_push_autorel(struct evdev_dev *evdev)
677 {
678 EVDEV_ENTER(evdev);
679 evdev_mt_send_autorel(evdev);
680 EVDEV_EXIT(evdev);
681 }
Cache object: d71c2f47831e04a31c0ce0d83c3bb793
|