Skip to content

Commit ebfa004

Browse files
semihalf-czubak-angeladtor
authored andcommitted
Input: deactivate MT slots when inhibiting or suspending devices
When inhibiting or suspending a device we are sending release events for all currently held keys and buttons, however we retain active MT slot state, which causes issues with gesture recognition when we resume or uninhibit. Let's fix it by introducing, in addition to input_dev_release_keys(), nput_mt_release_slots() that will deactivate all currently active slots. Signed-off-by: Angela Czubak <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Dmitry Torokhov <[email protected]>
1 parent 59b7a5a commit ebfa004

File tree

3 files changed

+80
-14
lines changed

3 files changed

+80
-14
lines changed

drivers/input/input-core-private.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
#ifndef _INPUT_CORE_PRIVATE_H
3+
#define _INPUT_CORE_PRIVATE_H
4+
5+
/*
6+
* Functions and definitions that are private to input core,
7+
* should not be used by input drivers or handlers.
8+
*/
9+
10+
struct input_dev;
11+
12+
void input_mt_release_slots(struct input_dev *dev);
13+
void input_handle_event(struct input_dev *dev,
14+
unsigned int type, unsigned int code, int value);
15+
16+
#endif /* _INPUT_CORE_PRIVATE_H */

drivers/input/input-mt.c

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <linux/input/mt.h>
99
#include <linux/export.h>
1010
#include <linux/slab.h>
11+
#include "input-core-private.h"
1112

1213
#define TRKID_SGN ((TRKID_MAX + 1) >> 1)
1314

@@ -259,10 +260,13 @@ static void __input_mt_drop_unused(struct input_dev *dev, struct input_mt *mt)
259260
{
260261
int i;
261262

263+
lockdep_assert_held(&dev->event_lock);
264+
262265
for (i = 0; i < mt->num_slots; i++) {
263-
if (!input_mt_is_used(mt, &mt->slots[i])) {
264-
input_mt_slot(dev, i);
265-
input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
266+
if (input_mt_is_active(&mt->slots[i]) &&
267+
!input_mt_is_used(mt, &mt->slots[i])) {
268+
input_handle_event(dev, EV_ABS, ABS_MT_SLOT, i);
269+
input_handle_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
266270
}
267271
}
268272
}
@@ -278,12 +282,43 @@ void input_mt_drop_unused(struct input_dev *dev)
278282
struct input_mt *mt = dev->mt;
279283

280284
if (mt) {
285+
unsigned long flags;
286+
287+
spin_lock_irqsave(&dev->event_lock, flags);
288+
281289
__input_mt_drop_unused(dev, mt);
282290
mt->frame++;
291+
292+
spin_unlock_irqrestore(&dev->event_lock, flags);
283293
}
284294
}
285295
EXPORT_SYMBOL(input_mt_drop_unused);
286296

