* [PATCH] Input: gpio-keys - add full support of EV_REL and EV_ABS
@ 2026-03-20 14:52 Xiong Nandi
2026-03-21 7:06 ` Dmitry Torokhov
0 siblings, 1 reply; 6+ messages in thread
From: Xiong Nandi @ 2026-03-20 14:52 UTC (permalink / raw)
To: dmitry.torokhov
Cc: linux-input, linux-kernel, Xiong Nandi, Gatien Chevallier,
Ingo Molnar, Thomas Gleixner, Marco Crivellari, Fabrice Gasnier
gpio_keys_gpio_report_event() handled EV_ABS but silently ignored EV_REL,
while the polled driver supports both. Extend the interrupt-driven driver
to fire an EV_REL event on button press.
For EV_ABS, use a shared atomic counter per (type, code) pair so that
a zero-value reset is sent only when the last active button on an axis
is released, avoiding premature axis resets when multiple buttons share
the same axis code.
Add gpio_keys_set_abs_params() to call input_set_abs_params() at setup
time, deriving the axis min/max from the configured button values.
Without this the input subsystem reports unbounded axis ranges.
Signed-off-by: Xiong Nandi <xndchn@gmail.com>
---
drivers/input/keyboard/gpio_keys.c | 65 +++++++++++++++++++++++++++++-
include/linux/gpio_keys.h | 4 +-
2 files changed, 65 insertions(+), 4 deletions(-)
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index e19617485679..652a6932c52f 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -51,8 +51,10 @@ struct gpio_button_data {
spinlock_t lock;
bool disabled;
bool key_pressed;
+ bool axis_active;
bool suspended;
bool debounce_use_hrtimer;
+ atomic_t *axis_count;
};
struct gpio_keys_drvdata {
@@ -373,9 +375,16 @@ static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata)
return;
}
- if (type == EV_ABS) {
- if (state)
+ if (type == EV_ABS || type == EV_REL) {
+ if (state && !bdata->axis_active) {
+ bdata->axis_active = true;
+ atomic_inc(bdata->axis_count);
input_event(input, type, button->code, button->value);
+ } else if (!state && bdata->axis_active) {
+ bdata->axis_active = false;
+ if (atomic_dec_and_test(bdata->axis_count))
+ input_event(input, type, button->code, 0);
+ }
} else {
input_event(input, type, *bdata->code, state);
}
@@ -493,6 +502,27 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static void gpio_keys_set_abs_params(struct input_dev *input,
+ struct gpio_keys_drvdata *ddata,
+ unsigned int code)
+{
+ int i, min = 0, max = 0;
+
+ for (i = 0; i < ddata->pdata->nbuttons; i++) {
+ const struct gpio_keys_button *button = &ddata->pdata->buttons[i];
+
+ if (button->type != EV_ABS || button->code != code)
+ continue;
+
+ if (button->value < min)
+ min = button->value;
+ if (button->value > max)
+ max = button->value;
+ }
+
+ input_set_abs_params(input, code, min, max, 0, 0);
+}
+
static int gpio_keys_setup_key(struct platform_device *pdev,
struct input_dev *input,
struct gpio_keys_drvdata *ddata,
@@ -651,6 +681,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
bdata->code = &ddata->keymap[idx];
*bdata->code = button->code;
input_set_capability(input, button->type ?: EV_KEY, *bdata->code);
+ if ((button->type ?: EV_KEY) == EV_ABS)
+ gpio_keys_set_abs_params(input, ddata, button->code);
/*
* Install custom action to cancel release timer and
@@ -928,6 +960,35 @@ static int gpio_keys_probe(struct platform_device *pdev)
fwnode_handle_put(child);
+ /* Allocate shared axis counters for EV_ABS/EV_REL buttons */
+ for (i = 0; i < pdata->nbuttons; i++) {
+ struct gpio_button_data *bdata = &ddata->data[i];
+ unsigned int type = bdata->button->type ?: EV_KEY;
+ int j;
+
+ if (type != EV_ABS && type != EV_REL)
+ continue;
+
+ /* Reuse counter from an earlier button with same (type, code) */
+ for (j = 0; j < i; j++) {
+ struct gpio_button_data *prev = &ddata->data[j];
+ unsigned int prev_type = prev->button->type ?: EV_KEY;
+
+ if (prev_type == type &&
+ prev->button->code == bdata->button->code) {
+ bdata->axis_count = prev->axis_count;
+ break;
+ }
+ }
+
+ if (!bdata->axis_count) {
+ bdata->axis_count = devm_kzalloc(dev,
+ sizeof(*bdata->axis_count), GFP_KERNEL);
+ if (!bdata->axis_count)
+ return -ENOMEM;
+ }
+ }
+
error = input_register_device(input);
if (error) {
dev_err(dev, "Unable to register input device, error: %d\n",
diff --git a/include/linux/gpio_keys.h b/include/linux/gpio_keys.h
index 80fa930b04c6..75a745a32fe1 100644
--- a/include/linux/gpio_keys.h
+++ b/include/linux/gpio_keys.h
@@ -13,13 +13,13 @@ struct device;
* @active_low: %true indicates that button is considered
* depressed when gpio is low
* @desc: label that will be attached to button's gpio
- * @type: input event type (%EV_KEY, %EV_SW, %EV_ABS)
+ * @type: input event type (%EV_KEY, %EV_SW, %EV_ABS, %EV_REL)
* @wakeup: configure the button as a wake-up source
* @wakeup_event_action: event action to trigger wakeup
* @debounce_interval: debounce ticks interval in msecs
* @can_disable: %true indicates that userspace is allowed to
* disable button via sysfs
- * @value: axis value for %EV_ABS
+ * @value: axis value for %EV_ABS/%EV_REL
* @irq: Irq number in case of interrupt keys
* @wakeirq: Optional dedicated wake-up interrupt
*/
--
2.25.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [PATCH] Input: gpio-keys - add full support of EV_REL and EV_ABS
2026-03-20 14:52 [PATCH] Input: gpio-keys - add full support of EV_REL and EV_ABS Xiong Nandi
@ 2026-03-21 7:06 ` Dmitry Torokhov
2026-03-22 11:35 ` [PATCH v2 0/3] " Xiong Nandi
` (3 more replies)
0 siblings, 4 replies; 6+ messages in thread
From: Dmitry Torokhov @ 2026-03-21 7:06 UTC (permalink / raw)
To: Xiong Nandi
Cc: linux-input, linux-kernel, Gatien Chevallier, Ingo Molnar,
Thomas Gleixner, Marco Crivellari, Fabrice Gasnier
Hi Xiong,
On Fri, Mar 20, 2026 at 10:52:14PM +0800, Xiong Nandi wrote:
> gpio_keys_gpio_report_event() handled EV_ABS but silently ignored EV_REL,
> while the polled driver supports both. Extend the interrupt-driven driver
> to fire an EV_REL event on button press.
>
> For EV_ABS, use a shared atomic counter per (type, code) pair so that
> a zero-value reset is sent only when the last active button on an axis
> is released, avoiding premature axis resets when multiple buttons share
> the same axis code.
>
> Add gpio_keys_set_abs_params() to call input_set_abs_params() at setup
> time, deriving the axis min/max from the configured button values.
> Without this the input subsystem reports unbounded axis ranges.
Could you please split this out? It looks like there are 2 or 3
logically separate changes.
Thanks.
--
Dmitry
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH v2 0/3] Input: gpio-keys - add full support of EV_REL and EV_ABS
2026-03-21 7:06 ` Dmitry Torokhov
@ 2026-03-22 11:35 ` Xiong Nandi
2026-03-22 11:35 ` [PATCH v2 1/3] Input: gpio-keys - set EV_ABS axis parameters at setup time Xiong Nandi
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Xiong Nandi @ 2026-03-22 11:35 UTC (permalink / raw)
To: dmitry.torokhov
Cc: linux-input, linux-kernel, Xiong Nandi, Fabrice Gasnier,
Gatien Chevallier, Ingo Molnar, Marco Crivellari, Thomas Gleixner
This series add full support of EV_REL and EV_ABS
v2: Split into 3 patches as requested. (In reply to ab5CXO6Fk7lhGazv@google.com)
Xiong Nandi (3):
Input: gpio-keys - set EV_ABS axis parameters at setup time
Input: gpio-keys - use shared axis counter for EV_ABS events
Input: gpio-keys - add EV_REL event type support
drivers/input/keyboard/gpio_keys.c | 65 +++++++++++++++++++++++++++++-
include/linux/gpio_keys.h | 4 +-
2 files changed, 65 insertions(+), 4 deletions(-)
--
2.25.1
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH v2 1/3] Input: gpio-keys - set EV_ABS axis parameters at setup time
2026-03-21 7:06 ` Dmitry Torokhov
2026-03-22 11:35 ` [PATCH v2 0/3] " Xiong Nandi
@ 2026-03-22 11:35 ` Xiong Nandi
2026-03-22 11:35 ` [PATCH v2 2/3] Input: gpio-keys - use shared axis counter for EV_ABS events Xiong Nandi
2026-03-22 11:35 ` [PATCH v2 3/3] Input: gpio-keys - add EV_REL event type support Xiong Nandi
3 siblings, 0 replies; 6+ messages in thread
From: Xiong Nandi @ 2026-03-22 11:35 UTC (permalink / raw)
To: dmitry.torokhov
Cc: linux-input, linux-kernel, Xiong Nandi, Gatien Chevallier,
Marco Crivellari, Thomas Gleixner, Fabrice Gasnier
The driver calls input_set_capability() for EV_ABS axes but never
sets the actual axis parameters, so the input subsystem sees
unbounded ranges.
Add a helper that scans buttons sharing the same axis code, works
out the min/max values, and calls input_set_abs_params().
Signed-off-by: Xiong Nandi <xndchn@gmail.com>
---
drivers/input/keyboard/gpio_keys.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index e19617485679..f97ca8dd073a 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -493,6 +493,27 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static void gpio_keys_set_abs_params(struct input_dev *input,
+ struct gpio_keys_drvdata *ddata,
+ unsigned int code)
+{
+ int i, min = 0, max = 0;
+
+ for (i = 0; i < ddata->pdata->nbuttons; i++) {
+ const struct gpio_keys_button *button = &ddata->pdata->buttons[i];
+
+ if (button->type != EV_ABS || button->code != code)
+ continue;
+
+ if (button->value < min)
+ min = button->value;
+ if (button->value > max)
+ max = button->value;
+ }
+
+ input_set_abs_params(input, code, min, max, 0, 0);
+}
+
static int gpio_keys_setup_key(struct platform_device *pdev,
struct input_dev *input,
struct gpio_keys_drvdata *ddata,
@@ -651,6 +672,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
bdata->code = &ddata->keymap[idx];
*bdata->code = button->code;
input_set_capability(input, button->type ?: EV_KEY, *bdata->code);
+ if ((button->type ?: EV_KEY) == EV_ABS)
+ gpio_keys_set_abs_params(input, ddata, button->code);
/*
* Install custom action to cancel release timer and
--
2.25.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v2 2/3] Input: gpio-keys - use shared axis counter for EV_ABS events
2026-03-21 7:06 ` Dmitry Torokhov
2026-03-22 11:35 ` [PATCH v2 0/3] " Xiong Nandi
2026-03-22 11:35 ` [PATCH v2 1/3] Input: gpio-keys - set EV_ABS axis parameters at setup time Xiong Nandi
@ 2026-03-22 11:35 ` Xiong Nandi
2026-03-22 11:35 ` [PATCH v2 3/3] Input: gpio-keys - add EV_REL event type support Xiong Nandi
3 siblings, 0 replies; 6+ messages in thread
From: Xiong Nandi @ 2026-03-22 11:35 UTC (permalink / raw)
To: dmitry.torokhov
Cc: linux-input, linux-kernel, Xiong Nandi, Gatien Chevallier,
Marco Crivellari, Ingo Molnar, Fabrice Gasnier, Thomas Gleixner
When two buttons share an EV_ABS axis code, releasing one button
zeroes the axis while the other is still held.
Add a shared atomic counter per (type, code) pair so the axis only
resets to zero when the last button on it is released.
Signed-off-by: Xiong Nandi <xndchn@gmail.com>
---
drivers/input/keyboard/gpio_keys.c | 40 +++++++++++++++++++++++++++++-
1 file changed, 39 insertions(+), 1 deletion(-)
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index f97ca8dd073a..4cbfd5a273bd 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -51,8 +51,10 @@ struct gpio_button_data {
spinlock_t lock;
bool disabled;
bool key_pressed;
+ bool axis_active;
bool suspended;
bool debounce_use_hrtimer;
+ atomic_t *axis_count;
};
struct gpio_keys_drvdata {
@@ -374,8 +376,15 @@ static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata)
}
if (type == EV_ABS) {
- if (state)
+ if (state && !bdata->axis_active) {
+ bdata->axis_active = true;
+ atomic_inc(bdata->axis_count);
input_event(input, type, button->code, button->value);
+ } else if (!state && bdata->axis_active) {
+ bdata->axis_active = false;
+ if (atomic_dec_and_test(bdata->axis_count))
+ input_event(input, type, button->code, 0);
+ }
} else {
input_event(input, type, *bdata->code, state);
}
@@ -951,6 +960,35 @@ static int gpio_keys_probe(struct platform_device *pdev)
fwnode_handle_put(child);
+ /* Allocate shared axis counters for EV_ABS buttons */
+ for (i = 0; i < pdata->nbuttons; i++) {
+ struct gpio_button_data *bdata = &ddata->data[i];
+ unsigned int type = bdata->button->type ?: EV_KEY;
+ int j;
+
+ if (type != EV_ABS)
+ continue;
+
+ /* Reuse counter from an earlier button with same (type, code) */
+ for (j = 0; j < i; j++) {
+ struct gpio_button_data *prev = &ddata->data[j];
+ unsigned int prev_type = prev->button->type ?: EV_KEY;
+
+ if (prev_type == type &&
+ prev->button->code == bdata->button->code) {
+ bdata->axis_count = prev->axis_count;
+ break;
+ }
+ }
+
+ if (!bdata->axis_count) {
+ bdata->axis_count = devm_kzalloc(dev,
+ sizeof(*bdata->axis_count), GFP_KERNEL);
+ if (!bdata->axis_count)
+ return -ENOMEM;
+ }
+ }
+
error = input_register_device(input);
if (error) {
dev_err(dev, "Unable to register input device, error: %d\n",
--
2.25.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v2 3/3] Input: gpio-keys - add EV_REL event type support
2026-03-21 7:06 ` Dmitry Torokhov
` (2 preceding siblings ...)
2026-03-22 11:35 ` [PATCH v2 2/3] Input: gpio-keys - use shared axis counter for EV_ABS events Xiong Nandi
@ 2026-03-22 11:35 ` Xiong Nandi
3 siblings, 0 replies; 6+ messages in thread
From: Xiong Nandi @ 2026-03-22 11:35 UTC (permalink / raw)
To: dmitry.torokhov
Cc: linux-input, linux-kernel, Xiong Nandi, Gatien Chevallier,
Thomas Gleixner, Fabrice Gasnier, Marco Crivellari
The polled path handles EV_REL but the interrupt path silently
ignores it. Widen the type check so EV_REL goes through the same
reporting and shared-counter logic as EV_ABS.
Signed-off-by: Xiong Nandi <xndchn@gmail.com>
---
drivers/input/keyboard/gpio_keys.c | 6 +++---
include/linux/gpio_keys.h | 4 ++--
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index 4cbfd5a273bd..652a6932c52f 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -375,7 +375,7 @@ static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata)
return;
}
- if (type == EV_ABS) {
+ if (type == EV_ABS || type == EV_REL) {
if (state && !bdata->axis_active) {
bdata->axis_active = true;
atomic_inc(bdata->axis_count);
@@ -960,13 +960,13 @@ static int gpio_keys_probe(struct platform_device *pdev)
fwnode_handle_put(child);
- /* Allocate shared axis counters for EV_ABS buttons */
+ /* Allocate shared axis counters for EV_ABS/EV_REL buttons */
for (i = 0; i < pdata->nbuttons; i++) {
struct gpio_button_data *bdata = &ddata->data[i];
unsigned int type = bdata->button->type ?: EV_KEY;
int j;
- if (type != EV_ABS)
+ if (type != EV_ABS && type != EV_REL)
continue;
/* Reuse counter from an earlier button with same (type, code) */
diff --git a/include/linux/gpio_keys.h b/include/linux/gpio_keys.h
index 80fa930b04c6..75a745a32fe1 100644
--- a/include/linux/gpio_keys.h
+++ b/include/linux/gpio_keys.h
@@ -13,13 +13,13 @@ struct device;
* @active_low: %true indicates that button is considered
* depressed when gpio is low
* @desc: label that will be attached to button's gpio
- * @type: input event type (%EV_KEY, %EV_SW, %EV_ABS)
+ * @type: input event type (%EV_KEY, %EV_SW, %EV_ABS, %EV_REL)
* @wakeup: configure the button as a wake-up source
* @wakeup_event_action: event action to trigger wakeup
* @debounce_interval: debounce ticks interval in msecs
* @can_disable: %true indicates that userspace is allowed to
* disable button via sysfs
- * @value: axis value for %EV_ABS
+ * @value: axis value for %EV_ABS/%EV_REL
* @irq: Irq number in case of interrupt keys
* @wakeirq: Optional dedicated wake-up interrupt
*/
--
2.25.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-03-22 11:36 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-20 14:52 [PATCH] Input: gpio-keys - add full support of EV_REL and EV_ABS Xiong Nandi
2026-03-21 7:06 ` Dmitry Torokhov
2026-03-22 11:35 ` [PATCH v2 0/3] " Xiong Nandi
2026-03-22 11:35 ` [PATCH v2 1/3] Input: gpio-keys - set EV_ABS axis parameters at setup time Xiong Nandi
2026-03-22 11:35 ` [PATCH v2 2/3] Input: gpio-keys - use shared axis counter for EV_ABS events Xiong Nandi
2026-03-22 11:35 ` [PATCH v2 3/3] Input: gpio-keys - add EV_REL event type support Xiong Nandi
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.