input: make short-inputs optional

By making short inputs optional, the user can bypass short-events all
together if necessary (e.g. custom button-press listener).

Signed-off-by: Juliane Schulze <juliane.schulze@deveritec.com>
This commit is contained in:
Juliane Schulze 2023-11-10 17:37:24 +01:00 committed by Fabio Baltieri
parent c3a54ae1c3
commit eeb6bf7dd9
4 changed files with 56 additions and 6 deletions

View File

@ -8,7 +8,9 @@ description: |
corresponding to short and long press.
Can be optionally be associated to a specific device to listen for events
only from that device. Example configuration:
only from that device.
Example configuration:
#include <zephyr/dt-bindings/input/input-event-codes.h>
@ -23,12 +25,14 @@ description: |
Example output:
# short press
input event: dev=buttons SYN type= 1 code= 11 value=1 # INPUT_KEY_0 press
# release before one second
input event: dev=buttons SYN type= 1 code= 11 value=0 # INPUT_KEY_0 release
input event: dev=longpress SYN type= 1 code= 30 value=1 # INPUT_KEY_A press
input event: dev=longpress SYN type= 1 code= 30 value=0 # INPUT_KEY_A release
# long press
input event: dev=buttons SYN type= 1 code= 11 value=1 # INPUT_KEY_0 press
# hold for more than one second
input event: dev=longpress SYN type= 1 code= 45 value=1 # INPUT_KEY_X press
@ -52,9 +56,8 @@ properties:
short-codes:
type: array
required: true
description: |
Array of key codes to be generated for short press (INPUT_KEY_* or
Optional array of key codes to be generated for short press (INPUT_KEY_* or
INPUT_BTN_*).
long-codes:

View File

@ -80,7 +80,7 @@ static void longpress_cb(const struct device *dev, struct input_event *evt)
k_work_cancel_delayable(&entry->work);
if (entry->long_fired) {
input_report_key(dev, cfg->long_codes[i], 0, true, K_FOREVER);
} else {
} else if (cfg->short_codes != NULL) {
input_report_key(dev, cfg->short_codes[i], 1, true, K_FOREVER);
input_report_key(dev, cfg->short_codes[i], 0, true, K_FOREVER);
}
@ -109,8 +109,9 @@ static int longpress_init(const struct device *dev)
}
#define INPUT_LONGPRESS_DEFINE(inst) \
BUILD_ASSERT(DT_INST_PROP_LEN(inst, input_codes) == \
DT_INST_PROP_LEN(inst, short_codes)); \
BUILD_ASSERT((DT_INST_PROP_LEN(inst, input_codes) == \
DT_INST_PROP_LEN_OR(inst, short_codes, 0)) || \
!DT_INST_NODE_HAS_PROP(inst, short_codes)); \
BUILD_ASSERT(DT_INST_PROP_LEN(inst, input_codes) == \
DT_INST_PROP_LEN(inst, long_codes)); \
static void longpress_cb_##inst(struct input_event *evt) \
@ -120,12 +121,16 @@ static int longpress_init(const struct device *dev)
INPUT_CALLBACK_DEFINE(DEVICE_DT_GET_OR_NULL(DT_INST_PHANDLE(inst, input)), \
longpress_cb_##inst); \
static const uint16_t longpress_input_codes_##inst[] = DT_INST_PROP(inst, input_codes); \
IF_ENABLED(DT_INST_NODE_HAS_PROP(inst, short_codes), ( \
static const uint16_t longpress_short_codes_##inst[] = DT_INST_PROP(inst, short_codes); \
)); \
static const uint16_t longpress_long_codes_##inst[] = DT_INST_PROP(inst, long_codes); \
static const struct longpress_config longpress_config_##inst = { \
.input_dev = DEVICE_DT_GET_OR_NULL(DT_INST_PHANDLE(inst, input)), \
.input_codes = longpress_input_codes_##inst, \
IF_ENABLED(DT_INST_NODE_HAS_PROP(inst, short_codes), ( \
.short_codes = longpress_short_codes_##inst, \
)) \
.long_codes = longpress_long_codes_##inst, \
.num_codes = DT_INST_PROP_LEN(inst, input_codes), \
.long_delays_ms = DT_INST_PROP(inst, long_delay_ms), \

View File

@ -19,4 +19,12 @@
long-codes = <INPUT_KEY_X>, <INPUT_KEY_Y>;
long-delay-ms = <100>;
};
longpress_no_short: longpress-no-short {
input = <&fake_input_device>;
compatible = "zephyr,input-longpress";
input-codes = <INPUT_KEY_0>, <INPUT_KEY_1>;
long-codes = <INPUT_KEY_X>, <INPUT_KEY_Y>;
long-delay-ms = <100>;
};
};

