lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <356b31ade897af77a06d6567601f038f56b3b2a2.1638538079.git.geert+renesas@glider.be>
Date:   Fri,  3 Dec 2021 14:35:08 +0100
From:   Geert Uytterhoeven <geert+renesas@...der.be>
To:     Dmitry Torokhov <dmitry.torokhov@...il.com>,
        Rob Herring <robh+dt@...nel.org>, Marc Zyngier <maz@...nel.org>
Cc:     linux-input@...r.kernel.org, devicetree@...r.kernel.org,
        linux-renesas-soc@...r.kernel.org, linux-kernel@...r.kernel.org,
        Geert Uytterhoeven <geert+renesas@...der.be>
Subject: [PATCH RFC 3/3] Input: gpio-keys - Fix ghost events with both-edge irqs

When using interrupts instead of GPIOs, the driver auto-generates
key-release events, either immediately or after a delay.  This works
fine with rising-edge or falling-edge interrupts, but causes ghost
events with both-edge interrupts.  Indeed, the driver will generate a
pair of key press/release events when pressing the key, and another pair
when releasing the key.

Fix this by not auto-generating key-release events for both-edge
interrupts.  Rename release_delay to auto_release_delay to clarify its
use.

Note that unlike with GPIOs, the driver cannot know the state of the key
at initialization time, or after resume.  Hence the driver assumes the
key is not pressed at initialization time, and does not reconfigure the
trigger type for wakeup.

Signed-off-by: Geert Uytterhoeven <geert+renesas@...der.be>
---
Tested on rskrza1.

Are these limitations acceptable? Or should users only use rising-edge
or falling-edge interrupts?
There are several existing users of IRQ_TYPE_EDGE_BOTH.
---
 drivers/input/keyboard/gpio_keys.c | 34 +++++++++++++++++++-----------
 1 file changed, 22 insertions(+), 12 deletions(-)

diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index ab077dfb90a76ac3..dfcbedec226cb4cf 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -38,7 +38,8 @@ struct gpio_button_data {
 	unsigned short *code;
 
 	struct hrtimer release_timer;
-	unsigned int release_delay;	/* in msecs, for IRQ-only buttons */
+	int auto_release_delay;	/* in msecs, for IRQ-only buttons */
+				/* a negative value means no auto-release */
 
 	struct delayed_work work;
 	struct hrtimer debounce_timer;
@@ -474,25 +475,25 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)
 
 	spin_lock_irqsave(&bdata->lock, flags);
 
-	if (!bdata->key_pressed) {
+	if (!bdata->key_pressed || bdata->auto_release_delay < 0) {
 		if (bdata->button->wakeup)
 			pm_wakeup_event(bdata->input->dev.parent, 0);
 
-		input_report_key(input, *bdata->code, 1);
+		input_report_key(input, *bdata->code, !bdata->key_pressed);
 		input_sync(input);
 
-		if (!bdata->release_delay) {
+		if (!bdata->auto_release_delay) {
 			input_report_key(input, *bdata->code, 0);
 			input_sync(input);
 			goto out;
 		}
 
-		bdata->key_pressed = true;
+		bdata->key_pressed = !bdata->key_pressed;
 	}
 
-	if (bdata->release_delay)
+	if (bdata->auto_release_delay > 0)
 		hrtimer_start(&bdata->release_timer,
-			      ms_to_ktime(bdata->release_delay),
+			      ms_to_ktime(bdata->auto_release_delay),
 			      HRTIMER_MODE_REL_HARD);
 out:
 	spin_unlock_irqrestore(&bdata->lock, flags);
@@ -630,7 +631,6 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
 			return -EINVAL;
 		}
 
-		bdata->release_delay = button->debounce_interval;
 		hrtimer_init(&bdata->release_timer,
 			     CLOCK_REALTIME, HRTIMER_MODE_REL_HARD);
 		bdata->release_timer.function = gpio_keys_irq_timer;
@@ -638,10 +638,20 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
 		isr = gpio_keys_irq_isr;
 		irqflags = 0;
 
-		/*
-		 * For IRQ buttons, there is no interrupt for release.
-		 * So we don't need to reconfigure the trigger type for wakeup.
-		 */
+		if (irq_get_trigger_type(bdata->irq) == IRQ_TYPE_EDGE_BOTH) {
+			bdata->auto_release_delay = -1;
+			/*
+			 * Unlike with GPIOs, we do not know what the state of
+			 * the key is at initialization time, or after resume.
+			 * So we don't reconfigure the trigger type for wakeup.
+			 */
+		} else {
+			bdata->auto_release_delay = button->debounce_interval;
+			/*
+			 * There is no interrupt for release.  So we don't
+			 * need to reconfigure the trigger type for wakeup.
+			 */
+		}
 	}
 
 	bdata->code = &ddata->keymap[idx];
-- 
2.25.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