static void __input_mt_drop_unused(struct input_dev *dev, struct input_mt *mt) { int i; for (i = 0; i < mt->num_slots; i++) { if (!input_mt_is_used(mt, &mt->slots[i])) { input_mt_slot(dev, i); input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1); } } }
/* * this function is called when a whole contact has been processed, * so that it can assign it to a slot and store the data there */ static void mt_complete_slot(struct mt_device *td, struct input_dev *input) { if ((td->mtclass.quirks & MT_QUIRK_CONTACT_CNT_ACCURATE) && td->num_received >= td->num_expected) return; if (td->curvalid || (td->mtclass.quirks & MT_QUIRK_ALWAYS_VALID)) { int active; int slotnum = mt_compute_slot(td, input); struct mt_slot *s = &td->curdata; struct input_mt *mt = input->mt; if (slotnum < 0 || slotnum >= td->maxcontacts) return; if ((td->mtclass.quirks & MT_QUIRK_IGNORE_DUPLICATES) && mt) { struct input_mt_slot *slot = &mt->slots[slotnum]; if (input_mt_is_active(slot) && input_mt_is_used(mt, slot)) return; } if (!(td->mtclass.quirks & MT_QUIRK_CONFIDENCE)) s->confidence_state = 1; active = (s->touch_state || s->inrange_state) && s->confidence_state; input_mt_slot(input, slotnum); input_mt_report_slot_state(input, MT_TOOL_FINGER, active); if (active) { /* this finger is in proximity of the sensor */ int wide = (s->w > s->h); /* divided by two to match visual scale of touch */ int major = max(s->w, s->h) >> 1; int minor = min(s->w, s->h) >> 1; input_event(input, EV_ABS, ABS_MT_POSITION_X, s->x); input_event(input, EV_ABS, ABS_MT_POSITION_Y, s->y); input_event(input, EV_ABS, ABS_MT_TOOL_X, s->cx); input_event(input, EV_ABS, ABS_MT_TOOL_Y, s->cy); input_event(input, EV_ABS, ABS_MT_DISTANCE, !s->touch_state); input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide); input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p); input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major); input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor); } }
/** * input_mt_sync_frame() - synchronize mt frame * @dev: input device with allocated MT slots * * Close the frame and prepare the internal state for a new one. * Depending on the flags, marks unused slots as inactive and performs * pointer emulation. */ void input_mt_sync_frame(struct input_dev *dev) { struct input_mt *mt = dev->mt; struct input_mt_slot *s; if (!mt) return; if (mt->flags & INPUT_MT_DROP_UNUSED) { for (s = mt->slots; s != mt->slots + mt->num_slots; s++) { if (input_mt_is_used(mt, s)) continue; input_mt_slot(dev, s - mt->slots); input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1); } } input_mt_report_pointer_emulation(dev, (mt->flags & INPUT_MT_POINTER)); mt->frame++; }