[PATCH v2 evemu] Record the state of SW/LED in the evemu file
Benjamin Tissoires
benjamin.tissoires at gmail.com
Wed Jul 22 12:31:25 PDT 2015
On Wed, Jul 22, 2015 at 3:05 AM, Peter Hutterer
<peter.hutterer at who-t.net> wrote:
> There is no evdev ioctl to set the state of a device without sending an event
> through the device, so we can't replicate the state without altering the
> recorded event sequence. For this reason, we use the libevdev shortcut to
> query the state rather than adding an evemu-specific API to get the state.
>
> The state is printed to the comments, and optionally printed to the recording
> (0 is assumed when missing).
>
> EV_KEY can give us the state but we don't print it, unlike the others a key
> state is too transient.
> EV_SND could be added, if we ever see demand for it.
>
> Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
> ---
> Changes to v1:
> - dropped EV_SND, who cares...
> - update file format to record LED/SW state
Applied and pushed:
3f1edc7..79b29f0 master -> master
Cheers,
Benjamin
>
> README.md | 11 ++++++--
> src/evemu.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
> 2 files changed, 98 insertions(+), 5 deletions(-)
>
> diff --git a/README.md b/README.md
> index 4b4b812..78c4bf6 100644
> --- a/README.md
> +++ b/README.md
> @@ -37,7 +37,7 @@ Device Description Format
> evemu produces two different data formats, one for the device description
> and one for the device event data. hex data is without a 0x prefix.
>
> - # EVEMU 1.2
> + # EVEMU 1.3
> # comments start with a # character and go to the end of the line
> N: <device name>
> I: <bustype (hex)> <vendor (hex)> <product (hex)> <version (hex)>
> @@ -49,12 +49,18 @@ and one for the device event data. hex data is without a 0x prefix.
> B: <index (hex)> <byte 8 (hex)> ...
> --- for each absolute axis ---
> A: <index (hex)> <min> <max> <fuzz> <flat> <resolution>
> + --- for each LED ---
> + L: <index (hex)> <state>
> + --- for each switch ---
> + S: <index (hex)> <state>
>
> The first line is a special comment and taken to describe the file format
> version. It is always comment character (#), space, "EVEMU", space, followed
> by a numeric version number in the format major.minor.
> If the line is missing, file format 1.0 is assumed.
>
> +If L and S are missing, the state of each LED/switch is 0
> +
> minor version numbers are additions of new fields, or alterations of a
> field.
> major version numbers are large redesigns of the format
> @@ -65,6 +71,7 @@ Current file format versions supported:
> * 1.1 - comments may be present at any line of the file, including at the
> end of a line
> * 1.2 - abs axis information has the resolution appended
> + * 1.3 - LED/switch state added
>
> Event Data Format
> -----------------
> @@ -97,4 +104,4 @@ Copyright
>
> * Copyright (C) 2010 Henrik Rydberg <rydberg at euromail.se>
> * Copyright (C) 2010 Canonical Ltd.
> - * Copyright (C) 2013 Red Hat, Inc.
> + * Copyright (C) 2013-2015 Red Hat, Inc.
> diff --git a/src/evemu.c b/src/evemu.c
> index 642597b..12a0038 100644
> --- a/src/evemu.c
> +++ b/src/evemu.c
> @@ -3,7 +3,7 @@
> * evemu - Kernel device emulation
> *
> * Copyright (C) 2010-2012 Canonical Ltd.
> - * Copyright (C) 2013 Red Hat, Inc.
> + * Copyright (C) 2013-2015 Red Hat, Inc.
> *
> * This library is free software: you can redistribute it and/or modify it
> * under the terms of the GNU Lesser General Public License version 3
> @@ -59,7 +59,7 @@
> /* File format version we write out
> NOTE: if you bump the version number, make sure you update README */
> #define EVEMU_FILE_MAJOR 1
> -#define EVEMU_FILE_MINOR 2
> +#define EVEMU_FILE_MINOR 3
>
> #define SYSCALL(call) while (((call) == -1) && (errno == EINTR))
>
> @@ -296,10 +296,21 @@ static void write_abs(FILE *fp, int index, const struct input_absinfo *abs)
> abs->minimum, abs->maximum, abs->fuzz, abs->flat, abs->resolution);
> }
>
> +static void write_led(FILE *fp, int index, int state)
> +{
> + fprintf(fp, "L: %02x %d\n", index, state);
> +}
> +
> +static void write_sw(FILE *fp, int index, int state)
> +{
> + fprintf(fp, "S: %02x %d\n", index, state);
> +}
> +
> /* Print an evtest-like description */
> static void write_desc(const struct evemu_device *dev, FILE *fp)
> {
> int i, j;
> + int state;
> fprintf(fp, "# Input device name: \"%s\"\n", evemu_get_name(dev));
> fprintf(fp, "# Input device ID: bus %#04x vendor %#04x product %#04x version %#04x\n",
> evemu_get_id_bustype(dev), evemu_get_id_vendor(dev),
> @@ -316,7 +327,8 @@ static void write_desc(const struct evemu_device *dev, FILE *fp)
>
> fprintf(fp, "# Event code %d (%s)\n",
> j, libevdev_event_code_get_name(i, j));
> - if (i == EV_ABS) {
> + switch(i) {
> + case EV_ABS:
> fprintf(fp, "# Value %6d\n"
> "# Min %6d\n"
> "# Max %6d\n"
> @@ -329,6 +341,13 @@ static void write_desc(const struct evemu_device *dev, FILE *fp)
> evemu_get_abs_fuzz(dev, j),
> evemu_get_abs_flat(dev, j),
> evemu_get_abs_resolution(dev, j));
> + case EV_LED:
> + case EV_SW:
> + state = libevdev_get_event_value(dev->evdev, i, j);
> + fprintf(fp, "# State %d\n", state);
> + break;
> + default:
> + break;
> }
> }
> }
> @@ -370,6 +389,7 @@ write_header(FILE *fp)
> int evemu_write(const struct evemu_device *dev, FILE *fp)
> {
> int i;
> + int state;
>
> write_header(fp);
>
> @@ -390,6 +410,16 @@ int evemu_write(const struct evemu_device *dev, FILE *fp)
> if (evemu_has_event(dev, EV_ABS, i))
> write_abs(fp, i, libevdev_get_abs_info(dev->evdev, i));
>
> + for (i = 0; i < LED_CNT; i++)
> + if (evemu_has_event(dev, EV_LED, i) &&
> + (state = libevdev_get_event_value(dev->evdev, EV_LED, i)) != 0)
> + write_led(fp, i, state);
> +
> + for (i = 0; i < SW_CNT; i++)
> + if (evemu_has_event(dev, EV_SW, i) &&
> + (state = libevdev_get_event_value(dev->evdev, EV_SW, i)) != 0)
> + write_sw(fp, i, state);
> +
> return 0;
> }
>
> @@ -525,6 +555,50 @@ static int parse_abs(struct evemu_device *dev, const char *line, struct version
> return 1;
> }
>
> +static int parse_led(const char *line)
> +{
> + int matched;
> + unsigned int index;
> + int state;
> +
> + if (strlen(line) <= 2 || strncmp(line, "L:", 2) != 0)
> + return 0;
> +
> + matched = sscanf(line, "L: %02x %d\n", &index, &state);
> +
> + if (matched != 2) {
> + error(FATAL, "Invalid EV_LED line. Parsed %d numbers, expected 2: %s", matched, line);
> + return -1;
> + }
> +
> + /* We can't set the LEDs directly, we'd have to send an event
> + * through the device but that's potentially racy */
> +
> + return 1;
> +}
> +
> +static int parse_sw(const char *line)
> +{
> + int matched;
> + unsigned int index;
> + int state;
> +
> + if (strlen(line) <= 2 || strncmp(line, "S:", 2) != 0)
> + return 0;
> +
> + matched = sscanf(line, "S: %02x %d\n", &index, &state);
> +
> + if (matched != 2) {
> + error(FATAL, "Invalid EV_SW line. Parsed %d numbers, expected 2: %s", matched, line);
> + return -1;
> + }
> +
> + /* We can't set the switches directly, we'd have to send an event
> + * through the device but that's potentially racy */
> +
> + return 1;
> +}
> +
> static struct version parse_file_format_version(const char *line)
> {
> struct version v;
> @@ -603,6 +677,18 @@ int evemu_read(struct evemu_device *dev, FILE *fp)
> if (rc == -1)
> goto out;
>
> + while((rc = parse_led(line)) > 0)
> + if (!next_line(fp, &line, &size))
> + break;
> + if (rc == -1)
> + goto out;
> +
> + while((rc = parse_sw(line)) > 0)
> + if (!next_line(fp, &line, &size))
> + break;
> + if (rc == -1)
> + goto out;
> +
> rc = 1;
>
> out:
> --
> 2.4.3
>
More information about the Input-tools
mailing list