Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <acz@semihalf.com>
Link: https://lore.kernel.org/r/20220718151715.1052842-3-acz@semihalf.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

authored by

Angela Czubak and committed by
Dmitry Torokhov
ebfa0043 59b7a5af

+80 -14
+16
drivers/input/input-core-private.h
··· 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 */
+44 -4
drivers/input/input-mt.c
··· 8 8 #include <linux/input/mt.h> 9 9 #include <linux/export.h> 10 10 #include <linux/slab.h> 11 + #include "input-core-private.h" 11 12 12 13 #define TRKID_SGN ((TRKID_MAX + 1) >> 1) 13 14 ··· 260 259 { 261 260 int i; 262 261 262 + lockdep_assert_held(&dev->event_lock); 263 + 263 264 for (i = 0; i < mt->num_slots; i++) { 264 - if (!input_mt_is_used(mt, &mt->slots[i])) { 265 - input_mt_slot(dev, i); 266 - input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1); 265 + if (input_mt_is_active(&mt->slots[i]) && 266 + !input_mt_is_used(mt, &mt->slots[i])) { 267 + input_handle_event(dev, EV_ABS, ABS_MT_SLOT, i); 268 + input_handle_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1); 267 269 } 268 270 } 269 271 } ··· 282 278 struct input_mt *mt = dev->mt; 283 279 284 280 if (mt) { 281 + unsigned long flags; 282 + 283 + spin_lock_irqsave(&dev->event_lock, flags); 284 + 285 285 __input_mt_drop_unused(dev, mt); 286 286 mt->frame++; 287 + 288 + spin_unlock_irqrestore(&dev->event_lock, flags); 287 289 } 288 290 } 289 291 EXPORT_SYMBOL(input_mt_drop_unused); 292 + 293 + /** 294 + * input_mt_release_slots() - Deactivate all slots 295 + * @dev: input device with allocated MT slots 296 + * 297 + * Lift all active slots. 298 + */ 299 + void input_mt_release_slots(struct input_dev *dev) 300 + { 301 + struct input_mt *mt = dev->mt; 302 + 303 + lockdep_assert_held(&dev->event_lock); 304 + 305 + if (mt) { 306 + /* This will effectively mark all slots unused. */ 307 + mt->frame++; 308 + 309 + __input_mt_drop_unused(dev, mt); 310 + 311 + if (test_bit(ABS_PRESSURE, dev->absbit)) 312 + input_handle_event(dev, EV_ABS, ABS_PRESSURE, 0); 313 + 314 + mt->frame++; 315 + } 316 + } 290 317 291 318 /** 292 319 * input_mt_sync_frame() - synchronize mt frame ··· 335 300 if (!mt) 336 301 return; 337 302 338 - if (mt->flags & INPUT_MT_DROP_UNUSED) 303 + if (mt->flags & INPUT_MT_DROP_UNUSED) { 304 + unsigned long flags; 305 + 306 + spin_lock_irqsave(&dev->event_lock, flags); 339 307 __input_mt_drop_unused(dev, mt); 308 + spin_unlock_irqrestore(&dev->event_lock, flags); 309 + } 340 310 341 311 if ((mt->flags & INPUT_MT_POINTER) && !(mt->flags & INPUT_MT_SEMI_MT)) 342 312 use_count = true;
+20 -10
drivers/input/input.c
··· 24 24 #include <linux/mutex.h> 25 25 #include <linux/rcupdate.h> 26 26 #include "input-compat.h" 27 + #include "input-core-private.h" 27 28 #include "input-poller.h" 28 29 29 30 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); ··· 142 141 { 143 142 struct input_handle *handle; 144 143 struct input_value *v; 144 + 145 + lockdep_assert_held(&dev->event_lock); 145 146 146 147 if (!count) 147 148 return; ··· 387 384 } 388 385 } 389 386 390 - static void input_handle_event(struct input_dev *dev, 391 - unsigned int type, unsigned int code, int value) 387 + void input_handle_event(struct input_dev *dev, 388 + unsigned int type, unsigned int code, int value) 392 389 { 393 390 int disposition; 394 391 ··· 725 722 * Simulate keyup events for all keys that are marked as pressed. 726 723 * The function must be called with dev->event_lock held. 727 724 */ 728 - static void input_dev_release_keys(struct input_dev *dev) 725 + static bool input_dev_release_keys(struct input_dev *dev) 729 726 { 730 727 bool need_sync = false; 731 728 int code; 729 + 730 + lockdep_assert_held(&dev->event_lock); 732 731 733 732 if (is_event_supported(EV_KEY, dev->evbit, EV_MAX)) { 734 733 for_each_set_bit(code, dev->key, KEY_CNT) { 735 734 input_handle_event(dev, EV_KEY, code, 0); 736 735 need_sync = true; 737 736 } 738 - 739 - if (need_sync) 740 - input_handle_event(dev, EV_SYN, SYN_REPORT, 1); 741 737 } 738 + 739 + return need_sync; 742 740 } 743 741 744 742 /* ··· 766 762 * generate events even after we done here but they will not 767 763 * reach any handlers. 768 764 */ 769 - input_dev_release_keys(dev); 765 + if (input_dev_release_keys(dev)) 766 + input_handle_event(dev, EV_SYN, SYN_REPORT, 1); 770 767 771 768 list_for_each_entry(handle, &dev->h_list, d_node) 772 769 handle->open = 0; ··· 1762 1757 spin_lock_irqsave(&dev->event_lock, flags); 1763 1758 1764 1759 input_dev_toggle(dev, true); 1765 - input_dev_release_keys(dev); 1760 + if (input_dev_release_keys(dev)) 1761 + input_handle_event(dev, EV_SYN, SYN_REPORT, 1); 1766 1762 1767 1763 spin_unlock_irqrestore(&dev->event_lock, flags); 1768 1764 mutex_unlock(&dev->mutex); ··· 1785 1779 } 1786 1780 1787 1781 spin_lock_irq(&dev->event_lock); 1782 + input_mt_release_slots(dev); 1788 1783 input_dev_release_keys(dev); 1784 + input_handle_event(dev, EV_SYN, SYN_REPORT, 1); 1789 1785 input_dev_toggle(dev, false); 1790 1786 spin_unlock_irq(&dev->event_lock); 1791 1787 ··· 1838 1830 * Keys that are pressed now are unlikely to be 1839 1831 * still pressed when we resume. 1840 1832 */ 1841 - input_dev_release_keys(input_dev); 1833 + if (input_dev_release_keys(input_dev)) 1834 + input_handle_event(input_dev, EV_SYN, SYN_REPORT, 1); 1842 1835 1843 1836 /* Turn off LEDs and sounds, if any are active. */ 1844 1837 input_dev_toggle(input_dev, false); ··· 1873 1864 * Keys that are pressed now are unlikely to be 1874 1865 * still pressed when we resume. 1875 1866 */ 1876 - input_dev_release_keys(input_dev); 1867 + if (input_dev_release_keys(input_dev)) 1868 + input_handle_event(input_dev, EV_SYN, SYN_REPORT, 1); 1877 1869 1878 1870 spin_unlock_irq(&input_dev->event_lock); 1879 1871