Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Input Multitouch Library
0004  *
0005  * Copyright (c) 2008-2010 Henrik Rydberg
0006  */
0007 
0008 #include <linux/input/mt.h>
0009 #include <linux/export.h>
0010 #include <linux/slab.h>
0011 #include "input-core-private.h"
0012 
0013 #define TRKID_SGN   ((TRKID_MAX + 1) >> 1)
0014 
0015 static void copy_abs(struct input_dev *dev, unsigned int dst, unsigned int src)
0016 {
0017     if (dev->absinfo && test_bit(src, dev->absbit)) {
0018         dev->absinfo[dst] = dev->absinfo[src];
0019         dev->absinfo[dst].fuzz = 0;
0020         __set_bit(dst, dev->absbit);
0021     }
0022 }
0023 
0024 /**
0025  * input_mt_init_slots() - initialize MT input slots
0026  * @dev: input device supporting MT events and finger tracking
0027  * @num_slots: number of slots used by the device
0028  * @flags: mt tasks to handle in core
0029  *
0030  * This function allocates all necessary memory for MT slot handling
0031  * in the input device, prepares the ABS_MT_SLOT and
0032  * ABS_MT_TRACKING_ID events for use and sets up appropriate buffers.
0033  * Depending on the flags set, it also performs pointer emulation and
0034  * frame synchronization.
0035  *
0036  * May be called repeatedly. Returns -EINVAL if attempting to
0037  * reinitialize with a different number of slots.
0038  */
0039 int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots,
0040             unsigned int flags)
0041 {
0042     struct input_mt *mt = dev->mt;
0043     int i;
0044 
0045     if (!num_slots)
0046         return 0;
0047     if (mt)
0048         return mt->num_slots != num_slots ? -EINVAL : 0;
0049 
0050     mt = kzalloc(struct_size(mt, slots, num_slots), GFP_KERNEL);
0051     if (!mt)
0052         goto err_mem;
0053 
0054     mt->num_slots = num_slots;
0055     mt->flags = flags;
0056     input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0);
0057     input_set_abs_params(dev, ABS_MT_TRACKING_ID, 0, TRKID_MAX, 0, 0);
0058 
0059     if (flags & (INPUT_MT_POINTER | INPUT_MT_DIRECT)) {
0060         __set_bit(EV_KEY, dev->evbit);
0061         __set_bit(BTN_TOUCH, dev->keybit);
0062 
0063         copy_abs(dev, ABS_X, ABS_MT_POSITION_X);
0064         copy_abs(dev, ABS_Y, ABS_MT_POSITION_Y);
0065         copy_abs(dev, ABS_PRESSURE, ABS_MT_PRESSURE);
0066     }
0067     if (flags & INPUT_MT_POINTER) {
0068         __set_bit(BTN_TOOL_FINGER, dev->keybit);
0069         __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit);
0070         if (num_slots >= 3)
0071             __set_bit(BTN_TOOL_TRIPLETAP, dev->keybit);
0072         if (num_slots >= 4)
0073             __set_bit(BTN_TOOL_QUADTAP, dev->keybit);
0074         if (num_slots >= 5)
0075             __set_bit(BTN_TOOL_QUINTTAP, dev->keybit);
0076         __set_bit(INPUT_PROP_POINTER, dev->propbit);
0077     }
0078     if (flags & INPUT_MT_DIRECT)
0079         __set_bit(INPUT_PROP_DIRECT, dev->propbit);
0080     if (flags & INPUT_MT_SEMI_MT)
0081         __set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
0082     if (flags & INPUT_MT_TRACK) {
0083         unsigned int n2 = num_slots * num_slots;
0084         mt->red = kcalloc(n2, sizeof(*mt->red), GFP_KERNEL);
0085         if (!mt->red)
0086             goto err_mem;
0087     }
0088 
0089     /* Mark slots as 'inactive' */
0090     for (i = 0; i < num_slots; i++)
0091         input_mt_set_value(&mt->slots[i], ABS_MT_TRACKING_ID, -1);
0092 
0093     /* Mark slots as 'unused' */
0094     mt->frame = 1;
0095 
0096     dev->mt = mt;
0097     return 0;
0098 err_mem:
0099     kfree(mt);
0100     return -ENOMEM;
0101 }
0102 EXPORT_SYMBOL(input_mt_init_slots);
0103 
0104 /**
0105  * input_mt_destroy_slots() - frees the MT slots of the input device
0106  * @dev: input device with allocated MT slots
0107  *
0108  * This function is only needed in error path as the input core will
0109  * automatically free the MT slots when the device is destroyed.
0110  */
0111 void input_mt_destroy_slots(struct input_dev *dev)
0112 {
0113     if (dev->mt) {
0114         kfree(dev->mt->red);
0115         kfree(dev->mt);
0116     }
0117     dev->mt = NULL;
0118 }
0119 EXPORT_SYMBOL(input_mt_destroy_slots);
0120 
0121 /**
0122  * input_mt_report_slot_state() - report contact state
0123  * @dev: input device with allocated MT slots
0124  * @tool_type: the tool type to use in this slot
0125  * @active: true if contact is active, false otherwise
0126  *
0127  * Reports a contact via ABS_MT_TRACKING_ID, and optionally
0128  * ABS_MT_TOOL_TYPE. If active is true and the slot is currently
0129  * inactive, or if the tool type is changed, a new tracking id is
0130  * assigned to the slot. The tool type is only reported if the
0131  * corresponding absbit field is set.
0132  *
0133  * Returns true if contact is active.
0134  */
0135 bool input_mt_report_slot_state(struct input_dev *dev,
0136                 unsigned int tool_type, bool active)
0137 {
0138     struct input_mt *mt = dev->mt;
0139     struct input_mt_slot *slot;
0140     int id;
0141 
0142     if (!mt)
0143         return false;
0144 
0145     slot = &mt->slots[mt->slot];
0146     slot->frame = mt->frame;
0147 
0148     if (!active) {
0149         input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
0150         return false;
0151     }
0152 
0153     id = input_mt_get_value(slot, ABS_MT_TRACKING_ID);
0154     if (id < 0)
0155         id = input_mt_new_trkid(mt);
0156 
0157     input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, id);
0158     input_event(dev, EV_ABS, ABS_MT_TOOL_TYPE, tool_type);
0159 
0160     return true;
0161 }
0162 EXPORT_SYMBOL(input_mt_report_slot_state);
0163 
0164 /**
0165  * input_mt_report_finger_count() - report contact count
0166  * @dev: input device with allocated MT slots
0167  * @count: the number of contacts
0168  *
0169  * Reports the contact count via BTN_TOOL_FINGER, BTN_TOOL_DOUBLETAP,
0170  * BTN_TOOL_TRIPLETAP and BTN_TOOL_QUADTAP.
0171  *
0172  * The input core ensures only the KEY events already setup for
0173  * this device will produce output.
0174  */
0175 void input_mt_report_finger_count(struct input_dev *dev, int count)
0176 {
0177     input_event(dev, EV_KEY, BTN_TOOL_FINGER, count == 1);
0178     input_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, count == 2);
0179     input_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, count == 3);
0180     input_event(dev, EV_KEY, BTN_TOOL_QUADTAP, count == 4);
0181     input_event(dev, EV_KEY, BTN_TOOL_QUINTTAP, count == 5);
0182 }
0183 EXPORT_SYMBOL(input_mt_report_finger_count);
0184 
0185 /**
0186  * input_mt_report_pointer_emulation() - common pointer emulation
0187  * @dev: input device with allocated MT slots
0188  * @use_count: report number of active contacts as finger count
0189  *
0190  * Performs legacy pointer emulation via BTN_TOUCH, ABS_X, ABS_Y and
0191  * ABS_PRESSURE. Touchpad finger count is emulated if use_count is true.
0192  *
0193  * The input core ensures only the KEY and ABS axes already setup for
0194  * this device will produce output.
0195  */
0196 void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count)
0197 {
0198     struct input_mt *mt = dev->mt;
0199     struct input_mt_slot *oldest;
0200     int oldid, count, i;
0201 
0202     if (!mt)
0203         return;
0204 
0205     oldest = NULL;
0206     oldid = mt->trkid;
0207     count = 0;
0208 
0209     for (i = 0; i < mt->num_slots; ++i) {
0210         struct input_mt_slot *ps = &mt->slots[i];
0211         int id = input_mt_get_value(ps, ABS_MT_TRACKING_ID);
0212 
0213         if (id < 0)
0214             continue;
0215         if ((id - oldid) & TRKID_SGN) {
0216             oldest = ps;
0217             oldid = id;
0218         }
0219         count++;
0220     }
0221 
0222     input_event(dev, EV_KEY, BTN_TOUCH, count > 0);
0223 
0224     if (use_count) {
0225         if (count == 0 &&
0226             !test_bit(ABS_MT_DISTANCE, dev->absbit) &&
0227             test_bit(ABS_DISTANCE, dev->absbit) &&
0228             input_abs_get_val(dev, ABS_DISTANCE) != 0) {
0229             /*
0230              * Force reporting BTN_TOOL_FINGER for devices that
0231              * only report general hover (and not per-contact
0232              * distance) when contact is in proximity but not
0233              * on the surface.
0234              */
0235             count = 1;
0236         }
0237 
0238         input_mt_report_finger_count(dev, count);
0239     }
0240 
0241     if (oldest) {
0242         int x = input_mt_get_value(oldest, ABS_MT_POSITION_X);
0243         int y = input_mt_get_value(oldest, ABS_MT_POSITION_Y);
0244 
0245         input_event(dev, EV_ABS, ABS_X, x);
0246         input_event(dev, EV_ABS, ABS_Y, y);
0247 
0248         if (test_bit(ABS_MT_PRESSURE, dev->absbit)) {
0249             int p = input_mt_get_value(oldest, ABS_MT_PRESSURE);
0250             input_event(dev, EV_ABS, ABS_PRESSURE, p);
0251         }
0252     } else {
0253         if (test_bit(ABS_MT_PRESSURE, dev->absbit))
0254             input_event(dev, EV_ABS, ABS_PRESSURE, 0);
0255     }
0256 }
0257 EXPORT_SYMBOL(input_mt_report_pointer_emulation);
0258 
0259 static void __input_mt_drop_unused(struct input_dev *dev, struct input_mt *mt)
0260 {
0261     int i;
0262 
0263     lockdep_assert_held(&dev->event_lock);
0264 
0265     for (i = 0; i < mt->num_slots; i++) {
0266         if (input_mt_is_active(&mt->slots[i]) &&
0267             !input_mt_is_used(mt, &mt->slots[i])) {
0268             input_handle_event(dev, EV_ABS, ABS_MT_SLOT, i);
0269             input_handle_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
0270         }
0271     }
0272 }
0273 
0274 /**
0275  * input_mt_drop_unused() - Inactivate slots not seen in this frame
0276  * @dev: input device with allocated MT slots
0277  *
0278  * Lift all slots not seen since the last call to this function.
0279  */
0280 void input_mt_drop_unused(struct input_dev *dev)
0281 {
0282     struct input_mt *mt = dev->mt;
0283 
0284     if (mt) {
0285         unsigned long flags;
0286 
0287         spin_lock_irqsave(&dev->event_lock, flags);
0288 
0289         __input_mt_drop_unused(dev, mt);
0290         mt->frame++;
0291 
0292         spin_unlock_irqrestore(&dev->event_lock, flags);
0293     }
0294 }
0295 EXPORT_SYMBOL(input_mt_drop_unused);
0296 
0297 /**
0298  * input_mt_release_slots() - Deactivate all slots
0299  * @dev: input device with allocated MT slots
0300  *
0301  * Lift all active slots.
0302  */
0303 void input_mt_release_slots(struct input_dev *dev)
0304 {
0305     struct input_mt *mt = dev->mt;
0306 
0307     lockdep_assert_held(&dev->event_lock);
0308 
0309     if (mt) {
0310         /* This will effectively mark all slots unused. */
0311         mt->frame++;
0312 
0313         __input_mt_drop_unused(dev, mt);
0314 
0315         if (test_bit(ABS_PRESSURE, dev->absbit))
0316             input_handle_event(dev, EV_ABS, ABS_PRESSURE, 0);
0317 
0318         mt->frame++;
0319     }
0320 }
0321 
0322 /**
0323  * input_mt_sync_frame() - synchronize mt frame
0324  * @dev: input device with allocated MT slots
0325  *
0326  * Close the frame and prepare the internal state for a new one.
0327  * Depending on the flags, marks unused slots as inactive and performs
0328  * pointer emulation.
0329  */
0330 void input_mt_sync_frame(struct input_dev *dev)
0331 {
0332     struct input_mt *mt = dev->mt;
0333     bool use_count = false;
0334 
0335     if (!mt)
0336         return;
0337 
0338     if (mt->flags & INPUT_MT_DROP_UNUSED) {
0339         unsigned long flags;
0340 
0341         spin_lock_irqsave(&dev->event_lock, flags);
0342         __input_mt_drop_unused(dev, mt);
0343         spin_unlock_irqrestore(&dev->event_lock, flags);
0344     }
0345 
0346     if ((mt->flags & INPUT_MT_POINTER) && !(mt->flags & INPUT_MT_SEMI_MT))
0347         use_count = true;
0348 
0349     input_mt_report_pointer_emulation(dev, use_count);
0350 
0351     mt->frame++;
0352 }
0353 EXPORT_SYMBOL(input_mt_sync_frame);
0354 
0355 static int adjust_dual(int *begin, int step, int *end, int eq, int mu)
0356 {
0357     int f, *p, s, c;
0358 
0359     if (begin == end)
0360         return 0;
0361 
0362     f = *begin;
0363     p = begin + step;
0364     s = p == end ? f + 1 : *p;
0365 
0366     for (; p != end; p += step) {
0367         if (*p < f) {
0368             s = f;
0369             f = *p;
0370         } else if (*p < s) {
0371             s = *p;
0372         }
0373     }
0374 
0375     c = (f + s + 1) / 2;
0376     if (c == 0 || (c > mu && (!eq || mu > 0)))
0377         return 0;
0378     /* Improve convergence for positive matrices by penalizing overcovers */
0379     if (s < 0 && mu <= 0)
0380         c *= 2;
0381 
0382     for (p = begin; p != end; p += step)
0383         *p -= c;
0384 
0385     return (c < s && s <= 0) || (f >= 0 && f < c);
0386 }
0387 
0388 static void find_reduced_matrix(int *w, int nr, int nc, int nrc, int mu)
0389 {
0390     int i, k, sum;
0391 
0392     for (k = 0; k < nrc; k++) {
0393         for (i = 0; i < nr; i++)
0394             adjust_dual(w + i, nr, w + i + nrc, nr <= nc, mu);
0395         sum = 0;
0396         for (i = 0; i < nrc; i += nr)
0397             sum += adjust_dual(w + i, 1, w + i + nr, nc <= nr, mu);
0398         if (!sum)
0399             break;
0400     }
0401 }
0402 
0403 static int input_mt_set_matrix(struct input_mt *mt,
0404                    const struct input_mt_pos *pos, int num_pos,
0405                    int mu)
0406 {
0407     const struct input_mt_pos *p;
0408     struct input_mt_slot *s;
0409     int *w = mt->red;
0410     int x, y;
0411 
0412     for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
0413         if (!input_mt_is_active(s))
0414             continue;
0415         x = input_mt_get_value(s, ABS_MT_POSITION_X);
0416         y = input_mt_get_value(s, ABS_MT_POSITION_Y);
0417         for (p = pos; p != pos + num_pos; p++) {
0418             int dx = x - p->x, dy = y - p->y;
0419             *w++ = dx * dx + dy * dy - mu;
0420         }
0421     }
0422 
0423     return w - mt->red;
0424 }
0425 
0426 static void input_mt_set_slots(struct input_mt *mt,
0427                    int *slots, int num_pos)
0428 {
0429     struct input_mt_slot *s;
0430     int *w = mt->red, j;
0431 
0432     for (j = 0; j != num_pos; j++)
0433         slots[j] = -1;
0434 
0435     for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
0436         if (!input_mt_is_active(s))
0437             continue;
0438 
0439         for (j = 0; j != num_pos; j++) {
0440             if (w[j] < 0) {
0441                 slots[j] = s - mt->slots;
0442                 break;
0443             }
0444         }
0445 
0446         w += num_pos;
0447     }
0448 
0449     for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
0450         if (input_mt_is_active(s))
0451             continue;
0452 
0453         for (j = 0; j != num_pos; j++) {
0454             if (slots[j] < 0) {
0455                 slots[j] = s - mt->slots;
0456                 break;
0457             }
0458         }
0459     }
0460 }
0461 
0462 /**
0463  * input_mt_assign_slots() - perform a best-match assignment
0464  * @dev: input device with allocated MT slots
0465  * @slots: the slot assignment to be filled
0466  * @pos: the position array to match
0467  * @num_pos: number of positions
0468  * @dmax: maximum ABS_MT_POSITION displacement (zero for infinite)
0469  *
0470  * Performs a best match against the current contacts and returns
0471  * the slot assignment list. New contacts are assigned to unused
0472  * slots.
0473  *
0474  * The assignments are balanced so that all coordinate displacements are
0475  * below the euclidian distance dmax. If no such assignment can be found,
0476  * some contacts are assigned to unused slots.
0477  *
0478  * Returns zero on success, or negative error in case of failure.
0479  */
0480 int input_mt_assign_slots(struct input_dev *dev, int *slots,
0481               const struct input_mt_pos *pos, int num_pos,
0482               int dmax)
0483 {
0484     struct input_mt *mt = dev->mt;
0485     int mu = 2 * dmax * dmax;
0486     int nrc;
0487 
0488     if (!mt || !mt->red)
0489         return -ENXIO;
0490     if (num_pos > mt->num_slots)
0491         return -EINVAL;
0492     if (num_pos < 1)
0493         return 0;
0494 
0495     nrc = input_mt_set_matrix(mt, pos, num_pos, mu);
0496     find_reduced_matrix(mt->red, num_pos, nrc / num_pos, nrc, mu);
0497     input_mt_set_slots(mt, slots, num_pos);
0498 
0499     return 0;
0500 }
0501 EXPORT_SYMBOL(input_mt_assign_slots);
0502 
0503 /**
0504  * input_mt_get_slot_by_key() - return slot matching key
0505  * @dev: input device with allocated MT slots
0506  * @key: the key of the sought slot
0507  *
0508  * Returns the slot of the given key, if it exists, otherwise
0509  * set the key on the first unused slot and return.
0510  *
0511  * If no available slot can be found, -1 is returned.
0512  * Note that for this function to work properly, input_mt_sync_frame() has
0513  * to be called at each frame.
0514  */
0515 int input_mt_get_slot_by_key(struct input_dev *dev, int key)
0516 {
0517     struct input_mt *mt = dev->mt;
0518     struct input_mt_slot *s;
0519 
0520     if (!mt)
0521         return -1;
0522 
0523     for (s = mt->slots; s != mt->slots + mt->num_slots; s++)
0524         if (input_mt_is_active(s) && s->key == key)
0525             return s - mt->slots;
0526 
0527     for (s = mt->slots; s != mt->slots + mt->num_slots; s++)
0528         if (!input_mt_is_active(s) && !input_mt_is_used(mt, s)) {
0529             s->key = key;
0530             return s - mt->slots;
0531         }
0532 
0533     return -1;
0534 }
0535 EXPORT_SYMBOL(input_mt_get_slot_by_key);