297+
/**
298+
* input_mt_release_slots() - Deactivate all slots
299+
* @dev: input device with allocated MT slots
300+
*
301+
* Lift all active slots.
302+
*/
303+
void input_mt_release_slots(struct input_dev *dev)
304+
{
305+
struct input_mt *mt = dev->mt;
306+
307+
lockdep_assert_held(&dev->event_lock);
308+
309+
if (mt) {
310+
/* This will effectively mark all slots unused. */
311+
mt->frame++;
312+
313+
__input_mt_drop_unused(dev, mt);
314+
315+
if (test_bit(ABS_PRESSURE, dev->absbit))
316+
input_handle_event(dev, EV_ABS, ABS_PRESSURE, 0);
317+
318+
mt->frame++;
319+
}
320+
}
321+
287322
/**
288323
* input_mt_sync_frame() - synchronize mt frame
289324
* @dev: input device with allocated MT slots
@@ -300,8 +335,13 @@ void input_mt_sync_frame(struct input_dev *dev)
300335
if (!mt)
301336
return;
302337

303-
if (mt->flags & INPUT_MT_DROP_UNUSED)
338+
if (mt->flags & INPUT_MT_DROP_UNUSED) {
339+
unsigned long flags;
340+
341+
spin_lock_irqsave(&dev->event_lock, flags);
304342
__input_mt_drop_unused(dev, mt);
343+
spin_unlock_irqrestore(&dev->event_lock, flags);
344+
}
305345

306346
if ((mt->flags & INPUT_MT_POINTER) && !(mt->flags & INPUT_MT_SEMI_MT))
307347
use_count = true;

drivers/input/input.c

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <linux/mutex.h>
2525
#include <linux/rcupdate.h>
2626
#include "input-compat.h"
27+
#include "input-core-private.h"
2728
#include "input-poller.h"
2829

2930
MODULE_AUTHOR("Vojtech Pavlik <[email protected]>");
@@ -142,6 +143,8 @@ static void input_pass_values(struct input_dev *dev,
142143
struct input_handle *handle;
143144
struct input_value *v;
144145

146+
lockdep_assert_held(&dev->event_lock);
147+
145148
if (!count)
146149
return;
147150

@@ -384,8 +387,8 @@ static void input_event_dispose(struct input_dev *dev, int disposition,
384387
}
385388
}
386389

387-
static void input_handle_event(struct input_dev *dev,
388-
unsigned int type, unsigned int code, int value)
390+
void input_handle_event(struct input_dev *dev,
391+
unsigned int type, unsigned int code, int value)
389392
{
390393
int disposition;
391394

@@ -722,20 +725,21 @@ EXPORT_SYMBOL(input_close_device);
722725
* Simulate keyup events for all keys that are marked as pressed.
723726
* The function must be called with dev->event_lock held.
724727
*/
725-
static void input_dev_release_keys(struct input_dev *dev)
728+
static bool input_dev_release_keys(struct input_dev *dev)
726729
{
727730
bool need_sync = false;
728731
int code;
729732

733+
lockdep_assert_held(&dev->event_lock);
734+
730735
if (is_event_supported(EV_KEY, dev->evbit, EV_MAX)) {
731736
for_each_set_bit(code, dev->key, KEY_CNT) {
732737
input_handle_event(dev, EV_KEY, code, 0);
733738
need_sync = true;
734739
}
735-
736-
if (need_sync)
737-
input_handle_event(dev, EV_SYN, SYN_REPORT, 1);
738740
}
741+
742+
return need_sync;
739743
}
740744

741745
/*
@@ -762,7 +766,8 @@ static void input_disconnect_device(struct input_dev *dev)
762766
* generate events even after we done here but they will not
763767
* reach any handlers.
764768
*/
765-
input_dev_release_keys(dev);
769+
if (input_dev_release_keys(dev))
770+
input_handle_event(dev, EV_SYN, SYN_REPORT, 1);
766771

767772
list_for_each_entry(handle, &dev->h_list, d_node)
768773
handle->open = 0;
@@ -1757,7 +1762,8 @@ void input_reset_device(struct input_dev *dev)
17571762
spin_lock_irqsave(&dev->event_lock, flags);
17581763

17591764
input_dev_toggle(dev, true);
1760-
input_dev_release_keys(dev);
1765+
if (input_dev_release_keys(dev))
1766+
input_handle_event(dev, EV_SYN, SYN_REPORT, 1);
17611767

17621768
spin_unlock_irqrestore(&dev->event_lock, flags);
17631769
mutex_unlock(&dev->mutex);
@@ -1779,7 +1785,9 @@ static int input_inhibit_device(struct input_dev *dev)
17791785
}
17801786

17811787
spin_lock_irq(&dev->event_lock);
1788+
input_mt_release_slots(dev);
17821789
input_dev_release_keys(dev);
1790+
input_handle_event(dev, EV_SYN, SYN_REPORT, 1);
17831791
input_dev_toggle(dev, false);
17841792
spin_unlock_irq(&dev->event_lock);
17851793

@@ -1830,7 +1838,8 @@ static int input_dev_suspend(struct device *dev)
18301838
* Keys that are pressed now are unlikely to be
18311839
* still pressed when we resume.
18321840
*/
1833-
input_dev_release_keys(input_dev);
1841+
if (input_dev_release_keys(input_dev))
1842+
input_handle_event(input_dev, EV_SYN, SYN_REPORT, 1);
18341843

18351844
/* Turn off LEDs and sounds, if any are active. */
18361845
input_dev_toggle(input_dev, false);
@@ -1864,7 +1873,8 @@ static int input_dev_freeze(struct device *dev)
18641873
* Keys that are pressed now are unlikely to be
18651874
* still pressed when we resume.
18661875
*/
1867-
input_dev_release_keys(input_dev);
1876+
if (input_dev_release_keys(input_dev))
1877+
input_handle_event(input_dev, EV_SYN, SYN_REPORT, 1);
18681878

18691879
spin_unlock_irq(&input_dev->event_lock);
18701880

0 commit comments

Comments
 (0)