On Tue, Nov 05, 2024 at 02:03:22PM +0100, Markus Burri wrote:
> 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.
And what if the state changes yet again during the 2nd scan attempt?
>
> Signed-off-by: Markus Burri <markus.burri@mt.com>
> ---
> drivers/input/keyboard/matrix_keypad.c | 17 +++++++++++++++++
> 1 file changed, 17 insertions(+)
>
> diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c
> index 46873b8..93c8404 100644
> --- a/drivers/input/keyboard/matrix_keypad.c
> +++ b/drivers/input/keyboard/matrix_keypad.c
> @@ -126,6 +126,10 @@ static void matrix_keypad_scan(struct work_struct *work)
> const unsigned short *keycodes = input_dev->keycode;
> uint32_t new_state[MATRIX_MAX_COLS];
> int row, col, code;
> + u32 init_row_state, new_row_state;
> +
> + /* read initial row state to detect changes between scan */
> + init_row_state = read_row_state(keypad);
>
> /* de-activate all columns for scanning */
> activate_all_cols(keypad, false);
> @@ -174,6 +178,19 @@ static void matrix_keypad_scan(struct work_struct *work)
> keypad->scan_pending = false;
> enable_row_irqs(keypad);
> spin_unlock_irq(&keypad->lock);
> +
> + /* read new row state and detect if value has changed */
> + new_row_state = read_row_state(keypad);
> + if (init_row_state != new_row_state) {
> + spin_lock_irq(&keypad->lock);
> + if (likely(!keypad->scan_pending && !keypad->stopped)) {
> + disable_row_irqs(keypad);
> + keypad->scan_pending = true;
> + schedule_delayed_work(&keypad->work,
> + msecs_to_jiffies(keypad->debounce_ms));
> + }
> + spin_unlock_irq(&keypad->lock);
> + }
> }
>
> static irqreturn_t matrix_keypad_interrupt(int irq, void *id)
> --
> 2.39.5
>
--
Dmitry