]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
Input: i8042 - Add support for platform filter contexts
authorArmin Wolf <W_Armin@gmx.de>
Mon, 13 Jan 2025 22:13:14 +0000 (23:13 +0100)
committerIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Wed, 15 Jan 2025 14:26:39 +0000 (16:26 +0200)
Currently the platform filter cannot access any driver-specific state
which forces drivers installing a i8042 filter to have at least some
kind of global pointer for their filter.

Allow callers of i8042_install_filter() to submit a context pointer
which is then passed to the i8042 filter. This frees drivers from the
responsibility of having to manage this global pointer themself.

Also introduce a separate type for the i8042 filter (i8042_filter_t)
so that the function definitions can stay compact.

Tested on a Dell Inspiron 3505.

Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Armin Wolf <W_Armin@gmx.de>
Link: https://lore.kernel.org/r/20250113221314.435812-1-W_Armin@gmx.de
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
drivers/input/misc/ideapad_slidebar.c
drivers/input/serio/i8042.c
drivers/platform/x86/asus-nb-wmi.c
drivers/platform/x86/asus-wmi.c
drivers/platform/x86/asus-wmi.h
drivers/platform/x86/dell/dell-laptop.c
drivers/platform/x86/hp/hp_accel.c
drivers/platform/x86/msi-laptop.c
drivers/platform/x86/panasonic-laptop.c
drivers/platform/x86/toshiba_acpi.c
include/linux/i8042.h

index f6e5fc807b4dfc75d17c5453f7aa15de264aea25..ab2e0a401904f661b3493ffcb1b06599e49f2cfc 100644 (file)
@@ -121,7 +121,7 @@ static void slidebar_mode_set(u8 mode)
 }
 
 static bool slidebar_i8042_filter(unsigned char data, unsigned char str,
-                                 struct serio *port)
+                                 struct serio *port, void *context)
 {
        static bool extended = false;
 
@@ -219,7 +219,7 @@ static int __init ideapad_probe(struct platform_device* pdev)
        input_set_capability(slidebar_input_dev, EV_ABS, ABS_X);
        input_set_abs_params(slidebar_input_dev, ABS_X, 0, 0xff, 0, 0);
 
-       err = i8042_install_filter(slidebar_i8042_filter);
+       err = i8042_install_filter(slidebar_i8042_filter, NULL);
        if (err) {
                dev_err(&pdev->dev,
                        "Failed to install i8042 filter: %d\n", err);
index 509330a27880275e440fbf57c732907c4340a8c6..cab5a4c5baf52aefb984d17cf1d119d3d23022ba 100644 (file)
@@ -179,8 +179,8 @@ static struct platform_device *i8042_platform_device;
 static struct notifier_block i8042_kbd_bind_notifier_block;
 
 static bool i8042_handle_data(int irq);
-static bool (*i8042_platform_filter)(unsigned char data, unsigned char str,
-                                    struct serio *serio);
+static i8042_filter_t i8042_platform_filter;
+static void *i8042_platform_filter_context;
 
 void i8042_lock_chip(void)
 {
@@ -194,8 +194,7 @@ void i8042_unlock_chip(void)
 }
 EXPORT_SYMBOL(i8042_unlock_chip);
 
-int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str,
-                                       struct serio *serio))
+int i8042_install_filter(i8042_filter_t filter, void *context)
 {
        guard(spinlock_irqsave)(&i8042_lock);
 
@@ -203,12 +202,12 @@ int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str,
                return -EBUSY;
 
        i8042_platform_filter = filter;
+       i8042_platform_filter_context = context;
        return 0;
 }
 EXPORT_SYMBOL(i8042_install_filter);
 
-int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str,
-                                      struct serio *port))
+int i8042_remove_filter(i8042_filter_t filter)
 {
        guard(spinlock_irqsave)(&i8042_lock);
 
@@ -216,6 +215,7 @@ int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str,
                return -EINVAL;
 
        i8042_platform_filter = NULL;
+       i8042_platform_filter_context = NULL;
        return 0;
 }
 EXPORT_SYMBOL(i8042_remove_filter);
@@ -480,7 +480,10 @@ static bool i8042_filter(unsigned char data, unsigned char str,
                }
        }
 
