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

Input: introduce notion of passive observers for input handlers

Sometimes it is useful to observe (and maybe modify) data coming from
an input device, but only do that if there are other users of such input
device. An example is touchpad switching functionality on Lenovo IdeaPad
Z570 where it is desirable to suppress events coming from the touchpad
if user toggles touchpad on/off button (on this laptop the firmware does
not stop the device).

Introduce notion of passive observers for input handlers to solve this
issue. An input handler marked as passive observer behaves exactly like
any other input handler or filter, but with one exception: it does not
open/start underlying input device when attaching to it.

Link: https://lore.kernel.org/r/ZxlEROX7bMo5cbZP@google.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

+15 -5
+10 -5
drivers/input/input.c
··· 605 605 606 606 handle->open++; 607 607 608 + if (handle->handler->passive_observer) 609 + goto out; 610 + 608 611 if (dev->users++ || dev->inhibited) { 609 612 /* 610 613 * Device is already opened and/or inhibited, ··· 671 668 672 669 __input_release_device(handle); 673 670 674 - if (!--dev->users && !dev->inhibited) { 675 - if (dev->poller) 676 - input_dev_poller_stop(dev->poller); 677 - if (dev->close) 678 - dev->close(dev); 671 + if (!handle->handler->passive_observer) { 672 + if (!--dev->users && !dev->inhibited) { 673 + if (dev->poller) 674 + input_dev_poller_stop(dev->poller); 675 + if (dev->close) 676 + dev->close(dev); 677 + } 679 678 } 680 679 681 680 if (!--handle->open) {
+5
include/linux/input.h
··· 286 286 * @start: starts handler for given handle. This function is called by 287 287 * input core right after connect() method and also when a process 288 288 * that "grabbed" a device releases it 289 + * @passive_observer: set to %true by drivers only interested in observing 290 + * data stream from devices if there are other users present. Such 291 + * drivers will not result in starting underlying hardware device 292 + * when input_open_device() is called for their handles 289 293 * @legacy_minors: set to %true by drivers using legacy minor ranges 290 294 * @minor: beginning of range of 32 legacy minors for devices this driver 291 295 * can provide ··· 325 321 void (*disconnect)(struct input_handle *handle); 326 322 void (*start)(struct input_handle *handle); 327 323 324 + bool passive_observer; 328 325 bool legacy_minors; 329 326 int minor; 330 327 const char *name;