Skip to content

Commit 353bdd7

Browse files
Markus Burridtor
authored andcommitted
Input: matrix_keypad - detect change during scan
For a setup where the matrix keypad is connected over a slow interface (e.g. a gpio-expansion over i2c), the scan can take a longer time to read. Interrupts need to be disabled during scan. And therefore changes in this period are not detected. To improve this situation, scan the matrix again if the row state changed during interrupts disabled. The rescan is repeated until no change is detected anymore. Signed-off-by: Markus Burri <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Dmitry Torokhov <[email protected]>
1 parent a37af8e commit 353bdd7

File tree

1 file changed

+16
-0
lines changed

1 file changed

+16
-0
lines changed

drivers/input/keyboard/matrix_keypad.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@ static void matrix_keypad_scan(struct work_struct *work)
125125
const unsigned short *keycodes = input_dev->keycode;
126126
uint32_t new_state[MATRIX_MAX_COLS];
127127
int row, col, code;
128+
u32 init_row_state, new_row_state;
129+
130+
/* read initial row state to detect changes between scan */
131+
init_row_state = read_row_state(keypad);
128132

129133
/* de-activate all columns for scanning */
130134
activate_all_cols(keypad, false);
@@ -173,6 +177,18 @@ static void matrix_keypad_scan(struct work_struct *work)
173177
keypad->scan_pending = false;
174178
enable_row_irqs(keypad);
175179
}
180+
181+
/* read new row state and detect if value has changed */
182+
new_row_state = read_row_state(keypad);
183+
if (init_row_state != new_row_state) {
184+
guard(spinlock_irq)(&keypad->lock);
185+
if (unlikely(keypad->scan_pending || keypad->stopped))
186+
return;
187+
disable_row_irqs(keypad);
188+
keypad->scan_pending = true;
189+
schedule_delayed_work(&keypad->work,
190+
msecs_to_jiffies(keypad->debounce_ms));
191+
}
176192
}
177193

178194
static irqreturn_t matrix_keypad_interrupt(int irq, void *id)

0 commit comments

Comments
 (0)