Commit 4307882d authored by Fabio Baltieri's avatar Fabio Baltieri Committed by Fabio Baltieri
Browse files

input: kbd_matrix: add actual key mask runtime control



Add an option to enable a input_kbd_matrix_actual_key_mask_set API to
enable or disable keys dynamically in the mask. This can be useful if
the exact key mask is determined in runtime and the device is using a
single firmware for multiple matrix configurations.

Signed-off-by: default avatarFabio Baltieri <fabiobaltieri@google.com>
parent 250d50e8
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -27,6 +27,13 @@ config INPUT_KBD_MATRIX_16_BIT_ROW
	  Use a 16 bit type for the internal structure, allow using a matrix
	  with up to 16 rows if the driver supports it.

config INPUT_KBD_ACTUAL_KEY_MASK_DYNAMIC
	bool "Allow runtime changes to the actual key mask"
	help
	  If enabled, the actual key mask data is stored in RAM, and a
	  input_kbd_matrix_actual_key_mask_set() function is available to
	  change the content at runtime.

config INPUT_SHELL_KBD_MATRIX_STATE
	bool "Input kbd_matrix_state shell command"
	depends on INPUT_SHELL
+16 −0
Original line number Diff line number Diff line
@@ -323,3 +323,19 @@ int input_kbd_matrix_common_init(const struct device *dev)

	return 0;
}

#if CONFIG_INPUT_KBD_ACTUAL_KEY_MASK_DYNAMIC
int input_kbd_matrix_actual_key_mask_set(const struct device *dev,
					  uint8_t row, uint8_t col, bool enabled)
{
	const struct input_kbd_matrix_common_config *cfg = dev->config;

	if (row >= cfg->row_size || col >= cfg->col_size) {
		return -EINVAL;
	}

	WRITE_BIT(cfg->actual_key_mask[col], row, enabled);

	return 0;
}
#endif
+29 −3
Original line number Diff line number Diff line
@@ -38,6 +38,31 @@ typedef uint8_t kbd_row_t;
#define PRIkbdrow "%02x"
#endif

#if CONFIG_INPUT_KBD_ACTUAL_KEY_MASK_DYNAMIC
#define INPUT_KBD_ACTUAL_KEY_MASK_CONST
/**
 * @brief Enables or disables a specific row, column combination in the actual
 * key mask.
 *
 * This allows enabling or disabling spcific row, column combination in the
 * actual key mask in runtime. It can be useful if some of the keys are not
 * present in some configuration, and the specific configuration is determined
 * in runtime. Requires CONFIG_INPUT_KBD_ACTUAL_KEY_MASK_DYNAMIC=y.
 *
 * @param dev Pointer to the keyboard matrix device.
 * @param row The matrix row to enable or disable.
 * @param col The matrix column to enable or disable.
 * @param enabled Whether the specificied row, col has to be enabled or disabled.
 *
 * @retval 0 If the change is successful.
 * @retval -errno Negative errno if row or col are out of range for the device.
 */
int input_kbd_matrix_actual_key_mask_set(const struct device *dev,
					  uint8_t row, uint8_t col, bool enabled);
#else
#define INPUT_KBD_ACTUAL_KEY_MASK_CONST const
#endif

/** Maximum number of rows */
#define INPUT_KBD_MATRIX_ROW_BITS NUM_BITS(kbd_row_t)

@@ -90,7 +115,7 @@ struct input_kbd_matrix_common_config {
	uint32_t debounce_up_us;
	uint32_t settle_time_us;
	bool ghostkey_check;
	const kbd_row_t *actual_key_mask;
	INPUT_KBD_ACTUAL_KEY_MASK_CONST kbd_row_t *actual_key_mask;

	/* extra data pointers */
	kbd_row_t *matrix_stable_state;
@@ -114,7 +139,8 @@ struct input_kbd_matrix_common_config {
	IF_ENABLED(DT_NODE_HAS_PROP(node_id, actual_key_mask), ( \
	BUILD_ASSERT(DT_PROP_LEN(node_id, actual_key_mask) == _col_size, \
		     "actual-key-mask size does not match the number of columns"); \
	static const kbd_row_t INPUT_KBD_MATRIX_DATA_NAME(node_id, actual_key_mask)[_col_size] = \
	static INPUT_KBD_ACTUAL_KEY_MASK_CONST kbd_row_t \
		INPUT_KBD_MATRIX_DATA_NAME(node_id, actual_key_mask)[_col_size] = \
			DT_PROP(node_id, actual_key_mask); \
	)) \
	static kbd_row_t INPUT_KBD_MATRIX_DATA_NAME(node_id, stable_state)[_col_size]; \
+39 −0
Original line number Diff line number Diff line
@@ -374,6 +374,45 @@ ZTEST(kbd_scan, test_kbd_actual_keymap)
	kbd_scan_wait_for_idle();
	assert_no_new_events();
}

ZTEST(kbd_scan, test_kbd_actual_key_map_set)
{
#if CONFIG_INPUT_KBD_ACTUAL_KEY_MASK_DYNAMIC
	kbd_row_t mask[4] = {0x00, 0xff, 0x00, 0x00};
	const struct input_kbd_matrix_common_config cfg = {
		.row_size = 3,
		.col_size = 4,
		.actual_key_mask = mask,
	};
	const struct device fake_dev = {
		.config = &cfg,
	};
	int ret;

	ret = input_kbd_matrix_actual_key_mask_set(&fake_dev, 0, 0, true);
	zassert_equal(ret, 0);
	zassert_equal(mask[0], 0x01);

	ret = input_kbd_matrix_actual_key_mask_set(&fake_dev, 2, 1, false);
	zassert_equal(ret, 0);
	zassert_equal(mask[1], 0xfb);

	ret = input_kbd_matrix_actual_key_mask_set(&fake_dev, 2, 3, true);
	zassert_equal(ret, 0);
	zassert_equal(mask[3], 0x04);

	ret = input_kbd_matrix_actual_key_mask_set(&fake_dev, 3, 0, true);
	zassert_equal(ret, -EINVAL);

	ret = input_kbd_matrix_actual_key_mask_set(&fake_dev, 0, 4, true);
	zassert_equal(ret, -EINVAL);

	zassert_equal(memcmp(mask, (uint8_t[]){0x01, 0xfb, 0x00, 0x04}, 4), 0);
#else
	ztest_test_skip();
#endif
}

static void *kbd_scan_setup(void)
{
	const struct input_kbd_matrix_common_config *cfg = test_dev->config;
+4 −0
Original line number Diff line number Diff line
@@ -17,6 +17,10 @@ tests:
  input.input_kbd_matrix.actual_key_mask:
    extra_args:
      - EXTRA_DTC_OVERLAY_FILE=actual-key-mask.overlay
  input.input_kbd_matrix.actual_key_mask_dynamic:
    extra_args:
      - EXTRA_DTC_OVERLAY_FILE=actual-key-mask.overlay
      - CONFIG_INPUT_KBD_ACTUAL_KEY_MASK_DYNAMIC=y
  input.input_kbd_matrix.row_16_bit:
    extra_args:
      - CONFIG_INPUT_KBD_MATRIX_16_BIT_ROW=y