diff options
author | Benjamin Tissoires <benjamin.tissoires@redhat.com> | 2015-03-30 14:54:15 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2015-04-07 09:16:36 -0400 |
commit | c627589282213bbef12a482c0b87f23526ceb3f0 (patch) | |
tree | 21f56937f6f819ce9bbc81aafdeeb2ce8a4f7938 | |
parent | b9e9cd32ba33d13c7ecbc15b9f4418beded403d2 (diff) |
Input - mt: Fix input_mt_get_slot_by_key
The case occurred recently with a touchscreen using twice a slot during a
single EV_SYN event:
E: 0.288415 0000 0000 0000 # ------------ SYN_REPORT (0) ----------
E: 0.296207 0003 002f 0000 # EV_ABS / ABS_MT_SLOT 0
E: 0.296207 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1
E: 0.296207 0003 002f 0001 # EV_ABS / ABS_MT_SLOT 1
E: 0.296207 0003 0035 0908 # EV_ABS / ABS_MT_POSITION_X 908
E: 0.296207 0003 0036 1062 # EV_ABS / ABS_MT_POSITION_Y 1062
E: 0.296207 0003 002f 0000 # EV_ABS / ABS_MT_SLOT 0
E: 0.296207 0003 0039 8787 # EV_ABS / ABS_MT_TRACKING_ID 8787
E: 0.296207 0003 0035 1566 # EV_ABS / ABS_MT_POSITION_X 1566
E: 0.296207 0003 0036 0861 # EV_ABS / ABS_MT_POSITION_Y 861
E: 0.296207 0003 0000 0908 # EV_ABS / ABS_X 908
E: 0.296207 0003 0001 1062 # EV_ABS / ABS_Y 1062
E: 0.296207 0000 0000 0000 # ------------ SYN_REPORT (0) ----------
This occurred because while having already slots 0 and 1 assigned, the
touchscreen sent:
0.293377 Tip Switch: 0 | Contact Id: 0 | X: 539 | Y: 1960 | Contact Count: 3
0.294783 Tip Switch: 1 | Contact Id: 1 | X: 908 | Y: 1062 | Contact Count: 0
0.296187 Tip Switch: 1 | Contact Id: 2 | X: 1566 | Y: 861 | Contact Count: 0
Slot 0 is released correclty, but when we look for Contact ID 2, the slot
0 is then picked up again because it is marked as inactive (trackingID < 0).
This is wrong, and we should not reuse a slot in the same frame.
The test should also check for input_mt_is_used().
In addition, we need to initialize mt->frame to an other value than 0.
With mt->frame being 0, all slots are tags as currently used, and so
input_mt_get_slot_by_key() would return -1 for all requests.
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=88903
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r-- | drivers/input/input-mt.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c index fbe29fcb15c5..f4b58f77c524 100644 --- a/drivers/input/input-mt.c +++ b/drivers/input/input-mt.c | |||
@@ -88,10 +88,13 @@ int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots, | |||
88 | goto err_mem; | 88 | goto err_mem; |
89 | } | 89 | } |
90 | 90 | ||
91 | /* Mark slots as 'unused' */ | 91 | /* Mark slots as 'inactive' */ |
92 | for (i = 0; i < num_slots; i++) | 92 | for (i = 0; i < num_slots; i++) |
93 | input_mt_set_value(&mt->slots[i], ABS_MT_TRACKING_ID, -1); | 93 | input_mt_set_value(&mt->slots[i], ABS_MT_TRACKING_ID, -1); |
94 | 94 | ||
95 | /* Mark slots as 'unused' */ | ||
96 | mt->frame = 1; | ||
97 | |||
95 | dev->mt = mt; | 98 | dev->mt = mt; |
96 | return 0; | 99 | return 0; |
97 | err_mem: | 100 | err_mem: |
@@ -430,6 +433,8 @@ EXPORT_SYMBOL(input_mt_assign_slots); | |||
430 | * set the key on the first unused slot and return. | 433 | * set the key on the first unused slot and return. |
431 | * | 434 | * |
432 | * If no available slot can be found, -1 is returned. | 435 | * If no available slot can be found, -1 is returned. |
436 | * Note that for this function to work properly, input_mt_sync_frame() has | ||
437 | * to be called at each frame. | ||
433 | */ | 438 | */ |
434 | int input_mt_get_slot_by_key(struct input_dev *dev, int key) | 439 | int input_mt_get_slot_by_key(struct input_dev *dev, int key) |
435 | { | 440 | { |
@@ -444,7 +449,7 @@ int input_mt_get_slot_by_key(struct input_dev *dev, int key) | |||
444 | return s - mt->slots; | 449 | return s - mt->slots; |
445 | 450 | ||
446 | for (s = mt->slots; s != mt->slots + mt->num_slots; s++) | 451 | for (s = mt->slots; s != mt->slots + mt->num_slots; s++) |
447 | if (!input_mt_is_active(s)) { | 452 | if (!input_mt_is_active(s) && !input_mt_is_used(mt, s)) { |
448 | s->key = key; | 453 | s->key = key; |
449 | return s - mt->slots; | 454 | return s - mt->slots; |
450 | } | 455 | } |