Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0-only
2 : /*
3 : * Input Multitouch Library
4 : *
5 : * Copyright (c) 2008-2010 Henrik Rydberg
6 : */
7 :
8 : #include <linux/input/mt.h>
9 : #include <linux/export.h>
10 : #include <linux/slab.h>
11 :
12 : #define TRKID_SGN ((TRKID_MAX + 1) >> 1)
13 :
14 0 : static void copy_abs(struct input_dev *dev, unsigned int dst, unsigned int src)
15 : {
16 0 : if (dev->absinfo && test_bit(src, dev->absbit)) {
17 0 : dev->absinfo[dst] = dev->absinfo[src];
18 0 : dev->absinfo[dst].fuzz = 0;
19 0 : __set_bit(dst, dev->absbit);
20 : }
21 0 : }
22 :
23 : /**
24 : * input_mt_init_slots() - initialize MT input slots
25 : * @dev: input device supporting MT events and finger tracking
26 : * @num_slots: number of slots used by the device
27 : * @flags: mt tasks to handle in core
28 : *
29 : * This function allocates all necessary memory for MT slot handling
30 : * in the input device, prepares the ABS_MT_SLOT and
31 : * ABS_MT_TRACKING_ID events for use and sets up appropriate buffers.
32 : * Depending on the flags set, it also performs pointer emulation and
33 : * frame synchronization.
34 : *
35 : * May be called repeatedly. Returns -EINVAL if attempting to
36 : * reinitialize with a different number of slots.
37 : */
38 0 : int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots,
39 : unsigned int flags)
40 : {
41 0 : struct input_mt *mt = dev->mt;
42 0 : int i;
43 :
44 0 : if (!num_slots)
45 : return 0;
46 0 : if (mt)
47 0 : return mt->num_slots != num_slots ? -EINVAL : 0;
48 :
49 0 : mt = kzalloc(struct_size(mt, slots, num_slots), GFP_KERNEL);
50 0 : if (!mt)
51 0 : goto err_mem;
52 :
53 0 : mt->num_slots = num_slots;
54 0 : mt->flags = flags;
55 0 : input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0);
56 0 : input_set_abs_params(dev, ABS_MT_TRACKING_ID, 0, TRKID_MAX, 0, 0);
57 :
58 0 : if (flags & (INPUT_MT_POINTER | INPUT_MT_DIRECT)) {
59 0 : __set_bit(EV_KEY, dev->evbit);
60 0 : __set_bit(BTN_TOUCH, dev->keybit);
61 :
62 0 : copy_abs(dev, ABS_X, ABS_MT_POSITION_X);
63 0 : copy_abs(dev, ABS_Y, ABS_MT_POSITION_Y);
64 0 : copy_abs(dev, ABS_PRESSURE, ABS_MT_PRESSURE);
65 : }
66 0 : if (flags & INPUT_MT_POINTER) {
67 0 : __set_bit(BTN_TOOL_FINGER, dev->keybit);
68 0 : __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit);
69 0 : if (num_slots >= 3)
70 0 : __set_bit(BTN_TOOL_TRIPLETAP, dev->keybit);
71 0 : if (num_slots >= 4)
72 0 : __set_bit(BTN_TOOL_QUADTAP, dev->keybit);
73 0 : if (num_slots >= 5)
74 0 : __set_bit(BTN_TOOL_QUINTTAP, dev->keybit);
75 0 : __set_bit(INPUT_PROP_POINTER, dev->propbit);
76 : }
77 0 : if (flags & INPUT_MT_DIRECT)
78 0 : __set_bit(INPUT_PROP_DIRECT, dev->propbit);
79 0 : if (flags & INPUT_MT_SEMI_MT)
80 0 : __set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
81 0 : if (flags & INPUT_MT_TRACK) {
82 0 : unsigned int n2 = num_slots * num_slots;
83 0 : mt->red = kcalloc(n2, sizeof(*mt->red), GFP_KERNEL);
84 0 : if (!mt->red)
85 0 : goto err_mem;
86 : }
87 :
88 : /* Mark slots as 'inactive' */
89 0 : for (i = 0; i < num_slots; i++)
90 0 : input_mt_set_value(&mt->slots[i], ABS_MT_TRACKING_ID, -1);
91 :
92 : /* Mark slots as 'unused' */
93 0 : mt->frame = 1;
94 :
95 0 : dev->mt = mt;
96 0 : return 0;
97 0 : err_mem:
98 0 : kfree(mt);
99 0 : return -ENOMEM;
100 : }
101 : EXPORT_SYMBOL(input_mt_init_slots);
102 :
103 : /**
104 : * input_mt_destroy_slots() - frees the MT slots of the input device
105 : * @dev: input device with allocated MT slots
106 : *
107 : * This function is only needed in error path as the input core will
108 : * automatically free the MT slots when the device is destroyed.
109 : */
110 0 : void input_mt_destroy_slots(struct input_dev *dev)
111 : {
112 0 : if (dev->mt) {
113 0 : kfree(dev->mt->red);
114 0 : kfree(dev->mt);
115 : }
116 0 : dev->mt = NULL;
117 0 : }
118 : EXPORT_SYMBOL(input_mt_destroy_slots);
119 :
120 : /**
121 : * input_mt_report_slot_state() - report contact state
122 : * @dev: input device with allocated MT slots
123 : * @tool_type: the tool type to use in this slot
124 : * @active: true if contact is active, false otherwise
125 : *
126 : * Reports a contact via ABS_MT_TRACKING_ID, and optionally
127 : * ABS_MT_TOOL_TYPE. If active is true and the slot is currently
128 : * inactive, or if the tool type is changed, a new tracking id is
129 : * assigned to the slot. The tool type is only reported if the
130 : * corresponding absbit field is set.
131 : *
132 : * Returns true if contact is active.
133 : */
134 0 : bool input_mt_report_slot_state(struct input_dev *dev,
135 : unsigned int tool_type, bool active)
136 : {
137 0 : struct input_mt *mt = dev->mt;
138 0 : struct input_mt_slot *slot;
139 0 : int id;
140 :
141 0 : if (!mt)
142 : return false;
143 :
144 0 : slot = &mt->slots[mt->slot];
145 0 : slot->frame = mt->frame;
146 :
147 0 : if (!active) {
148 0 : input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
149 0 : return false;
150 : }
151 :
152 0 : id = input_mt_get_value(slot, ABS_MT_TRACKING_ID);
153 0 : if (id < 0)
154 0 : id = input_mt_new_trkid(mt);
155 :
156 0 : input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, id);
157 0 : input_event(dev, EV_ABS, ABS_MT_TOOL_TYPE, tool_type);
158 :
159 0 : return true;
160 : }
161 : EXPORT_SYMBOL(input_mt_report_slot_state);
162 :
163 : /**
164 : * input_mt_report_finger_count() - report contact count
165 : * @dev: input device with allocated MT slots
166 : * @count: the number of contacts
167 : *
168 : * Reports the contact count via BTN_TOOL_FINGER, BTN_TOOL_DOUBLETAP,
169 : * BTN_TOOL_TRIPLETAP and BTN_TOOL_QUADTAP.
170 : *
171 : * The input core ensures only the KEY events already setup for
172 : * this device will produce output.
173 : */
174 0 : void input_mt_report_finger_count(struct input_dev *dev, int count)
175 : {
176 0 : input_event(dev, EV_KEY, BTN_TOOL_FINGER, count == 1);
177 0 : input_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, count == 2);
178 0 : input_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, count == 3);
179 0 : input_event(dev, EV_KEY, BTN_TOOL_QUADTAP, count == 4);
180 0 : input_event(dev, EV_KEY, BTN_TOOL_QUINTTAP, count == 5);
181 0 : }
182 : EXPORT_SYMBOL(input_mt_report_finger_count);
183 :
184 : /**
185 : * input_mt_report_pointer_emulation() - common pointer emulation
186 : * @dev: input device with allocated MT slots
187 : * @use_count: report number of active contacts as finger count
188 : *
189 : * Performs legacy pointer emulation via BTN_TOUCH, ABS_X, ABS_Y and
190 : * ABS_PRESSURE. Touchpad finger count is emulated if use_count is true.
191 : *
192 : * The input core ensures only the KEY and ABS axes already setup for
193 : * this device will produce output.
194 : */
195 0 : void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count)
196 : {
197 0 : struct input_mt *mt = dev->mt;
198 0 : struct input_mt_slot *oldest;
199 0 : int oldid, count, i;
200 :
201 0 : if (!mt)
202 : return;
203 :
204 0 : oldest = NULL;
205 0 : oldid = mt->trkid;
206 0 : count = 0;
207 :
208 0 : for (i = 0; i < mt->num_slots; ++i) {
209 0 : struct input_mt_slot *ps = &mt->slots[i];
210 0 : int id = input_mt_get_value(ps, ABS_MT_TRACKING_ID);
211 :
212 0 : if (id < 0)
213 0 : continue;
214 0 : if ((id - oldid) & TRKID_SGN) {
215 0 : oldest = ps;
216 0 : oldid = id;
217 : }
218 0 : count++;
219 : }
220 :
221 0 : input_event(dev, EV_KEY, BTN_TOUCH, count > 0);
222 :
223 0 : if (use_count) {
224 0 : if (count == 0 &&
225 0 : !test_bit(ABS_MT_DISTANCE, dev->absbit) &&
226 0 : test_bit(ABS_DISTANCE, dev->absbit) &&
227 0 : input_abs_get_val(dev, ABS_DISTANCE) != 0) {
228 : /*
229 : * Force reporting BTN_TOOL_FINGER for devices that
230 : * only report general hover (and not per-contact
231 : * distance) when contact is in proximity but not
232 : * on the surface.
233 : */
234 0 : count = 1;
235 : }
236 :
237 0 : input_mt_report_finger_count(dev, count);
238 : }
239 :
240 0 : if (oldest) {
241 0 : int x = input_mt_get_value(oldest, ABS_MT_POSITION_X);
242 0 : int y = input_mt_get_value(oldest, ABS_MT_POSITION_Y);
243 :
244 0 : input_event(dev, EV_ABS, ABS_X, x);
245 0 : input_event(dev, EV_ABS, ABS_Y, y);
246 :
247 0 : if (test_bit(ABS_MT_PRESSURE, dev->absbit)) {
248 0 : int p = input_mt_get_value(oldest, ABS_MT_PRESSURE);
249 0 : input_event(dev, EV_ABS, ABS_PRESSURE, p);
250 : }
251 : } else {
252 0 : if (test_bit(ABS_MT_PRESSURE, dev->absbit))
253 0 : input_event(dev, EV_ABS, ABS_PRESSURE, 0);
254 : }
255 : }
256 : EXPORT_SYMBOL(input_mt_report_pointer_emulation);
257 :
258 0 : static void __input_mt_drop_unused(struct input_dev *dev, struct input_mt *mt)
259 : {
260 0 : int i;
261 :
262 0 : for (i = 0; i < mt->num_slots; i++) {
263 0 : if (!input_mt_is_used(mt, &mt->slots[i])) {
264 0 : input_mt_slot(dev, i);
265 0 : input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
266 : }
267 : }
268 0 : }
269 :
270 : /**
271 : * input_mt_drop_unused() - Inactivate slots not seen in this frame
272 : * @dev: input device with allocated MT slots
273 : *
274 : * Lift all slots not seen since the last call to this function.
275 : */
276 0 : void input_mt_drop_unused(struct input_dev *dev)
277 : {
278 0 : struct input_mt *mt = dev->mt;
279 :
280 0 : if (mt) {
281 0 : __input_mt_drop_unused(dev, mt);
282 0 : mt->frame++;
283 : }
284 0 : }
285 : EXPORT_SYMBOL(input_mt_drop_unused);
286 :
287 : /**
288 : * input_mt_sync_frame() - synchronize mt frame
289 : * @dev: input device with allocated MT slots
290 : *
291 : * Close the frame and prepare the internal state for a new one.
292 : * Depending on the flags, marks unused slots as inactive and performs
293 : * pointer emulation.
294 : */
295 0 : void input_mt_sync_frame(struct input_dev *dev)
296 : {
297 0 : struct input_mt *mt = dev->mt;
298 0 : bool use_count = false;
299 :
300 0 : if (!mt)
301 : return;
302 :
303 0 : if (mt->flags & INPUT_MT_DROP_UNUSED)
304 0 : __input_mt_drop_unused(dev, mt);
305 :
306 0 : if ((mt->flags & INPUT_MT_POINTER) && !(mt->flags & INPUT_MT_SEMI_MT))
307 0 : use_count = true;
308 :
309 0 : input_mt_report_pointer_emulation(dev, use_count);
310 :
311 0 : mt->frame++;
312 : }
313 : EXPORT_SYMBOL(input_mt_sync_frame);
314 :
315 0 : static int adjust_dual(int *begin, int step, int *end, int eq, int mu)
316 : {
317 0 : int f, *p, s, c;
318 :
319 0 : if (begin == end)
320 : return 0;
321 :
322 0 : f = *begin;
323 0 : p = begin + step;
324 0 : s = p == end ? f + 1 : *p;
325 :
326 0 : for (; p != end; p += step) {
327 0 : if (*p < f) {
328 : s = f;
329 : f = *p;
330 0 : } else if (*p < s) {
331 : s = *p;
332 : }
333 : }
334 :
335 0 : c = (f + s + 1) / 2;
336 0 : if (c == 0 || (c > mu && (!eq || mu > 0)))
337 : return 0;
338 : /* Improve convergence for positive matrices by penalizing overcovers */
339 0 : if (s < 0 && mu <= 0)
340 0 : c *= 2;
341 :
342 0 : for (p = begin; p != end; p += step)
343 0 : *p -= c;
344 :
345 0 : return (c < s && s <= 0) || (f >= 0 && f < c);
346 : }
347 :
348 0 : static void find_reduced_matrix(int *w, int nr, int nc, int nrc, int mu)
349 : {
350 0 : int i, k, sum;
351 :
352 0 : for (k = 0; k < nrc; k++) {
353 0 : for (i = 0; i < nr; i++)
354 0 : adjust_dual(w + i, nr, w + i + nrc, nr <= nc, mu);
355 : sum = 0;
356 0 : for (i = 0; i < nrc; i += nr)
357 0 : sum += adjust_dual(w + i, 1, w + i + nr, nc <= nr, mu);
358 0 : if (!sum)
359 : break;
360 : }
361 0 : }
362 :
363 0 : static int input_mt_set_matrix(struct input_mt *mt,
364 : const struct input_mt_pos *pos, int num_pos,
365 : int mu)
366 : {
367 0 : const struct input_mt_pos *p;
368 0 : struct input_mt_slot *s;
369 0 : int *w = mt->red;
370 0 : int x, y;
371 :
372 0 : for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
373 0 : if (!input_mt_is_active(s))
374 0 : continue;
375 0 : x = input_mt_get_value(s, ABS_MT_POSITION_X);
376 0 : y = input_mt_get_value(s, ABS_MT_POSITION_Y);
377 0 : for (p = pos; p != pos + num_pos; p++) {
378 0 : int dx = x - p->x, dy = y - p->y;
379 0 : *w++ = dx * dx + dy * dy - mu;
380 : }
381 : }
382 :
383 0 : return w - mt->red;
384 : }
385 :
386 0 : static void input_mt_set_slots(struct input_mt *mt,
387 : int *slots, int num_pos)
388 : {
389 0 : struct input_mt_slot *s;
390 0 : int *w = mt->red, j;
391 :
392 0 : for (j = 0; j != num_pos; j++)
393 0 : slots[j] = -1;
394 :
395 0 : for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
396 0 : if (!input_mt_is_active(s))
397 0 : continue;
398 :
399 0 : for (j = 0; j != num_pos; j++) {
400 0 : if (w[j] < 0) {
401 0 : slots[j] = s - mt->slots;
402 0 : break;
403 : }
404 : }
405 :
406 0 : w += num_pos;
407 : }
408 :
409 0 : for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
410 0 : if (input_mt_is_active(s))
411 0 : continue;
412 :
413 0 : for (j = 0; j != num_pos; j++) {
414 0 : if (slots[j] < 0) {
415 0 : slots[j] = s - mt->slots;
416 0 : break;
417 : }
418 : }
419 : }
420 0 : }
421 :
422 : /**
423 : * input_mt_assign_slots() - perform a best-match assignment
424 : * @dev: input device with allocated MT slots
425 : * @slots: the slot assignment to be filled
426 : * @pos: the position array to match
427 : * @num_pos: number of positions
428 : * @dmax: maximum ABS_MT_POSITION displacement (zero for infinite)
429 : *
430 : * Performs a best match against the current contacts and returns
431 : * the slot assignment list. New contacts are assigned to unused
432 : * slots.
433 : *
434 : * The assignments are balanced so that all coordinate displacements are
435 : * below the euclidian distance dmax. If no such assignment can be found,
436 : * some contacts are assigned to unused slots.
437 : *
438 : * Returns zero on success, or negative error in case of failure.
439 : */
440 0 : int input_mt_assign_slots(struct input_dev *dev, int *slots,
441 : const struct input_mt_pos *pos, int num_pos,
442 : int dmax)
443 : {
444 0 : struct input_mt *mt = dev->mt;
445 0 : int mu = 2 * dmax * dmax;
446 0 : int nrc;
447 :
448 0 : if (!mt || !mt->red)
449 : return -ENXIO;
450 0 : if (num_pos > mt->num_slots)
451 : return -EINVAL;
452 0 : if (num_pos < 1)
453 : return 0;
454 :
455 0 : nrc = input_mt_set_matrix(mt, pos, num_pos, mu);
456 0 : find_reduced_matrix(mt->red, num_pos, nrc / num_pos, nrc, mu);
457 0 : input_mt_set_slots(mt, slots, num_pos);
458 :
459 0 : return 0;
460 : }
461 : EXPORT_SYMBOL(input_mt_assign_slots);
462 :
463 : /**
464 : * input_mt_get_slot_by_key() - return slot matching key
465 : * @dev: input device with allocated MT slots
466 : * @key: the key of the sought slot
467 : *
468 : * Returns the slot of the given key, if it exists, otherwise
469 : * set the key on the first unused slot and return.
470 : *
471 : * If no available slot can be found, -1 is returned.
472 : * Note that for this function to work properly, input_mt_sync_frame() has
473 : * to be called at each frame.
474 : */
475 0 : int input_mt_get_slot_by_key(struct input_dev *dev, int key)
476 : {
477 0 : struct input_mt *mt = dev->mt;
478 0 : struct input_mt_slot *s;
479 :
480 0 : if (!mt)
481 : return -1;
482 :
483 0 : for (s = mt->slots; s != mt->slots + mt->num_slots; s++)
484 0 : if (input_mt_is_active(s) && s->key == key)
485 0 : return s - mt->slots;
486 :
487 0 : for (s = mt->slots; s != mt->slots + mt->num_slots; s++)
488 0 : if (!input_mt_is_active(s) && !input_mt_is_used(mt, s)) {
489 0 : s->key = key;
490 0 : return s - mt->slots;
491 : }
492 :
493 : return -1;
494 : }
495 : EXPORT_SYMBOL(input_mt_get_slot_by_key);
|