[PATCH evtest] Add evstate tool for evdev state querying
Peter Hutterer
peter.hutterer at who-t.net
Tue Jul 12 16:12:46 PDT 2011
On Tue, Jul 12, 2011 at 09:04:34PM +0100, Daniel Drake wrote:
> evstate is a small utility that queries evdev state of a specific
> key, switch, button, LED or sound event. This is useful in programs
> such as powerd (http://wiki.laptop.org/go/Powerd) which need to query
> things like the state of the laptop lid switch from shell code.
>
> Signed-off-by: Daniel Drake <dsd at laptop.org>
> ---
> Makefile.am | 4 +-
> evstate.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> evstate.txt | 43 +++++++++++++++++++++
> 3 files changed, 167 insertions(+), 2 deletions(-)
> create mode 100644 evstate.c
> create mode 100644 evstate.txt
>
> I wrote this tool without realising that evtest exists. Now that I have
> found evtest, I see that it is similar (but doesn't quite fulfill the same
> role).
>
> Is this acceptable as-is, or would you prefer it merged into evtest as
> another mode of functionality? I could see either way: evstate as a
> trivial, small, standalone app is desirable as it will be called often by
> powerd and other shell scripts, but in the interest of consolidation perhaps
> it would instead make sense to make evtest offer this instant-query
> functionality. What do you think?
I think I'd prefer it merged into evdev, simply because we have all the
lookup tables there already. Which allows a state query for "Key Comma"
instead of the numbers, making it a nicer interface IMO.
Ideally we could also make it parse KEY_FOO definitions, since those are the
ones programmers see and are most familiar with (as opposed to the ones
evtest currently uses).
Cheers,
Peter
> diff --git a/Makefile.am b/Makefile.am
> index c78d17d..51dd7ae 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -1,6 +1,6 @@
>
> -bin_PROGRAMS = evtest
> -man_pages_src = evtest.txt
> +bin_PROGRAMS = evtest evstate
> +man_pages_src = evtest.txt evstate.txt
>
> if HAVE_LIBXML
> bin_PROGRAMS += evtest-capture
> diff --git a/evstate.c b/evstate.c
> new file mode 100644
> index 0000000..f797403
> --- /dev/null
> +++ b/evstate.c
> @@ -0,0 +1,122 @@
> +/*
> + * evstate: query evdev key/led/sw/snd state
> + * Returns exit code 1 if the state bit is set (key pressed, LED on, etc.),
> + * and 0 if the state bit is unset.
> + *
> + * Copyright (C) 2011 One Laptop per Child
> + * Written by Daniel Drake <dsd at laptop.org>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + */
> +
> +#define _GNU_SOURCE
> +#include <errno.h>
> +#include <fcntl.h>
> +#include <stdint.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <sys/stat.h>
> +#include <sys/types.h>
> +#include <unistd.h>
> +
> +#include <linux/input.h>
> +
> +#define BITS_PER_LONG (sizeof(long) * 8)
> +
> +static int test_bit(unsigned int nr, void *addr)
> +{
> + return ((1UL << (nr % BITS_PER_LONG)) &
> + (((unsigned long *) addr)[nr / BITS_PER_LONG])) != 0;
> +}
> +
> +static void __attribute__((noreturn)) usage(void)
> +{
> + fprintf(stderr, "Usage: %s <device> <mode> <key>\n",
> + program_invocation_short_name);
> + fprintf(stderr, "Valid modes: key, led, snd, sw\n");
> + exit(2);
> +}
> +
> +static const struct mode {
> + const char *name;
> + int max;
> + int rq;
> +} requests[] = {
> + { "key", KEY_MAX, EVIOCGKEY(KEY_MAX) },
> + { "led", LED_MAX, EVIOCGLED(LED_MAX) },
> + { "snd", SND_MAX, EVIOCGSND(SND_MAX) },
> + { "sw", SW_MAX, EVIOCGSW(SW_MAX) },
> +};
> +
> +static const struct mode *find_mode(const char *name)
> +{
> + int i;
> + for (i = 0; i < sizeof(requests) / sizeof(*requests); i++) {
> + const struct mode *mode = &requests[i];
> + if (strcmp(mode->name, name) == 0)
> + return mode;
> + }
> + return NULL;
> +}
> +
> +static int query_state(const char *device, long int keyno,
> + const struct mode *mode)
> +{
> + uint8_t state[(mode->max / 8) + 1];
> + int fd;
> + int r;
> +
> + if (keyno < 0 || keyno > mode->max) {
> + fprintf(stderr, "Unrecognised key %d\n", keyno);
> + exit(3);
> + }
> +
> + fd = open(device, O_RDONLY);
> + if (fd == -1) {
> + perror("open");
> + exit(3);
> + }
> +
> + memset(state, 0, sizeof(state));
> + r = ioctl(fd, mode->rq, state);
> + close(fd);
> +
> + if (r == -1) {
> + perror("ioctl");
> + exit(3);
> + }
> +
> + return test_bit(keyno, state);
> +}
> +
> +int main(int argc, char **argv)
> +{
> + const struct mode *mode;
> + long int keyno;
> +
> + if (argc != 4)
> + usage();
> +
> + mode = find_mode(argv[2]);
> + if (!mode) {
> + fprintf(stderr, "Unrecognised mode.\n");
> + usage();
> + }
> +
> + keyno = strtol(argv[3], NULL, 10);
> + return query_state(argv[1], keyno, mode);
> +}
> +
> diff --git a/evstate.txt b/evstate.txt
> new file mode 100644
> index 0000000..29b2156
> --- /dev/null
> +++ b/evstate.txt
> @@ -0,0 +1,43 @@
> +EVSTATE(1)
> +==========
> +
> +NAME
> +----
> +
> + evstate - query evdev key/LED/switch/sound state
> +
> +SYNOPSIS
> +--------
> + evstate device mode key
> +
> +DESCRIPTION
> +-----------
> +evstate queries the state of a Linux evdev key/button, LED, switch or sound
> +status.
> +
> +Ordinarily, no textual output is produced. evstate returns exit code 1 if
> +the state bit is set (key pressed, LED on, etc.), or exit code 0 if the state
> +bit is unset.
> +
> +*device* is the evdev device node of the input device you wish to query, such
> +as /dev/input/event0.
> +
> +*mode* is one of key, led, snd, or sw.
> +
> +*key* is the index of the key/switch/event you wish to query in integer form
> +(see <linux/input.h> for values).
> +
> +EXAMPLE
> +-------
> +Given /dev/input/event0 as the input device of my laptop dock switch, the
> +following command will determine if the laptop is plugged into dock (SW_DOCK).
> +
> + evstate /dev/input/event0 sw 5
> +
> +SEE ALSO
> +--------
> +evtest(1)
> +
> +AUTHOR
> +------
> +evstate was written by Daniel Drake <dsd at laptop.org>
> --
> 1.7.5.4
>
More information about the xorg-devel
mailing list