From 497049ff68a43bb52f0138952e1e403be78607f2 Mon Sep 17 00:00:00 2001
From: Pete Johanson <peter@peterjohanson.com>
Date: Tue, 7 Jul 2020 16:26:11 -0400
Subject: [PATCH] Detect additional key presses on the same output.

* Interrupts won't follow on additional keys
  pressed on an already "held" output pin,
  so queue additional reads while any keys are held.
---
 app/drivers/zephyr/kscan_gpio_matrix.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/app/drivers/zephyr/kscan_gpio_matrix.c b/app/drivers/zephyr/kscan_gpio_matrix.c
index 8b9d143f..4a1e0bb1 100644
--- a/app/drivers/zephyr/kscan_gpio_matrix.c
+++ b/app/drivers/zephyr/kscan_gpio_matrix.c
@@ -125,6 +125,7 @@ static int kscan_gpio_config_interrupts(struct device **devices,
 	}                                                                                                                                                                                                                                       \
 	static int kscan_gpio_read_##n(struct device *dev)                                                                                                                                                                                      \
 	{                                                                                                                                                                                                                                       \
+		bool submit_follow_up_read = false;                                                                                                                                                                                                   \
 		struct kscan_gpio_data_##n *data = dev->driver_data;                                                                                                                                                                                \
 		static bool read_state[INST_MATRIX_ROWS(n)][INST_MATRIX_COLS(n)];                                                                                                                                                                   \
 		LOG_DBG("Scanning the matrix for updated state");                                                                                                                                                                                   \
@@ -155,6 +156,8 @@ static int kscan_gpio_config_interrupts(struct device **devices,
 			for (int c = 0; c < INST_MATRIX_COLS(n); c++)                                                                                                                                                                                   \
 			{                                                                                                                                                                                                                               \
 				bool pressed = read_state[r][c];                                                                                                                                                                                            \
+				/* Follow up reads needed because further interrupts won't fire on already tripped input GPIO pins */                                                                                                                       \
+				submit_follow_up_read = (submit_follow_up_read || pressed);                                                                                                                                                                 \
 				if (pressed != data->matrix_state[r][c])                                                                                                                                                                                    \
 				{                                                                                                                                                                                                                           \
 					LOG_DBG("Sending event at %d,%d state %s",                                                                                                                                                                              \
@@ -164,6 +167,13 @@ static int kscan_gpio_config_interrupts(struct device **devices,
 				}                                                                                                                                                                                                                           \
 			}                                                                                                                                                                                                                               \
 		}                                                                                                                                                                                                                                   \
+		if (submit_follow_up_read) {                                                                                                                                                                                                        \
+			COND_CODE_0(DT_INST_PROP(n, debounce_period),                                                                                                                                                                                   \
+					({ k_work_submit(&data->work); }),                                                                                                                                                                                      \
+					({                                                                                                                                                                                                                      \
+						k_delayed_work_cancel(&data->work);                                                                                                                                                                                 \
+						k_delayed_work_submit(&data->work, K_MSEC(1)); }))                                                                                                                                                                  \
+		}                                                                                                                                                                                                                                   \
 		return 0;                                                                                                                                                                                                                           \
 	}                                                                                                                                                                                                                                       \
 	static void kscan_gpio_work_handler_##n(struct k_work *work)                                                                                                                                                                            \
@@ -179,9 +189,9 @@ static int kscan_gpio_config_interrupts(struct device **devices,
 			CONTAINER_OF(cb, struct kscan_gpio_irq_callback_##n, callback);                                                                                                                                                                 \
 		COND_CODE_0(DT_INST_PROP(n, debounce_period),                                                                                                                                                                                       \
 					({ k_work_submit(data->work); }),                                                                                                                                                                                       \
-					({                                                                                                                                                                                                                                                                                    \
-						k_delayed_work_cancel(data->work);                                                                                                                                                                                                                                               \
-						k_delayed_work_submit(data->work, K_MSEC(DT_INST_PROP(n, debounce_period))); }))                                                                                                                                                                                                                  \
+					({                                                                                                                                                                                                                      \
+						k_delayed_work_cancel(data->work);                                                                                                                                                                                  \
+						k_delayed_work_submit(data->work, K_MSEC(DT_INST_PROP(n, debounce_period))); }))                                                                                                                                    \
 	}                                                                                                                                                                                                                                       \
 	static struct kscan_gpio_data_##n kscan_gpio_data_##n = { \
 		.rows = { [INST_MATRIX_ROWS(n)-1] = NULL}, \