xref: /freebsd-14.2/sys/dev/evdev/evdev_mt.c (revision 4c0a134e)
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