1 /*
2  * Copyright (c) 2022 Google LLC
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/sys/util.h>
8 #include <zephyr/device.h>
9 #include <zephyr/drivers/gpio.h>
10 #include <zephyr/drivers/gpio/gpio_emul.h>
11 #include <zephyr/kernel.h>
12 #include <zephyr/ztest.h>
13 #include <zephyr/input/input.h>
14 
15 static const struct device *const test_gpio_keys_dev = DEVICE_DT_GET(DT_NODELABEL(buttons));
16 #define BUTTON_0_IDX DT_NODE_CHILD_IDX(DT_NODELABEL(voldown_button))
17 
18 struct gpio_keys_pin_config {
19 	/** GPIO specification from devicetree */
20 	struct gpio_dt_spec spec;
21 	/** Zephyr code from devicetree */
22 	uint32_t zephyr_code;
23 };
24 struct gpio_keys_config {
25 	/** Debounce interval in milliseconds from devicetree */
26 	uint32_t debounce_interval_ms;
27 	const int num_keys;
28 	const struct gpio_keys_pin_config *pin_cfg;
29 };
30 
31 /**
32  * @brief Test Suite: Verifies gpio_keys_config functionality.
33  */
34 ZTEST_SUITE(gpio_keys, NULL, NULL, NULL, NULL, NULL);
35 
36 static int event_count;
37 static uint16_t last_code;
38 static bool last_val;
test_gpio_keys_cb_handler(struct input_event * evt,void * user_data)39 static void test_gpio_keys_cb_handler(struct input_event *evt, void *user_data)
40 {
41 	TC_PRINT("GPIO_KEY %s pressed, zephyr_code=%u, value=%d\n",
42 		 evt->dev->name, evt->code, evt->value);
43 	event_count++;
44 	last_code = evt->code;
45 	last_val = evt->value;
46 }
47 INPUT_CALLBACK_DEFINE(test_gpio_keys_dev, test_gpio_keys_cb_handler, NULL);
48 
49 /**
50  * @brief TestPurpose: Verify gpio_keys_config pressed raw.
51  *
52  */
ZTEST(gpio_keys,test_gpio_keys_pressed)53 ZTEST(gpio_keys, test_gpio_keys_pressed)
54 {
55 	const struct gpio_keys_config *config = test_gpio_keys_dev->config;
56 	const struct gpio_keys_pin_config *pin_cfg = &config->pin_cfg[BUTTON_0_IDX];
57 	const struct gpio_dt_spec *spec = &pin_cfg->spec;
58 
59 	last_code = 0;
60 	last_val = false;
61 
62 	zassert_ok(gpio_emul_input_set(spec->port, spec->pin, 0));
63 
64 	/* Check interrupt doesn't prematurely fires */
65 	k_sleep(K_MSEC(config->debounce_interval_ms / 2));
66 	zassert_equal(event_count, 0);
67 
68 	/* Check interrupt fires after debounce interval */
69 	k_sleep(K_MSEC(config->debounce_interval_ms));
70 	zassert_equal(event_count, 1);
71 	zassert_equal(last_code, pin_cfg->zephyr_code);
72 	zassert_equal(last_val, true);
73 
74 	zassert_ok(gpio_emul_input_set(spec->port, spec->pin, 1));
75 
76 	/* Check interrupt doesn't prematurely fires */
77 	k_sleep(K_MSEC(config->debounce_interval_ms / 2));
78 	zassert_equal(event_count, 1);
79 
80 	/* Check interrupt fires after debounce interval */
81 	k_sleep(K_MSEC(config->debounce_interval_ms));
82 	zassert_equal(event_count, 2);
83 	zassert_equal(last_code, pin_cfg->zephyr_code);
84 	zassert_equal(last_val, false);
85 }
86