Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+18 -3
+18 -3
drivers/input/joystick/adafruit-seesaw.c
··· 56 56 #define SEESAW_GAMEPAD_POLL_MIN 8 57 57 #define SEESAW_GAMEPAD_POLL_MAX 32 58 58 59 - static const unsigned long SEESAW_BUTTON_MASK = 59 + static const u32 SEESAW_BUTTON_MASK = 60 60 BIT(SEESAW_BUTTON_A) | BIT(SEESAW_BUTTON_B) | BIT(SEESAW_BUTTON_X) | 61 61 BIT(SEESAW_BUTTON_Y) | BIT(SEESAW_BUTTON_START) | 62 62 BIT(SEESAW_BUTTON_SELECT); ··· 64 64 struct seesaw_gamepad { 65 65 struct input_dev *input_dev; 66 66 struct i2c_client *i2c_client; 67 + u32 button_state; 67 68 }; 68 69 69 70 struct seesaw_data { ··· 179 178 return 0; 180 179 } 181 180 181 + static int seesaw_open(struct input_dev *input) 182 + { 183 + struct seesaw_gamepad *private = input_get_drvdata(input); 184 + 185 + private->button_state = 0; 186 + 187 + return 0; 188 + } 189 + 182 190 static void seesaw_poll(struct input_dev *input) 183 191 { 184 192 struct seesaw_gamepad *private = input_get_drvdata(input); 185 193 struct seesaw_data data; 194 + unsigned long changed; 186 195 int err, i; 187 196 188 197 err = seesaw_read_data(private->i2c_client, &data); ··· 205 194 input_report_abs(input, ABS_X, data.x); 206 195 input_report_abs(input, ABS_Y, data.y); 207 196 208 - for_each_set_bit(i, &SEESAW_BUTTON_MASK, 209 - BITS_PER_TYPE(SEESAW_BUTTON_MASK)) { 197 + data.button_state &= SEESAW_BUTTON_MASK; 198 + changed = private->button_state ^ data.button_state; 199 + private->button_state = data.button_state; 200 + 201 + for_each_set_bit(i, &changed, fls(SEESAW_BUTTON_MASK)) { 210 202 if (!sparse_keymap_report_event(input, i, 211 203 data.button_state & BIT(i), 212 204 false)) ··· 267 253 seesaw->input_dev->id.bustype = BUS_I2C; 268 254 seesaw->input_dev->name = "Adafruit Seesaw Gamepad"; 269 255 seesaw->input_dev->phys = "i2c/" SEESAW_DEVICE_NAME; 256 + seesaw->input_dev->open = seesaw_open; 270 257 input_set_drvdata(seesaw->input_dev, seesaw); 271 258 input_set_abs_params(seesaw->input_dev, ABS_X, 272 259 0, SEESAW_JOYSTICK_MAX_AXIS,