From: David Herrmann Date: Wed, 30 Oct 2013 07:44:48 +0000 (+0100) Subject: Add libevdev_event_type/code_from_name() resolvers X-Git-Tag: libevdev-0.5~15 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=12717d796c077fc45e69f3d2f379306c867f1d3b;p=platform%2Fupstream%2Flibevdev.git Add libevdev_event_type/code_from_name() resolvers 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_code_from_name() takes a string describing an event code and returns the given event-code constant. Signed-off-by: David Herrmann Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- diff --git a/libevdev/Makefile.am b/libevdev/Makefile.am index 3833d61..74b3c51 100644 --- a/libevdev/Makefile.am +++ b/libevdev/Makefile.am @@ -10,6 +10,7 @@ libevdev_la_SOURCES = \ libevdev-uinput.h \ libevdev-uinput-int.h \ libevdev.c \ + libevdev-names.c \ ../include/linux/input.h libevdev_la_LDFLAGS = \ diff --git a/libevdev/libevdev-names.c b/libevdev/libevdev-names.c new file mode 100644 index 0000000..f9669cc --- /dev/null +++ b/libevdev/libevdev-names.c @@ -0,0 +1,134 @@ +/* + * Copyright © 2013 David Herrmann + * + * 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 +#include +#include +#include +#include + +#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; +} + +static int 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 so @e is suffix of [EV_]XYZ */ + e = &ev_names[i].name[3]; + l = strlen(e); + + /* compare prefix and test for 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(unsigned int type, const char *name, ssize_t len) +{ + struct name_lookup lookup; + const struct name_entry *entry; + int real_type; + + /* verify that @name is really of type @type */ + real_type = type_from_prefix(name, len); + if (real_type < 0 || (unsigned int)real_type != type) + return -1; + + /* now look up the name @name and return the constant */ + 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..2bba4ba 100644 --- a/libevdev/libevdev.h +++ b/libevdev/libevdev.h @@ -1460,6 +1460,48 @@ 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-code by its type and 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. + * + * You have to pass the event-type where to look for the name. For instance, to + * resolve "ABS_X" you need to pass EV_ABS as type and "ABS_X" as string. + * Supported event-codes are codes starting with SYN_, KEY_, BTN_, REL_, ABS_, + * MSC_, SND_, SW_, LED_, REP_, FF_. + * + * @param type The event type (EV_* constant) where to look for the name. + * @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(unsigned int type, 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 \