[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