diff --git a/.gitignore b/.gitignore index 19ee82b..28dd248 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,4 @@ ylwrap *.tar.* *.3 libevdev-events +event-names.h diff --git a/libevdev/Makefile.am b/libevdev/Makefile.am index e03be9b..cb7455e 100644 --- a/libevdev/Makefile.am +++ b/libevdev/Makefile.am @@ -9,3 +9,11 @@ libevdev_la_LDFLAGS = -version-info $(LIBEVDEV_LT_VERSION) -export-symbols-regex libevdevincludedir = $(includedir)/libevdev-1.0/libevdev libevdevinclude_HEADERS = libevdev.h + +event-names.h: Makefile make-event-names.py + $(srcdir)/make-event-names.py --output=c > $@ + +EXTRA_DIST = make-event-names.py +CLEANFILES = event-names.h +BUILT_SOURCES = event-names.h + diff --git a/libevdev/libevdev.c b/libevdev/libevdev.c index 7632467..b19f7f6 100644 --- a/libevdev/libevdev.c +++ b/libevdev/libevdev.c @@ -29,6 +29,7 @@ #include "libevdev.h" #include "libevdev-int.h" +#include "event-names.h" #define MAXEVENTS 64 @@ -937,3 +938,33 @@ libevdev_grab(struct libevdev *dev, int grab) return rc < 0 ? -errno : 0; } + +const char* +libevdev_get_event_type_name(unsigned int type) +{ + if (type > EV_MAX) + return NULL; + + return ev_map[type]; +} + +const char* +libevdev_get_event_code_name(unsigned int type, unsigned int code) +{ + if (type > EV_MAX) + return NULL; + + if (code > ev_max[type]) + return NULL; + + return event_type_map[type][code]; +} + +const char* +libevdev_get_input_prop_name(unsigned int prop) +{ + if (prop > INPUT_PROP_MAX) + return NULL; + + return input_prop_map[prop]; +} diff --git a/libevdev/libevdev.h b/libevdev/libevdev.h index 5e42f32..a693acd 100644 --- a/libevdev/libevdev.h +++ b/libevdev/libevdev.h @@ -464,4 +464,32 @@ int libevdev_disable_event_code(struct libevdev *dev, unsigned int type, unsigne */ int libevdev_kernel_set_abs_value(struct libevdev *dev, unsigned int code, const struct input_absinfo *abs); +/** + * @return The name of the given event type (e.g. EV_ABS) or NULL for an + * invalid type + * + * @note The list of names is compiled into libevdev. If the kernel adds new + * defines for new properties libevdev will not automatically pick these up. + */ +const char * libevdev_get_event_type_name(unsigned int type); +/** + * @return The name of the given event code (e.g. ABS_X) or NULL for an + * invalid type or code + * + * @note The list of names is compiled into libevdev. If the kernel adds new + * defines for new properties libevdev will not automatically pick these up. + */ +const char * libevdev_get_event_code_name(unsigned int type, unsigned int code); + +/** + * @return The name of the given input prop (e.g. INPUT_PROP_BUTTONPAD) or NULL for an + * invalid property + * + * @note The list of names is compiled into libevdev. If the kernel adds new + * defines for new properties libevdev will not automatically pick these up. + * @note On older kernels input properties may not be defined and + * libevdev_get_input_prop_name will always return NULL + */ +const char * libevdev_get_input_prop_name(unsigned int prop); + #endif /* libevdev_H */ diff --git a/libevdev/make-event-names.py b/libevdev/make-event-names.py new file mode 100755 index 0000000..62dcf7f --- /dev/null +++ b/libevdev/make-event-names.py @@ -0,0 +1,178 @@ +#!/usr/bin/env python +# Parses linux/input.h scanning for #define KEY_FOO 134 +# Prints a C header file or a Python file that can be used as +# mapping table +# + +import re +import sys +import argparse + +SOURCE_FILE = "/usr/include/linux/input.h" + +class Bits(object): + pass + +prefixes = [ + "EV_", + "REL_", + "ABS_", + "KEY_", + "BTN_", + "LED_", + "SND_", + "MSC_", + "SW_", + "FF_", + "SYN_", + "INPUT_PROP_", +] + +blacklist = [ + "EV_VERSION" +] + +def print_bits(bits, prefix): + if not hasattr(bits, prefix): + return + print "static const char * const %s_map[%s_MAX + 1] = {" % (prefix, prefix.upper()) + print " [0 ... %s_MAX] = NULL," % prefix.upper() + for val, name in getattr(bits, prefix).items(): + print " [%s] = \"%s\"," % (name, name) + print "};" + print "" + +def print_python_bits(bits, prefix): + if not hasattr(bits, prefix): + return + + print "%s_map = {" % (prefix) + for val, name in getattr(bits, prefix).items(): + print " %d : \"%s\"," % (val, name) + print "}" + print "for k, v in %s_map.items():" % (prefix) + print " %s_map[v] = k" % (prefix) + print "" + +def print_map(bits): + print "static const char * const * const event_type_map[EV_MAX + 1] = {" + print " [0 ... EV_MAX] = NULL," + + for prefix in prefixes: + if prefix == "BTN_" or prefix == "EV_" or prefix == "INPUT_PROP_": + continue + print " [EV_%s] = %s_map," % (prefix[:-1], prefix[:-1].lower()) + + print "};" + print "" + + print "static const int ev_max[EV_MAX + 1] = {" + for prefix in prefixes: + if prefix == "BTN_" or prefix == "EV_" or prefix == "INPUT_PROP_": + continue + print " [EV_%s] = %s_MAX," % (prefix[:-1], prefix[:-1]) + print "};" + print "" + +def print_python_map(bits): + print "map = {" + + for val, name in getattr(bits, "ev").items(): + name = name[3:] + if name == "REP" or name == "PWR" or name == "FF_STATUS" or name == "MAX": + continue + print " %d : %s_map," % (val, name.lower()) + + print "}" + print "" + +def print_mapping_table(bits): + print "/* THIS FILE IS GENERATED, DO NOT EDIT */" + print "" + print "#ifndef EVENT_NAMES_H" + print "#define EVENT_NAMES_H" + print "" + print "#define SYN_MAX 3 /* linux/input.h doesn't define that */" + print "" + + for prefix in prefixes: + if prefix == "BTN_": + continue + print_bits(bits, prefix[:-1].lower()) + + print_map(bits) + + print "#endif /* EVENT_NAMES_H */" + +def print_python_mapping_table(bits): + print "# THIS FILE IS GENERATED, DO NOT EDIT" + print "" + + for prefix in prefixes: + if prefix == "BTN_": + continue + print_python_bits(bits, prefix[:-1].lower()) + + print_python_map(bits) + + print "def event_get_type_name(type):" + print " return ev_map[type]" + print "" + print "" + print "def event_get_code_name(type, code):" + print " if map.has_key(type) and map[type].has_key(code):" + print " return map[type][code]" + print " return 'UNKNOWN'" + print "" + +def parse_define(bits, line): + m = re.match(r"^#define\s+(\w+)\s+(\w+)", line) + if m == None: + return + + name = m.group(1) + + if name in blacklist: + return + + try: + value = int(m.group(2), 0) + except ValueError: + return + + for prefix in prefixes: + if not name.startswith(prefix): + continue + + attrname = prefix[:-1].lower() + if attrname == "btn": + attrname = "key" + + if not hasattr(bits, attrname): + setattr(bits, attrname, {}) + b = getattr(bits, attrname) + b[value] = name + +def parse(path): + fp = open(path) + + bits = Bits() + + lines = fp.readlines() + for line in lines: + if not line.startswith("#define"): + continue + parse_define(bits, line) + + return bits + +if __name__ == "__main__": + bits = parse(SOURCE_FILE) + parser = argparse.ArgumentParser() + parser.add_argument("--output", default="c") + + args = parser.parse_args(sys.argv[1:]) + if args.output == "python": + print_python_mapping_table(bits) + else: + print_mapping_table(bits) diff --git a/man/Makefile.am b/man/Makefile.am index d80a7cc..8ea48fc 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -7,6 +7,7 @@ dist_man3_MANS = $(shell find . -name "libevdev_*.3" -printf "%P\n") man_src = \ libevdev_enable_event_type.txt \ libevdev_get_abs_min.txt \ + libevdev_get_event_type_name.txt\ libevdev_get_name.txt \ libevdev_get_num_slots.txt \ libevdev_get_phys.txt \ diff --git a/man/libevdev_get_event_type_name.txt b/man/libevdev_get_event_type_name.txt new file mode 100644 index 0000000..caa0651 --- /dev/null +++ b/man/libevdev_get_event_type_name.txt @@ -0,0 +1,71 @@ +libevdev_get_event_type_name(3) +=============================== + +NAME +---- + +libevdev_get_event_type_name, libevdev_get_event_code_name, libevdev_get_input_prop_name - get the name of the event type, code or input property + +SYNOPSIS +-------- + +#include + +const char * libevdev_get_event_type_name(unsigned int type); + +const char * libevdev_get_event_code_name(unsigned int type, unsigned int code); + +const char * libevdev_get_input_prop_name(unsigned int prop); + +DESCRIPTION +----------- +*libevdev_get_event_type_name*, *libevdev_get_event_code_name* and +*libevdev_get_input_prop_name* are helper functions for callers that need to +display the symbolic name of an event type or code or an input property. + +*libevdev_get_event_type_name* returns the name of the event type as string. +Possible return values include EV_SYN, EV_REL, EV_ABS, EV_LED, etc. + +*libevdev_get_event_code_name* returns the name of the event code as string. +Possible return values include ABS_X, ABS_Y, REL_X, BTN_TOOL_DOUBLETAP, etc. + +*libevdev_get_input_prop_name* returns the name of the input property as +string. Possible return values include INPUT_PROP_BUTTONPAD, +INPUT_PROP_POINTER, etc. + +PARAMETERS +---------- +*type*:: + Specifies the event type to query. The valid range for 'type' is 0 to + EV_MAX. + +*code*:: + Specifies the event code to query. The valid range for 'code' + depends on the 'type' and is defined in . For + example, for 'type' EV_ABS, the range is 0 to 'ABS_MAX'. + +*prop*:: + Specifies the input property to query. The valid range for 'prop' is + 0 to INPUT_PROP_MAX. + + +RETURN VALUE +------------ +On success, *libevdev_get_event_type_name* and *libevdev_get_event_code_name* return +the symbolic name of the event type or code. If no such name is defined or +'type' or 'code' are outside of the valid range, NULL is returned. + + +On success, *libevdev_get_input_prop_name* returns the symbolic name of the +input property. If no such name is defined or 'prop' is outside +of the valid range, NULL is returned. + +NOTES +----- +Use with caution. +The set of event names is built into libevdev and does not change even if +the underlying kernel changes the set of symbolic names. It is the set of +event names as defined on the host libevdev was built on. A rebuild of +libevdev is required to sync the event names with linux/input.h. +This affects both event names and ranges. +