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