diff --git a/package/Config.in b/package/Config.in index b7d0be23..8d01bbc4 100644 --- a/package/Config.in +++ b/package/Config.in @@ -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" diff --git a/package/keyack/Config.in b/package/keyack/Config.in new file mode 100644 index 00000000..10b89622 --- /dev/null +++ b/package/keyack/Config.in @@ -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. diff --git a/package/keyack/keyack.mk b/package/keyack/keyack.mk new file mode 100644 index 00000000..87d92684 --- /dev/null +++ b/package/keyack/keyack.mk @@ -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)) diff --git a/src/keyack/Makefile b/src/keyack/Makefile new file mode 100644 index 00000000..fd25f0a9 --- /dev/null +++ b/src/keyack/Makefile @@ -0,0 +1,12 @@ +CFLAGS += -Wall -Wextra -Werror + +all: keyack + +clean: + -rm -f keyack + +distclean: clean + -rm *~ + +install: + install -D keyack $(DESTDIR)/sbin/ diff --git a/src/keyack/keyack.c b/src/keyack/keyack.c new file mode 100644 index 00000000..e2b2eb86 --- /dev/null +++ b/src/keyack/keyack.c @@ -0,0 +1,84 @@ +#include +#include +#include +#include +#include + +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; +}