View File

@ -13,6 +13,8 @@ static const struct device *const fake_dev = DEVICE_DT_GET(
DT_NODELABEL(fake_input_device));
static const struct device *const longpress_dev = DEVICE_DT_GET(
DT_NODELABEL(longpress));
static const struct device *const longpress_no_short_dev = DEVICE_DT_GET(
DT_NODELABEL(longpress_no_short));
DEVICE_DT_DEFINE(DT_INST(0, vnd_input_device), NULL, NULL, NULL, NULL,
PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, NULL);
@ -30,6 +32,18 @@ static void test_cb(struct input_event *evt)
}
INPUT_CALLBACK_DEFINE(longpress_dev, test_cb);
static int event_count_no_short;
static struct input_event last_events_no_short[2];
static void test_cb_no_short(struct input_event *evt)
{
TC_PRINT("%s: %d %x %d\n", __func__, event_count_no_short, evt->code, evt->value);
event_count_no_short++;
memcpy(&last_events_no_short[1], &last_events_no_short[0], sizeof(struct input_event));
memcpy(&last_events_no_short[0], evt, sizeof(struct input_event));
}
INPUT_CALLBACK_DEFINE(longpress_no_short_dev, test_cb_no_short);
ZTEST(longpress, test_longpress_test)
{
zassert_equal(event_count, 0);
@ -38,9 +52,11 @@ ZTEST(longpress, test_longpress_test)
input_report_key(fake_dev, INPUT_KEY_3, 1, true, K_FOREVER);
input_report_key(fake_dev, INPUT_KEY_3, 0, true, K_FOREVER);
zassert_equal(event_count, 0);
zassert_equal(event_count_no_short, 0);
input_report_abs(fake_dev, INPUT_KEY_0, 1, true, K_FOREVER);
input_report_abs(fake_dev, INPUT_KEY_0, 0, true, K_FOREVER);
zassert_equal(event_count, 0);
zassert_equal(event_count_no_short, 0);
/* short press */
input_report_key(fake_dev, INPUT_KEY_0, 1, true, K_FOREVER);
@ -53,6 +69,7 @@ ZTEST(longpress, test_longpress_test)
zassert_equal(last_events[0].type, INPUT_EV_KEY);
zassert_equal(last_events[0].code, INPUT_KEY_A);
zassert_equal(last_events[0].value, 0);
zassert_equal(event_count_no_short, 0);
/* short press - other key */
input_report_key(fake_dev, INPUT_KEY_1, 1, true, K_FOREVER);
@ -65,6 +82,7 @@ ZTEST(longpress, test_longpress_test)
zassert_equal(last_events[0].type, INPUT_EV_KEY);
zassert_equal(last_events[0].code, INPUT_KEY_B);
zassert_equal(last_events[0].value, 0);
zassert_equal(event_count_no_short, 0);
/* long press */
input_report_key(fake_dev, INPUT_KEY_0, 1, true, K_FOREVER);
@ -78,6 +96,14 @@ ZTEST(longpress, test_longpress_test)
zassert_equal(last_events[0].code, INPUT_KEY_X);
zassert_equal(last_events[0].value, 0);
zassert_equal(event_count_no_short, 2);
zassert_equal(last_events_no_short[1].type, INPUT_EV_KEY);
zassert_equal(last_events_no_short[1].code, INPUT_KEY_X);
zassert_equal(last_events_no_short[1].value, 1);
zassert_equal(last_events_no_short[0].type, INPUT_EV_KEY);
zassert_equal(last_events_no_short[0].code, INPUT_KEY_X);
zassert_equal(last_events_no_short[0].value, 0);
/* long press - other key */
input_report_key(fake_dev, INPUT_KEY_1, 1, true, K_FOREVER);
k_sleep(K_MSEC(150));
@ -89,6 +115,14 @@ ZTEST(longpress, test_longpress_test)
zassert_equal(last_events[0].type, INPUT_EV_KEY);
zassert_equal(last_events[0].code, INPUT_KEY_Y);
zassert_equal(last_events[0].value, 0);
zassert_equal(event_count_no_short, 4);
zassert_equal(last_events_no_short[1].type, INPUT_EV_KEY);
zassert_equal(last_events_no_short[1].code, INPUT_KEY_Y);
zassert_equal(last_events_no_short[1].value, 1);
zassert_equal(last_events_no_short[0].type, INPUT_EV_KEY);
zassert_equal(last_events_no_short[0].code, INPUT_KEY_Y);
zassert_equal(last_events_no_short[0].value, 0);
}
ZTEST_SUITE(longpress, NULL, NULL, NULL, NULL, NULL);