1 /*
2  * Copyright 2023 Google LLC
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/device.h>
8 #include <zephyr/input/input.h>
9 #include <zephyr/input/input_kbd_matrix.h>
10 #include <zephyr/kernel.h>
11 #include <zephyr/sys/util.h>
12 #include <zephyr/ztest.h>
13 
14 #define TEST_KBD_SCAN_NODE DT_INST(0, test_kbd_scan)
15 
16 /* test driver */
17 
18 /* Mock data for every valid column. */
19 static struct {
20 	kbd_row_t rows[3];
21 	int col;
22 	bool detect_mode;
23 } state;
24 
test_drive_column(const struct device * dev,int col)25 static void test_drive_column(const struct device *dev, int col)
26 {
27 	state.col = col;
28 }
29 
test_read_row(const struct device * dev)30 static kbd_row_t test_read_row(const struct device *dev)
31 {
32 	if (state.col == INPUT_KBD_MATRIX_COLUMN_DRIVE_NONE ||
33 	    state.col == INPUT_KBD_MATRIX_COLUMN_DRIVE_ALL) {
34 		return 0;
35 	}
36 
37 	return state.rows[state.col];
38 }
39 
test_set_detect_mode(const struct device * dev,bool enabled)40 static void test_set_detect_mode(const struct device *dev, bool enabled)
41 {
42 	TC_PRINT("detect mode: enabled=%d\n", enabled);
43 	state.detect_mode = enabled;
44 }
45 
46 static const struct input_kbd_matrix_api test_api = {
47 	.drive_column = test_drive_column,
48 	.read_row = test_read_row,
49 	.set_detect_mode = test_set_detect_mode,
50 };
51 
52 INPUT_KBD_MATRIX_DT_DEFINE(TEST_KBD_SCAN_NODE);
53 
54 static const struct input_kbd_matrix_common_config
55 	test_cfg = INPUT_KBD_MATRIX_DT_COMMON_CONFIG_INIT(
56 			TEST_KBD_SCAN_NODE, &test_api);
57 
58 static struct input_kbd_matrix_common_data test_data;
59 
60 DEVICE_DT_DEFINE(TEST_KBD_SCAN_NODE, input_kbd_matrix_common_init, NULL,
61 		 &test_data, &test_cfg,
62 		 POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, NULL);
63 
64 static const struct device *const test_dev = DEVICE_DT_GET(TEST_KBD_SCAN_NODE);
65 
66 /* The test only supports a 3 column matrix */
67 BUILD_ASSERT(DT_PROP(TEST_KBD_SCAN_NODE, col_size) == 3);
68 
69 /* support stuff */
70 
71 static const struct device *column_hook_last_dev;
72 static int column_hook_last_col;
73 
input_kbd_matrix_drive_column_hook(const struct device * dev,int col)74 void input_kbd_matrix_drive_column_hook(const struct device *dev, int col)
75 {
76 	column_hook_last_dev = dev;
77 	column_hook_last_col = col;
78 }
79 
state_set_rows_by_column(kbd_row_t c0,kbd_row_t c1,kbd_row_t c2)80 static void state_set_rows_by_column(kbd_row_t c0, kbd_row_t c1, kbd_row_t c2)
81 {
82 	memcpy(&state.rows, (kbd_row_t[]){c0, c1, c2}, sizeof(state.rows));
83 	TC_PRINT("set state [%" PRIkbdrow " %" PRIkbdrow " %" PRIkbdrow "]\n", c0, c1, c2);
84 }
85 
86 static struct {
87 	int row;
88 	int col;
89 	int val;
90 	int event_count;
91 } test_event_data;
92 
93 static int last_checked_event_count;
94 
95 #define assert_no_new_events() \
96 	zassert_equal(last_checked_event_count, test_event_data.event_count);
97 
98 #define  assert_new_event(_row, _col, _val) { \
99 	last_checked_event_count++; \
100 	zassert_equal(last_checked_event_count, test_event_data.event_count); \
101 	zassert_equal(_row, test_event_data.row); \
102 	zassert_equal(_col, test_event_data.col); \
103 	zassert_equal(_val, test_event_data.val); \
104 }
105 
test_cb(struct input_event * evt,void * user_data)106 static void test_cb(struct input_event *evt, void *user_data)
107 {
108 	static int row, col, val;
109 
110 	switch (evt->code) {
111 	case INPUT_ABS_X:
112 		col = evt->value;
113 		break;
114 	case INPUT_ABS_Y:
115 		row = evt->value;
116 		break;
117 	case INPUT_BTN_TOUCH:
118 		val = evt->value;
119 		break;
120 	}
121 
122 	if (evt->sync) {
123 		test_event_data.row = row;
124 		test_event_data.col = col;
125 		test_event_data.val = val;
126 		test_event_data.event_count++;
127 		TC_PRINT("input event: count=%d row=%d col=%d val=%d\n",
128 			 test_event_data.event_count, row, col, val);
129 	}
130 }
131 INPUT_CALLBACK_DEFINE(test_dev, test_cb, NULL);
132 
133 #define WAIT_FOR_IDLE_TIMEOUT_US (5 * USEC_PER_SEC)
134 
kbd_scan_wait_for_idle(void)135 static void kbd_scan_wait_for_idle(void)
136 {
137 	bool to;
138 
139 	to = WAIT_FOR(state.detect_mode,
140 		      WAIT_FOR_IDLE_TIMEOUT_US,
141 		      k_sleep(K_MSEC(100)));
142 
143 	zassert_true(to, "timeout waiting for idle state");
144 }
145 
146 /* actual tests */
147 
148 /* no event before debounce time, event after */
ZTEST(kbd_scan,test_kbd_scan)149 ZTEST(kbd_scan, test_kbd_scan)
150 {
151 	const struct input_kbd_matrix_common_config *cfg = test_dev->config;
152 
153 	input_kbd_matrix_poll_start(test_dev);
154 
155 	state_set_rows_by_column(0x00, BIT(2), 0x00);
156 	k_sleep(K_USEC(cfg->debounce_down_us / 2));
157 	assert_no_new_events();
158 
159 	k_sleep(K_USEC(cfg->debounce_down_us));
160 	assert_new_event(2, 1, 1);
161 
162 	state_set_rows_by_column(0x00, 0x00, 0x00);
163 	k_sleep(K_USEC(cfg->debounce_up_us / 2));
164 	assert_no_new_events();
165 
166 	k_sleep(K_USEC(cfg->debounce_up_us));
167 	assert_new_event(2, 1, 0);
168 
169 	kbd_scan_wait_for_idle();
170 	assert_no_new_events();
171 
172 	zassert_equal(column_hook_last_dev, test_dev);
173 	zassert_equal(column_hook_last_col, INPUT_KBD_MATRIX_COLUMN_DRIVE_ALL);
174 }
175 
176 /* no event for short glitches */
ZTEST(kbd_scan,test_kbd_scan_glitch)177 ZTEST(kbd_scan, test_kbd_scan_glitch)
178 {
179 	const struct input_kbd_matrix_common_config *cfg = test_dev->config;
180 
181 	input_kbd_matrix_poll_start(test_dev);
182 
183 	state_set_rows_by_column(0x00, BIT(2), 0x00);
184 	k_sleep(K_USEC(cfg->debounce_down_us / 2));
185 	assert_no_new_events();
186 
187 	state_set_rows_by_column(0x00, 0x00, 0x00);
188 	k_sleep(K_USEC(cfg->debounce_down_us));
189 	assert_no_new_events();
190 
191 	kbd_scan_wait_for_idle();
192 	assert_no_new_events();
193 }
194 
195 /* very bouncy key delays events indefinitely */
ZTEST(kbd_scan,test_kbd_long_debounce)196 ZTEST(kbd_scan, test_kbd_long_debounce)
197 {
198 	const struct input_kbd_matrix_common_config *cfg = test_dev->config;
199 
200 	input_kbd_matrix_poll_start(test_dev);
201 
202 	state_set_rows_by_column(0x00, BIT(2), 0x00);
203 	k_sleep(K_USEC(cfg->debounce_down_us / 2));
204 	assert_no_new_events();
205 
206 	for (int i = 0; i < 10; i++) {
207 		state_set_rows_by_column(0x00, 0x00, 0x00);
208 		k_sleep(K_USEC(cfg->debounce_down_us / 2));
209 		assert_no_new_events();
210 
211 		state_set_rows_by_column(0x00, BIT(2), 0x00);
212 		k_sleep(K_USEC(cfg->debounce_down_us / 2));
213 		assert_no_new_events();
214 	}
215 
216 	k_sleep(K_USEC(cfg->debounce_down_us));
217 	assert_new_event(2, 1, 1);
218 
219 	state_set_rows_by_column(0x00, 0x00, 0x00);
220 	k_sleep(K_USEC(cfg->debounce_up_us / 2));
221 	assert_no_new_events();
222 
223 	for (int i = 0; i < 10; i++) {
224 		state_set_rows_by_column(0x00, BIT(2), 0x00);
225 		k_sleep(K_USEC(cfg->debounce_up_us / 2));
226 		assert_no_new_events();
227 
228 		state_set_rows_by_column(0x00, 0x00, 0x00);
229 		k_sleep(K_USEC(cfg->debounce_up_us / 2));
230 		assert_no_new_events();
231 	}
232 
233 	k_sleep(K_USEC(cfg->debounce_up_us));
234 	assert_new_event(2, 1, 0);
235 
236 	kbd_scan_wait_for_idle();
237 	assert_no_new_events();
238 }
239 
240 /* ghosting keys should not produce any event */
ZTEST(kbd_scan,test_kbd_ghosting_check)241 ZTEST(kbd_scan, test_kbd_ghosting_check)
242 {
243 	const struct input_kbd_matrix_common_config *cfg = test_dev->config;
244 
245 	if (cfg->ghostkey_check == false) {
246 		ztest_test_skip();
247 		return;
248 	}
249 
250 	input_kbd_matrix_poll_start(test_dev);
251 
252 	state_set_rows_by_column(BIT(0), 0x00, 0x00);
253 	k_sleep(K_USEC(cfg->debounce_down_us * 1.5));
254 	assert_new_event(0, 0, 1);
255 
256 	state_set_rows_by_column(BIT(0), BIT(1), 0x00);
257 	k_sleep(K_USEC(cfg->debounce_down_us * 1.5));
258 	assert_new_event(1, 1, 1);
259 
260 	/* ghosting */
261 	state_set_rows_by_column(BIT(0) | BIT(1), BIT(0) | BIT(1), 0x00);
262 	k_sleep(K_USEC(cfg->debounce_down_us * 10));
263 	assert_no_new_events();
264 
265 	/* back to not ghosting anymore */
266 	state_set_rows_by_column(BIT(0), BIT(1), 0x00);
267 	k_sleep(K_USEC(cfg->debounce_down_us * 10));
268 	assert_no_new_events();
269 
270 	state_set_rows_by_column(0x00, BIT(1), 0x00);
271 	k_sleep(K_USEC(cfg->debounce_up_us * 1.5));
272 	assert_new_event(0, 0, 0);
273 
274 	state_set_rows_by_column(0x00, 0x00, 0x00);
275 	k_sleep(K_USEC(cfg->debounce_up_us * 1.5));
276 	assert_new_event(1, 1, 0);
277 
278 	kbd_scan_wait_for_idle();
279 	assert_no_new_events();
280 }
281 
282 /* ghosting keys can be disabled */
ZTEST(kbd_scan,test_kbd_no_ghosting_check)283 ZTEST(kbd_scan, test_kbd_no_ghosting_check)
284 {
285 	const struct input_kbd_matrix_common_config *cfg = test_dev->config;
286 
287 	if (cfg->ghostkey_check == true) {
288 		ztest_test_skip();
289 		return;
290 	}
291 
292 	input_kbd_matrix_poll_start(test_dev);
293 
294 	state_set_rows_by_column(BIT(0), 0x00, 0x00);
295 	k_sleep(K_USEC(cfg->debounce_down_us * 1.5));
296 	assert_new_event(0, 0, 1);
297 
298 	state_set_rows_by_column(BIT(0), BIT(1), 0x00);
299 	k_sleep(K_USEC(cfg->debounce_down_us * 1.5));
300 	assert_new_event(1, 1, 1);
301 
302 	state_set_rows_by_column(BIT(0) | BIT(1), BIT(1), 0x00);
303 	k_sleep(K_USEC(cfg->debounce_down_us * 1.5));
304 	assert_new_event(1, 0, 1);
305 
306 	state_set_rows_by_column(BIT(0) | BIT(1), BIT(0) | BIT(1), 0x00);
307 	k_sleep(K_USEC(cfg->debounce_down_us * 1.5));
308 	assert_new_event(0, 1, 1);
309 
310 	k_sleep(K_USEC(cfg->debounce_down_us * 10));
311 	assert_no_new_events();
312 
313 	state_set_rows_by_column(BIT(1), BIT(0) | BIT(1), 0x00);
314 	k_sleep(K_USEC(cfg->debounce_up_us * 1.5));
315 	assert_new_event(0, 0, 0);
316 
317 	state_set_rows_by_column(BIT(1), BIT(0), 0x00);
318 	k_sleep(K_USEC(cfg->debounce_up_us * 1.5));
319 	assert_new_event(1, 1, 0);
320 
321 	state_set_rows_by_column(0x00, BIT(0), 0x00);
322 	k_sleep(K_USEC(cfg->debounce_up_us * 1.5));
323 	assert_new_event(1, 0, 0);
324 
325 	state_set_rows_by_column(0x00, 0x00, 0x00);
326 	k_sleep(K_USEC(cfg->debounce_up_us * 1.5));
327 	assert_new_event(0, 1, 0);
328 
329 	kbd_scan_wait_for_idle();
330 	assert_no_new_events();
331 }
332 
333 /* keymap is applied and can skip ghosting */
ZTEST(kbd_scan,test_kbd_actual_keymap)334 ZTEST(kbd_scan, test_kbd_actual_keymap)
335 {
336 	const struct input_kbd_matrix_common_config *cfg = test_dev->config;
337 
338 	if (cfg->actual_key_mask == NULL) {
339 		ztest_test_skip();
340 		return;
341 	}
342 
343 	input_kbd_matrix_poll_start(test_dev);
344 
345 	state_set_rows_by_column(BIT(0), 0x00, 0x00);
346 	k_sleep(K_USEC(cfg->debounce_down_us * 1.5));
347 	assert_new_event(0, 0, 1);
348 
349 	state_set_rows_by_column(BIT(0), 0x00, BIT(0));
350 	k_sleep(K_USEC(cfg->debounce_down_us * 1.5));
351 	assert_new_event(0, 2, 1);
352 
353 	/* ghosting cleared by the keymap */
354 	state_set_rows_by_column(BIT(0) | BIT(2), 0x00, BIT(0) | BIT(2));
355 	k_sleep(K_USEC(cfg->debounce_down_us * 1.5));
356 	assert_new_event(2, 0, 1);
357 
358 	state_set_rows_by_column(BIT(0) | BIT(2), 0x00, BIT(2));
359 	k_sleep(K_USEC(cfg->debounce_up_us * 1.5));
360 	assert_new_event(0, 2, 0);
361 
362 	state_set_rows_by_column(BIT(2), 0x00, BIT(2));
363 	k_sleep(K_USEC(cfg->debounce_up_us * 1.5));
364 	assert_new_event(0, 0, 0);
365 
366 	state_set_rows_by_column(BIT(2), 0x00, 0x00);
367 	k_sleep(K_USEC(cfg->debounce_up_us * 1.5));
368 	assert_no_new_events();
369 
370 	state_set_rows_by_column(0x00, 0x00, 0x00);
371 	k_sleep(K_USEC(cfg->debounce_up_us * 1.5));
372 	assert_new_event(2, 0, 0);
373 
374 	kbd_scan_wait_for_idle();
375 	assert_no_new_events();
376 }
377 
ZTEST(kbd_scan,test_kbd_actual_key_map_set)378 ZTEST(kbd_scan, test_kbd_actual_key_map_set)
379 {
380 #if CONFIG_INPUT_KBD_ACTUAL_KEY_MASK_DYNAMIC
381 	kbd_row_t mask[4] = {0x00, 0xff, 0x00, 0x00};
382 	const struct input_kbd_matrix_common_config cfg = {
383 		.row_size = 3,
384 		.col_size = 4,
385 		.actual_key_mask = mask,
386 	};
387 	const struct device fake_dev = {
388 		.config = &cfg,
389 	};
390 	int ret;
391 
392 	ret = input_kbd_matrix_actual_key_mask_set(&fake_dev, 0, 0, true);
393 	zassert_equal(ret, 0);
394 	zassert_equal(mask[0], 0x01);
395 
396 	ret = input_kbd_matrix_actual_key_mask_set(&fake_dev, 2, 1, false);
397 	zassert_equal(ret, 0);
398 	zassert_equal(mask[1], 0xfb);
399 
400 	ret = input_kbd_matrix_actual_key_mask_set(&fake_dev, 2, 3, true);
401 	zassert_equal(ret, 0);
402 	zassert_equal(mask[3], 0x04);
403 
404 	ret = input_kbd_matrix_actual_key_mask_set(&fake_dev, 3, 0, true);
405 	zassert_equal(ret, -EINVAL);
406 
407 	ret = input_kbd_matrix_actual_key_mask_set(&fake_dev, 0, 4, true);
408 	zassert_equal(ret, -EINVAL);
409 
410 	zassert_equal(memcmp(mask, (uint8_t[]){0x01, 0xfb, 0x00, 0x04}, 4), 0);
411 #else
412 	ztest_test_skip();
413 #endif
414 }
415 
kbd_scan_setup(void)416 static void *kbd_scan_setup(void)
417 {
418 	const struct input_kbd_matrix_common_config *cfg = test_dev->config;
419 
420 	TC_PRINT("actual kbd-matrix timing: poll_period_us=%d "
421 		 "debounce_down_us=%d debounce_up_us=%d\n",
422 		 cfg->poll_period_us,
423 		 cfg->debounce_down_us,
424 		 cfg->debounce_up_us);
425 
426 	return NULL;
427 }
428 
kbd_scan_before(void * data)429 static void kbd_scan_before(void *data)
430 {
431 	memset(&state, 0, sizeof(state));
432 	state.detect_mode = true;
433 
434 	last_checked_event_count = 0;
435 	memset(&test_event_data, 0, sizeof(test_event_data));
436 }
437 
kbd_scan_after(void * data)438 static void kbd_scan_after(void *data)
439 {
440 	/* Clear the test data so if a test fails early the testsuite does not
441 	 * hang indefinitely.
442 	 */
443 	state_set_rows_by_column(0x00, 0x00, 0x00);
444 	kbd_scan_wait_for_idle();
445 }
446 
447 ZTEST_SUITE(kbd_scan, NULL, kbd_scan_setup, kbd_scan_before, kbd_scan_after, NULL);
448