diff --git a/dts/bindings/input/zephyr,input-longpress.yaml b/dts/bindings/input/zephyr,input-longpress.yaml index abf87a15803..a6ef96f5d40 100644 --- a/dts/bindings/input/zephyr,input-longpress.yaml +++ b/dts/bindings/input/zephyr,input-longpress.yaml @@ -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 @@ -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: diff --git a/subsys/input/input_longpress.c b/subsys/input/input_longpress.c index c9acbbf14fe..5e0b6f0ac9f 100644 --- a/subsys/input/input_longpress.c +++ b/subsys/input/input_longpress.c @@ -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), \ diff --git a/tests/subsys/input/longpress/boards/native_sim.overlay b/tests/subsys/input/longpress/boards/native_sim.overlay index 14dcd8d0d4e..a742ed99c5c 100644 --- a/tests/subsys/input/longpress/boards/native_sim.overlay +++ b/tests/subsys/input/longpress/boards/native_sim.overlay @@ -19,4 +19,12 @@ long-codes = , ; long-delay-ms = <100>; }; + + longpress_no_short: longpress-no-short { + input = <&fake_input_device>; + compatible = "zephyr,input-longpress"; + input-codes = , ; + long-codes = , ; + long-delay-ms = <100>; + }; }; diff --git a/tests/subsys/input/longpress/src/main.c b/tests/subsys/input/longpress/src/main.c index 22d5e720038..4f81901a742 100644 --- a/tests/subsys/input/longpress/src/main.c +++ b/tests/subsys/input/longpress/src/main.c @@ -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);