-       if (i8042_platform_filter && i8042_platform_filter(data, str, serio)) {
+       if (!i8042_platform_filter)
+               return false;
+
+       if (i8042_platform_filter(data, str, serio, i8042_platform_filter_context)) {
                dbg("Filtered out by platform filter\n");
                return true;
        }
index ef04d396f61c7738d5620ea1abe4a317da2efef2..a3d4b98045f88d4e7e42e5fa195615b53622a98a 100644 (file)
@@ -50,7 +50,8 @@ MODULE_PARM_DESC(tablet_mode_sw, "Tablet mode detect: -1:auto 0:disable 1:kbd-do
 static struct quirk_entry *quirks;
 static bool atkbd_reports_vol_keys;
 
-static bool asus_i8042_filter(unsigned char data, unsigned char str, struct serio *port)
+static bool asus_i8042_filter(unsigned char data, unsigned char str, struct serio *port,
+                             void *context)
 {
        static bool extended_e0;
        static bool extended_e1;
index fdeebab96fc008b287210ff23855129f1bdc171e..6c674de60ec06254eda09c7d52922dbd5cbc2764 100644 (file)
@@ -4824,7 +4824,7 @@ static int asus_wmi_add(struct platform_device *pdev)
        }
 
        if (asus->driver->i8042_filter) {
-               err = i8042_install_filter(asus->driver->i8042_filter);
+               err = i8042_install_filter(asus->driver->i8042_filter, NULL);
                if (err)
                        pr_warn("Unable to install key filter - %d\n", err);
        }
index d02f15fd3482fa3d96154c122b42d4b654127c5b..018dfde4025e79007f3d2ee838ceda4e1a0db2c6 100644 (file)
@@ -73,8 +73,7 @@ struct asus_wmi_driver {
        void (*key_filter) (struct asus_wmi_driver *driver, int *code,
                            unsigned int *value, bool *autorelease);
        /* Optional standard i8042 filter */
-       bool (*i8042_filter)(unsigned char data, unsigned char str,
-                            struct serio *serio);
+       i8042_filter_t          i8042_filter;
 
        int (*probe) (struct platform_device *device);
        void (*detect_quirks) (struct asus_wmi_driver *driver);
index 5671bd0deee7d1602284ba1b47cfa223a23b9c5f..58b860b88fff491ec4509748bda9e85bd4fdae4a 100644 (file)
@@ -725,8 +725,8 @@ static void dell_update_rfkill(struct work_struct *ignored)
 }
 static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill);
 
-static bool dell_laptop_i8042_filter(unsigned char data, unsigned char str,
-                             struct serio *port)
+static bool dell_laptop_i8042_filter(unsigned char data, unsigned char str, struct serio *port,
+                                    void *context)
 {
        static bool extended;
 
@@ -884,7 +884,7 @@ static int __init dell_setup_rfkill(void)
                pr_warn("Unable to register dell rbtn notifier\n");
                goto err_filter;
        } else {
-               ret = i8042_install_filter(dell_laptop_i8042_filter);
+               ret = i8042_install_filter(dell_laptop_i8042_filter, NULL);
                if (ret) {
                        pr_warn("Unable to install key filter\n");
                        goto err_filter;
index 39a6530f5072badcda3c911df111cfa054a8aa14..10d5af18d639849f58380649acb9f4e9fce3be6c 100644 (file)
@@ -267,7 +267,7 @@ static struct delayed_led_classdev hpled_led = {
 };
 
 static bool hp_accel_i8042_filter(unsigned char data, unsigned char str,
-                                 struct serio *port)
+                                 struct serio *port, void *context)
 {
        static bool extended;
 
@@ -326,7 +326,7 @@ static int lis3lv02d_probe(struct platform_device *device)
        /* filter to remove HPQ6000 accelerometer data
         * from keyboard bus stream */
        if (strstr(dev_name(&device->dev), "HPQ6000"))
-               i8042_install_filter(hp_accel_i8042_filter);
+               i8042_install_filter(hp_accel_i8042_filter, NULL);
 
        INIT_WORK(&hpled_led.work, delayed_set_status_worker);
        ret = led_classdev_register(NULL, &hpled_led.led_classdev);
index e5391a37014d83be42155a615edbd791b69268f0..c4b150fa093fefb39a28be3b122233637e8ab478 100644 (file)
@@ -806,8 +806,8 @@ static void msi_send_touchpad_key(struct work_struct *ignored)
 }
 static DECLARE_DELAYED_WORK(msi_touchpad_dwork, msi_send_touchpad_key);
 
-static bool msi_laptop_i8042_filter(unsigned char data, unsigned char str,
-                               struct serio *port)
+static bool msi_laptop_i8042_filter(unsigned char data, unsigned char str, struct serio *port,
+                                   void *context)
 {
        static bool extended;
 
@@ -996,7 +996,7 @@ static int __init load_scm_model_init(struct platform_device *sdev)
        if (result)
                goto fail_input;
 
-       result = i8042_install_filter(msi_laptop_i8042_filter);
+       result = i8042_install_filter(msi_laptop_i8042_filter, NULL);
        if (result) {
                pr_err("Unable to install key filter\n");
                goto fail_filter;
index 22ca70eb822718eb2d870857d975b7b89ef9521f..2987b4db60096bbb85c14ce208c37680a08110d2 100644 (file)
@@ -260,7 +260,7 @@ struct pcc_acpi {
  * keypress events over the PS/2 kbd interface, filter these out.
  */
 static bool panasonic_i8042_filter(unsigned char data, unsigned char str,
-                                  struct serio *port)
+                                  struct serio *port, void *context)
 {
        static bool extended;
 
@@ -1100,7 +1100,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
                pcc->platform = NULL;
        }
 
-       i8042_install_filter(panasonic_i8042_filter);
+       i8042_install_filter(panasonic_i8042_filter, NULL);
        return 0;
 
 out_platform:
index 78a5aac2dcfd65b9afd8b477bc0e95ee7154c5c8..5ad3a7183d337568b3c49ad8fc9138e04639ec66 100644 (file)
@@ -2755,7 +2755,7 @@ static int toshiba_acpi_enable_hotkeys(struct toshiba_acpi_dev *dev)
 }
 
 static bool toshiba_acpi_i8042_filter(unsigned char data, unsigned char str,
-                                     struct serio *port)
+                                     struct serio *port, void *context)
 {
        if (str & I8042_STR_AUXDATA)
                return false;
@@ -2915,7 +2915,7 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
        if (ec_handle && acpi_has_method(ec_handle, "NTFY")) {
                INIT_WORK(&dev->hotkey_work, toshiba_acpi_hotkey_work);
 
-               error = i8042_install_filter(toshiba_acpi_i8042_filter);
+               error = i8042_install_filter(toshiba_acpi_i8042_filter, NULL);
                if (error) {
                        pr_err("Error installing key filter\n");
                        goto err_free_dev;
index 95b07f8b77fe547fd6d94fb4e380315d5e5de595..00037c13abc82b62ca9b48f67eb569a191a6a3a1 100644 (file)
 
 struct serio;
 
+/**
+ * typedef i8042_filter_t - i8042 filter callback
+ * @data: Data received by the i8042 controller
+ * @str: Status register of the i8042 controller
+ * @serio: Serio of the i8042 controller
+ * @context: Context pointer associated with this callback
+ *
+ * This represents a i8042 filter callback which can be used with i8042_install_filter()
+ * and i8042_remove_filter() to filter the i8042 input for platform-specific key codes.
+ *
+ * Context: Interrupt context.
+ * Returns: true if the data should be filtered out, false if otherwise.
+ */
+typedef bool (*i8042_filter_t)(unsigned char data, unsigned char str, struct serio *serio,
+                              void *context);
+
 #if defined(CONFIG_SERIO_I8042) || defined(CONFIG_SERIO_I8042_MODULE)
 
 void i8042_lock_chip(void);
 void i8042_unlock_chip(void);
 int i8042_command(unsigned char *param, int command);
-int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str,
-                                       struct serio *serio));
-int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str,
-                                      struct serio *serio));
+int i8042_install_filter(i8042_filter_t filter, void *context);
+int i8042_remove_filter(i8042_filter_t filter);
 
 #else
 
@@ -79,14 +93,12 @@ static inline int i8042_command(unsigned char *param, int command)
        return -ENODEV;
 }
 
-static inline int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str,
-                                       struct serio *serio))
+static inline int i8042_install_filter(i8042_filter_t filter, void *context)
 {
        return -ENODEV;
 }
 
-static inline int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str,
-                                      struct serio *serio))
+static inline int i8042_remove_filter(i8042_filter_t filter)
 {
        return -ENODEV;
 }