blob: a3d615ed9a09f3c96bef1bb589e41e5af51534fc [file] [log] [blame]
/*
* Copyright 2023 Google LLC
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/input/input.h>
#include <zephyr/ztest.h>
#include <zephyr/device.h>
static const struct device fake_dev;
static int message_count_filtered;
static int message_count_unfiltered;
#if CONFIG_INPUT_MODE_THREAD
static K_SEM_DEFINE(cb_start, 1, 1);
static K_SEM_DEFINE(cb_done, 1, 1);
static void input_cb_filtered(struct input_event *evt)
{
TC_PRINT("%s: %d\n", __func__, message_count_filtered);
k_sem_take(&cb_start, K_FOREVER);
if (evt->dev == &fake_dev && evt->code == message_count_filtered) {
message_count_filtered++;
}
k_sem_give(&cb_start);
}
INPUT_LISTENER_CB_DEFINE(&fake_dev, input_cb_filtered);
static void input_cb_unfiltered(struct input_event *evt)
{
TC_PRINT("%s: %d\n", __func__, message_count_unfiltered);
message_count_unfiltered++;
if (message_count_unfiltered == CONFIG_INPUT_QUEUE_MAX_MSGS + 1) {
TC_PRINT("cb: done\n");
k_sem_give(&cb_done);
}
}
INPUT_LISTENER_CB_DEFINE(NULL, input_cb_unfiltered);
ZTEST(input_api, test_sequence_thread)
{
int i;
int ret;
message_count_filtered = 0;
message_count_unfiltered = 0;
k_sem_take(&cb_start, K_FOREVER);
k_sem_take(&cb_done, K_FOREVER);
/* fill the queue */
for (i = 0; i < CONFIG_INPUT_QUEUE_MAX_MSGS; i++) {
TC_PRINT("report: %d\n", i);
ret = input_report_key(&fake_dev, i, 1, false, K_FOREVER);
zassert_equal(ret, 0, "ret: %d", ret);
}
/* one extra with no dev to acconut for the message pending in the
* locked cb
*/
ret = input_report_key(NULL, 0, 1, false, K_FOREVER);
zassert_equal(ret, 0, "ret: %d", ret);
zassert_false(input_queue_empty());
/* next message finds the queue full */
ret = input_report_key(&fake_dev, 0, 1, false, K_NO_WAIT);
zassert_equal(ret, -ENOMSG, "ret: %d", ret);
k_sem_give(&cb_start);
/* wait for cb to get all the messages */
k_sem_take(&cb_done, K_FOREVER);
zassert_equal(message_count_filtered, CONFIG_INPUT_QUEUE_MAX_MSGS);
zassert_equal(message_count_unfiltered, CONFIG_INPUT_QUEUE_MAX_MSGS + 1);
}
#else /* CONFIG_INPUT_MODE_THREAD */
static void input_cb_filtered(struct input_event *evt)
{
if (evt->dev == &fake_dev) {
message_count_filtered++;
}
}
INPUT_LISTENER_CB_DEFINE(&fake_dev, input_cb_filtered);
static void input_cb_unfiltered(struct input_event *evt)
{
message_count_unfiltered++;
}
INPUT_LISTENER_CB_DEFINE(NULL, input_cb_unfiltered);
ZTEST(input_api, test_synchronous)
{
int ret;
message_count_filtered = 0;
message_count_unfiltered = 0;
ret = input_report_key(&fake_dev, 0, 1, false, K_FOREVER);
zassert_equal(ret, 0, "ret: %d", ret);
ret = input_report_key(NULL, 0, 1, false, K_FOREVER);
zassert_equal(ret, 0, "ret: %d", ret);
zassert_equal(message_count_filtered, 1);
zassert_equal(message_count_unfiltered, 2);
}
static struct input_event last_event;
static void input_cb_last_event(struct input_event *evt)
{
memcpy(&last_event, evt, sizeof(last_event));
}
INPUT_LISTENER_CB_DEFINE(NULL, input_cb_last_event);
ZTEST(input_api, test_report_apis)
{
int ret;
ret = input_report_key(&fake_dev, INPUT_KEY_A, 1, false, K_FOREVER);
zassert_equal(ret, 0);
zassert_equal(last_event.dev, &fake_dev);
zassert_equal(last_event.type, INPUT_EV_KEY);
zassert_equal(last_event.code, INPUT_KEY_A);
zassert_equal(last_event.value, 1);
zassert_equal(last_event.sync, 0);
ret = input_report_key(&fake_dev, INPUT_KEY_B, 1234, true, K_FOREVER);
zassert_equal(ret, 0);
zassert_equal(last_event.dev, &fake_dev);
zassert_equal(last_event.type, INPUT_EV_KEY);
zassert_equal(last_event.code, INPUT_KEY_B);
zassert_equal(last_event.value, 1); /* key events are always 0 or 1 */
zassert_equal(last_event.sync, 1);
ret = input_report_abs(&fake_dev, INPUT_ABS_X, 100, false, K_FOREVER);
zassert_equal(ret, 0);
zassert_equal(last_event.dev, &fake_dev);
zassert_equal(last_event.type, INPUT_EV_ABS);
zassert_equal(last_event.code, INPUT_ABS_X);
zassert_equal(last_event.value, 100);
zassert_equal(last_event.sync, 0);
ret = input_report_rel(&fake_dev, INPUT_REL_Y, -100, true, K_FOREVER);
zassert_equal(ret, 0);
zassert_equal(last_event.dev, &fake_dev);
zassert_equal(last_event.type, INPUT_EV_REL);
zassert_equal(last_event.code, INPUT_REL_Y);
zassert_equal(last_event.value, -100);
zassert_equal(last_event.sync, 1);
ret = input_report(&fake_dev, INPUT_EV_MSC, INPUT_MSC_SCAN, 0x12341234, true, K_FOREVER);
zassert_equal(ret, 0);
zassert_equal(last_event.dev, &fake_dev);
zassert_equal(last_event.type, INPUT_EV_MSC);
zassert_equal(last_event.code, INPUT_MSC_SCAN);
zassert_equal(last_event.value, 0x12341234);
zassert_equal(last_event.sync, 1);
ret = input_report(&fake_dev, INPUT_EV_VENDOR_START, 0xaaaa, 0xaaaaaaaa, true, K_FOREVER);
zassert_equal(ret, 0);
zassert_equal(last_event.dev, &fake_dev);
zassert_equal(last_event.type, INPUT_EV_VENDOR_START);
zassert_equal(last_event.code, 0xaaaa);
zassert_equal(last_event.value, 0xaaaaaaaa);
zassert_equal(last_event.sync, 1);
ret = input_report(&fake_dev, INPUT_EV_VENDOR_STOP, 0x5555, 0x55555555, true, K_FOREVER);
zassert_equal(ret, 0);
zassert_equal(last_event.dev, &fake_dev);
zassert_equal(last_event.type, INPUT_EV_VENDOR_STOP);
zassert_equal(last_event.code, 0x5555);
zassert_equal(last_event.value, 0x55555555);
zassert_equal(last_event.sync, 1);
}
#endif /* CONFIG_INPUT_MODE_THREAD */
ZTEST_SUITE(input_api, NULL, NULL, NULL, NULL, NULL);