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