1 /*
2  * Copyright 2023 Google LLC
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/input/input.h>
8 #include <zephyr/ztest.h>
9 #include <zephyr/device.h>
10 
11 static const struct device fake_dev;
12 static int message_count_filtered;
13 static int message_count_unfiltered;
14 
15 #if CONFIG_INPUT_MODE_THREAD
16 
17 static K_SEM_DEFINE(cb_start, 1, 1);
18 static K_SEM_DEFINE(cb_done, 1, 1);
19 
input_cb_filtered(struct input_event * evt,void * user_data)20 static void input_cb_filtered(struct input_event *evt, void *user_data)
21 {
22 	TC_PRINT("%s: %d\n", __func__, message_count_filtered);
23 
24 	k_sem_take(&cb_start, K_FOREVER);
25 
26 	if (evt->dev == &fake_dev && evt->code == message_count_filtered) {
27 		message_count_filtered++;
28 	}
29 
30 	k_sem_give(&cb_start);
31 }
32 INPUT_CALLBACK_DEFINE(&fake_dev, input_cb_filtered, NULL);
33 
input_cb_unfiltered(struct input_event * evt,void * user_data)34 static void input_cb_unfiltered(struct input_event *evt, void *user_data)
35 {
36 	TC_PRINT("%s: %d\n", __func__, message_count_unfiltered);
37 
38 	message_count_unfiltered++;
39 
40 	if (message_count_unfiltered == CONFIG_INPUT_QUEUE_MAX_MSGS + 1) {
41 		TC_PRINT("cb: done\n");
42 		k_sem_give(&cb_done);
43 	}
44 }
45 INPUT_CALLBACK_DEFINE_NAMED(NULL, input_cb_unfiltered, NULL,
46 			    input_cb_unfiltered_custom_name);
47 
ZTEST(input_api,test_sequence_thread)48 ZTEST(input_api, test_sequence_thread)
49 {
50 	int i;
51 	int ret;
52 
53 	message_count_filtered = 0;
54 	message_count_unfiltered = 0;
55 
56 	k_sem_take(&cb_start, K_FOREVER);
57 	k_sem_take(&cb_done, K_FOREVER);
58 
59 	/* fill the queue */
60 	for (i = 0; i < CONFIG_INPUT_QUEUE_MAX_MSGS; i++) {
61 		TC_PRINT("report: %d\n", i);
62 		ret = input_report_key(&fake_dev, i, 1, false, K_FOREVER);
63 		zassert_equal(ret, 0, "ret: %d", ret);
64 	}
65 
66 	/* one extra with no dev to acconut for the message pending in the
67 	 * locked cb
68 	 */
69 	ret = input_report_key(NULL, 0, 1, false, K_FOREVER);
70 	zassert_equal(ret, 0, "ret: %d", ret);
71 
72 	zassert_false(input_queue_empty());
73 
74 	/* next message finds the queue full */
75 	ret = input_report_key(&fake_dev, 0, 1, false, K_NO_WAIT);
76 	zassert_equal(ret, -ENOMSG, "ret: %d", ret);
77 
78 	k_sem_give(&cb_start);
79 
80 	/* wait for cb to get all the messages */
81 	k_sem_take(&cb_done, K_FOREVER);
82 
83 	zassert_equal(message_count_filtered, CONFIG_INPUT_QUEUE_MAX_MSGS);
84 	zassert_equal(message_count_unfiltered, CONFIG_INPUT_QUEUE_MAX_MSGS + 1);
85 }
86 
87 #else /* CONFIG_INPUT_MODE_THREAD */
88 
input_cb_filtered(struct input_event * evt,void * user_data)89 static void input_cb_filtered(struct input_event *evt, void *user_data)
90 {
91 	if (evt->dev == &fake_dev) {
92 		message_count_filtered++;
93 	}
94 }
95 INPUT_CALLBACK_DEFINE(&fake_dev, input_cb_filtered, NULL);
96 
input_cb_unfiltered(struct input_event * evt,void * user_data)97 static void input_cb_unfiltered(struct input_event *evt, void *user_data)
98 {
99 	message_count_unfiltered++;
100 }
101 INPUT_CALLBACK_DEFINE(NULL, input_cb_unfiltered, NULL);
102 
ZTEST(input_api,test_synchronous)103 ZTEST(input_api, test_synchronous)
104 {
105 	int ret;
106 
107 	message_count_filtered = 0;
108 	message_count_unfiltered = 0;
109 
110 	ret = input_report_key(&fake_dev, 0, 1, false, K_FOREVER);
111 	zassert_equal(ret, 0, "ret: %d", ret);
112 
113 	ret = input_report_key(NULL, 0, 1, false, K_FOREVER);
114 	zassert_equal(ret, 0, "ret: %d", ret);
115 
116 	zassert_equal(message_count_filtered, 1);
117 	zassert_equal(message_count_unfiltered, 2);
118 }
119 
120 static struct input_event last_event;
121 
input_cb_last_event(struct input_event * evt,void * user_data)122 static void input_cb_last_event(struct input_event *evt, void *user_data)
123 {
124 	memcpy(&last_event, evt, sizeof(last_event));
125 }
126 INPUT_CALLBACK_DEFINE(NULL, input_cb_last_event, NULL);
127 
ZTEST(input_api,test_report_apis)128 ZTEST(input_api, test_report_apis)
129 {
130 	int ret;
131 
132 	ret = input_report_key(&fake_dev, INPUT_KEY_A, 1, false, K_FOREVER);
133 	zassert_equal(ret, 0);
134 	zassert_equal(last_event.dev, &fake_dev);
135 	zassert_equal(last_event.type, INPUT_EV_KEY);
136 	zassert_equal(last_event.code, INPUT_KEY_A);
137 	zassert_equal(last_event.value, 1);
138 	zassert_equal(last_event.sync, 0);
139 
140 	ret = input_report_key(&fake_dev, INPUT_KEY_B, 1234, true, K_FOREVER);
141 	zassert_equal(ret, 0);
142 	zassert_equal(last_event.dev, &fake_dev);
143 	zassert_equal(last_event.type, INPUT_EV_KEY);
144 	zassert_equal(last_event.code, INPUT_KEY_B);
145 	zassert_equal(last_event.value, 1); /* key events are always 0 or 1 */
146 	zassert_equal(last_event.sync, 1);
147 
148 	ret = input_report_abs(&fake_dev, INPUT_ABS_X, 100, false, K_FOREVER);
149 	zassert_equal(ret, 0);
150 	zassert_equal(last_event.dev, &fake_dev);
151 	zassert_equal(last_event.type, INPUT_EV_ABS);
152 	zassert_equal(last_event.code, INPUT_ABS_X);
153 	zassert_equal(last_event.value, 100);
154 	zassert_equal(last_event.sync, 0);
155 
156 	ret = input_report_rel(&fake_dev, INPUT_REL_Y, -100, true, K_FOREVER);
157 	zassert_equal(ret, 0);
158 	zassert_equal(last_event.dev, &fake_dev);
159 	zassert_equal(last_event.type, INPUT_EV_REL);
160 	zassert_equal(last_event.code, INPUT_REL_Y);
161 	zassert_equal(last_event.value, -100);
162 	zassert_equal(last_event.sync, 1);
163 
164 	ret = input_report(&fake_dev, INPUT_EV_MSC, INPUT_MSC_SCAN, 0x12341234, true, K_FOREVER);
165 	zassert_equal(ret, 0);
166 	zassert_equal(last_event.dev, &fake_dev);
167 	zassert_equal(last_event.type, INPUT_EV_MSC);
168 	zassert_equal(last_event.code, INPUT_MSC_SCAN);
169 	zassert_equal(last_event.value, 0x12341234);
170 	zassert_equal(last_event.sync, 1);
171 
172 	ret = input_report(&fake_dev, INPUT_EV_VENDOR_START, 0xaaaa, 0xaaaaaaaa, true, K_FOREVER);
173 	zassert_equal(ret, 0);
174 	zassert_equal(last_event.dev, &fake_dev);
175 	zassert_equal(last_event.type, INPUT_EV_VENDOR_START);
176 	zassert_equal(last_event.code, 0xaaaa);
177 	zassert_equal(last_event.value, 0xaaaaaaaa);
178 	zassert_equal(last_event.sync, 1);
179 
180 	ret = input_report(&fake_dev, INPUT_EV_VENDOR_STOP, 0x5555, 0x55555555, true, K_FOREVER);
181 	zassert_equal(ret, 0);
182 	zassert_equal(last_event.dev, &fake_dev);
183 	zassert_equal(last_event.type, INPUT_EV_VENDOR_STOP);
184 	zassert_equal(last_event.code, 0x5555);
185 	zassert_equal(last_event.value, 0x55555555);
186 	zassert_equal(last_event.sync, 1);
187 }
188 
189 #endif /* CONFIG_INPUT_MODE_THREAD */
190 
191 ZTEST_SUITE(input_api, NULL, NULL, NULL, NULL, NULL);
192