[PATCH libevdev v2 4/5] Add libevdev_event_type/code_from_name() resolvers
Peter Hutterer
peter.hutterer at who-t.net
Tue Oct 29 11:25:20 CET 2013
On 29/10/13 16:37 , David Herrmann wrote:
> Hi Peter
>
> On Tue, Oct 29, 2013 at 2:06 AM, Peter Hutterer
> <peter.hutterer at who-t.net> wrote:
>> On Mon, Oct 28, 2013 at 05:16:46PM +0100, David Herrmann wrote:
>>> Three new helpers are added:
>>> (1) libevdev_event_type_from_name() takes a string describing an EV_*
>>> event type and returns the given event-type constant.
>>> (2) libevdev_event_type_from_prefix() takes a string describing an event
>>> code and returns the type given by the prefix of the event code.
>>
>> what's the use-case for this? Specifically returning a valid type for an
>> invalid event code is what worries me a bit.
>
> use-case is pretty simple. Say you have a config-option to map an ABS
> value to another ABS value. You would do:
> if (libevdev_event_type_from_prefix(name, -1) != EV_ABS)
> return -EINVAL;
> r = libevdev_event_code_from_name(name, -1);
> if (r == -1)
> return -EINVAL;
> sth->code = r;
>
> So you need it to verify your code is really an EV_ABS value. I
> explicitly called it "from_prefix" to note that it does nothing more
> than prefix-matching. This is the simplest API I could come up with
> and I like it now. If you have ideas how to make it better, lemme
> know.
> The only other idea I had is adding an "unsigned int type" argument to
> libevdev_event_code_from_name() to limit it explicitly to a given
> group of names. I'm fine with both ideas.
I think that is my preferred option. I'd like to keep the API narrow and
well defined, at least in the beginning. If having a type argument
becomes too restricting and the workarounds too complicated we can add
something later but for now let's keep it simple.
Cheers,
Peter
>
>>> (2) libevdev_event_code_from_name() takes a string describing an event
>>> code and returns the given event-code constant.
>>>
>>> Signed-off-by: David Herrmann <dh.herrmann at gmail.com>
>>> ---
>>> libevdev/Makefile.am | 3 +-
>>> libevdev/libevdev-names.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++
>>> libevdev/libevdev.h | 63 +++++++++++++++++++++++
>>> test/Makefile.am | 1 +
>>> 4 files changed, 194 insertions(+), 1 deletion(-)
>>> create mode 100644 libevdev/libevdev-names.c
>>>
>>> diff --git a/libevdev/Makefile.am b/libevdev/Makefile.am
>>> index 3833d61..38c8de0 100644
>>> --- a/libevdev/Makefile.am
>>> +++ b/libevdev/Makefile.am
>>> @@ -10,7 +10,8 @@ libevdev_la_SOURCES = \
>>> libevdev-uinput.h \
>>> libevdev-uinput-int.h \
>>> libevdev.c \
>>> - ../include/linux/input.h
>>> + ../include/linux/input.h \
>>> + libevdev-names.c
>>
>> this is personal style, but I'd prefer to have the libevdev stuff grouped
>> together, so that linux/input.h is always the last line (amplifies that it's
>> a bit special). also, it'll mean the diff is only one line as opposed to
>> two.
>
> Will fix that once we agreed on the API above.
>
>> The rest of the patch looks good, thanks.
>
> Thanks!
> David
>
>> Cheers,
>> Peter
>>
>>
>>>
>>> libevdev_la_LDFLAGS = \
>>> -version-info $(LIBEVDEV_LT_VERSION) \
>>> diff --git a/libevdev/libevdev-names.c b/libevdev/libevdev-names.c
>>> new file mode 100644
>>> index 0000000..ee6c7f3
>>> --- /dev/null
>>> +++ b/libevdev/libevdev-names.c
>>> @@ -0,0 +1,128 @@
>>> +/*
>>> + * Copyright © 2013 David Herrmann <dh.herrmann at gmail.com>
>>> + *
>>> + * Permission to use, copy, modify, distribute, and sell this software and its
>>> + * documentation for any purpose is hereby granted without fee, provided that
>>> + * the above copyright notice appear in all copies and that both that copyright
>>> + * notice and this permission notice appear in supporting documentation, and
>>> + * that the name of the copyright holders not be used in advertising or
>>> + * publicity pertaining to distribution of the software without specific,
>>> + * written prior permission. The copyright holders make no representations
>>> + * about the suitability of this software for any purpose. It is provided "as
>>> + * is" without express or implied warranty.
>>> + *
>>> + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
>>> + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
>>> + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
>>> + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
>>> + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
>>> + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
>>> + * OF THIS SOFTWARE.
>>> + */
>>> +
>>> +#include <config.h>
>>> +#include <errno.h>
>>> +#include <stdlib.h>
>>> +#include <string.h>
>>> +#include <strings.h>
>>> +
>>> +#include "libevdev.h"
>>> +#include "libevdev-int.h"
>>> +#include "libevdev-util.h"
>>> +#include "event-names.h"
>>> +
>>> +struct name_lookup {
>>> + const char *name;
>>> + size_t len;
>>> +};
>>> +
>>> +static int cmp_entry(const void *vlookup, const void *ventry)
>>> +{
>>> + const struct name_lookup *lookup = vlookup;
>>> + const struct name_entry *entry = ventry;
>>> + int r;
>>> +
>>> + r = strncmp(lookup->name, entry->name, lookup->len);
>>> + if (!r) {
>>> + if (entry->name[lookup->len])
>>> + r = -1;
>>> + else
>>> + r = 0;
>>> + }
>>> +
>>> + return r;
>>> +}
>>> +
>>> +static const struct name_entry*
>>> +lookup_name(const struct name_entry *array, size_t asize,
>>> + struct name_lookup *lookup)
>>> +{
>>> + const struct name_entry *entry;
>>> +
>>> + entry = bsearch(lookup, array, asize, sizeof(*array), cmp_entry);
>>> + if (!entry)
>>> + return NULL;
>>> +
>>> + return entry;
>>> +}
>>> +
>>> +LIBEVDEV_EXPORT int
>>> +libevdev_event_type_from_name(const char *name, ssize_t len)
>>> +{
>>> + struct name_lookup lookup;
>>> + const struct name_entry *entry;
>>> +
>>> + lookup.name = name;
>>> + lookup.len = (len < 0) ? strlen(name) : (size_t)len;
>>> +
>>> + entry = lookup_name(ev_names, ARRAY_LENGTH(ev_names), &lookup);
>>> +
>>> + return entry ? (int)entry->value : -1;
>>> +}
>>> +
>>> +LIBEVDEV_EXPORT int
>>> +libevdev_event_type_from_prefix(const char *name, ssize_t len)
>>> +{
>>> + const char *e;
>>> + size_t i;
>>> + ssize_t l;
>>> +
>>> + if (len < 0)
>>> + len = strlen(name);
>>> +
>>> + /* MAX_ is not allowed, even though EV_MAX exists */
>>> + if (startswith(name, len, "MAX_", 4))
>>> + return -1;
>>> + /* BTN_ is special as there is no EV_BTN type */
>>> + if (startswith(name, len, "BTN_", 4))
>>> + return EV_KEY;
>>> + /* FF_STATUS_ is special as FF_ is a prefix of it, so test it first */
>>> + if (startswith(name, len, "FF_STATUS_", 10))
>>> + return EV_FF_STATUS;
>>> +
>>> + for (i = 0; i < ARRAY_LENGTH(ev_names); ++i) {
>>> + /* skip EV_ prefix */
>>> + e = &ev_names[i].name[3];
>>> + l = strlen(e);
>>> +
>>> + /* @e is suffix of [EV_]XYZ, test it and trailing _ */
>>> + if (len > l && startswith(name, len, e, l) && name[l] == '_')
>>> + return ev_names[i].value;
>>> + }
>>> +
>>> + return -1;
>>> +}
>>> +
>>> +LIBEVDEV_EXPORT int
>>> +libevdev_event_code_from_name(const char *name, ssize_t len)
>>> +{
>>> + struct name_lookup lookup;
>>> + const struct name_entry *entry;
>>> +
>>> + lookup.name = name;
>>> + lookup.len = (len < 0) ? strlen(name) : (size_t)len;
>>> +
>>> + entry = lookup_name(code_names, ARRAY_LENGTH(code_names), &lookup);
>>> +
>>> + return entry ? (int)entry->value : -1;
>>> +}
>>> diff --git a/libevdev/libevdev.h b/libevdev/libevdev.h
>>> index 426e9c8..b8d85e1 100644
>>> --- a/libevdev/libevdev.h
>>> +++ b/libevdev/libevdev.h
>>> @@ -1416,6 +1416,7 @@ int libevdev_event_is_code(const struct input_event *ev, unsigned int type, unsi
>>> * defines for new properties libevdev will not automatically pick these up.
>>> */
>>> const char * libevdev_event_type_get_name(unsigned int type);
>>> +
>>> /**
>>> * @ingroup misc
>>> *
>>> @@ -1460,6 +1461,68 @@ const char* libevdev_property_get_name(unsigned int prop);
>>> int libevdev_event_type_get_max(unsigned int type);
>>>
>>> /**
>>> + * @ingroup misc
>>> + *
>>> + * Look up an event-type by its name. Event-types start with "EV_" followed by
>>> + * the name (eg., "EV_ABS"). The "EV_" prefix must be included in the name. It
>>> + * returns the constant assigned to the event-type or -1 if not found.
>>> + *
>>> + * @param name A non-NULL string describing an input-event type ("EV_KEY",
>>> + * "EV_ABS", ...).
>>> + * @param len The length of the passed string excluding any terminating 0
>>> + * character. If less than zero the string is assumed to be zero-terminated.
>>> + *
>>> + * @return The given type constant for the passed name or -1 if not found.
>>> + *
>>> + * @note EV_MAX is also recognized.
>>> + */
>>> +int libevdev_event_type_from_name(const char *name, ssize_t len);
>>> +
>>> +/**
>>> + * @ingroup misc
>>> + *
>>> + * Look up an event-type by an event-code name. Event-codes start with a fixed
>>> + * prefix followed by their name (eg., "ABS_X"). It performs a prefix-match on
>>> + * the name and returns the constant assigned to the event-type of the
>>> + * event-code or -1 if the prefix is unknown.
>>> + *
>>> + * For instance this returns the constant EV_ABS for the string "ABS_X". Note
>>> + * that the event-code must not necessarily exist. A lookup for "ABS_XYZ" will
>>> + * also return EV_ABS, even though ABS_XYZ is not a valid event-code. This only
>>> + * tests the prefix (for performance reasons).
>>> + *
>>> + * All EV_* codes are supported by this call and are returned if their prefix
>>> + * is used. For BTN_* codes, EV_KEY is returned.
>>> + *
>>> + * @param name A non-NULL string describing an input-event code (KEY_A,
>>> + * ABS_X, BTN_Y, ...).
>>> + * @param len The length of the passed string excluding any terminating 0
>>> + * character. If less than zero the string is assumed to be zero-terminated.
>>> + *
>>> + * @return The given type constant for the passed name or -1 if not found.
>>> + */
>>> +int libevdev_event_type_from_prefix(const char *name, ssize_t len);
>>> +
>>> +/**
>>> + * @ingroup misc
>>> + *
>>> + * Look up an event-code by its name. Event-codes start with a fixed prefix
>>> + * followed by their name (eg., "ABS_X"). The prefix must be included in the
>>> + * name. It returns the constant assigned to the event-code or -1 if not found.
>>> + *
>>> + * Supported event-codes are codes starting with SYN_, KEY_, BTN_, REL_, ABS_,
>>> + * MSC_, SND_, SW_, LED_, REP_, FF_.
>>> + *
>>> + * @param name A non-NULL string describing an input-event code (KEY_A,
>>> + * ABS_X, BTN_Y, ...).
>>> + * @param len The length of the passed string excluding any terminating 0
>>> + * character. If less than zero the string is assumed to be zero-terminated.
>>> + *
>>> + * @return The given code constant for the passed name or -1 if not found.
>>> + */
>>> +int libevdev_event_code_from_name(const char *name, ssize_t len);
>>> +
>>> +/**
>>> * @ingroup bits
>>> *
>>> * Get the repeat delay and repeat period values for this device.
>>> diff --git a/test/Makefile.am b/test/Makefile.am
>>> index 2baafb0..c18b277 100644
>>> --- a/test/Makefile.am
>>> +++ b/test/Makefile.am
>>> @@ -5,6 +5,7 @@ TESTS = $(noinst_PROGRAMS)
>>>
>>> libevdev_sources = $(top_srcdir)/libevdev/libevdev.c \
>>> $(top_srcdir)/libevdev/libevdev.h \
>>> + $(top_srcdir)/libevdev/libevdev-names.c \
>>> $(top_srcdir)/libevdev/libevdev-uinput.h \
>>> $(top_srcdir)/libevdev/libevdev-uinput.c \
>>> $(top_srcdir)/libevdev/libevdev-uinput-int.h \
>>> --
>>> 1.8.4.1
>>>
>
More information about the Input-tools
mailing list