Skip to content

Commit 55e4908

Browse files
committed
Input: MT - Handle frame synchronization in core
Most MT drivers perform the same actions on frame synchronization. Some actions, like dropping unseen contacts, are also unnecessarily complex. Collect common frame synchronization tasks in a new function, input_mt_sync_frame(). Depending on the flags set, it drops unseen contacts and performs pointer emulation. With init flags and frame synchronization in place, most MT drivers can be simplified. First out are the bcm5974 and hid-multitouch drivers, following this patch. Reviewed-and-tested-by: Benjamin Tissoires <benjamin.tissoires@enac.fr> Tested-by: Ping Cheng <pingc@wacom.com> Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
1 parent b4adbbe commit 55e4908

2 files changed

Lines changed: 77 additions & 2 deletions

File tree

drivers/input/input-mt.c

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@
1414

1515
#define TRKID_SGN ((TRKID_MAX + 1) >> 1)
1616

17+
static void copy_abs(struct input_dev *dev, unsigned int dst, unsigned int src)
18+
{
19+
if (dev->absinfo && test_bit(src, dev->absbit)) {
20+
dev->absinfo[dst] = dev->absinfo[src];
21+
dev->absbit[BIT_WORD(dst)] |= BIT_MASK(dst);
22+
}
23+
}
24+
1725
/**
1826
* input_mt_init_slots() - initialize MT input slots
1927
* @dev: input device supporting MT events and finger tracking
@@ -45,6 +53,28 @@ int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots,
4553
input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0);
4654
input_set_abs_params(dev, ABS_MT_TRACKING_ID, 0, TRKID_MAX, 0, 0);
4755

56+
if (flags & (INPUT_MT_POINTER | INPUT_MT_DIRECT)) {
57+
__set_bit(EV_KEY, dev->evbit);
58+
__set_bit(BTN_TOUCH, dev->keybit);
59+
60+
copy_abs(dev, ABS_X, ABS_MT_POSITION_X);
61+
copy_abs(dev, ABS_Y, ABS_MT_POSITION_Y);
62+
copy_abs(dev, ABS_PRESSURE, ABS_MT_PRESSURE);
63+
}
64+
if (flags & INPUT_MT_POINTER) {
65+
__set_bit(BTN_TOOL_FINGER, dev->keybit);
66+
__set_bit(BTN_TOOL_DOUBLETAP, dev->keybit);
67+
if (num_slots >= 3)
68+
__set_bit(BTN_TOOL_TRIPLETAP, dev->keybit);
69+
if (num_slots >= 4)
70+
__set_bit(BTN_TOOL_QUADTAP, dev->keybit);
71+
if (num_slots >= 5)
72+
__set_bit(BTN_TOOL_QUINTTAP, dev->keybit);
73+
__set_bit(INPUT_PROP_POINTER, dev->propbit);
74+
}
75+
if (flags & INPUT_MT_DIRECT)
76+
__set_bit(INPUT_PROP_DIRECT, dev->propbit);
77+
4878
/* Mark slots as 'unused' */
4979
for (i = 0; i < num_slots; i++)
5080
input_mt_set_value(&mt->slots[i], ABS_MT_TRACKING_ID, -1);
@@ -87,12 +117,17 @@ void input_mt_report_slot_state(struct input_dev *dev,
87117
struct input_mt_slot *slot;
88118
int id;
89119

90-
if (!mt || !active) {
120+
if (!mt)
121+
return;
122+
123+
slot = &mt->slots[mt->slot];
124+
slot->frame = mt->frame;
125+
126+
if (!active) {
91127
input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
92128
return;
93129
}
94130

95-
slot = &mt->slots[mt->slot];
96131
id = input_mt_get_value(slot, ABS_MT_TRACKING_ID);
97132
if (id < 0 || input_mt_get_value(slot, ABS_MT_TOOL_TYPE) != tool_type)
98133
id = input_mt_new_trkid(mt);
@@ -177,3 +212,34 @@ void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count)
177212
}
178213
}
179214
EXPORT_SYMBOL(input_mt_report_pointer_emulation);
215+
216+
/**
217+
* input_mt_sync_frame() - synchronize mt frame
218+
* @dev: input device with allocated MT slots
219+
*
220+
* Close the frame and prepare the internal state for a new one.
221+
* Depending on the flags, marks unused slots as inactive and performs
222+
* pointer emulation.
223+
*/
224+
void input_mt_sync_frame(struct input_dev *dev)
225+
{
226+
struct input_mt *mt = dev->mt;
227+
struct input_mt_slot *s;
228+
229+
if (!mt)
230+
return;
231+
232+
if (mt->flags & INPUT_MT_DROP_UNUSED) {
233+
for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
234+
if (s->frame == mt->frame)
235+
continue;
236+
input_mt_slot(dev, s - mt->slots);
237+
input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
238+
}
239+
}
240+
241+
input_mt_report_pointer_emulation(dev, (mt->flags & INPUT_MT_POINTER));
242+
243+
mt->frame++;
244+
}
245+
EXPORT_SYMBOL(input_mt_sync_frame);

include/linux/input/mt.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,17 @@
1515

1616
#define TRKID_MAX 0xffff
1717

18+
#define INPUT_MT_POINTER 0x0001 /* pointer device, e.g. trackpad */
19+
#define INPUT_MT_DIRECT 0x0002 /* direct device, e.g. touchscreen */
20+
#define INPUT_MT_DROP_UNUSED 0x0004 /* drop contacts not seen in frame */
1821
/**
1922
* struct input_mt_slot - represents the state of an input MT slot
2023
* @abs: holds current values of ABS_MT axes for this slot
24+
* @frame: last frame at which input_mt_report_slot_state() was called
2125
*/
2226
struct input_mt_slot {
2327
int abs[ABS_MT_LAST - ABS_MT_FIRST + 1];
28+
unsigned int frame;
2429
};
2530

2631
/**
@@ -29,13 +34,15 @@ struct input_mt_slot {
2934
* @num_slots: number of MT slots the device uses
3035
* @slot: MT slot currently being transmitted
3136
* @flags: input_mt operation flags
37+
* @frame: increases every time input_mt_sync_frame() is called
3238
* @slots: array of slots holding current values of tracked contacts
3339
*/
3440
struct input_mt {
3541
int trkid;
3642
int num_slots;
3743
int slot;
3844
unsigned int flags;
45+
unsigned int frame;
3946
struct input_mt_slot slots[];
4047
};
4148

@@ -81,4 +88,6 @@ void input_mt_report_slot_state(struct input_dev *dev,
8188
void input_mt_report_finger_count(struct input_dev *dev, int count);
8289
void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count);
8390

91+
void input_mt_sync_frame(struct input_dev *dev);
92+
8493
#endif

0 commit comments

Comments
 (0)