Testing: split input test (#2762)

test(pointing): Add mock input device.

New mock input device to generate input events for tests.

test(split): Add peripheral input test.

Test event propagation from peripheral input devices.

fix(split): Proper scoping for local within switch.

Minor compile fix.

chore: Fix up test snapshots after logging changes.

Adjust the test snapshots after logging changes to the central.

fix(kscan): Don't fire last mock event twice.

Fix a bug where the kscan mock would raise the last mock event
twice before halting processing.
This commit is contained in:
Pete Johanson
2025-01-13 13:15:16 -07:00
committed by GitHub
parent 022603ec16
commit 8dddb1d9d7
25 changed files with 332 additions and 21 deletions

View File

@@ -5,3 +5,4 @@ add_subdirectory_ifdef(CONFIG_GPIO gpio)
add_subdirectory_ifdef(CONFIG_KSCAN kscan)
add_subdirectory_ifdef(CONFIG_SENSOR sensor)
add_subdirectory_ifdef(CONFIG_DISPLAY display)
add_subdirectory_ifdef(CONFIG_INPUT input)

View File

@@ -5,3 +5,4 @@ rsource "gpio/Kconfig"
rsource "kscan/Kconfig"
rsource "sensor/Kconfig"
rsource "display/Kconfig"
rsource "input/Kconfig"

View File

@@ -0,0 +1,6 @@
# Copyright (c) 2020-2023 The ZMK Contributors
# SPDX-License-Identifier: MIT
zephyr_library_amend()
zephyr_library_sources_ifdef(CONFIG_ZMK_INPUT_MOCK input_mock.c)

View File

@@ -0,0 +1,9 @@
if INPUT
config ZMK_INPUT_MOCK
bool "Input Mock"
default y
depends on DT_HAS_ZMK_INPUT_MOCK_ENABLED
endif

View File

@@ -0,0 +1,87 @@
/*
* Copyright (c) 2024 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#define DT_DRV_COMPAT zmk_input_mock
#include <stdlib.h>
#include <zephyr/device.h>
#include <zephyr/input/input.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
struct input_mock_config {
uint16_t startup_delay;
uint16_t event_period;
bool exit_after;
const uint32_t *events;
size_t events_len;
};
struct input_mock_data {
size_t event_index;
struct k_work_delayable work;
const struct device *dev;
};
static void input_mock_work_cb(struct k_work *work) {
struct k_work_delayable *dwork = CONTAINER_OF(work, struct k_work_delayable, work);
struct input_mock_data *data = CONTAINER_OF(dwork, struct input_mock_data, work);
const struct device *dev = data->dev;
const struct input_mock_config *cfg = dev->config;
data->event_index++;
size_t base_idx = data->event_index * 4;
if (base_idx >= cfg->events_len) {
if (cfg->exit_after) {
exit(0);
} else {
return;
}
}
input_report(dev, cfg->events[base_idx], cfg->events[base_idx + 1], cfg->events[base_idx + 2],
cfg->events[base_idx + 3], K_NO_WAIT);
k_work_schedule(&data->work, K_MSEC(cfg->event_period));
}
int input_mock_init(const struct device *dev) {
struct input_mock_data *drv_data = dev->data;
const struct input_mock_config *drv_cfg = dev->config;
drv_data->dev = dev;
drv_data->event_index = -1;
k_work_init_delayable(&drv_data->work, input_mock_work_cb);
k_work_schedule(&drv_data->work, K_MSEC(drv_cfg->startup_delay));
return 0;
}
#define GET_EVENT(n, inst) \
{}
#define INPUT_MOCK_INST(n) \
struct input_mock_data input_mock_data_##n = {}; \
const uint32_t mock_data_##n[] = DT_INST_PROP(n, events); \
const struct input_mock_config input_mock_cfg_##n = { \
.events = mock_data_##n, \
.events_len = DT_INST_PROP_LEN(n, events), \
.startup_delay = DT_INST_PROP(n, event_startup_delay), \
.event_period = DT_INST_PROP(n, event_period), \
.exit_after = DT_INST_PROP(n, exit_after), \
}; \
DEVICE_DT_INST_DEFINE(n, input_mock_init, NULL, &input_mock_data_##n, &input_mock_cfg_##n, \
POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, NULL);
DT_INST_FOREACH_STATUS_OKAY(INPUT_MOCK_INST)

View File

@@ -65,6 +65,12 @@ static int kscan_mock_configure(const struct device *dev, kscan_callback_t callb
struct k_work_delayable *d_work = k_work_delayable_from_work(work); \
struct kscan_mock_data *data = CONTAINER_OF(d_work, struct kscan_mock_data, work); \
const struct kscan_mock_config_##n *cfg = data->dev->config; \
if (data->event_index >= DT_INST_PROP_LEN(n, events)) { \
if (cfg->exit_after) \
exit(0); \
else \
return; \
} \
uint32_t ev = cfg->events[data->event_index]; \
LOG_DBG("ev %u row %d column %d state %d\n", ev, ZMK_MOCK_ROW(ev), ZMK_MOCK_COL(ev), \
ZMK_MOCK_IS_PRESS(ev)); \

View File

@@ -0,0 +1,21 @@
# Copyright (c) 2024 The ZMK Contributors
# SPDX-License-Identifier: MIT
description: |
Allows defining a mock input driver that simulates periodic input events.
compatible: "zmk,input-mock"
properties:
event-startup-delay:
type: int
default: 0
description: Milliseconds to delay before starting generating the events
event-period:
type: int
description: Milliseconds between each generated event
events:
type: array
description: List of tuples of (type, code, value, sync)
exit-after:
type: boolean