keyack: Add program to wait for key press and release

Useful for testing buttons bound to a gpio-key, e.g. a factory reset
button.
This commit is contained in:
Tobias Waldekranz
2024-02-01 14:18:14 +01:00
committed by Mattias Walström
parent 8e0caed530
commit 583881c1f9
5 changed files with 127 additions and 0 deletions
+1
View File
@@ -6,6 +6,7 @@ source "$BR2_EXTERNAL_INFIX_PATH/package/faux/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/finit/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/ifupdown-ng/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/iito/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/keyack/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/klish-plugin-infix/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/klish/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/klish-plugin-sysrepo/Config.in"
+6
View File
@@ -0,0 +1,6 @@
config BR2_PACKAGE_KEYACK
bool "keyack"
help
Blocks until a specific key is pressed and released. Useful
when you want a user to confirm some action by physically
pressing a button.
+24
View File
@@ -0,0 +1,24 @@
################################################################################
#
# keyack
#
################################################################################
KEYACK_VERSION = 1.0
KEYACK_LICENSE = MIT
KEYACK_LICENSE_FILES = LICENSE
KEYACK_SITE_METHOD = local
KEYACK_SITE = $(BR2_EXTERNAL_INFIX_PATH)/src/keyack
KEYACK_REDISTRIBUTE = NO
define KEYACK_BUILD_CMDS
$(TARGET_MAKE_ENV) $(TARGET_CONFIGURE_OPTS) $(MAKE) -C $(@D) \
LDLIBS="$(TARGET_LDFLAGS)"
endef
define KEYACK_INSTALL_TARGET_CMDS
$(TARGET_MAKE_ENV) $(TARGET_CONFIGURE_OPTS) $(MAKE) -C $(@D) \
DESTDIR="$(TARGET_DIR)" install
endef
$(eval $(generic-package))
+12
View File
@@ -0,0 +1,12 @@
CFLAGS += -Wall -Wextra -Werror
all: keyack
clean:
-rm -f keyack
distclean: clean
-rm *~
install:
install -D keyack $(DESTDIR)/sbin/
+84
View File
@@ -0,0 +1,84 @@
#include <getopt.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <linux/input.h>
static void usage()
{
fputs("keyack - Wait for key press and release\n"
"\n"
"Usage:\n"
" keyack [options]\n"
"\n"
"Options:\n"
" -d DEVICE Operate on DEVICE, instead of /dev/input/event0.\n"
" -k KEYCODE Wait for KEYCODE, instead of KEY_RESTART.\n"
" -h Print usage message and exit.\n",
stderr);
}
static const char *sopts = "d:hk:";
static struct option lopts[] = {
{ "device", required_argument, 0, 'd' },
{ "help", no_argument, 0, 'h' },
{ "key", required_argument, 0, 'k' },
{ NULL }
};
bool wait_key_state(FILE *fp, int code, int val)
{
struct input_event ev;
while (fread(&ev, sizeof(ev), 1, fp)) {
if (ev.type == EV_KEY && ev.code == code && ev.value == val)
return true;
}
return false;
}
int main(int argc, char **argv)
{
char *dev = "/dev/input/event0";
int opt, code = KEY_RESTART;
bool success;
FILE *fp;
while ((opt = getopt_long(argc, argv, sopts, lopts, NULL)) > 0) {
switch (opt) {
case 'd':
dev = optarg;
break;
case 'h':
usage(); exit(0);
break;
case 'k':
code = strtol(optarg, NULL, 0);
break;
default:
fprintf(stderr, "unknown option '%c'\n", opt);
usage(); exit(1);
break;
}
}
fp = fopen(dev, "r");
if (!fp) {
fprintf(stderr, "Unable to open \"%s\": %m\n", dev);
exit(1);
}
success = wait_key_state(fp, code, 1) && wait_key_state(fp, code, 0);
fclose(fp);
if (!success) {
fprintf(stderr, "Failed to read events");
exit(1);
}
return 0;
}