Unverified Commit cec8c359 authored by Armin Wolf's avatar Armin Wolf Committed by Ilpo Järvinen
Browse files

Input: i8042 - Add support for platform filter contexts



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: default avatarIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Acked-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: default avatarArmin Wolf <W_Armin@gmx.de>
Link: https://lore.kernel.org/r/20250113221314.435812-1-W_Armin@gmx.de


Signed-off-by: default avatarIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
parent 1e4e3dff
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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);
+10 −7
Original line number Diff line number Diff line
@@ -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;
	}
+2 −1
Original line number Diff line number Diff line
@@ -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;
+1 −1
Original line number Diff line number Diff line
@@ -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);
	}
+1 −2
Original line number Diff line number Diff line
@@ -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);
Loading