aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2024-01-10 23:13:01 -0800
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2024-03-28 13:37:55 -0700
commit8984e0b569236c8581901efce2f1f4d03cd3dec1 (patch)
tree92c5239ce068427757789e40db22ef69d569efca
parentd40e9edcf3eb925c259df9f9dd7319a4fcbc675b (diff)
downloadinput-8984e0b569236c8581901efce2f1f4d03cd3dec1.tar.gz
Input: adafruit-seesaw - only report buttons that changed state
If a button has not changed its state when we poll the device the driver does not need to report it. While duplicate events will be filtered out by the input core anyway we can do it very cheaply directly in the driver. Link: https://lore.kernel.org/r/ZZ-U_bmZpIdoYA6c@google.com Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
-rw-r--r--drivers/input/joystick/adafruit-seesaw.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/drivers/input/joystick/adafruit-seesaw.c b/drivers/input/joystick/adafruit-seesaw.c
index 1b9279f024cc6f..5c775ca886a581 100644
--- a/drivers/input/joystick/adafruit-seesaw.c
+++ b/drivers/input/joystick/adafruit-seesaw.c
@@ -56,7 +56,7 @@
#define SEESAW_GAMEPAD_POLL_MIN 8
#define SEESAW_GAMEPAD_POLL_MAX 32
-static const unsigned long SEESAW_BUTTON_MASK =
+static const u32 SEESAW_BUTTON_MASK =
BIT(SEESAW_BUTTON_A) | BIT(SEESAW_BUTTON_B) | BIT(SEESAW_BUTTON_X) |
BIT(SEESAW_BUTTON_Y) | BIT(SEESAW_BUTTON_START) |
BIT(SEESAW_BUTTON_SELECT);
@@ -64,6 +64,7 @@ static const unsigned long SEESAW_BUTTON_MASK =
struct seesaw_gamepad {
struct input_dev *input_dev;
struct i2c_client *i2c_client;
+ u32 button_state;
};
struct seesaw_data {
@@ -178,10 +179,20 @@ static int seesaw_read_data(struct i2c_client *client, struct seesaw_data *data)
return 0;
}
+static int seesaw_open(struct input_dev *input)
+{
+ struct seesaw_gamepad *private = input_get_drvdata(input);
+
+ private->button_state = 0;
+
+ return 0;
+}
+
static void seesaw_poll(struct input_dev *input)
{
struct seesaw_gamepad *private = input_get_drvdata(input);
struct seesaw_data data;
+ unsigned long changed;
int err, i;
err = seesaw_read_data(private->i2c_client, &data);
@@ -194,8 +205,11 @@ static void seesaw_poll(struct input_dev *input)
input_report_abs(input, ABS_X, data.x);
input_report_abs(input, ABS_Y, data.y);
- for_each_set_bit(i, &SEESAW_BUTTON_MASK,
- BITS_PER_TYPE(SEESAW_BUTTON_MASK)) {
+ data.button_state &= SEESAW_BUTTON_MASK;
+ changed = private->button_state ^ data.button_state;
+ private->button_state = data.button_state;
+
+ for_each_set_bit(i, &changed, fls(SEESAW_BUTTON_MASK)) {
if (!sparse_keymap_report_event(input, i,
data.button_state & BIT(i),
false))
@@ -253,6 +267,7 @@ static int seesaw_probe(struct i2c_client *client)
seesaw->input_dev->id.bustype = BUS_I2C;
seesaw->input_dev->name = "Adafruit Seesaw Gamepad";
seesaw->input_dev->phys = "i2c/" SEESAW_DEVICE_NAME;
+ seesaw->input_dev->open = seesaw_open;
input_set_drvdata(seesaw->input_dev, seesaw);
input_set_abs_params(seesaw->input_dev, ABS_X,
0, SEESAW_JOYSTICK_MAX_AXIS,