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 <[email protected]> > --- > 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 <[email protected]> > + * > + * 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 <[email protected]> > -- > 1.7.5.4 > _______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
