libevdev 1.5.4 sandbox/jeon/devel
authorJengHyun Kang <jhyuni.kang@samsung.com>
Tue, 22 Nov 2016 09:31:47 +0000 (18:31 +0900)
committerJengHyun Kang <jhyuni.kang@samsung.com>
Tue, 22 Nov 2016 09:31:47 +0000 (18:31 +0900)
38 files changed:
.gitignore
configure.ac
doc/libevdev.doxygen.in
include/linux/input-event-codes.h [new file with mode: 0644]
include/linux/input.h
include/linux/uinput.h [new file with mode: 0644]
libevdev/Makefile.am
libevdev/libevdev-int.h
libevdev/libevdev-names.c
libevdev/libevdev-uinput-int.h
libevdev/libevdev-uinput.c
libevdev/libevdev-uinput.h
libevdev/libevdev-util.h
libevdev/libevdev.c
libevdev/libevdev.h
libevdev/libevdev.sym
libevdev/make-event-names.py
m4/attributes.m4
packaging/libevdev.spec
test/Makefile.am
test/test-common-uinput.c
test/test-common-uinput.h
test/test-common.c
test/test-common.h
test/test-event-codes.c
test/test-event-names.c
test/test-int-queue.c
test/test-kernel.c
test/test-libevdev-events.c
test/test-libevdev-has-event.c
test/test-libevdev-init.c
test/valgrind.suppressions
tools/.gitignore
tools/Makefile.am
tools/libevdev-events.c
tools/libevdev-tweak-device.c [new file with mode: 0644]
tools/mouse-dpi-tool.c [new file with mode: 0644]
tools/touchpad-edge-detector.c

index 957e4c03bb406f2ed2cfd53f44762e26943e7fb0..9fd134f485968eb8b1da2b721e1451edae993ed5 100644 (file)
@@ -68,3 +68,6 @@ texinfo.tex
 .vimdir
 ylwrap
 #      Application Specific Files
+*.trs
+*.log
+*.sig
index dc17109aebb9d9e4035951dd26c2cce5931ec336..ee6861432e5840a941137562d75bcc87ef494e14 100644 (file)
@@ -21,7 +21,7 @@
 AC_PREREQ([2.62])
 
 AC_INIT([libevdev],
-        [1.2.2],
+        [1.5.4],
         [https://bugs.freedesktop.org/enter_bug.cgi?product=libevdev],
         [libevdev],
         [http://freedesktop.org/wiki/Software/libevdev/])
@@ -42,7 +42,7 @@ AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz])
 # - If binary compatibility has been broken (eg removed or changed interfaces)
 #   change to C+1:0:0
 # - If the interface is the same as the previous version, change to C:R+1:A
-LIBEVDEV_LT_VERSION=2:3:0
+LIBEVDEV_LT_VERSION=3:16:1
 AC_SUBST(LIBEVDEV_LT_VERSION)
 
 
@@ -66,6 +66,8 @@ if test "x$lt_cv_prog_gnu_ld" = "xyes"; then
 fi
 AC_SUBST([GNU_LD_FLAGS], $with_ldflags)
 
+AC_CHECK_LIB([m], [round])
+
 PKG_PROG_PKG_CONFIG()
 PKG_CHECK_MODULES(CHECK, [check >= 0.9.9], [HAVE_CHECK="yes"], [HAVE_CHECK="no"])
 if test "x$HAVE_CHECK" = "xyes"; then
@@ -74,7 +76,8 @@ else
        AC_MSG_WARN([check not found - skipping building unit tests])
 fi
 AM_CONDITIONAL(HAVE_VALGRIND, [test "x$VALGRIND" != "x"])
-AM_CONDITIONAL(BUILD_TESTS, [test "x$HAVE_CHECK" = "xyes"])
+AM_CONDITIONAL(ENABLE_RUNTIME_TESTS, [test "x$HAVE_CHECK" = "xyes"])
+AM_CONDITIONAL(ENABLE_STATIC_LINK_TEST, [test "x$enable_static" = "xyes"])
 
 with_cflags=""
 if test "x$GCC" = "xyes"; then
@@ -118,14 +121,32 @@ AS_IF([test "x$enable_gcov" != "xno"],
        enable_gcov=yes
        ],
 )
-
-AM_PATH_PYTHON([2.6])
-
 AM_CONDITIONAL([GCOV_ENABLED], [test "x$enable_gcov" != "xno"])
 AC_SUBST([GCOV_CFLAGS])
 AC_SUBST([GCOV_LDFLAGS])
 AC_MSG_RESULT([$enable_gcov])
 
+AM_PATH_PYTHON([2.6])
+AC_PATH_PROG(CAT, [cat])
+
+# nm to check for leaking symbols in the static library
+AC_PATH_PROG(NM, [nm])
+AM_CONDITIONAL(HAVE_NM, [test "x$NM" != "x"])
+if test "x$enable_static" = "xno"; then
+       static_symbol_leaks_test="no - static build disabled"
+else
+       if test "x$NM" = "x"; then
+               AC_MSG_WARN([nm not found - skipping symbol leak test])
+               have_nm="no"
+               static_symbol_leaks_test="no - nm not found"
+       else
+               have_nm="yes"
+               static_symbol_leaks_test="yes"
+       fi
+fi
+
+AM_CONDITIONAL(ENABLE_STATIC_SYMBOL_LEAKS_TEST, [test "x$static_symbol_leaks_test" = "xyes"])
+
 AC_CONFIG_FILES([Makefile
                 libevdev/Makefile
                 doc/Makefile
@@ -137,7 +158,11 @@ AC_CONFIG_FILES([Makefile
 AC_OUTPUT
 
 AC_MSG_RESULT([
-              Build documentation      ${have_doxygen}
-              Build unit-tests         ${HAVE_CHECK}
-              Enable profiling         ${enable_gcov}
+              Prefix                           ${prefix}
+              Libdir                           ${libdir}
+
+              Build documentation              ${have_doxygen}
+              Enable unit-tests                ${HAVE_CHECK}
+              Enable profiling                 ${enable_gcov}
+              Static library symbol check      ${static_symbol_leaks_test}
               ])
index 853c47d81a92699fb7ab5712a769a920ba370e46..d64efa97b1af0d731c27d1f1bd7b18dda6f94535 100644 (file)
-# Doxyfile 1.8.3.1
-
-# This file describes the settings to be used by the documentation system
-# doxygen (www.doxygen.org) for a project.
-#
-# All text after a hash (#) is considered a comment and will be ignored.
-# The format is:
-#       TAG = value [value, ...]
-# For lists items can also be appended using:
-#       TAG += value [value, ...]
-# Values that contain spaces should be placed between quotes (" ").
-
-#---------------------------------------------------------------------------
-# Project related configuration options
-#---------------------------------------------------------------------------
-
-# This tag specifies the encoding used for all characters in the config file
-# that follow. The default is UTF-8 which is also the encoding used for all
-# text before the first occurrence of this tag. Doxygen uses libiconv (or the
-# iconv built into libc) for the transcoding. See
-# http://www.gnu.org/software/libiconv for the list of possible encodings.
-
-DOXYFILE_ENCODING      = UTF-8
-
-# The PROJECT_NAME tag is a single word (or sequence of words) that should
-# identify the project. Note that if you do not use Doxywizard you need
-# to put quotes around the project name if it contains spaces.
-
 PROJECT_NAME           = @PACKAGE_NAME@
-
-# The PROJECT_NUMBER tag can be used to enter a project or revision number.
-# This could be handy for archiving the generated documentation or
-# if some version control system is used.
-
 PROJECT_NUMBER         = @PACKAGE_VERSION@
-
-# Using the PROJECT_BRIEF tag one can provide an optional one line description
-# for a project that appears at the top of each page and should give viewer
-# a quick idea about the purpose of the project. Keep the description short.
-
 PROJECT_BRIEF          = "A wrapper library for evdev devices"
-
-# With the PROJECT_LOGO tag one can specify an logo or icon that is
-# included in the documentation. The maximum height of the logo should not
-# exceed 55 pixels and the maximum width should not exceed 200 pixels.
-# Doxygen will copy the logo to the output directory.
-
-PROJECT_LOGO           =
-
-# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
-# base path where the generated documentation will be put.
-# If a relative path is entered, it will be relative to the location
-# where doxygen was started. If left blank the current directory will be used.
-
-OUTPUT_DIRECTORY       =
-
-# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
-# 4096 sub-directories (in 2 levels) under the output directory of each output
-# format and will distribute the generated files over these directories.
-# Enabling this option can be useful when feeding doxygen a huge amount of
-# source files, where putting all generated files in the same directory would
-# otherwise cause performance problems for the file system.
-
-CREATE_SUBDIRS         = NO
-
-# The OUTPUT_LANGUAGE tag is used to specify the language in which all
-# documentation generated by doxygen is written. Doxygen will use this
-# information to generate all constant output in the proper language.
-# The default language is English, other supported languages are:
-# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
-# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
-# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
-# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
-# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
-# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
-
-OUTPUT_LANGUAGE        = English
-
-# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
-# include brief member descriptions after the members that are listed in
-# the file and class documentation (similar to JavaDoc).
-# Set to NO to disable this.
-
-BRIEF_MEMBER_DESC      = YES
-
-# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
-# the brief description of a member or function before the detailed description.
-# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
-# brief descriptions will be completely suppressed.
-
-REPEAT_BRIEF           = YES
-
-# This tag implements a quasi-intelligent brief description abbreviator
-# that is used to form the text in various listings. Each string
-# in this list, if found as the leading text of the brief description, will be
-# stripped from the text and the result after processing the whole list, is
-# used as the annotated text. Otherwise, the brief description is used as-is.
-# If left blank, the following values are used ("$name" is automatically
-# replaced with the name of the entity): "The $name class" "The $name widget"
-# "The $name file" "is" "provides" "specifies" "contains"
-# "represents" "a" "an" "the"
-
-ABBREVIATE_BRIEF       =
-
-# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
-# Doxygen will generate a detailed section even if there is only a brief
-# description.
-
-ALWAYS_DETAILED_SEC    = NO
-
-# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
-# inherited members of a class in the documentation of that class as if those
-# members were ordinary class members. Constructors, destructors and assignment
-# operators of the base classes will not be shown.
-
-INLINE_INHERITED_MEMB  = NO
-
-# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
-# path before files name in the file list and in the header files. If set
-# to NO the shortest path that makes the file name unique will be used.
-
-FULL_PATH_NAMES        = YES
-
-# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
-# can be used to strip a user-defined part of the path. Stripping is
-# only done if one of the specified strings matches the left-hand part of
-# the path. The tag can be used to show relative paths in the file list.
-# If left blank the directory from which doxygen is run is used as the
-# path to strip. Note that you specify absolute paths here, but also
-# relative paths, which will be relative from the directory where doxygen is
-# started.
-
-STRIP_FROM_PATH        =
-
-# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
-# the path mentioned in the documentation of a class, which tells
-# the reader which header file to include in order to use a class.
-# If left blank only the name of the header file containing the class
-# definition is used. Otherwise one should specify the include paths that
-# are normally passed to the compiler using the -I flag.
-
-STRIP_FROM_INC_PATH    =
-
-# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
-# (but less readable) file names. This can be useful if your file system
-# doesn't support long names like on DOS, Mac, or CD-ROM.
-
-SHORT_NAMES            = NO
-
-# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
-# will interpret the first line (until the first dot) of a JavaDoc-style
-# comment as the brief description. If set to NO, the JavaDoc
-# comments will behave just like regular Qt-style comments
-# (thus requiring an explicit @brief command for a brief description.)
-
 JAVADOC_AUTOBRIEF      = YES
-
-# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
-# interpret the first line (until the first dot) of a Qt-style
-# comment as the brief description. If set to NO, the comments
-# will behave just like regular Qt-style comments (thus requiring
-# an explicit \brief command for a brief description.)
-
-QT_AUTOBRIEF           = NO
-
-# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
-# treat a multi-line C++ special comment block (i.e. a block of //! or ///
-# comments) as a brief description. This used to be the default behaviour.
-# The new default is to treat a multi-line C++ comment block as a detailed
-# description. Set this tag to YES if you prefer the old behaviour instead.
-
-MULTILINE_CPP_IS_BRIEF = NO
-
-# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
-# member inherits the documentation from any documented member that it
-# re-implements.
-
-INHERIT_DOCS           = YES
-
-# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
-# a new page for each member. If set to NO, the documentation of a member will
-# be part of the file/class/namespace that contains it.
-
-SEPARATE_MEMBER_PAGES  = NO
-
-# The TAB_SIZE tag can be used to set the number of spaces in a tab.
-# Doxygen uses this value to replace tabs by spaces in code fragments.
-
 TAB_SIZE               = 8
-
-# This tag can be used to specify a number of aliases that acts
-# as commands in the documentation. An alias has the form "name=value".
-# For example adding "sideeffect=\par Side Effects:\n" will allow you to
-# put the command \sideeffect (or @sideeffect) in the documentation, which
-# will result in a user-defined paragraph with heading "Side Effects:".
-# You can put \n's in the value part of an alias to insert newlines.
-
-ALIASES                =
-
-# This tag can be used to specify a number of word-keyword mappings (TCL only).
-# A mapping has the form "name=value". For example adding
-# "class=itcl::class" will allow you to use the command class in the
-# itcl::class meaning.
-
-TCL_SUBST              =
-
-# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
-# sources only. Doxygen will then generate output that is more tailored for C.
-# For instance, some of the names that are used will be different. The list
-# of all members will be omitted, etc.
-
 OPTIMIZE_OUTPUT_FOR_C  = YES
-
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
-# sources only. Doxygen will then generate output that is more tailored for
-# Java. For instance, namespaces will be presented as packages, qualified
-# scopes will look different, etc.
-
-OPTIMIZE_OUTPUT_JAVA   = NO
-
-# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
-# sources only. Doxygen will then generate output that is more tailored for
-# Fortran.
-
-OPTIMIZE_FOR_FORTRAN   = NO
-
-# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
-# sources. Doxygen will then generate output that is tailored for
-# VHDL.
-
-OPTIMIZE_OUTPUT_VHDL   = NO
-
-# Doxygen selects the parser to use depending on the extension of the files it
-# parses. With this tag you can assign which parser to use for a given
-# extension. Doxygen has a built-in mapping, but you can override or extend it
-# using this tag. The format is ext=language, where ext is a file extension,
-# and language is one of the parsers supported by doxygen: IDL, Java,
-# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C,
-# C++. For instance to make doxygen treat .inc files as Fortran files (default
-# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note
-# that for custom extensions you also need to set FILE_PATTERNS otherwise the
-# files are not read by doxygen.
-
-EXTENSION_MAPPING      =
-
-# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all
-# comments according to the Markdown format, which allows for more readable
-# documentation. See http://daringfireball.net/projects/markdown/ for details.
-# The output of markdown processing is further processed by doxygen, so you
-# can mix doxygen, HTML, and XML commands with Markdown formatting.
-# Disable only in case of backward compatibilities issues.
-
-MARKDOWN_SUPPORT       = YES
-
-# When enabled doxygen tries to link words that correspond to documented classes,
-# or namespaces to their corresponding documentation. Such a link can be
-# prevented in individual cases by by putting a % sign in front of the word or
-# globally by setting AUTOLINK_SUPPORT to NO.
-
-AUTOLINK_SUPPORT       = YES
-
-# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
-# to include (a tag file for) the STL sources as input, then you should
-# set this tag to YES in order to let doxygen match functions declarations and
-# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
-# func(std::string) {}). This also makes the inheritance and collaboration
-# diagrams that involve STL classes more complete and accurate.
-
-BUILTIN_STL_SUPPORT    = NO
-
-# If you use Microsoft's C++/CLI language, you should set this option to YES to
-# enable parsing support.
-
-CPP_CLI_SUPPORT        = NO
-
-# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
-# Doxygen will parse them like normal C++ but will assume all classes use public
-# instead of private inheritance when no explicit protection keyword is present.
-
-SIP_SUPPORT            = NO
-
-# For Microsoft's IDL there are propget and propput attributes to indicate
-# getter and setter methods for a property. Setting this option to YES (the
-# default) will make doxygen replace the get and set methods by a property in
-# the documentation. This will only work if the methods are indeed getting or
-# setting a simple type. If this is not the case, or you want to show the
-# methods anyway, you should set this option to NO.
-
-IDL_PROPERTY_SUPPORT   = YES
-
-# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
-# tag is set to YES, then doxygen will reuse the documentation of the first
-# member in the group (if any) for the other members of the group. By default
-# all members of a group must be documented explicitly.
-
-DISTRIBUTE_GROUP_DOC   = NO
-
-# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
-# the same type (for instance a group of public functions) to be put as a
-# subgroup of that type (e.g. under the Public Functions section). Set it to
-# NO to prevent subgrouping. Alternatively, this can be done per class using
-# the \nosubgrouping command.
-
-SUBGROUPING            = YES
-
-# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
-# unions are shown inside the group in which they are included (e.g. using
-# @ingroup) instead of on a separate page (for HTML and Man pages) or
-# section (for LaTeX and RTF).
-
-INLINE_GROUPED_CLASSES = NO
-
-# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
-# unions with only public data fields will be shown inline in the documentation
-# of the scope in which they are defined (i.e. file, namespace, or group
-# documentation), provided this scope is documented. If set to NO (the default),
-# structs, classes, and unions are shown on a separate page (for HTML and Man
-# pages) or section (for LaTeX and RTF).
-
-INLINE_SIMPLE_STRUCTS  = NO
-
-# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
-# is documented as struct, union, or enum with the name of the typedef. So
-# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
-# with name TypeT. When disabled the typedef will appear as a member of a file,
-# namespace, or class. And the struct will be named TypeS. This can typically
-# be useful for C code in case the coding convention dictates that all compound
-# types are typedef'ed and only the typedef is referenced, never the tag name.
-
-TYPEDEF_HIDES_STRUCT   = NO
-
-# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be
-# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given
-# their name and scope. Since this can be an expensive process and often the
-# same symbol appear multiple times in the code, doxygen keeps a cache of
-# pre-resolved symbols. If the cache is too small doxygen will become slower.
-# If the cache is too large, memory is wasted. The cache size is given by this
-# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0,
-# corresponding to a cache size of 2^16 = 65536 symbols.
-
-LOOKUP_CACHE_SIZE      = 0
-
-#---------------------------------------------------------------------------
-# Build related configuration options
-#---------------------------------------------------------------------------
-
-# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
-# documentation are documented, even if no documentation was available.
-# Private class members and static file members will be hidden unless
-# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
-
 EXTRACT_ALL            = YES
-
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
-# will be included in the documentation.
-
-EXTRACT_PRIVATE        = NO
-
-# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
-# scope will be included in the documentation.
-
-EXTRACT_PACKAGE        = NO
-
-# If the EXTRACT_STATIC tag is set to YES all static members of a file
-# will be included in the documentation.
-
-EXTRACT_STATIC         = NO
-
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
-# defined locally in source files will be included in the documentation.
-# If set to NO only classes defined in header files are included.
-
-EXTRACT_LOCAL_CLASSES  = YES
-
-# This flag is only useful for Objective-C code. When set to YES local
-# methods, which are defined in the implementation section but not in
-# the interface are included in the documentation.
-# If set to NO (the default) only methods in the interface are included.
-
-EXTRACT_LOCAL_METHODS  = NO
-
-# If this flag is set to YES, the members of anonymous namespaces will be
-# extracted and appear in the documentation as a namespace called
-# 'anonymous_namespace{file}', where file will be replaced with the base
-# name of the file that contains the anonymous namespace. By default
-# anonymous namespaces are hidden.
-
-EXTRACT_ANON_NSPACES   = NO
-
-# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
-# undocumented members of documented classes, files or namespaces.
-# If set to NO (the default) these members will be included in the
-# various overviews, but no documentation section is generated.
-# This option has no effect if EXTRACT_ALL is enabled.
-
-HIDE_UNDOC_MEMBERS     = NO
-
-# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
-# undocumented classes that are normally visible in the class hierarchy.
-# If set to NO (the default) these classes will be included in the various
-# overviews. This option has no effect if EXTRACT_ALL is enabled.
-
-HIDE_UNDOC_CLASSES     = NO
-
-# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
-# friend (class|struct|union) declarations.
-# If set to NO (the default) these declarations will be included in the
-# documentation.
-
-HIDE_FRIEND_COMPOUNDS  = NO
-
-# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
-# documentation blocks found inside the body of a function.
-# If set to NO (the default) these blocks will be appended to the
-# function's detailed documentation block.
-
-HIDE_IN_BODY_DOCS      = NO
-
-# The INTERNAL_DOCS tag determines if documentation
-# that is typed after a \internal command is included. If the tag is set
-# to NO (the default) then the documentation will be excluded.
-# Set it to YES to include the internal documentation.
-
-INTERNAL_DOCS          = NO
-
-# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
-# file names in lower-case letters. If set to YES upper-case letters are also
-# allowed. This is useful if you have classes or files whose names only differ
-# in case and if your file system supports case sensitive file names. Windows
-# and Mac users are advised to set this option to NO.
-
-CASE_SENSE_NAMES       = YES
-
-# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
-# will show members with their full class and namespace scopes in the
-# documentation. If set to YES the scope will be hidden.
-
-HIDE_SCOPE_NAMES       = NO
-
-# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
-# will put a list of the files that are included by a file in the documentation
-# of that file.
-
-SHOW_INCLUDE_FILES     = YES
-
-# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
-# will list include files with double quotes in the documentation
-# rather than with sharp brackets.
-
-FORCE_LOCAL_INCLUDES   = NO
-
-# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
-# is inserted in the documentation for inline members.
-
-INLINE_INFO            = YES
-
-# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
-# will sort the (detailed) documentation of file and class members
-# alphabetically by member name. If set to NO the members will appear in
-# declaration order.
-
-SORT_MEMBER_DOCS       = YES
-
-# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
-# brief documentation of file, namespace and class members alphabetically
-# by member name. If set to NO (the default) the members will appear in
-# declaration order.
-
-SORT_BRIEF_DOCS        = NO
-
-# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
-# will sort the (brief and detailed) documentation of class members so that
-# constructors and destructors are listed first. If set to NO (the default)
-# the constructors will appear in the respective orders defined by
-# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
-# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
-# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
-
-SORT_MEMBERS_CTORS_1ST = NO
-
-# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
-# hierarchy of group names into alphabetical order. If set to NO (the default)
-# the group names will appear in their defined order.
-
-SORT_GROUP_NAMES       = NO
-
-# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
-# sorted by fully-qualified names, including namespaces. If set to
-# NO (the default), the class list will be sorted only by class name,
-# not including the namespace part.
-# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
-# Note: This option applies only to the class list, not to the
-# alphabetical list.
-
-SORT_BY_SCOPE_NAME     = NO
-
-# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
-# do proper type resolution of all parameters of a function it will reject a
-# match between the prototype and the implementation of a member function even
-# if there is only one candidate or it is obvious which candidate to choose
-# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
-# will still accept a match between prototype and implementation in such cases.
-
-STRICT_PROTO_MATCHING  = NO
-
-# The GENERATE_TODOLIST tag can be used to enable (YES) or
-# disable (NO) the todo list. This list is created by putting \todo
-# commands in the documentation.
-
-GENERATE_TODOLIST      = YES
-
-# The GENERATE_TESTLIST tag can be used to enable (YES) or
-# disable (NO) the test list. This list is created by putting \test
-# commands in the documentation.
-
-GENERATE_TESTLIST      = YES
-
-# The GENERATE_BUGLIST tag can be used to enable (YES) or
-# disable (NO) the bug list. This list is created by putting \bug
-# commands in the documentation.
-
-GENERATE_BUGLIST       = YES
-
-# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
-# disable (NO) the deprecated list. This list is created by putting
-# \deprecated commands in the documentation.
-
-GENERATE_DEPRECATEDLIST= YES
-
-# The ENABLED_SECTIONS tag can be used to enable conditional
-# documentation sections, marked by \if section-label ... \endif
-# and \cond section-label ... \endcond blocks.
-
-ENABLED_SECTIONS       =
-
-# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
-# the initial value of a variable or macro consists of for it to appear in
-# the documentation. If the initializer consists of more lines than specified
-# here it will be hidden. Use a value of 0 to hide initializers completely.
-# The appearance of the initializer of individual variables and macros in the
-# documentation can be controlled using \showinitializer or \hideinitializer
-# command in the documentation regardless of this setting.
-
 MAX_INITIALIZER_LINES  = 0
-
-# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
-# at the bottom of the documentation of classes and structs. If set to YES the
-# list will mention the files that were used to generate the documentation.
-
-SHOW_USED_FILES        = YES
-
-# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
-# This will remove the Files entry from the Quick Index and from the
-# Folder Tree View (if specified). The default is YES.
-
-SHOW_FILES             = YES
-
-# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
-# Namespaces page.
-# This will remove the Namespaces entry from the Quick Index
-# and from the Folder Tree View (if specified). The default is YES.
-
-SHOW_NAMESPACES        = YES
-
-# The FILE_VERSION_FILTER tag can be used to specify a program or script that
-# doxygen should invoke to get the current version for each file (typically from
-# the version control system). Doxygen will invoke the program by executing (via
-# popen()) the command <command> <input-file>, where <command> is the value of
-# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
-# provided by doxygen. Whatever the program writes to standard output
-# is used as the file version. See the manual for examples.
-
-FILE_VERSION_FILTER    =
-
-# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
-# by doxygen. The layout file controls the global structure of the generated
-# output files in an output format independent way. To create the layout file
-# that represents doxygen's defaults, run doxygen with the -l option.
-# You can optionally specify a file name after the option, if omitted
-# DoxygenLayout.xml will be used as the name of the layout file.
-
-LAYOUT_FILE            =
-
-# The CITE_BIB_FILES tag can be used to specify one or more bib files
-# containing the references data. This must be a list of .bib files. The
-# .bib extension is automatically appended if omitted. Using this command
-# requires the bibtex tool to be installed. See also
-# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
-# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
-# feature you need bibtex and perl available in the search path. Do not use
-# file names with spaces, bibtex cannot handle them.
-
-CITE_BIB_FILES         =
-
-#---------------------------------------------------------------------------
-# configuration options related to warning and progress messages
-#---------------------------------------------------------------------------
-
-# The QUIET tag can be used to turn on/off the messages that are generated
-# by doxygen. Possible values are YES and NO. If left blank NO is used.
-
 QUIET                  = YES
-
-# The WARNINGS tag can be used to turn on/off the warning messages that are
-# generated by doxygen. Possible values are YES and NO. If left blank
-# NO is used.
-
-WARNINGS               = YES
-
-# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
-# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
-# automatically be disabled.
-
-WARN_IF_UNDOCUMENTED   = YES
-
-# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
-# potential errors in the documentation, such as not documenting some
-# parameters in a documented function, or documenting parameters that
-# don't exist or using markup commands wrongly.
-
-WARN_IF_DOC_ERROR      = YES
-
-# The WARN_NO_PARAMDOC option can be enabled to get warnings for
-# functions that are documented, but have no documentation for their parameters
-# or return value. If set to NO (the default) doxygen will only warn about
-# wrong or incomplete parameter documentation, but not about the absence of
-# documentation.
-
-WARN_NO_PARAMDOC       = NO
-
-# The WARN_FORMAT tag determines the format of the warning messages that
-# doxygen can produce. The string should contain the $file, $line, and $text
-# tags, which will be replaced by the file and line number from which the
-# warning originated and the warning text. Optionally the format may contain
-# $version, which will be replaced by the version of the file (if it could
-# be obtained via FILE_VERSION_FILTER)
-
-WARN_FORMAT            = "$file:$line: $text"
-
-# The WARN_LOGFILE tag can be used to specify a file to which warning
-# and error messages should be written. If left blank the output is written
-# to stderr.
-
-WARN_LOGFILE           =
-
-#---------------------------------------------------------------------------
-# configuration options related to the input files
-#---------------------------------------------------------------------------
-
-# The INPUT tag can be used to specify the files and/or directories that contain
-# documented source files. You may enter file names like "myfile.cpp" or
-# directories like "/usr/src/myproject". Separate the files or directories
-# with spaces.
-
 INPUT                  = @top_srcdir@/libevdev/libevdev.h \
-                        @top_srcdir@/libevdev/libevdev-uinput.h
-
-# This tag can be used to specify the character encoding of the source files
-# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
-# also the default input encoding. Doxygen uses libiconv (or the iconv built
-# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
-# the list of possible encodings.
-
-INPUT_ENCODING         = UTF-8
-
-# If the value of the INPUT tag contains directories, you can use the
-# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
-# and *.h) to filter out the source-files in the directories. If left
-# blank the following patterns are tested:
-# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
-# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
-# *.f90 *.f *.for *.vhd *.vhdl
-
-FILE_PATTERNS          =
-
-# The RECURSIVE tag can be used to turn specify whether or not subdirectories
-# should be searched for input files as well. Possible values are YES and NO.
-# If left blank NO is used.
-
-RECURSIVE              = NO
-
-# The EXCLUDE tag can be used to specify files and/or directories that should be
-# excluded from the INPUT source files. This way you can easily exclude a
-# subdirectory from a directory tree whose root is specified with the INPUT tag.
-# Note that relative paths are relative to the directory from which doxygen is
-# run.
-
-EXCLUDE                =
-
-# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
-# directories that are symbolic links (a Unix file system feature) are excluded
-# from the input.
-
-EXCLUDE_SYMLINKS       = NO
-
-# If the value of the INPUT tag contains directories, you can use the
-# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
-# certain files from those directories. Note that the wildcards are matched
-# against the file with absolute path, so to exclude all test directories
-# for example use the pattern */test/*
-
-EXCLUDE_PATTERNS       =
-
-# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
-# (namespaces, classes, functions, etc.) that should be excluded from the
-# output. The symbol name can be a fully qualified name, a word, or if the
-# wildcard * is used, a substring. Examples: ANamespace, AClass,
-# AClass::ANamespace, ANamespace::*Test
-
-EXCLUDE_SYMBOLS        =
-
-# The EXAMPLE_PATH tag can be used to specify one or more files or
-# directories that contain example code fragments that are included (see
-# the \include command).
-
+                         @top_srcdir@/libevdev/libevdev-uinput.h
 EXAMPLE_PATH           = @top_srcdir@/include
-
-# If the value of the EXAMPLE_PATH tag contains directories, you can use the
-# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
-# and *.h) to filter out the source-files in the directories. If left
-# blank all files are included.
-
-EXAMPLE_PATTERNS       =
-
-# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
-# searched for input files to be used with the \include or \dontinclude
-# commands irrespective of the value of the RECURSIVE tag.
-# Possible values are YES and NO. If left blank NO is used.
-
-EXAMPLE_RECURSIVE      = NO
-
-# The IMAGE_PATH tag can be used to specify one or more files or
-# directories that contain image that are included in the documentation (see
-# the \image command).
-
-IMAGE_PATH             =
-
-# The INPUT_FILTER tag can be used to specify a program that doxygen should
-# invoke to filter for each input file. Doxygen will invoke the filter program
-# by executing (via popen()) the command <filter> <input-file>, where <filter>
-# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
-# input file. Doxygen will then use the output that the filter program writes
-# to standard output.
-# If FILTER_PATTERNS is specified, this tag will be
-# ignored.
-
-INPUT_FILTER           =
-
-# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
-# basis.
-# Doxygen will compare the file name with each pattern and apply the
-# filter if there is a match.
-# The filters are a list of the form:
-# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
-# info on how filters are used. If FILTER_PATTERNS is empty or if
-# non of the patterns match the file name, INPUT_FILTER is applied.
-
-FILTER_PATTERNS        =
-
-# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
-# INPUT_FILTER) will be used to filter the input files when producing source
-# files to browse (i.e. when SOURCE_BROWSER is set to YES).
-
-FILTER_SOURCE_FILES    = NO
-
-# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
-# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
-# and it is also possible to disable source filtering for a specific pattern
-# using *.ext= (so without naming a filter). This option only has effect when
-# FILTER_SOURCE_FILES is enabled.
-
-FILTER_SOURCE_PATTERNS =
-
-# If the USE_MD_FILE_AS_MAINPAGE tag refers to the name of a markdown file that
-# is part of the input, its contents will be placed on the main page (index.html).
-# This can be useful if you have a project on for instance GitHub and want reuse
-# the introduction page also for the doxygen output.
-
-USE_MDFILE_AS_MAINPAGE =
-
-#---------------------------------------------------------------------------
-# configuration options related to source browsing
-#---------------------------------------------------------------------------
-
-# If the SOURCE_BROWSER tag is set to YES then a list of source files will
-# be generated. Documented entities will be cross-referenced with these sources.
-# Note: To get rid of all source code in the generated output, make sure also
-# VERBATIM_HEADERS is set to NO.
-
-SOURCE_BROWSER         = NO
-
-# Setting the INLINE_SOURCES tag to YES will include the body
-# of functions and classes directly in the documentation.
-
-INLINE_SOURCES         = NO
-
-# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
-# doxygen to hide any special comment blocks from generated source code
-# fragments. Normal C, C++ and Fortran comments will always remain visible.
-
-STRIP_CODE_COMMENTS    = YES
-
-# If the REFERENCED_BY_RELATION tag is set to YES
-# then for each documented function all documented
-# functions referencing it will be listed.
-
-REFERENCED_BY_RELATION = NO
-
-# If the REFERENCES_RELATION tag is set to YES
-# then for each documented function all documented entities
-# called/used by that function will be listed.
-
-REFERENCES_RELATION    = NO
-
-# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
-# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
-# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
-# link to the source code.
-# Otherwise they will link to the documentation.
-
-REFERENCES_LINK_SOURCE = YES
-
-# If the USE_HTAGS tag is set to YES then the references to source code
-# will point to the HTML generated by the htags(1) tool instead of doxygen
-# built-in source browser. The htags tool is part of GNU's global source
-# tagging system (see http://www.gnu.org/software/global/global.html). You
-# will need version 4.8.6 or higher.
-
-USE_HTAGS              = NO
-
-# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
-# will generate a verbatim copy of the header file for each class for
-# which an include is specified. Set to NO to disable this.
-
-VERBATIM_HEADERS       = YES
-
-#---------------------------------------------------------------------------
-# configuration options related to the alphabetical class index
-#---------------------------------------------------------------------------
-
-# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
-# of all compounds will be generated. Enable this if the project
-# contains a lot of classes, structs, unions or interfaces.
-
-ALPHABETICAL_INDEX     = YES
-
-# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
-# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
-# in which this list will be split (can be a number in the range [1..20])
-
-COLS_IN_ALPHA_INDEX    = 5
-
-# In case all classes in a project start with a common prefix, all
-# classes will be put under the same header in the alphabetical index.
-# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
-# should be ignored while generating the index headers.
-
-IGNORE_PREFIX          =
-
-#---------------------------------------------------------------------------
-# configuration options related to the HTML output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
-# generate HTML output.
-
 GENERATE_HTML          = YES
-
-# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `html' will be used as the default path.
-
-HTML_OUTPUT            = html
-
-# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
-# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
-# doxygen will generate files with .html extension.
-
-HTML_FILE_EXTENSION    = .html
-
-# The HTML_HEADER tag can be used to specify a personal HTML header for
-# each generated HTML page. If it is left blank doxygen will generate a
-# standard header. Note that when using a custom header you are responsible
-#  for the proper inclusion of any scripts and style sheets that doxygen
-# needs, which is dependent on the configuration options used.
-# It is advised to generate a default header using "doxygen -w html
-# header.html footer.html stylesheet.css YourConfigFile" and then modify
-# that header. Note that the header is subject to change so you typically
-# have to redo this when upgrading to a newer version of doxygen or when
-# changing the value of configuration settings such as GENERATE_TREEVIEW!
-
-HTML_HEADER            =
-
-# The HTML_FOOTER tag can be used to specify a personal HTML footer for
-# each generated HTML page. If it is left blank doxygen will generate a
-# standard footer.
-
-HTML_FOOTER            =
-
-# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
-# style sheet that is used by each HTML page. It can be used to
-# fine-tune the look of the HTML output. If left blank doxygen will
-# generate a default style sheet. Note that it is recommended to use
-# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this
-# tag will in the future become obsolete.
-
-HTML_STYLESHEET        =
-
-# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional
-# user-defined cascading style sheet that is included after the standard
-# style sheets created by doxygen. Using this option one can overrule
-# certain style aspects. This is preferred over using HTML_STYLESHEET
-# since it does not replace the standard style sheet and is therefor more
-# robust against future updates. Doxygen will copy the style sheet file to
-# the output directory.
-
 HTML_EXTRA_STYLESHEET  = @srcdir@/libevdev.css
-
-# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
-# other source files which should be copied to the HTML output directory. Note
-# that these files will be copied to the base HTML output directory. Use the
-# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
-# files. In the HTML_STYLESHEET file, use the file name only. Also note that
-# the files will be copied as-is; there are no commands or markers available.
-
-HTML_EXTRA_FILES       =
-
-# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
-# Doxygen will adjust the colors in the style sheet and background images
-# according to this color. Hue is specified as an angle on a colorwheel,
-# see http://en.wikipedia.org/wiki/Hue for more information.
-# For instance the value 0 represents red, 60 is yellow, 120 is green,
-# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
-# The allowed range is 0 to 359.
-
-HTML_COLORSTYLE_HUE    = 220
-
-# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
-# the colors in the HTML output. For a value of 0 the output will use
-# grayscales only. A value of 255 will produce the most vivid colors.
-
-HTML_COLORSTYLE_SAT    = 100
-
-# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
-# the luminance component of the colors in the HTML output. Values below
-# 100 gradually make the output lighter, whereas values above 100 make
-# the output darker. The value divided by 100 is the actual gamma applied,
-# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
-# and 100 does not change the gamma.
-
-HTML_COLORSTYLE_GAMMA  = 80
-
-# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
-# page will contain the date and time when the page was generated. Setting
-# this to NO can help when comparing the output of multiple runs.
-
 HTML_TIMESTAMP         = YES
-
-# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
-# documentation will contain sections that can be hidden and shown after the
-# page has loaded.
-
-HTML_DYNAMIC_SECTIONS  = NO
-
-# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of
-# entries shown in the various tree structured indices initially; the user
-# can expand and collapse entries dynamically later on. Doxygen will expand
-# the tree to such a level that at most the specified number of entries are
-# visible (unless a fully collapsed tree already exceeds this amount).
-# So setting the number of entries 1 will produce a full collapsed tree by
-# default. 0 is a special value representing an infinite number of entries
-# and will result in a full expanded tree by default.
-
-HTML_INDEX_NUM_ENTRIES = 100
-
-# If the GENERATE_DOCSET tag is set to YES, additional index files
-# will be generated that can be used as input for Apple's Xcode 3
-# integrated development environment, introduced with OSX 10.5 (Leopard).
-# To create a documentation set, doxygen will generate a Makefile in the
-# HTML output directory. Running make will produce the docset in that
-# directory and running "make install" will install the docset in
-# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
-# it at startup.
-# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
-# for more information.
-
-GENERATE_DOCSET        = NO
-
-# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
-# feed. A documentation feed provides an umbrella under which multiple
-# documentation sets from a single provider (such as a company or product suite)
-# can be grouped.
-
-DOCSET_FEEDNAME        = "Doxygen generated docs"
-
-# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
-# should uniquely identify the documentation set bundle. This should be a
-# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
-# will append .docset to the name.
-
-DOCSET_BUNDLE_ID       = org.doxygen.Project
-
-# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely
-# identify the documentation publisher. This should be a reverse domain-name
-# style string, e.g. com.mycompany.MyDocSet.documentation.
-
-DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
-
-# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
-
-DOCSET_PUBLISHER_NAME  = Publisher
-
-# If the GENERATE_HTMLHELP tag is set to YES, additional index files
-# will be generated that can be used as input for tools like the
-# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
-# of the generated HTML documentation.
-
-GENERATE_HTMLHELP      = NO
-
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
-# be used to specify the file name of the resulting .chm file. You
-# can add a path in front of the file if the result should not be
-# written to the html output directory.
-
-CHM_FILE               =
-
-# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
-# be used to specify the location (absolute path including file name) of
-# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
-# the HTML help compiler on the generated index.hhp.
-
-HHC_LOCATION           =
-
-# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
-# controls if a separate .chi index file is generated (YES) or that
-# it should be included in the master .chm file (NO).
-
-GENERATE_CHI           = NO
-
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
-# is used to encode HtmlHelp index (hhk), content (hhc) and project file
-# content.
-
-CHM_INDEX_ENCODING     =
-
-# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
-# controls whether a binary table of contents is generated (YES) or a
-# normal table of contents (NO) in the .chm file.
-
-BINARY_TOC             = NO
-
-# The TOC_EXPAND flag can be set to YES to add extra items for group members
-# to the contents of the HTML help documentation and to the tree view.
-
-TOC_EXPAND             = NO
-
-# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
-# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
-# that can be used as input for Qt's qhelpgenerator to generate a
-# Qt Compressed Help (.qch) of the generated HTML documentation.
-
-GENERATE_QHP           = NO
-
-# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
-# be used to specify the file name of the resulting .qch file.
-# The path specified is relative to the HTML output folder.
-
-QCH_FILE               =
-
-# The QHP_NAMESPACE tag specifies the namespace to use when generating
-# Qt Help Project output. For more information please see
-# http://doc.trolltech.com/qthelpproject.html#namespace
-
-QHP_NAMESPACE          = org.doxygen.Project
-
-# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
-# Qt Help Project output. For more information please see
-# http://doc.trolltech.com/qthelpproject.html#virtual-folders
-
-QHP_VIRTUAL_FOLDER     = doc
-
-# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
-# add. For more information please see
-# http://doc.trolltech.com/qthelpproject.html#custom-filters
-
-QHP_CUST_FILTER_NAME   =
-
-# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
-# custom filter to add. For more information please see
-# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
-# Qt Help Project / Custom Filters</a>.
-
-QHP_CUST_FILTER_ATTRS  =
-
-# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
-# project's
-# filter section matches.
-# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
-# Qt Help Project / Filter Attributes</a>.
-
-QHP_SECT_FILTER_ATTRS  =
-
-# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
-# be used to specify the location of Qt's qhelpgenerator.
-# If non-empty doxygen will try to run qhelpgenerator on the generated
-# .qhp file.
-
-QHG_LOCATION           =
-
-# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
-#  will be generated, which together with the HTML files, form an Eclipse help
-# plugin. To install this plugin and make it available under the help contents
-# menu in Eclipse, the contents of the directory containing the HTML and XML
-# files needs to be copied into the plugins directory of eclipse. The name of
-# the directory within the plugins directory should be the same as
-# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
-# the help appears.
-
-GENERATE_ECLIPSEHELP   = NO
-
-# A unique identifier for the eclipse help plugin. When installing the plugin
-# the directory name containing the HTML and XML files should also have
-# this name.
-
-ECLIPSE_DOC_ID         = org.doxygen.Project
-
-# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
-# at top of each HTML page. The value NO (the default) enables the index and
-# the value YES disables it. Since the tabs have the same information as the
-# navigation tree you can set this option to NO if you already set
-# GENERATE_TREEVIEW to YES.
-
-DISABLE_INDEX          = NO
-
-# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
-# structure should be generated to display hierarchical information.
-# If the tag value is set to YES, a side panel will be generated
-# containing a tree-like index structure (just like the one that
-# is generated for HTML Help). For this to work a browser that supports
-# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
-# Windows users are probably better off using the HTML help feature.
-# Since the tree basically has the same information as the tab index you
-# could consider to set DISABLE_INDEX to NO when enabling this option.
-
-GENERATE_TREEVIEW      = NO
-
-# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
-# (range [0,1..20]) that doxygen will group on one line in the generated HTML
-# documentation. Note that a value of 0 will completely suppress the enum
-# values from appearing in the overview section.
-
-ENUM_VALUES_PER_LINE   = 4
-
-# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
-# used to set the initial width (in pixels) of the frame in which the tree
-# is shown.
-
-TREEVIEW_WIDTH         = 250
-
-# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
-# links to external symbols imported via tag files in a separate window.
-
-EXT_LINKS_IN_WINDOW    = NO
-
-# Use this tag to change the font size of Latex formulas included
-# as images in the HTML documentation. The default is 10. Note that
-# when you change the font size after a successful doxygen run you need
-# to manually remove any form_*.png images from the HTML output directory
-# to force them to be regenerated.
-
-FORMULA_FONTSIZE       = 10
-
-# Use the FORMULA_TRANPARENT tag to determine whether or not the images
-# generated for formulas are transparent PNGs. Transparent PNGs are
-# not supported properly for IE 6.0, but are supported on all modern browsers.
-# Note that when changing this option you need to delete any form_*.png files
-# in the HTML output before the changes have effect.
-
-FORMULA_TRANSPARENT    = YES
-
-# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
-# (see http://www.mathjax.org) which uses client side Javascript for the
-# rendering instead of using prerendered bitmaps. Use this if you do not
-# have LaTeX installed or if you want to formulas look prettier in the HTML
-# output. When enabled you may also need to install MathJax separately and
-# configure the path to it using the MATHJAX_RELPATH option.
-
-USE_MATHJAX            = NO
-
-# When MathJax is enabled you can set the default output format to be used for
-# thA MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and
-# SVG. The default value is HTML-CSS, which is slower, but has the best
-# compatibility.
-
-MATHJAX_FORMAT         = HTML-CSS
-
-# When MathJax is enabled you need to specify the location relative to the
-# HTML output directory using the MATHJAX_RELPATH option. The destination
-# directory should contain the MathJax.js script. For instance, if the mathjax
-# directory is located at the same level as the HTML output directory, then
-# MATHJAX_RELPATH should be ../mathjax. The default value points to
-# the MathJax Content Delivery Network so you can quickly see the result without
-# installing MathJax.
-# However, it is strongly recommended to install a local
-# copy of MathJax from http://www.mathjax.org before deployment.
-
-MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
-
-# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
-# names that should be enabled during MathJax rendering.
-
-MATHJAX_EXTENSIONS     =
-
-# When the SEARCHENGINE tag is enabled doxygen will generate a search box
-# for the HTML output. The underlying search engine uses javascript
-# and DHTML and should work on any modern browser. Note that when using
-# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
-# (GENERATE_DOCSET) there is already a search function so this one should
-# typically be disabled. For large projects the javascript based search engine
-# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
-
-SEARCHENGINE           = YES
-
-# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
-# implemented using a web server instead of a web client using Javascript.
-# There are two flavours of web server based search depending on the
-# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
-# searching and an index file used by the script. When EXTERNAL_SEARCH is
-# enabled the indexing and searching needs to be provided by external tools.
-# See the manual for details.
-
-SERVER_BASED_SEARCH    = NO
-
-# When EXTERNAL_SEARCH is enabled doxygen will no longer generate the PHP
-# script for searching. Instead the search results are written to an XML file
-# which needs to be processed by an external indexer. Doxygen will invoke an
-# external search engine pointed to by the SEARCHENGINE_URL option to obtain
-# the search results. Doxygen ships with an example indexer (doxyindexer) and
-# search engine (doxysearch.cgi) which are based on the open source search engine
-# library Xapian. See the manual for configuration details.
-
-EXTERNAL_SEARCH        = NO
-
-# The SEARCHENGINE_URL should point to a search engine hosted by a web server
-# which will returned the search results when EXTERNAL_SEARCH is enabled.
-# Doxygen ships with an example search engine (doxysearch) which is based on
-# the open source search engine library Xapian. See the manual for configuration
-# details.
-
-SEARCHENGINE_URL       =
-
-# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
-# search data is written to a file for indexing by an external tool. With the
-# SEARCHDATA_FILE tag the name of this file can be specified.
-
-SEARCHDATA_FILE        = searchdata.xml
-
-# When SERVER_BASED_SEARCH AND EXTERNAL_SEARCH are both enabled the
-# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
-# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
-# projects and redirect the results back to the right project.
-
-EXTERNAL_SEARCH_ID     =
-
-# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
-# projects other than the one defined by this configuration file, but that are
-# all added to the same external search index. Each project needs to have a
-# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id
-# of to a relative location where the documentation can be found.
-# The format is: EXTRA_SEARCH_MAPPINGS = id1=loc1 id2=loc2 ...
-
-EXTRA_SEARCH_MAPPINGS  =
-
-#---------------------------------------------------------------------------
-# configuration options related to the LaTeX output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
-# generate Latex output.
-
 GENERATE_LATEX         = NO
-
-# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `latex' will be used as the default path.
-
-LATEX_OUTPUT           = latex
-
-# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
-# invoked. If left blank `latex' will be used as the default command name.
-# Note that when enabling USE_PDFLATEX this option is only used for
-# generating bitmaps for formulas in the HTML output, but not in the
-# Makefile that is written to the output directory.
-
-LATEX_CMD_NAME         = latex
-
-# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
-# generate index for LaTeX. If left blank `makeindex' will be used as the
-# default command name.
-
-MAKEINDEX_CMD_NAME     = makeindex
-
-# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
-# LaTeX documents. This may be useful for small projects and may help to
-# save some trees in general.
-
-COMPACT_LATEX          = NO
-
-# The PAPER_TYPE tag can be used to set the paper type that is used
-# by the printer. Possible values are: a4, letter, legal and
-# executive. If left blank a4wide will be used.
-
-PAPER_TYPE             = a4
-
-# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
-# packages that should be included in the LaTeX output.
-
-EXTRA_PACKAGES         =
-
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
-# the generated latex document. The header should contain everything until
-# the first chapter. If it is left blank doxygen will generate a
-# standard header. Notice: only use this tag if you know what you are doing!
-
-LATEX_HEADER           =
-
-# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
-# the generated latex document. The footer should contain everything after
-# the last chapter. If it is left blank doxygen will generate a
-# standard footer. Notice: only use this tag if you know what you are doing!
-
-LATEX_FOOTER           =
-
-# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
-# is prepared for conversion to pdf (using ps2pdf). The pdf file will
-# contain links (just like the HTML output) instead of page references
-# This makes the output suitable for online browsing using a pdf viewer.
-
-PDF_HYPERLINKS         = YES
-
-# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
-# plain latex in the generated Makefile. Set this option to YES to get a
-# higher quality PDF documentation.
-
-USE_PDFLATEX           = YES
-
-# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
-# command to the generated LaTeX files. This will instruct LaTeX to keep
-# running if errors occur, instead of asking the user for help.
-# This option is also used when generating formulas in HTML.
-
-LATEX_BATCHMODE        = NO
-
-# If LATEX_HIDE_INDICES is set to YES then doxygen will not
-# include the index chapters (such as File Index, Compound Index, etc.)
-# in the output.
-
-LATEX_HIDE_INDICES     = NO
-
-# If LATEX_SOURCE_CODE is set to YES then doxygen will include
-# source code with syntax highlighting in the LaTeX output.
-# Note that which sources are shown also depends on other settings
-# such as SOURCE_BROWSER.
-
-LATEX_SOURCE_CODE      = NO
-
-# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
-# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
-# http://en.wikipedia.org/wiki/BibTeX for more info.
-
-LATEX_BIB_STYLE        = plain
-
-#---------------------------------------------------------------------------
-# configuration options related to the RTF output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
-# The RTF output is optimized for Word 97 and may not look very pretty with
-# other RTF readers or editors.
-
-GENERATE_RTF           = NO
-
-# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `rtf' will be used as the default path.
-
-RTF_OUTPUT             = rtf
-
-# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
-# RTF documents. This may be useful for small projects and may help to
-# save some trees in general.
-
-COMPACT_RTF            = NO
-
-# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
-# will contain hyperlink fields. The RTF file will
-# contain links (just like the HTML output) instead of page references.
-# This makes the output suitable for online browsing using WORD or other
-# programs which support those fields.
-# Note: wordpad (write) and others do not support links.
-
-RTF_HYPERLINKS         = NO
-
-# Load style sheet definitions from file. Syntax is similar to doxygen's
-# config file, i.e. a series of assignments. You only have to provide
-# replacements, missing definitions are set to their default value.
-
-RTF_STYLESHEET_FILE    =
-
-# Set optional variables used in the generation of an rtf document.
-# Syntax is similar to doxygen's config file.
-
-RTF_EXTENSIONS_FILE    =
-
-#---------------------------------------------------------------------------
-# configuration options related to the man page output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
-# generate man pages
-
-GENERATE_MAN           = NO
-
-# The MAN_OUTPUT tag is used to specify where the man pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `man' will be used as the default path.
-
-MAN_OUTPUT             = man
-
-# The MAN_EXTENSION tag determines the extension that is added to
-# the generated man pages (default is the subroutine's section .3)
-
-MAN_EXTENSION          = .3
-
-# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
-# then it will generate one additional man file for each entity
-# documented in the real man page(s). These additional files
-# only source the real man page, but without them the man command
-# would be unable to find the correct page. The default is NO.
-
-MAN_LINKS              = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the XML output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_XML tag is set to YES Doxygen will
-# generate an XML file that captures the structure of
-# the code including all documentation.
-
-GENERATE_XML           = NO
-
-# The XML_OUTPUT tag is used to specify where the XML pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `xml' will be used as the default path.
-
-XML_OUTPUT             = xml
-
-# The XML_SCHEMA tag can be used to specify an XML schema,
-# which can be used by a validating XML parser to check the
-# syntax of the XML files.
-
-XML_SCHEMA             =
-
-# The XML_DTD tag can be used to specify an XML DTD,
-# which can be used by a validating XML parser to check the
-# syntax of the XML files.
-
-XML_DTD                =
-
-# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
-# dump the program listings (including syntax highlighting
-# and cross-referencing information) to the XML output. Note that
-# enabling this will significantly increase the size of the XML output.
-
-XML_PROGRAMLISTING     = YES
-
-#---------------------------------------------------------------------------
-# configuration options for the AutoGen Definitions output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
-# generate an AutoGen Definitions (see autogen.sf.net) file
-# that captures the structure of the code including all
-# documentation. Note that this feature is still experimental
-# and incomplete at the moment.
-
-GENERATE_AUTOGEN_DEF   = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the Perl module output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_PERLMOD tag is set to YES Doxygen will
-# generate a Perl module file that captures the structure of
-# the code including all documentation. Note that this
-# feature is still experimental and incomplete at the
-# moment.
-
-GENERATE_PERLMOD       = NO
-
-# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
-# the necessary Makefile rules, Perl scripts and LaTeX code to be able
-# to generate PDF and DVI output from the Perl module output.
-
-PERLMOD_LATEX          = NO
-
-# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
-# nicely formatted so it can be parsed by a human reader.
-# This is useful
-# if you want to understand what is going on.
-# On the other hand, if this
-# tag is set to NO the size of the Perl module output will be much smaller
-# and Perl will parse it just the same.
-
-PERLMOD_PRETTY         = YES
-
-# The names of the make variables in the generated doxyrules.make file
-# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
-# This is useful so different doxyrules.make files included by the same
-# Makefile don't overwrite each other's variables.
-
-PERLMOD_MAKEVAR_PREFIX =
-
-#---------------------------------------------------------------------------
-# Configuration options related to the preprocessor
-#---------------------------------------------------------------------------
-
-# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
-# evaluate all C-preprocessor directives found in the sources and include
-# files.
-
-ENABLE_PREPROCESSING   = YES
-
-# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
-# names in the source code. If set to NO (the default) only conditional
-# compilation will be performed. Macro expansion can be done in a controlled
-# way by setting EXPAND_ONLY_PREDEF to YES.
-
 MACRO_EXPANSION        = YES
-
-# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
-# then the macro expansion is limited to the macros specified with the
-# PREDEFINED and EXPAND_AS_DEFINED tags.
-
 EXPAND_ONLY_PREDEF     = YES
-
-# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
-# pointed to by INCLUDE_PATH will be searched when a #include is found.
-
-SEARCH_INCLUDES        = YES
-
-# The INCLUDE_PATH tag can be used to specify one or more directories that
-# contain include files that are not input files but should be processed by
-# the preprocessor.
-
-INCLUDE_PATH           =
-
-# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
-# patterns (like *.h and *.hpp) to filter out the header-files in the
-# directories. If left blank, the patterns specified with FILE_PATTERNS will
-# be used.
-
-INCLUDE_FILE_PATTERNS  =
-
-# The PREDEFINED tag can be used to specify one or more macro names that
-# are defined before the preprocessor is started (similar to the -D option of
-# gcc). The argument of the tag is a list of macros of the form: name
-# or name=definition (no spaces). If the definition and the = are
-# omitted =1 is assumed. To prevent a macro definition from being
-# undefined via #undef or recursively expanded use the := operator
-# instead of the = operator.
-
 PREDEFINED             = LIBEVDEV_ATTRIBUTE_PRINTF(f,a)=
-
-# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
-# this tag can be used to specify a list of macro names that should be expanded.
-# The macro definition that is found in the sources will be used.
-# Use the PREDEFINED tag if you want to use a different macro definition that
-# overrules the definition found in the source code.
-
-EXPAND_AS_DEFINED      =
-
-# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
-# doxygen's preprocessor will remove all references to function-like macros
-# that are alone on a line, have an all uppercase name, and do not end with a
-# semicolon, because these will confuse the parser if not removed.
-
-SKIP_FUNCTION_MACROS   = YES
-
-#---------------------------------------------------------------------------
-# Configuration::additions related to external references
-#---------------------------------------------------------------------------
-
-# The TAGFILES option can be used to specify one or more tagfiles. For each
-# tag file the location of the external documentation should be added. The
-# format of a tag file without this location is as follows:
-#
-# TAGFILES = file1 file2 ...
-# Adding location for the tag files is done as follows:
-#
-# TAGFILES = file1=loc1 "file2 = loc2" ...
-# where "loc1" and "loc2" can be relative or absolute paths
-# or URLs. Note that each tag file must have a unique name (where the name does
-# NOT include the path). If a tag file is not located in the directory in which
-# doxygen is run, you must also specify the path to the tagfile here.
-
-TAGFILES               =
-
-# When a file name is specified after GENERATE_TAGFILE, doxygen will create
-# a tag file that is based on the input files it reads.
-
-GENERATE_TAGFILE       =
-
-# If the ALLEXTERNALS tag is set to YES all external classes will be listed
-# in the class index. If set to NO only the inherited external classes
-# will be listed.
-
-ALLEXTERNALS           = NO
-
-# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
-# in the modules index. If set to NO, only the current project's groups will
-# be listed.
-
-EXTERNAL_GROUPS        = YES
-
-# The PERL_PATH should be the absolute path and name of the perl script
-# interpreter (i.e. the result of `which perl').
-
-PERL_PATH              = /usr/bin/perl
-
-#---------------------------------------------------------------------------
-# Configuration options related to the dot tool
-#---------------------------------------------------------------------------
-
-# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
-# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
-# or super classes. Setting the tag to NO turns the diagrams off. Note that
-# this option also works with HAVE_DOT disabled, but it is recommended to
-# install and use dot, since it yields more powerful graphs.
-
-CLASS_DIAGRAMS         = YES
-
-# You can define message sequence charts within doxygen comments using the \msc
-# command. Doxygen will then run the mscgen tool (see
-# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
-# documentation. The MSCGEN_PATH tag allows you to specify the directory where
-# the mscgen tool resides. If left empty the tool is assumed to be found in the
-# default search path.
-
-MSCGEN_PATH            =
-
-# If set to YES, the inheritance and collaboration graphs will hide
-# inheritance and usage relations if the target is undocumented
-# or is not a class.
-
-HIDE_UNDOC_RELATIONS   = YES
-
-# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
-# available from the path. This tool is part of Graphviz, a graph visualization
-# toolkit from AT&T and Lucent Bell Labs. The other options in this section
-# have no effect if this option is set to NO (the default)
-
-HAVE_DOT               = NO
-
-# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
-# allowed to run in parallel. When set to 0 (the default) doxygen will
-# base this on the number of processors available in the system. You can set it
-# explicitly to a value larger than 0 to get control over the balance
-# between CPU load and processing speed.
-
-DOT_NUM_THREADS        = 0
-
-# By default doxygen will use the Helvetica font for all dot files that
-# doxygen generates. When you want a differently looking font you can specify
-# the font name using DOT_FONTNAME. You need to make sure dot is able to find
-# the font, which can be done by putting it in a standard location or by setting
-# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
-# directory containing the font.
-
-DOT_FONTNAME           = Helvetica
-
-# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
-# The default size is 10pt.
-
-DOT_FONTSIZE           = 10
-
-# By default doxygen will tell dot to use the Helvetica font.
-# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
-# set the path where dot can find it.
-
-DOT_FONTPATH           =
-
-# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for each documented class showing the direct and
-# indirect inheritance relations. Setting this tag to YES will force the
-# CLASS_DIAGRAMS tag to NO.
-
-CLASS_GRAPH            = YES
-
-# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for each documented class showing the direct and
-# indirect implementation dependencies (inheritance, containment, and
-# class references variables) of the class with other documented classes.
-
-COLLABORATION_GRAPH    = YES
-
-# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for groups, showing the direct groups dependencies
-
-GROUP_GRAPHS           = YES
-
-# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
-# collaboration diagrams in a style similar to the OMG's Unified Modeling
-# Language.
-
-UML_LOOK               = NO
-
-# If the UML_LOOK tag is enabled, the fields and methods are shown inside
-# the class node. If there are many fields or methods and many nodes the
-# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS
-# threshold limits the number of items for each type to make the size more
-# managable. Set this to 0 for no limit. Note that the threshold may be
-# exceeded by 50% before the limit is enforced.
-
-UML_LIMIT_NUM_FIELDS   = 10
-
-# If set to YES, the inheritance and collaboration graphs will show the
-# relations between templates and their instances.
-
-TEMPLATE_RELATIONS     = NO
-
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
-# tags are set to YES then doxygen will generate a graph for each documented
-# file showing the direct and indirect include dependencies of the file with
-# other documented files.
-
-INCLUDE_GRAPH          = YES
-
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
-# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
-# documented header file showing the documented files that directly or
-# indirectly include this file.
-
-INCLUDED_BY_GRAPH      = YES
-
-# If the CALL_GRAPH and HAVE_DOT options are set to YES then
-# doxygen will generate a call dependency graph for every global function
-# or class method. Note that enabling this option will significantly increase
-# the time of a run. So in most cases it will be better to enable call graphs
-# for selected functions only using the \callgraph command.
-
-CALL_GRAPH             = NO
-
-# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
-# doxygen will generate a caller dependency graph for every global function
-# or class method. Note that enabling this option will significantly increase
-# the time of a run. So in most cases it will be better to enable caller
-# graphs for selected functions only using the \callergraph command.
-
-CALLER_GRAPH           = NO
-
-# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
-# will generate a graphical hierarchy of all classes instead of a textual one.
-
-GRAPHICAL_HIERARCHY    = YES
-
-# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES
-# then doxygen will show the dependencies a directory has on other directories
-# in a graphical way. The dependency relations are determined by the #include
-# relations between the files in the directories.
-
-DIRECTORY_GRAPH        = YES
-
-# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
-# generated by dot. Possible values are svg, png, jpg, or gif.
-# If left blank png will be used. If you choose svg you need to set
-# HTML_FILE_EXTENSION to xhtml in order to make the SVG files
-# visible in IE 9+ (other browsers do not have this requirement).
-
-DOT_IMAGE_FORMAT       = png
-
-# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
-# enable generation of interactive SVG images that allow zooming and panning.
-# Note that this requires a modern browser other than Internet Explorer.
-# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
-# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
-# visible. Older versions of IE do not have SVG support.
-
-INTERACTIVE_SVG        = NO
-
-# The tag DOT_PATH can be used to specify the path where the dot tool can be
-# found. If left blank, it is assumed the dot tool can be found in the path.
-
-DOT_PATH               =
-
-# The DOTFILE_DIRS tag can be used to specify one or more directories that
-# contain dot files that are included in the documentation (see the
-# \dotfile command).
-
-DOTFILE_DIRS           =
-
-# The MSCFILE_DIRS tag can be used to specify one or more directories that
-# contain msc files that are included in the documentation (see the
-# \mscfile command).
-
-MSCFILE_DIRS           =
-
-# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
-# nodes that will be shown in the graph. If the number of nodes in a graph
-# becomes larger than this value, doxygen will truncate the graph, which is
-# visualized by representing a node as a red box. Note that doxygen if the
-# number of direct children of the root node in a graph is already larger than
-# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
-# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
-
-DOT_GRAPH_MAX_NODES    = 50
-
-# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
-# graphs generated by dot. A depth value of 3 means that only nodes reachable
-# from the root by following a path via at most 3 edges will be shown. Nodes
-# that lay further from the root node will be omitted. Note that setting this
-# option to 1 or 2 may greatly reduce the computation time needed for large
-# code bases. Also note that the size of a graph can be further restricted by
-# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
-
-MAX_DOT_GRAPH_DEPTH    = 0
-
-# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
-# background. This is disabled by default, because dot on Windows does not
-# seem to support this out of the box. Warning: Depending on the platform used,
-# enabling this option may lead to badly anti-aliased labels on the edges of
-# a graph (i.e. they become hard to read).
-
-DOT_TRANSPARENT        = NO
-
-# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
-# files in one run (i.e. multiple -o and -T options on the command line). This
-# makes dot run faster, but since only newer versions of dot (>1.8.10)
-# support this, this feature is disabled by default.
-
-DOT_MULTI_TARGETS      = NO
-
-# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
-# generate a legend page explaining the meaning of the various boxes and
-# arrows in the dot generated graphs.
-
-GENERATE_LEGEND        = YES
-
-# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
-# remove the intermediate dot files that are used to generate
-# the various graphs.
-
-DOT_CLEANUP            = YES
diff --git a/include/linux/input-event-codes.h b/include/linux/input-event-codes.h
new file mode 100644 (file)
index 0000000..49f75c8
--- /dev/null
@@ -0,0 +1,804 @@
+/*
+ * Input event codes
+ *
+ *    *** IMPORTANT ***
+ * This file is not only included from C-code but also from devicetree source
+ * files. As such this file MUST only contain comments and defines.
+ *
+ * Copyright (c) 1999-2002 Vojtech Pavlik
+ * Copyright (c) 2015 Hans de Goede <hdegoede@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef _UAPI_INPUT_EVENT_CODES_H
+#define _UAPI_INPUT_EVENT_CODES_H
+
+/*
+ * Device properties and quirks
+ */
+
+#define INPUT_PROP_POINTER             0x00    /* needs a pointer */
+#define INPUT_PROP_DIRECT              0x01    /* direct input devices */
+#define INPUT_PROP_BUTTONPAD           0x02    /* has button(s) under pad */
+#define INPUT_PROP_SEMI_MT             0x03    /* touch rectangle only */
+#define INPUT_PROP_TOPBUTTONPAD                0x04    /* softbuttons at top of pad */
+#define INPUT_PROP_POINTING_STICK      0x05    /* is a pointing stick */
+#define INPUT_PROP_ACCELEROMETER       0x06    /* has accelerometer */
+
+#define INPUT_PROP_MAX                 0x1f
+#define INPUT_PROP_CNT                 (INPUT_PROP_MAX + 1)
+
+/*
+ * Event types
+ */
+
+#define EV_SYN                 0x00
+#define EV_KEY                 0x01
+#define EV_REL                 0x02
+#define EV_ABS                 0x03
+#define EV_MSC                 0x04
+#define EV_SW                  0x05
+#define EV_LED                 0x11
+#define EV_SND                 0x12
+#define EV_REP                 0x14
+#define EV_FF                  0x15
+#define EV_PWR                 0x16
+#define EV_FF_STATUS           0x17
+#define EV_MAX                 0x1f
+#define EV_CNT                 (EV_MAX+1)
+
+/*
+ * Synchronization events.
+ */
+
+#define SYN_REPORT             0
+#define SYN_CONFIG             1
+#define SYN_MT_REPORT          2
+#define SYN_DROPPED            3
+#define SYN_MAX                        0xf
+#define SYN_CNT                        (SYN_MAX+1)
+
+/*
+ * Keys and buttons
+ *
+ * Most of the keys/buttons are modeled after USB HUT 1.12
+ * (see http://www.usb.org/developers/hidpage).
+ * Abbreviations in the comments:
+ * AC - Application Control
+ * AL - Application Launch Button
+ * SC - System Control
+ */
+
+#define KEY_RESERVED           0
+#define KEY_ESC                        1
+#define KEY_1                  2
+#define KEY_2                  3
+#define KEY_3                  4
+#define KEY_4                  5
+#define KEY_5                  6
+#define KEY_6                  7
+#define KEY_7                  8
+#define KEY_8                  9
+#define KEY_9                  10
+#define KEY_0                  11
+#define KEY_MINUS              12
+#define KEY_EQUAL              13
+#define KEY_BACKSPACE          14
+#define KEY_TAB                        15
+#define KEY_Q                  16
+#define KEY_W                  17
+#define KEY_E                  18
+#define KEY_R                  19
+#define KEY_T                  20
+#define KEY_Y                  21
+#define KEY_U                  22
+#define KEY_I                  23
+#define KEY_O                  24
+#define KEY_P                  25
+#define KEY_LEFTBRACE          26
+#define KEY_RIGHTBRACE         27
+#define KEY_ENTER              28
+#define KEY_LEFTCTRL           29
+#define KEY_A                  30
+#define KEY_S                  31
+#define KEY_D                  32
+#define KEY_F                  33
+#define KEY_G                  34
+#define KEY_H                  35
+#define KEY_J                  36
+#define KEY_K                  37
+#define KEY_L                  38
+#define KEY_SEMICOLON          39
+#define KEY_APOSTROPHE         40
+#define KEY_GRAVE              41
+#define KEY_LEFTSHIFT          42
+#define KEY_BACKSLASH          43
+#define KEY_Z                  44
+#define KEY_X                  45
+#define KEY_C                  46
+#define KEY_V                  47
+#define KEY_B                  48
+#define KEY_N                  49
+#define KEY_M                  50
+#define KEY_COMMA              51
+#define KEY_DOT                        52
+#define KEY_SLASH              53
+#define KEY_RIGHTSHIFT         54
+#define KEY_KPASTERISK         55
+#define KEY_LEFTALT            56
+#define KEY_SPACE              57
+#define KEY_CAPSLOCK           58
+#define KEY_F1                 59
+#define KEY_F2                 60
+#define KEY_F3                 61
+#define KEY_F4                 62
+#define KEY_F5                 63
+#define KEY_F6                 64
+#define KEY_F7                 65
+#define KEY_F8                 66
+#define KEY_F9                 67
+#define KEY_F10                        68
+#define KEY_NUMLOCK            69
+#define KEY_SCROLLLOCK         70
+#define KEY_KP7                        71
+#define KEY_KP8                        72
+#define KEY_KP9                        73
+#define KEY_KPMINUS            74
+#define KEY_KP4                        75
+#define KEY_KP5                        76
+#define KEY_KP6                        77
+#define KEY_KPPLUS             78
+#define KEY_KP1                        79
+#define KEY_KP2                        80
+#define KEY_KP3                        81
+#define KEY_KP0                        82
+#define KEY_KPDOT              83
+
+#define KEY_ZENKAKUHANKAKU     85
+#define KEY_102ND              86
+#define KEY_F11                        87
+#define KEY_F12                        88
+#define KEY_RO                 89
+#define KEY_KATAKANA           90
+#define KEY_HIRAGANA           91
+#define KEY_HENKAN             92
+#define KEY_KATAKANAHIRAGANA   93
+#define KEY_MUHENKAN           94
+#define KEY_KPJPCOMMA          95
+#define KEY_KPENTER            96
+#define KEY_RIGHTCTRL          97
+#define KEY_KPSLASH            98
+#define KEY_SYSRQ              99
+#define KEY_RIGHTALT           100
+#define KEY_LINEFEED           101
+#define KEY_HOME               102
+#define KEY_UP                 103
+#define KEY_PAGEUP             104
+#define KEY_LEFT               105
+#define KEY_RIGHT              106
+#define KEY_END                        107
+#define KEY_DOWN               108
+#define KEY_PAGEDOWN           109
+#define KEY_INSERT             110
+#define KEY_DELETE             111
+#define KEY_MACRO              112
+#define KEY_MUTE               113
+#define KEY_VOLUMEDOWN         114
+#define KEY_VOLUMEUP           115
+#define KEY_POWER              116     /* SC System Power Down */
+#define KEY_KPEQUAL            117
+#define KEY_KPPLUSMINUS                118
+#define KEY_PAUSE              119
+#define KEY_SCALE              120     /* AL Compiz Scale (Expose) */
+
+#define KEY_KPCOMMA            121
+#define KEY_HANGEUL            122
+#define KEY_HANGUEL            KEY_HANGEUL
+#define KEY_HANJA              123
+#define KEY_YEN                        124
+#define KEY_LEFTMETA           125
+#define KEY_RIGHTMETA          126
+#define KEY_COMPOSE            127
+
+#define KEY_STOP               128     /* AC Stop */
+#define KEY_AGAIN              129
+#define KEY_PROPS              130     /* AC Properties */
+#define KEY_UNDO               131     /* AC Undo */
+#define KEY_FRONT              132
+#define KEY_COPY               133     /* AC Copy */
+#define KEY_OPEN               134     /* AC Open */
+#define KEY_PASTE              135     /* AC Paste */
+#define KEY_FIND               136     /* AC Search */
+#define KEY_CUT                        137     /* AC Cut */
+#define KEY_HELP               138     /* AL Integrated Help Center */
+#define KEY_MENU               139     /* Menu (show menu) */
+#define KEY_CALC               140     /* AL Calculator */
+#define KEY_SETUP              141
+#define KEY_SLEEP              142     /* SC System Sleep */
+#define KEY_WAKEUP             143     /* System Wake Up */
+#define KEY_FILE               144     /* AL Local Machine Browser */
+#define KEY_SENDFILE           145
+#define KEY_DELETEFILE         146
+#define KEY_XFER               147
+#define KEY_PROG1              148
+#define KEY_PROG2              149
+#define KEY_WWW                        150     /* AL Internet Browser */
+#define KEY_MSDOS              151
+#define KEY_COFFEE             152     /* AL Terminal Lock/Screensaver */
+#define KEY_SCREENLOCK         KEY_COFFEE
+#define KEY_ROTATE_DISPLAY     153     /* Display orientation for e.g. tablets */
+#define KEY_DIRECTION          KEY_ROTATE_DISPLAY
+#define KEY_CYCLEWINDOWS       154
+#define KEY_MAIL               155
+#define KEY_BOOKMARKS          156     /* AC Bookmarks */
+#define KEY_COMPUTER           157
+#define KEY_BACK               158     /* AC Back */
+#define KEY_FORWARD            159     /* AC Forward */
+#define KEY_CLOSECD            160
+#define KEY_EJECTCD            161
+#define KEY_EJECTCLOSECD       162
+#define KEY_NEXTSONG           163
+#define KEY_PLAYPAUSE          164
+#define KEY_PREVIOUSSONG       165
+#define KEY_STOPCD             166
+#define KEY_RECORD             167
+#define KEY_REWIND             168
+#define KEY_PHONE              169     /* Media Select Telephone */
+#define KEY_ISO                        170
+#define KEY_CONFIG             171     /* AL Consumer Control Configuration */
+#define KEY_HOMEPAGE           172     /* AC Home */
+#define KEY_REFRESH            173     /* AC Refresh */
+#define KEY_EXIT               174     /* AC Exit */
+#define KEY_MOVE               175
+#define KEY_EDIT               176
+#define KEY_SCROLLUP           177
+#define KEY_SCROLLDOWN         178
+#define KEY_KPLEFTPAREN                179
+#define KEY_KPRIGHTPAREN       180
+#define KEY_NEW                        181     /* AC New */
+#define KEY_REDO               182     /* AC Redo/Repeat */
+
+#define KEY_F13                        183
+#define KEY_F14                        184
+#define KEY_F15                        185
+#define KEY_F16                        186
+#define KEY_F17                        187
+#define KEY_F18                        188
+#define KEY_F19                        189
+#define KEY_F20                        190
+#define KEY_F21                        191
+#define KEY_F22                        192
+#define KEY_F23                        193
+#define KEY_F24                        194
+
+#define KEY_PLAYCD             200
+#define KEY_PAUSECD            201
+#define KEY_PROG3              202
+#define KEY_PROG4              203
+#define KEY_DASHBOARD          204     /* AL Dashboard */
+#define KEY_SUSPEND            205
+#define KEY_CLOSE              206     /* AC Close */
+#define KEY_PLAY               207
+#define KEY_FASTFORWARD                208
+#define KEY_BASSBOOST          209
+#define KEY_PRINT              210     /* AC Print */
+#define KEY_HP                 211
+#define KEY_CAMERA             212
+#define KEY_SOUND              213
+#define KEY_QUESTION           214
+#define KEY_EMAIL              215
+#define KEY_CHAT               216
+#define KEY_SEARCH             217
+#define KEY_CONNECT            218
+#define KEY_FINANCE            219     /* AL Checkbook/Finance */
+#define KEY_SPORT              220
+#define KEY_SHOP               221
+#define KEY_ALTERASE           222
+#define KEY_CANCEL             223     /* AC Cancel */
+#define KEY_BRIGHTNESSDOWN     224
+#define KEY_BRIGHTNESSUP       225
+#define KEY_MEDIA              226
+
+#define KEY_SWITCHVIDEOMODE    227     /* Cycle between available video
+                                          outputs (Monitor/LCD/TV-out/etc) */
+#define KEY_KBDILLUMTOGGLE     228
+#define KEY_KBDILLUMDOWN       229
+#define KEY_KBDILLUMUP         230
+
+#define KEY_SEND               231     /* AC Send */
+#define KEY_REPLY              232     /* AC Reply */
+#define KEY_FORWARDMAIL                233     /* AC Forward Msg */
+#define KEY_SAVE               234     /* AC Save */
+#define KEY_DOCUMENTS          235
+
+#define KEY_BATTERY            236
+
+#define KEY_BLUETOOTH          237
+#define KEY_WLAN               238
+#define KEY_UWB                        239
+
+#define KEY_UNKNOWN            240
+
+#define KEY_VIDEO_NEXT         241     /* drive next video source */
+#define KEY_VIDEO_PREV         242     /* drive previous video source */
+#define KEY_BRIGHTNESS_CYCLE   243     /* brightness up, after max is min */
+#define KEY_BRIGHTNESS_AUTO    244     /* Set Auto Brightness: manual
+                                         brightness control is off,
+                                         rely on ambient */
+#define KEY_BRIGHTNESS_ZERO    KEY_BRIGHTNESS_AUTO
+#define KEY_DISPLAY_OFF                245     /* display device to off state */
+
+#define KEY_WWAN               246     /* Wireless WAN (LTE, UMTS, GSM, etc.) */
+#define KEY_WIMAX              KEY_WWAN
+#define KEY_RFKILL             247     /* Key that controls all radios */
+
+#define KEY_MICMUTE            248     /* Mute / unmute the microphone */
+
+/* Code 255 is reserved for special needs of AT keyboard driver */
+
+#define BTN_MISC               0x100
+#define BTN_0                  0x100
+#define BTN_1                  0x101
+#define BTN_2                  0x102
+#define BTN_3                  0x103
+#define BTN_4                  0x104
+#define BTN_5                  0x105
+#define BTN_6                  0x106
+#define BTN_7                  0x107
+#define BTN_8                  0x108
+#define BTN_9                  0x109
+
+#define BTN_MOUSE              0x110
+#define BTN_LEFT               0x110
+#define BTN_RIGHT              0x111
+#define BTN_MIDDLE             0x112
+#define BTN_SIDE               0x113
+#define BTN_EXTRA              0x114
+#define BTN_FORWARD            0x115
+#define BTN_BACK               0x116
+#define BTN_TASK               0x117
+
+#define BTN_JOYSTICK           0x120
+#define BTN_TRIGGER            0x120
+#define BTN_THUMB              0x121
+#define BTN_THUMB2             0x122
+#define BTN_TOP                        0x123
+#define BTN_TOP2               0x124
+#define BTN_PINKIE             0x125
+#define BTN_BASE               0x126
+#define BTN_BASE2              0x127
+#define BTN_BASE3              0x128
+#define BTN_BASE4              0x129
+#define BTN_BASE5              0x12a
+#define BTN_BASE6              0x12b
+#define BTN_DEAD               0x12f
+
+#define BTN_GAMEPAD            0x130
+#define BTN_SOUTH              0x130
+#define BTN_A                  BTN_SOUTH
+#define BTN_EAST               0x131
+#define BTN_B                  BTN_EAST
+#define BTN_C                  0x132
+#define BTN_NORTH              0x133
+#define BTN_X                  BTN_NORTH
+#define BTN_WEST               0x134
+#define BTN_Y                  BTN_WEST
+#define BTN_Z                  0x135
+#define BTN_TL                 0x136
+#define BTN_TR                 0x137
+#define BTN_TL2                        0x138
+#define BTN_TR2                        0x139
+#define BTN_SELECT             0x13a
+#define BTN_START              0x13b
+#define BTN_MODE               0x13c
+#define BTN_THUMBL             0x13d
+#define BTN_THUMBR             0x13e
+
+#define BTN_DIGI               0x140
+#define BTN_TOOL_PEN           0x140
+#define BTN_TOOL_RUBBER                0x141
+#define BTN_TOOL_BRUSH         0x142
+#define BTN_TOOL_PENCIL                0x143
+#define BTN_TOOL_AIRBRUSH      0x144
+#define BTN_TOOL_FINGER                0x145
+#define BTN_TOOL_MOUSE         0x146
+#define BTN_TOOL_LENS          0x147
+#define BTN_TOOL_QUINTTAP      0x148   /* Five fingers on trackpad */
+#define BTN_TOUCH              0x14a
+#define BTN_STYLUS             0x14b
+#define BTN_STYLUS2            0x14c
+#define BTN_TOOL_DOUBLETAP     0x14d
+#define BTN_TOOL_TRIPLETAP     0x14e
+#define BTN_TOOL_QUADTAP       0x14f   /* Four fingers on trackpad */
+
+#define BTN_WHEEL              0x150
+#define BTN_GEAR_DOWN          0x150
+#define BTN_GEAR_UP            0x151
+
+#define KEY_OK                 0x160
+#define KEY_SELECT             0x161
+#define KEY_GOTO               0x162
+#define KEY_CLEAR              0x163
+#define KEY_POWER2             0x164
+#define KEY_OPTION             0x165
+#define KEY_INFO               0x166   /* AL OEM Features/Tips/Tutorial */
+#define KEY_TIME               0x167
+#define KEY_VENDOR             0x168
+#define KEY_ARCHIVE            0x169
+#define KEY_PROGRAM            0x16a   /* Media Select Program Guide */
+#define KEY_CHANNEL            0x16b
+#define KEY_FAVORITES          0x16c
+#define KEY_EPG                        0x16d
+#define KEY_PVR                        0x16e   /* Media Select Home */
+#define KEY_MHP                        0x16f
+#define KEY_LANGUAGE           0x170
+#define KEY_TITLE              0x171
+#define KEY_SUBTITLE           0x172
+#define KEY_ANGLE              0x173
+#define KEY_ZOOM               0x174
+#define KEY_MODE               0x175
+#define KEY_KEYBOARD           0x176
+#define KEY_SCREEN             0x177
+#define KEY_PC                 0x178   /* Media Select Computer */
+#define KEY_TV                 0x179   /* Media Select TV */
+#define KEY_TV2                        0x17a   /* Media Select Cable */
+#define KEY_VCR                        0x17b   /* Media Select VCR */
+#define KEY_VCR2               0x17c   /* VCR Plus */
+#define KEY_SAT                        0x17d   /* Media Select Satellite */
+#define KEY_SAT2               0x17e
+#define KEY_CD                 0x17f   /* Media Select CD */
+#define KEY_TAPE               0x180   /* Media Select Tape */
+#define KEY_RADIO              0x181
+#define KEY_TUNER              0x182   /* Media Select Tuner */
+#define KEY_PLAYER             0x183
+#define KEY_TEXT               0x184
+#define KEY_DVD                        0x185   /* Media Select DVD */
+#define KEY_AUX                        0x186
+#define KEY_MP3                        0x187
+#define KEY_AUDIO              0x188   /* AL Audio Browser */
+#define KEY_VIDEO              0x189   /* AL Movie Browser */
+#define KEY_DIRECTORY          0x18a
+#define KEY_LIST               0x18b
+#define KEY_MEMO               0x18c   /* Media Select Messages */
+#define KEY_CALENDAR           0x18d
+#define KEY_RED                        0x18e
+#define KEY_GREEN              0x18f
+#define KEY_YELLOW             0x190
+#define KEY_BLUE               0x191
+#define KEY_CHANNELUP          0x192   /* Channel Increment */
+#define KEY_CHANNELDOWN                0x193   /* Channel Decrement */
+#define KEY_FIRST              0x194
+#define KEY_LAST               0x195   /* Recall Last */
+#define KEY_AB                 0x196
+#define KEY_NEXT               0x197
+#define KEY_RESTART            0x198
+#define KEY_SLOW               0x199
+#define KEY_SHUFFLE            0x19a
+#define KEY_BREAK              0x19b
+#define KEY_PREVIOUS           0x19c
+#define KEY_DIGITS             0x19d
+#define KEY_TEEN               0x19e
+#define KEY_TWEN               0x19f
+#define KEY_VIDEOPHONE         0x1a0   /* Media Select Video Phone */
+#define KEY_GAMES              0x1a1   /* Media Select Games */
+#define KEY_ZOOMIN             0x1a2   /* AC Zoom In */
+#define KEY_ZOOMOUT            0x1a3   /* AC Zoom Out */
+#define KEY_ZOOMRESET          0x1a4   /* AC Zoom */
+#define KEY_WORDPROCESSOR      0x1a5   /* AL Word Processor */
+#define KEY_EDITOR             0x1a6   /* AL Text Editor */
+#define KEY_SPREADSHEET                0x1a7   /* AL Spreadsheet */
+#define KEY_GRAPHICSEDITOR     0x1a8   /* AL Graphics Editor */
+#define KEY_PRESENTATION       0x1a9   /* AL Presentation App */
+#define KEY_DATABASE           0x1aa   /* AL Database App */
+#define KEY_NEWS               0x1ab   /* AL Newsreader */
+#define KEY_VOICEMAIL          0x1ac   /* AL Voicemail */
+#define KEY_ADDRESSBOOK                0x1ad   /* AL Contacts/Address Book */
+#define KEY_MESSENGER          0x1ae   /* AL Instant Messaging */
+#define KEY_DISPLAYTOGGLE      0x1af   /* Turn display (LCD) on and off */
+#define KEY_BRIGHTNESS_TOGGLE  KEY_DISPLAYTOGGLE
+#define KEY_SPELLCHECK         0x1b0   /* AL Spell Check */
+#define KEY_LOGOFF             0x1b1   /* AL Logoff */
+
+#define KEY_DOLLAR             0x1b2
+#define KEY_EURO               0x1b3
+
+#define KEY_FRAMEBACK          0x1b4   /* Consumer - transport controls */
+#define KEY_FRAMEFORWARD       0x1b5
+#define KEY_CONTEXT_MENU       0x1b6   /* GenDesc - system context menu */
+#define KEY_MEDIA_REPEAT       0x1b7   /* Consumer - transport control */
+#define KEY_10CHANNELSUP       0x1b8   /* 10 channels up (10+) */
+#define KEY_10CHANNELSDOWN     0x1b9   /* 10 channels down (10-) */
+#define KEY_IMAGES             0x1ba   /* AL Image Browser */
+
+#define KEY_DEL_EOL            0x1c0
+#define KEY_DEL_EOS            0x1c1
+#define KEY_INS_LINE           0x1c2
+#define KEY_DEL_LINE           0x1c3
+
+#define KEY_FN                 0x1d0
+#define KEY_FN_ESC             0x1d1
+#define KEY_FN_F1              0x1d2
+#define KEY_FN_F2              0x1d3
+#define KEY_FN_F3              0x1d4
+#define KEY_FN_F4              0x1d5
+#define KEY_FN_F5              0x1d6
+#define KEY_FN_F6              0x1d7
+#define KEY_FN_F7              0x1d8
+#define KEY_FN_F8              0x1d9
+#define KEY_FN_F9              0x1da
+#define KEY_FN_F10             0x1db
+#define KEY_FN_F11             0x1dc
+#define KEY_FN_F12             0x1dd
+#define KEY_FN_1               0x1de
+#define KEY_FN_2               0x1df
+#define KEY_FN_D               0x1e0
+#define KEY_FN_E               0x1e1
+#define KEY_FN_F               0x1e2
+#define KEY_FN_S               0x1e3
+#define KEY_FN_B               0x1e4
+
+#define KEY_BRL_DOT1           0x1f1
+#define KEY_BRL_DOT2           0x1f2
+#define KEY_BRL_DOT3           0x1f3
+#define KEY_BRL_DOT4           0x1f4
+#define KEY_BRL_DOT5           0x1f5
+#define KEY_BRL_DOT6           0x1f6
+#define KEY_BRL_DOT7           0x1f7
+#define KEY_BRL_DOT8           0x1f8
+#define KEY_BRL_DOT9           0x1f9
+#define KEY_BRL_DOT10          0x1fa
+
+#define KEY_NUMERIC_0          0x200   /* used by phones, remote controls, */
+#define KEY_NUMERIC_1          0x201   /* and other keypads */
+#define KEY_NUMERIC_2          0x202
+#define KEY_NUMERIC_3          0x203
+#define KEY_NUMERIC_4          0x204
+#define KEY_NUMERIC_5          0x205
+#define KEY_NUMERIC_6          0x206
+#define KEY_NUMERIC_7          0x207
+#define KEY_NUMERIC_8          0x208
+#define KEY_NUMERIC_9          0x209
+#define KEY_NUMERIC_STAR       0x20a
+#define KEY_NUMERIC_POUND      0x20b
+#define KEY_NUMERIC_A          0x20c   /* Phone key A - HUT Telephony 0xb9 */
+#define KEY_NUMERIC_B          0x20d
+#define KEY_NUMERIC_C          0x20e
+#define KEY_NUMERIC_D          0x20f
+
+#define KEY_CAMERA_FOCUS       0x210
+#define KEY_WPS_BUTTON         0x211   /* WiFi Protected Setup key */
+
+#define KEY_TOUCHPAD_TOGGLE    0x212   /* Request switch touchpad on or off */
+#define KEY_TOUCHPAD_ON                0x213
+#define KEY_TOUCHPAD_OFF       0x214
+
+#define KEY_CAMERA_ZOOMIN      0x215
+#define KEY_CAMERA_ZOOMOUT     0x216
+#define KEY_CAMERA_UP          0x217
+#define KEY_CAMERA_DOWN                0x218
+#define KEY_CAMERA_LEFT                0x219
+#define KEY_CAMERA_RIGHT       0x21a
+
+#define KEY_ATTENDANT_ON       0x21b
+#define KEY_ATTENDANT_OFF      0x21c
+#define KEY_ATTENDANT_TOGGLE   0x21d   /* Attendant call on or off */
+#define KEY_LIGHTS_TOGGLE      0x21e   /* Reading light on or off */
+
+#define BTN_DPAD_UP            0x220
+#define BTN_DPAD_DOWN          0x221
+#define BTN_DPAD_LEFT          0x222
+#define BTN_DPAD_RIGHT         0x223
+
+#define KEY_ALS_TOGGLE         0x230   /* Ambient light sensor */
+
+#define KEY_BUTTONCONFIG               0x240   /* AL Button Configuration */
+#define KEY_TASKMANAGER                0x241   /* AL Task/Project Manager */
+#define KEY_JOURNAL            0x242   /* AL Log/Journal/Timecard */
+#define KEY_CONTROLPANEL               0x243   /* AL Control Panel */
+#define KEY_APPSELECT          0x244   /* AL Select Task/Application */
+#define KEY_SCREENSAVER                0x245   /* AL Screen Saver */
+#define KEY_VOICECOMMAND               0x246   /* Listening Voice Command */
+
+#define KEY_BRIGHTNESS_MIN             0x250   /* Set Brightness to Minimum */
+#define KEY_BRIGHTNESS_MAX             0x251   /* Set Brightness to Maximum */
+
+#define KEY_KBDINPUTASSIST_PREV                0x260
+#define KEY_KBDINPUTASSIST_NEXT                0x261
+#define KEY_KBDINPUTASSIST_PREVGROUP           0x262
+#define KEY_KBDINPUTASSIST_NEXTGROUP           0x263
+#define KEY_KBDINPUTASSIST_ACCEPT              0x264
+#define KEY_KBDINPUTASSIST_CANCEL              0x265
+
+#define BTN_TRIGGER_HAPPY              0x2c0
+#define BTN_TRIGGER_HAPPY1             0x2c0
+#define BTN_TRIGGER_HAPPY2             0x2c1
+#define BTN_TRIGGER_HAPPY3             0x2c2
+#define BTN_TRIGGER_HAPPY4             0x2c3
+#define BTN_TRIGGER_HAPPY5             0x2c4
+#define BTN_TRIGGER_HAPPY6             0x2c5
+#define BTN_TRIGGER_HAPPY7             0x2c6
+#define BTN_TRIGGER_HAPPY8             0x2c7
+#define BTN_TRIGGER_HAPPY9             0x2c8
+#define BTN_TRIGGER_HAPPY10            0x2c9
+#define BTN_TRIGGER_HAPPY11            0x2ca
+#define BTN_TRIGGER_HAPPY12            0x2cb
+#define BTN_TRIGGER_HAPPY13            0x2cc
+#define BTN_TRIGGER_HAPPY14            0x2cd
+#define BTN_TRIGGER_HAPPY15            0x2ce
+#define BTN_TRIGGER_HAPPY16            0x2cf
+#define BTN_TRIGGER_HAPPY17            0x2d0
+#define BTN_TRIGGER_HAPPY18            0x2d1
+#define BTN_TRIGGER_HAPPY19            0x2d2
+#define BTN_TRIGGER_HAPPY20            0x2d3
+#define BTN_TRIGGER_HAPPY21            0x2d4
+#define BTN_TRIGGER_HAPPY22            0x2d5
+#define BTN_TRIGGER_HAPPY23            0x2d6
+#define BTN_TRIGGER_HAPPY24            0x2d7
+#define BTN_TRIGGER_HAPPY25            0x2d8
+#define BTN_TRIGGER_HAPPY26            0x2d9
+#define BTN_TRIGGER_HAPPY27            0x2da
+#define BTN_TRIGGER_HAPPY28            0x2db
+#define BTN_TRIGGER_HAPPY29            0x2dc
+#define BTN_TRIGGER_HAPPY30            0x2dd
+#define BTN_TRIGGER_HAPPY31            0x2de
+#define BTN_TRIGGER_HAPPY32            0x2df
+#define BTN_TRIGGER_HAPPY33            0x2e0
+#define BTN_TRIGGER_HAPPY34            0x2e1
+#define BTN_TRIGGER_HAPPY35            0x2e2
+#define BTN_TRIGGER_HAPPY36            0x2e3
+#define BTN_TRIGGER_HAPPY37            0x2e4
+#define BTN_TRIGGER_HAPPY38            0x2e5
+#define BTN_TRIGGER_HAPPY39            0x2e6
+#define BTN_TRIGGER_HAPPY40            0x2e7
+
+/* We avoid low common keys in module aliases so they don't get huge. */
+#define KEY_MIN_INTERESTING    KEY_MUTE
+#define KEY_MAX                        0x2ff
+#define KEY_CNT                        (KEY_MAX+1)
+
+/*
+ * Relative axes
+ */
+
+#define REL_X                  0x00
+#define REL_Y                  0x01
+#define REL_Z                  0x02
+#define REL_RX                 0x03
+#define REL_RY                 0x04
+#define REL_RZ                 0x05
+#define REL_HWHEEL             0x06
+#define REL_DIAL               0x07
+#define REL_WHEEL              0x08
+#define REL_MISC               0x09
+#define REL_MAX                        0x0f
+#define REL_CNT                        (REL_MAX+1)
+
+/*
+ * Absolute axes
+ */
+
+#define ABS_X                  0x00
+#define ABS_Y                  0x01
+#define ABS_Z                  0x02
+#define ABS_RX                 0x03
+#define ABS_RY                 0x04
+#define ABS_RZ                 0x05
+#define ABS_THROTTLE           0x06
+#define ABS_RUDDER             0x07
+#define ABS_WHEEL              0x08
+#define ABS_GAS                        0x09
+#define ABS_BRAKE              0x0a
+#define ABS_HAT0X              0x10
+#define ABS_HAT0Y              0x11
+#define ABS_HAT1X              0x12
+#define ABS_HAT1Y              0x13
+#define ABS_HAT2X              0x14
+#define ABS_HAT2Y              0x15
+#define ABS_HAT3X              0x16
+#define ABS_HAT3Y              0x17
+#define ABS_PRESSURE           0x18
+#define ABS_DISTANCE           0x19
+#define ABS_TILT_X             0x1a
+#define ABS_TILT_Y             0x1b
+#define ABS_TOOL_WIDTH         0x1c
+
+#define ABS_VOLUME             0x20
+
+#define ABS_MISC               0x28
+
+#define ABS_MT_SLOT            0x2f    /* MT slot being modified */
+#define ABS_MT_TOUCH_MAJOR     0x30    /* Major axis of touching ellipse */
+#define ABS_MT_TOUCH_MINOR     0x31    /* Minor axis (omit if circular) */
+#define ABS_MT_WIDTH_MAJOR     0x32    /* Major axis of approaching ellipse */
+#define ABS_MT_WIDTH_MINOR     0x33    /* Minor axis (omit if circular) */
+#define ABS_MT_ORIENTATION     0x34    /* Ellipse orientation */
+#define ABS_MT_POSITION_X      0x35    /* Center X touch position */
+#define ABS_MT_POSITION_Y      0x36    /* Center Y touch position */
+#define ABS_MT_TOOL_TYPE       0x37    /* Type of touching device */
+#define ABS_MT_BLOB_ID         0x38    /* Group a set of packets as a blob */
+#define ABS_MT_TRACKING_ID     0x39    /* Unique ID of initiated contact */
+#define ABS_MT_PRESSURE                0x3a    /* Pressure on contact area */
+#define ABS_MT_DISTANCE                0x3b    /* Contact hover distance */
+#define ABS_MT_TOOL_X          0x3c    /* Center X tool position */
+#define ABS_MT_TOOL_Y          0x3d    /* Center Y tool position */
+
+#define ABS_MAX                        0x3f
+#define ABS_CNT                        (ABS_MAX+1)
+
+/*
+ * Switch events
+ */
+
+#define SW_LID                 0x00  /* set = lid shut */
+#define SW_TABLET_MODE         0x01  /* set = tablet mode */
+#define SW_HEADPHONE_INSERT    0x02  /* set = inserted */
+#define SW_RFKILL_ALL          0x03  /* rfkill master switch, type "any"
+                                        set = radio enabled */
+#define SW_RADIO               SW_RFKILL_ALL   /* deprecated */
+#define SW_MICROPHONE_INSERT   0x04  /* set = inserted */
+#define SW_DOCK                        0x05  /* set = plugged into dock */
+#define SW_LINEOUT_INSERT      0x06  /* set = inserted */
+#define SW_JACK_PHYSICAL_INSERT 0x07  /* set = mechanical switch set */
+#define SW_VIDEOOUT_INSERT     0x08  /* set = inserted */
+#define SW_CAMERA_LENS_COVER   0x09  /* set = lens covered */
+#define SW_KEYPAD_SLIDE                0x0a  /* set = keypad slide out */
+#define SW_FRONT_PROXIMITY     0x0b  /* set = front proximity sensor active */
+#define SW_ROTATE_LOCK         0x0c  /* set = rotate locked/disabled */
+#define SW_LINEIN_INSERT       0x0d  /* set = inserted */
+#define SW_MUTE_DEVICE         0x0e  /* set = device disabled */
+#define SW_MAX                 0x0f
+#define SW_CNT                 (SW_MAX+1)
+
+/*
+ * Misc events
+ */
+
+#define MSC_SERIAL             0x00
+#define MSC_PULSELED           0x01
+#define MSC_GESTURE            0x02
+#define MSC_RAW                        0x03
+#define MSC_SCAN               0x04
+#define MSC_TIMESTAMP          0x05
+#define MSC_MAX                        0x07
+#define MSC_CNT                        (MSC_MAX+1)
+
+/*
+ * LEDs
+ */
+
+#define LED_NUML               0x00
+#define LED_CAPSL              0x01
+#define LED_SCROLLL            0x02
+#define LED_COMPOSE            0x03
+#define LED_KANA               0x04
+#define LED_SLEEP              0x05
+#define LED_SUSPEND            0x06
+#define LED_MUTE               0x07
+#define LED_MISC               0x08
+#define LED_MAIL               0x09
+#define LED_CHARGING           0x0a
+#define LED_MAX                        0x0f
+#define LED_CNT                        (LED_MAX+1)
+
+/*
+ * Autorepeat values
+ */
+
+#define REP_DELAY              0x00
+#define REP_PERIOD             0x01
+#define REP_MAX                        0x01
+#define REP_CNT                        (REP_MAX+1)
+
+/*
+ * Sounds
+ */
+
+#define SND_CLICK              0x00
+#define SND_BELL               0x01
+#define SND_TONE               0x02
+#define SND_MAX                        0x07
+#define SND_CNT                        (SND_MAX+1)
+
+#endif
index e37293bbba4aada1bac2114b52fe2362f6e0593e..fbc968f224972c0880d4bffdcc4a218d4b61350e 100644 (file)
@@ -14,6 +14,7 @@
 #include <sys/types.h>
 #include <linux/types.h>
 
+#include "input-event-codes.h"
 
 /*
  * The event structure itself
@@ -95,6 +96,12 @@ struct input_keymap_entry {
        __u8  scancode[32];
 };
 
+struct input_mask {
+       __u32 type;
+       __u32 codes_size;
+       __u64 codes_ptr;
+};
+
 #define EVIOCGVERSION          _IOR('E', 0x01, int)                    /* get driver version */
 #define EVIOCGID               _IOR('E', 0x02, struct input_id)        /* get device ID */
 #define EVIOCGREP              _IOR('E', 0x03, unsigned int[2])        /* get repeat settings */
@@ -145,771 +152,68 @@ struct input_keymap_entry {
 #define EVIOCGABS(abs)         _IOR('E', 0x40 + (abs), struct input_absinfo)   /* get abs value/limits */
 #define EVIOCSABS(abs)         _IOW('E', 0xc0 + (abs), struct input_absinfo)   /* set abs value/limits */
 
-#define EVIOCSFF               _IOC(_IOC_WRITE, 'E', 0x80, sizeof(struct ff_effect))   /* send a force effect to a force feedback device */
+#define EVIOCSFF               _IOW('E', 0x80, struct ff_effect)       /* send a force effect to a force feedback device */
 #define EVIOCRMFF              _IOW('E', 0x81, int)                    /* Erase a force effect */
 #define EVIOCGEFFECTS          _IOR('E', 0x84, int)                    /* Report number of effects playable at the same time */
 
 #define EVIOCGRAB              _IOW('E', 0x90, int)                    /* Grab/Release device */
 #define EVIOCREVOKE            _IOW('E', 0x91, int)                    /* Revoke device access */
 
-#define EVIOCSCLOCKID          _IOW('E', 0xa0, int)                    /* Set clockid to be used for timestamps */
-
-/*
- * Device properties and quirks
- */
-
-#define INPUT_PROP_POINTER             0x00    /* needs a pointer */
-#define INPUT_PROP_DIRECT              0x01    /* direct input devices */
-#define INPUT_PROP_BUTTONPAD           0x02    /* has button(s) under pad */
-#define INPUT_PROP_SEMI_MT             0x03    /* touch rectangle only */
-
-#define INPUT_PROP_MAX                 0x1f
-#define INPUT_PROP_CNT                 (INPUT_PROP_MAX + 1)
-
-/*
- * Event types
- */
-
-#define EV_SYN                 0x00
-#define EV_KEY                 0x01
-#define EV_REL                 0x02
-#define EV_ABS                 0x03
-#define EV_MSC                 0x04
-#define EV_SW                  0x05
-#define EV_LED                 0x11
-#define EV_SND                 0x12
-#define EV_REP                 0x14
-#define EV_FF                  0x15
-#define EV_PWR                 0x16
-#define EV_FF_STATUS           0x17
-#define EV_MAX                 0x1f
-#define EV_CNT                 (EV_MAX+1)
-
-/*
- * Synchronization events.
- */
-
-#define SYN_REPORT             0
-#define SYN_CONFIG             1
-#define SYN_MT_REPORT          2
-#define SYN_DROPPED            3
-#define SYN_MAX                        0xf
-#define SYN_CNT                        (SYN_MAX+1)
-
-/*
- * Keys and buttons
+/**
+ * EVIOCGMASK - Retrieve current event mask
  *
- * Most of the keys/buttons are modeled after USB HUT 1.12
- * (see http://www.usb.org/developers/hidpage).
- * Abbreviations in the comments:
- * AC - Application Control
- * AL - Application Launch Button
- * SC - System Control
- */
-
-#define KEY_RESERVED           0
-#define KEY_ESC                        1
-#define KEY_1                  2
-#define KEY_2                  3
-#define KEY_3                  4
-#define KEY_4                  5
-#define KEY_5                  6
-#define KEY_6                  7
-#define KEY_7                  8
-#define KEY_8                  9
-#define KEY_9                  10
-#define KEY_0                  11
-#define KEY_MINUS              12
-#define KEY_EQUAL              13
-#define KEY_BACKSPACE          14
-#define KEY_TAB                        15
-#define KEY_Q                  16
-#define KEY_W                  17
-#define KEY_E                  18
-#define KEY_R                  19
-#define KEY_T                  20
-#define KEY_Y                  21
-#define KEY_U                  22
-#define KEY_I                  23
-#define KEY_O                  24
-#define KEY_P                  25
-#define KEY_LEFTBRACE          26
-#define KEY_RIGHTBRACE         27
-#define KEY_ENTER              28
-#define KEY_LEFTCTRL           29
-#define KEY_A                  30
-#define KEY_S                  31
-#define KEY_D                  32
-#define KEY_F                  33
-#define KEY_G                  34
-#define KEY_H                  35
-#define KEY_J                  36
-#define KEY_K                  37
-#define KEY_L                  38
-#define KEY_SEMICOLON          39
-#define KEY_APOSTROPHE         40
-#define KEY_GRAVE              41
-#define KEY_LEFTSHIFT          42
-#define KEY_BACKSLASH          43
-#define KEY_Z                  44
-#define KEY_X                  45
-#define KEY_C                  46
-#define KEY_V                  47
-#define KEY_B                  48
-#define KEY_N                  49
-#define KEY_M                  50
-#define KEY_COMMA              51
-#define KEY_DOT                        52
-#define KEY_SLASH              53
-#define KEY_RIGHTSHIFT         54
-#define KEY_KPASTERISK         55
-#define KEY_LEFTALT            56
-#define KEY_SPACE              57
-#define KEY_CAPSLOCK           58
-#define KEY_F1                 59
-#define KEY_F2                 60
-#define KEY_F3                 61
-#define KEY_F4                 62
-#define KEY_F5                 63
-#define KEY_F6                 64
-#define KEY_F7                 65
-#define KEY_F8                 66
-#define KEY_F9                 67
-#define KEY_F10                        68
-#define KEY_NUMLOCK            69
-#define KEY_SCROLLLOCK         70
-#define KEY_KP7                        71
-#define KEY_KP8                        72
-#define KEY_KP9                        73
-#define KEY_KPMINUS            74
-#define KEY_KP4                        75
-#define KEY_KP5                        76
-#define KEY_KP6                        77
-#define KEY_KPPLUS             78
-#define KEY_KP1                        79
-#define KEY_KP2                        80
-#define KEY_KP3                        81
-#define KEY_KP0                        82
-#define KEY_KPDOT              83
-
-#define KEY_ZENKAKUHANKAKU     85
-#define KEY_102ND              86
-#define KEY_F11                        87
-#define KEY_F12                        88
-#define KEY_RO                 89
-#define KEY_KATAKANA           90
-#define KEY_HIRAGANA           91
-#define KEY_HENKAN             92
-#define KEY_KATAKANAHIRAGANA   93
-#define KEY_MUHENKAN           94
-#define KEY_KPJPCOMMA          95
-#define KEY_KPENTER            96
-#define KEY_RIGHTCTRL          97
-#define KEY_KPSLASH            98
-#define KEY_SYSRQ              99
-#define KEY_RIGHTALT           100
-#define KEY_LINEFEED           101
-#define KEY_HOME               102
-#define KEY_UP                 103
-#define KEY_PAGEUP             104
-#define KEY_LEFT               105
-#define KEY_RIGHT              106
-#define KEY_END                        107
-#define KEY_DOWN               108
-#define KEY_PAGEDOWN           109
-#define KEY_INSERT             110
-#define KEY_DELETE             111
-#define KEY_MACRO              112
-#define KEY_MUTE               113
-#define KEY_VOLUMEDOWN         114
-#define KEY_VOLUMEUP           115
-#define KEY_POWER              116     /* SC System Power Down */
-#define KEY_KPEQUAL            117
-#define KEY_KPPLUSMINUS                118
-#define KEY_PAUSE              119
-#define KEY_SCALE              120     /* AL Compiz Scale (Expose) */
-
-#define KEY_KPCOMMA            121
-#define KEY_HANGEUL            122
-#define KEY_HANGUEL            KEY_HANGEUL
-#define KEY_HANJA              123
-#define KEY_YEN                        124
-#define KEY_LEFTMETA           125
-#define KEY_RIGHTMETA          126
-#define KEY_COMPOSE            127
-
-#define KEY_STOP               128     /* AC Stop */
-#define KEY_AGAIN              129
-#define KEY_PROPS              130     /* AC Properties */
-#define KEY_UNDO               131     /* AC Undo */
-#define KEY_FRONT              132
-#define KEY_COPY               133     /* AC Copy */
-#define KEY_OPEN               134     /* AC Open */
-#define KEY_PASTE              135     /* AC Paste */
-#define KEY_FIND               136     /* AC Search */
-#define KEY_CUT                        137     /* AC Cut */
-#define KEY_HELP               138     /* AL Integrated Help Center */
-#define KEY_MENU               139     /* Menu (show menu) */
-#define KEY_CALC               140     /* AL Calculator */
-#define KEY_SETUP              141
-#define KEY_SLEEP              142     /* SC System Sleep */
-#define KEY_WAKEUP             143     /* System Wake Up */
-#define KEY_FILE               144     /* AL Local Machine Browser */
-#define KEY_SENDFILE           145
-#define KEY_DELETEFILE         146
-#define KEY_XFER               147
-#define KEY_PROG1              148
-#define KEY_PROG2              149
-#define KEY_WWW                        150     /* AL Internet Browser */
-#define KEY_MSDOS              151
-#define KEY_COFFEE             152     /* AL Terminal Lock/Screensaver */
-#define KEY_SCREENLOCK         KEY_COFFEE
-#define KEY_DIRECTION          153
-#define KEY_CYCLEWINDOWS       154
-#define KEY_MAIL               155
-#define KEY_BOOKMARKS          156     /* AC Bookmarks */
-#define KEY_COMPUTER           157
-#define KEY_BACK               158     /* AC Back */
-#define KEY_FORWARD            159     /* AC Forward */
-#define KEY_CLOSECD            160
-#define KEY_EJECTCD            161
-#define KEY_EJECTCLOSECD       162
-#define KEY_NEXTSONG           163
-#define KEY_PLAYPAUSE          164
-#define KEY_PREVIOUSSONG       165
-#define KEY_STOPCD             166
-#define KEY_RECORD             167
-#define KEY_REWIND             168
-#define KEY_PHONE              169     /* Media Select Telephone */
-#define KEY_ISO                        170
-#define KEY_CONFIG             171     /* AL Consumer Control Configuration */
-#define KEY_HOMEPAGE           172     /* AC Home */
-#define KEY_REFRESH            173     /* AC Refresh */
-#define KEY_EXIT               174     /* AC Exit */
-#define KEY_MOVE               175
-#define KEY_EDIT               176
-#define KEY_SCROLLUP           177
-#define KEY_SCROLLDOWN         178
-#define KEY_KPLEFTPAREN                179
-#define KEY_KPRIGHTPAREN       180
-#define KEY_NEW                        181     /* AC New */
-#define KEY_REDO               182     /* AC Redo/Repeat */
-
-#define KEY_F13                        183
-#define KEY_F14                        184
-#define KEY_F15                        185
-#define KEY_F16                        186
-#define KEY_F17                        187
-#define KEY_F18                        188
-#define KEY_F19                        189
-#define KEY_F20                        190
-#define KEY_F21                        191
-#define KEY_F22                        192
-#define KEY_F23                        193
-#define KEY_F24                        194
-
-#define KEY_PLAYCD             200
-#define KEY_PAUSECD            201
-#define KEY_PROG3              202
-#define KEY_PROG4              203
-#define KEY_DASHBOARD          204     /* AL Dashboard */
-#define KEY_SUSPEND            205
-#define KEY_CLOSE              206     /* AC Close */
-#define KEY_PLAY               207
-#define KEY_FASTFORWARD                208
-#define KEY_BASSBOOST          209
-#define KEY_PRINT              210     /* AC Print */
-#define KEY_HP                 211
-#define KEY_CAMERA             212
-#define KEY_SOUND              213
-#define KEY_QUESTION           214
-#define KEY_EMAIL              215
-#define KEY_CHAT               216
-#define KEY_SEARCH             217
-#define KEY_CONNECT            218
-#define KEY_FINANCE            219     /* AL Checkbook/Finance */
-#define KEY_SPORT              220
-#define KEY_SHOP               221
-#define KEY_ALTERASE           222
-#define KEY_CANCEL             223     /* AC Cancel */
-#define KEY_BRIGHTNESSDOWN     224
-#define KEY_BRIGHTNESSUP       225
-#define KEY_MEDIA              226
-
-#define KEY_SWITCHVIDEOMODE    227     /* Cycle between available video
-                                          outputs (Monitor/LCD/TV-out/etc) */
-#define KEY_KBDILLUMTOGGLE     228
-#define KEY_KBDILLUMDOWN       229
-#define KEY_KBDILLUMUP         230
-
-#define KEY_SEND               231     /* AC Send */
-#define KEY_REPLY              232     /* AC Reply */
-#define KEY_FORWARDMAIL                233     /* AC Forward Msg */
-#define KEY_SAVE               234     /* AC Save */
-#define KEY_DOCUMENTS          235
-
-#define KEY_BATTERY            236
-
-#define KEY_BLUETOOTH          237
-#define KEY_WLAN               238
-#define KEY_UWB                        239
-
-#define KEY_UNKNOWN            240
-
-#define KEY_VIDEO_NEXT         241     /* drive next video source */
-#define KEY_VIDEO_PREV         242     /* drive previous video source */
-#define KEY_BRIGHTNESS_CYCLE   243     /* brightness up, after max is min */
-#define KEY_BRIGHTNESS_ZERO    244     /* brightness off, use ambient */
-#define KEY_DISPLAY_OFF                245     /* display device to off state */
-
-#define KEY_WWAN               246     /* Wireless WAN (LTE, UMTS, GSM, etc.) */
-#define KEY_WIMAX              KEY_WWAN
-#define KEY_RFKILL             247     /* Key that controls all radios */
-
-#define KEY_MICMUTE            248     /* Mute / unmute the microphone */
-
-/* Code 255 is reserved for special needs of AT keyboard driver */
-
-#define BTN_MISC               0x100
-#define BTN_0                  0x100
-#define BTN_1                  0x101
-#define BTN_2                  0x102
-#define BTN_3                  0x103
-#define BTN_4                  0x104
-#define BTN_5                  0x105
-#define BTN_6                  0x106
-#define BTN_7                  0x107
-#define BTN_8                  0x108
-#define BTN_9                  0x109
-
-#define BTN_MOUSE              0x110
-#define BTN_LEFT               0x110
-#define BTN_RIGHT              0x111
-#define BTN_MIDDLE             0x112
-#define BTN_SIDE               0x113
-#define BTN_EXTRA              0x114
-#define BTN_FORWARD            0x115
-#define BTN_BACK               0x116
-#define BTN_TASK               0x117
-
-#define BTN_JOYSTICK           0x120
-#define BTN_TRIGGER            0x120
-#define BTN_THUMB              0x121
-#define BTN_THUMB2             0x122
-#define BTN_TOP                        0x123
-#define BTN_TOP2               0x124
-#define BTN_PINKIE             0x125
-#define BTN_BASE               0x126
-#define BTN_BASE2              0x127
-#define BTN_BASE3              0x128
-#define BTN_BASE4              0x129
-#define BTN_BASE5              0x12a
-#define BTN_BASE6              0x12b
-#define BTN_DEAD               0x12f
-
-#define BTN_GAMEPAD            0x130
-#define BTN_SOUTH              0x130
-#define BTN_A                  BTN_SOUTH
-#define BTN_EAST               0x131
-#define BTN_B                  BTN_EAST
-#define BTN_C                  0x132
-#define BTN_NORTH              0x133
-#define BTN_X                  BTN_NORTH
-#define BTN_WEST               0x134
-#define BTN_Y                  BTN_WEST
-#define BTN_Z                  0x135
-#define BTN_TL                 0x136
-#define BTN_TR                 0x137
-#define BTN_TL2                        0x138
-#define BTN_TR2                        0x139
-#define BTN_SELECT             0x13a
-#define BTN_START              0x13b
-#define BTN_MODE               0x13c
-#define BTN_THUMBL             0x13d
-#define BTN_THUMBR             0x13e
-
-#define BTN_DIGI               0x140
-#define BTN_TOOL_PEN           0x140
-#define BTN_TOOL_RUBBER                0x141
-#define BTN_TOOL_BRUSH         0x142
-#define BTN_TOOL_PENCIL                0x143
-#define BTN_TOOL_AIRBRUSH      0x144
-#define BTN_TOOL_FINGER                0x145
-#define BTN_TOOL_MOUSE         0x146
-#define BTN_TOOL_LENS          0x147
-#define BTN_TOOL_QUINTTAP      0x148   /* Five fingers on trackpad */
-#define BTN_TOUCH              0x14a
-#define BTN_STYLUS             0x14b
-#define BTN_STYLUS2            0x14c
-#define BTN_TOOL_DOUBLETAP     0x14d
-#define BTN_TOOL_TRIPLETAP     0x14e
-#define BTN_TOOL_QUADTAP       0x14f   /* Four fingers on trackpad */
-
-#define BTN_WHEEL              0x150
-#define BTN_GEAR_DOWN          0x150
-#define BTN_GEAR_UP            0x151
-
-#define KEY_OK                 0x160
-#define KEY_SELECT             0x161
-#define KEY_GOTO               0x162
-#define KEY_CLEAR              0x163
-#define KEY_POWER2             0x164
-#define KEY_OPTION             0x165
-#define KEY_INFO               0x166   /* AL OEM Features/Tips/Tutorial */
-#define KEY_TIME               0x167
-#define KEY_VENDOR             0x168
-#define KEY_ARCHIVE            0x169
-#define KEY_PROGRAM            0x16a   /* Media Select Program Guide */
-#define KEY_CHANNEL            0x16b
-#define KEY_FAVORITES          0x16c
-#define KEY_EPG                        0x16d
-#define KEY_PVR                        0x16e   /* Media Select Home */
-#define KEY_MHP                        0x16f
-#define KEY_LANGUAGE           0x170
-#define KEY_TITLE              0x171
-#define KEY_SUBTITLE           0x172
-#define KEY_ANGLE              0x173
-#define KEY_ZOOM               0x174
-#define KEY_MODE               0x175
-#define KEY_KEYBOARD           0x176
-#define KEY_SCREEN             0x177
-#define KEY_PC                 0x178   /* Media Select Computer */
-#define KEY_TV                 0x179   /* Media Select TV */
-#define KEY_TV2                        0x17a   /* Media Select Cable */
-#define KEY_VCR                        0x17b   /* Media Select VCR */
-#define KEY_VCR2               0x17c   /* VCR Plus */
-#define KEY_SAT                        0x17d   /* Media Select Satellite */
-#define KEY_SAT2               0x17e
-#define KEY_CD                 0x17f   /* Media Select CD */
-#define KEY_TAPE               0x180   /* Media Select Tape */
-#define KEY_RADIO              0x181
-#define KEY_TUNER              0x182   /* Media Select Tuner */
-#define KEY_PLAYER             0x183
-#define KEY_TEXT               0x184
-#define KEY_DVD                        0x185   /* Media Select DVD */
-#define KEY_AUX                        0x186
-#define KEY_MP3                        0x187
-#define KEY_AUDIO              0x188   /* AL Audio Browser */
-#define KEY_VIDEO              0x189   /* AL Movie Browser */
-#define KEY_DIRECTORY          0x18a
-#define KEY_LIST               0x18b
-#define KEY_MEMO               0x18c   /* Media Select Messages */
-#define KEY_CALENDAR           0x18d
-#define KEY_RED                        0x18e
-#define KEY_GREEN              0x18f
-#define KEY_YELLOW             0x190
-#define KEY_BLUE               0x191
-#define KEY_CHANNELUP          0x192   /* Channel Increment */
-#define KEY_CHANNELDOWN                0x193   /* Channel Decrement */
-#define KEY_FIRST              0x194
-#define KEY_LAST               0x195   /* Recall Last */
-#define KEY_AB                 0x196
-#define KEY_NEXT               0x197
-#define KEY_RESTART            0x198
-#define KEY_SLOW               0x199
-#define KEY_SHUFFLE            0x19a
-#define KEY_BREAK              0x19b
-#define KEY_PREVIOUS           0x19c
-#define KEY_DIGITS             0x19d
-#define KEY_TEEN               0x19e
-#define KEY_TWEN               0x19f
-#define KEY_VIDEOPHONE         0x1a0   /* Media Select Video Phone */
-#define KEY_GAMES              0x1a1   /* Media Select Games */
-#define KEY_ZOOMIN             0x1a2   /* AC Zoom In */
-#define KEY_ZOOMOUT            0x1a3   /* AC Zoom Out */
-#define KEY_ZOOMRESET          0x1a4   /* AC Zoom */
-#define KEY_WORDPROCESSOR      0x1a5   /* AL Word Processor */
-#define KEY_EDITOR             0x1a6   /* AL Text Editor */
-#define KEY_SPREADSHEET                0x1a7   /* AL Spreadsheet */
-#define KEY_GRAPHICSEDITOR     0x1a8   /* AL Graphics Editor */
-#define KEY_PRESENTATION       0x1a9   /* AL Presentation App */
-#define KEY_DATABASE           0x1aa   /* AL Database App */
-#define KEY_NEWS               0x1ab   /* AL Newsreader */
-#define KEY_VOICEMAIL          0x1ac   /* AL Voicemail */
-#define KEY_ADDRESSBOOK                0x1ad   /* AL Contacts/Address Book */
-#define KEY_MESSENGER          0x1ae   /* AL Instant Messaging */
-#define KEY_DISPLAYTOGGLE      0x1af   /* Turn display (LCD) on and off */
-#define KEY_SPELLCHECK         0x1b0   /* AL Spell Check */
-#define KEY_LOGOFF             0x1b1   /* AL Logoff */
-
-#define KEY_DOLLAR             0x1b2
-#define KEY_EURO               0x1b3
-
-#define KEY_FRAMEBACK          0x1b4   /* Consumer - transport controls */
-#define KEY_FRAMEFORWARD       0x1b5
-#define KEY_CONTEXT_MENU       0x1b6   /* GenDesc - system context menu */
-#define KEY_MEDIA_REPEAT       0x1b7   /* Consumer - transport control */
-#define KEY_10CHANNELSUP       0x1b8   /* 10 channels up (10+) */
-#define KEY_10CHANNELSDOWN     0x1b9   /* 10 channels down (10-) */
-#define KEY_IMAGES             0x1ba   /* AL Image Browser */
-
-#define KEY_DEL_EOL            0x1c0
-#define KEY_DEL_EOS            0x1c1
-#define KEY_INS_LINE           0x1c2
-#define KEY_DEL_LINE           0x1c3
-
-#define KEY_FN                 0x1d0
-#define KEY_FN_ESC             0x1d1
-#define KEY_FN_F1              0x1d2
-#define KEY_FN_F2              0x1d3
-#define KEY_FN_F3              0x1d4
-#define KEY_FN_F4              0x1d5
-#define KEY_FN_F5              0x1d6
-#define KEY_FN_F6              0x1d7
-#define KEY_FN_F7              0x1d8
-#define KEY_FN_F8              0x1d9
-#define KEY_FN_F9              0x1da
-#define KEY_FN_F10             0x1db
-#define KEY_FN_F11             0x1dc
-#define KEY_FN_F12             0x1dd
-#define KEY_FN_1               0x1de
-#define KEY_FN_2               0x1df
-#define KEY_FN_D               0x1e0
-#define KEY_FN_E               0x1e1
-#define KEY_FN_F               0x1e2
-#define KEY_FN_S               0x1e3
-#define KEY_FN_B               0x1e4
-
-#define KEY_BRL_DOT1           0x1f1
-#define KEY_BRL_DOT2           0x1f2
-#define KEY_BRL_DOT3           0x1f3
-#define KEY_BRL_DOT4           0x1f4
-#define KEY_BRL_DOT5           0x1f5
-#define KEY_BRL_DOT6           0x1f6
-#define KEY_BRL_DOT7           0x1f7
-#define KEY_BRL_DOT8           0x1f8
-#define KEY_BRL_DOT9           0x1f9
-#define KEY_BRL_DOT10          0x1fa
-
-#define KEY_NUMERIC_0          0x200   /* used by phones, remote controls, */
-#define KEY_NUMERIC_1          0x201   /* and other keypads */
-#define KEY_NUMERIC_2          0x202
-#define KEY_NUMERIC_3          0x203
-#define KEY_NUMERIC_4          0x204
-#define KEY_NUMERIC_5          0x205
-#define KEY_NUMERIC_6          0x206
-#define KEY_NUMERIC_7          0x207
-#define KEY_NUMERIC_8          0x208
-#define KEY_NUMERIC_9          0x209
-#define KEY_NUMERIC_STAR       0x20a
-#define KEY_NUMERIC_POUND      0x20b
-
-#define KEY_CAMERA_FOCUS       0x210
-#define KEY_WPS_BUTTON         0x211   /* WiFi Protected Setup key */
-
-#define KEY_TOUCHPAD_TOGGLE    0x212   /* Request switch touchpad on or off */
-#define KEY_TOUCHPAD_ON                0x213
-#define KEY_TOUCHPAD_OFF       0x214
-
-#define KEY_CAMERA_ZOOMIN      0x215
-#define KEY_CAMERA_ZOOMOUT     0x216
-#define KEY_CAMERA_UP          0x217
-#define KEY_CAMERA_DOWN                0x218
-#define KEY_CAMERA_LEFT                0x219
-#define KEY_CAMERA_RIGHT       0x21a
-
-#define KEY_ATTENDANT_ON       0x21b
-#define KEY_ATTENDANT_OFF      0x21c
-#define KEY_ATTENDANT_TOGGLE   0x21d   /* Attendant call on or off */
-#define KEY_LIGHTS_TOGGLE      0x21e   /* Reading light on or off */
-
-#define BTN_DPAD_UP            0x220
-#define BTN_DPAD_DOWN          0x221
-#define BTN_DPAD_LEFT          0x222
-#define BTN_DPAD_RIGHT         0x223
-
-#define KEY_ALS_TOGGLE         0x230   /* Ambient light sensor */
-
-#define BTN_TRIGGER_HAPPY              0x2c0
-#define BTN_TRIGGER_HAPPY1             0x2c0
-#define BTN_TRIGGER_HAPPY2             0x2c1
-#define BTN_TRIGGER_HAPPY3             0x2c2
-#define BTN_TRIGGER_HAPPY4             0x2c3
-#define BTN_TRIGGER_HAPPY5             0x2c4
-#define BTN_TRIGGER_HAPPY6             0x2c5
-#define BTN_TRIGGER_HAPPY7             0x2c6
-#define BTN_TRIGGER_HAPPY8             0x2c7
-#define BTN_TRIGGER_HAPPY9             0x2c8
-#define BTN_TRIGGER_HAPPY10            0x2c9
-#define BTN_TRIGGER_HAPPY11            0x2ca
-#define BTN_TRIGGER_HAPPY12            0x2cb
-#define BTN_TRIGGER_HAPPY13            0x2cc
-#define BTN_TRIGGER_HAPPY14            0x2cd
-#define BTN_TRIGGER_HAPPY15            0x2ce
-#define BTN_TRIGGER_HAPPY16            0x2cf
-#define BTN_TRIGGER_HAPPY17            0x2d0
-#define BTN_TRIGGER_HAPPY18            0x2d1
-#define BTN_TRIGGER_HAPPY19            0x2d2
-#define BTN_TRIGGER_HAPPY20            0x2d3
-#define BTN_TRIGGER_HAPPY21            0x2d4
-#define BTN_TRIGGER_HAPPY22            0x2d5
-#define BTN_TRIGGER_HAPPY23            0x2d6
-#define BTN_TRIGGER_HAPPY24            0x2d7
-#define BTN_TRIGGER_HAPPY25            0x2d8
-#define BTN_TRIGGER_HAPPY26            0x2d9
-#define BTN_TRIGGER_HAPPY27            0x2da
-#define BTN_TRIGGER_HAPPY28            0x2db
-#define BTN_TRIGGER_HAPPY29            0x2dc
-#define BTN_TRIGGER_HAPPY30            0x2dd
-#define BTN_TRIGGER_HAPPY31            0x2de
-#define BTN_TRIGGER_HAPPY32            0x2df
-#define BTN_TRIGGER_HAPPY33            0x2e0
-#define BTN_TRIGGER_HAPPY34            0x2e1
-#define BTN_TRIGGER_HAPPY35            0x2e2
-#define BTN_TRIGGER_HAPPY36            0x2e3
-#define BTN_TRIGGER_HAPPY37            0x2e4
-#define BTN_TRIGGER_HAPPY38            0x2e5
-#define BTN_TRIGGER_HAPPY39            0x2e6
-#define BTN_TRIGGER_HAPPY40            0x2e7
-
-/* We avoid low common keys in module aliases so they don't get huge. */
-#define KEY_MIN_INTERESTING    KEY_MUTE
-#define KEY_MAX                        0x2ff
-#define KEY_CNT                        (KEY_MAX+1)
-
-/*
- * Relative axes
- */
-
-#define REL_X                  0x00
-#define REL_Y                  0x01
-#define REL_Z                  0x02
-#define REL_RX                 0x03
-#define REL_RY                 0x04
-#define REL_RZ                 0x05
-#define REL_HWHEEL             0x06
-#define REL_DIAL               0x07
-#define REL_WHEEL              0x08
-#define REL_MISC               0x09
-#define REL_MAX                        0x0f
-#define REL_CNT                        (REL_MAX+1)
-
-/*
- * Absolute axes
- */
-
-#define ABS_X                  0x00
-#define ABS_Y                  0x01
-#define ABS_Z                  0x02
-#define ABS_RX                 0x03
-#define ABS_RY                 0x04
-#define ABS_RZ                 0x05
-#define ABS_THROTTLE           0x06
-#define ABS_RUDDER             0x07
-#define ABS_WHEEL              0x08
-#define ABS_GAS                        0x09
-#define ABS_BRAKE              0x0a
-#define ABS_HAT0X              0x10
-#define ABS_HAT0Y              0x11
-#define ABS_HAT1X              0x12
-#define ABS_HAT1Y              0x13
-#define ABS_HAT2X              0x14
-#define ABS_HAT2Y              0x15
-#define ABS_HAT3X              0x16
-#define ABS_HAT3Y              0x17
-#define ABS_PRESSURE           0x18
-#define ABS_DISTANCE           0x19
-#define ABS_TILT_X             0x1a
-#define ABS_TILT_Y             0x1b
-#define ABS_TOOL_WIDTH         0x1c
-
-#define ABS_VOLUME             0x20
-
-#define ABS_MISC               0x28
-
-#define ABS_MT_SLOT            0x2f    /* MT slot being modified */
-#define ABS_MT_TOUCH_MAJOR     0x30    /* Major axis of touching ellipse */
-#define ABS_MT_TOUCH_MINOR     0x31    /* Minor axis (omit if circular) */
-#define ABS_MT_WIDTH_MAJOR     0x32    /* Major axis of approaching ellipse */
-#define ABS_MT_WIDTH_MINOR     0x33    /* Minor axis (omit if circular) */
-#define ABS_MT_ORIENTATION     0x34    /* Ellipse orientation */
-#define ABS_MT_POSITION_X      0x35    /* Center X touch position */
-#define ABS_MT_POSITION_Y      0x36    /* Center Y touch position */
-#define ABS_MT_TOOL_TYPE       0x37    /* Type of touching device */
-#define ABS_MT_BLOB_ID         0x38    /* Group a set of packets as a blob */
-#define ABS_MT_TRACKING_ID     0x39    /* Unique ID of initiated contact */
-#define ABS_MT_PRESSURE                0x3a    /* Pressure on contact area */
-#define ABS_MT_DISTANCE                0x3b    /* Contact hover distance */
-#define ABS_MT_TOOL_X          0x3c    /* Center X tool position */
-#define ABS_MT_TOOL_Y          0x3d    /* Center Y tool position */
-
-
-#define ABS_MAX                        0x3f
-#define ABS_CNT                        (ABS_MAX+1)
-
-/*
- * Switch events
- */
-
-#define SW_LID                 0x00  /* set = lid shut */
-#define SW_TABLET_MODE         0x01  /* set = tablet mode */
-#define SW_HEADPHONE_INSERT    0x02  /* set = inserted */
-#define SW_RFKILL_ALL          0x03  /* rfkill master switch, type "any"
-                                        set = radio enabled */
-#define SW_RADIO               SW_RFKILL_ALL   /* deprecated */
-#define SW_MICROPHONE_INSERT   0x04  /* set = inserted */
-#define SW_DOCK                        0x05  /* set = plugged into dock */
-#define SW_LINEOUT_INSERT      0x06  /* set = inserted */
-#define SW_JACK_PHYSICAL_INSERT 0x07  /* set = mechanical switch set */
-#define SW_VIDEOOUT_INSERT     0x08  /* set = inserted */
-#define SW_CAMERA_LENS_COVER   0x09  /* set = lens covered */
-#define SW_KEYPAD_SLIDE                0x0a  /* set = keypad slide out */
-#define SW_FRONT_PROXIMITY     0x0b  /* set = front proximity sensor active */
-#define SW_ROTATE_LOCK         0x0c  /* set = rotate locked/disabled */
-#define SW_LINEIN_INSERT       0x0d  /* set = inserted */
-#define SW_MUTE_DEVICE         0x0e  /* set = device disabled */
-#define SW_MAX                 0x0f
-#define SW_CNT                 (SW_MAX+1)
-
-/*
- * Misc events
- */
-
-#define MSC_SERIAL             0x00
-#define MSC_PULSELED           0x01
-#define MSC_GESTURE            0x02
-#define MSC_RAW                        0x03
-#define MSC_SCAN               0x04
-#define MSC_TIMESTAMP          0x05
-#define MSC_MAX                        0x07
-#define MSC_CNT                        (MSC_MAX+1)
-
-/*
- * LEDs
- */
-
-#define LED_NUML               0x00
-#define LED_CAPSL              0x01
-#define LED_SCROLLL            0x02
-#define LED_COMPOSE            0x03
-#define LED_KANA               0x04
-#define LED_SLEEP              0x05
-#define LED_SUSPEND            0x06
-#define LED_MUTE               0x07
-#define LED_MISC               0x08
-#define LED_MAIL               0x09
-#define LED_CHARGING           0x0a
-#define LED_MAX                        0x0f
-#define LED_CNT                        (LED_MAX+1)
-
-/*
- * Autorepeat values
+ * This ioctl allows user to retrieve the current event mask for specific
+ * event type. The argument must be of type "struct input_mask" and
+ * specifies the event type to query, the address of the receive buffer and
+ * the size of the receive buffer.
+ *
+ * The event mask is a per-client mask that specifies which events are
+ * forwarded to the client. Each event code is represented by a single bit
+ * in the event mask. If the bit is set, the event is passed to the client
+ * normally. Otherwise, the event is filtered and will never be queued on
+ * the client's receive buffer.
+ *
+ * Event masks do not affect global state of the input device. They only
+ * affect the file descriptor they are applied to.
+ *
+ * The default event mask for a client has all bits set, i.e. all events
+ * are forwarded to the client. If the kernel is queried for an unknown
+ * event type or if the receive buffer is larger than the number of
+ * event codes known to the kernel, the kernel returns all zeroes for those
+ * codes.
+ *
+ * At maximum, codes_size bytes are copied.
+ *
+ * This ioctl may fail with ENODEV in case the file is revoked, EFAULT
+ * if the receive-buffer points to invalid memory, or EINVAL if the kernel
+ * does not implement the ioctl.
  */
+#define EVIOCGMASK             _IOR('E', 0x92, struct input_mask)      /* Get event-masks */
 
-#define REP_DELAY              0x00
-#define REP_PERIOD             0x01
-#define REP_MAX                        0x01
-#define REP_CNT                        (REP_MAX+1)
-
-/*
- * Sounds
+/**
+ * EVIOCSMASK - Set event mask
+ *
+ * This ioctl is the counterpart to EVIOCGMASK. Instead of receiving the
+ * current event mask, this changes the client's event mask for a specific
+ * type.  See EVIOCGMASK for a description of event-masks and the
+ * argument-type.
+ *
+ * This ioctl provides full forward compatibility. If the passed event type
+ * is unknown to the kernel, or if the number of event codes specified in
+ * the mask is bigger than what is known to the kernel, the ioctl is still
+ * accepted and applied. However, any unknown codes are left untouched and
+ * stay cleared. That means, the kernel always filters unknown codes
+ * regardless of what the client requests.  If the new mask doesn't cover
+ * all known event-codes, all remaining codes are automatically cleared and
+ * thus filtered.
+ *
+ * This ioctl may fail with ENODEV in case the file is revoked. EFAULT is
+ * returned if the receive-buffer points to invalid memory. EINVAL is returned
+ * if the kernel does not implement the ioctl.
  */
+#define EVIOCSMASK             _IOW('E', 0x93, struct input_mask)      /* Set event-masks */
 
-#define SND_CLICK              0x00
-#define SND_BELL               0x01
-#define SND_TONE               0x02
-#define SND_MAX                        0x07
-#define SND_CNT                        (SND_MAX+1)
+#define EVIOCSCLOCKID          _IOW('E', 0xa0, int)                    /* Set clockid to be used for timestamps */
 
 /*
  * IDs.
@@ -940,13 +244,15 @@ struct input_keymap_entry {
 #define BUS_GSC                        0x1A
 #define BUS_ATARI              0x1B
 #define BUS_SPI                        0x1C
+#define BUS_RMI                        0x1D
 
 /*
  * MT_TOOL types
  */
 #define MT_TOOL_FINGER         0
 #define MT_TOOL_PEN            1
-#define MT_TOOL_MAX            1
+#define MT_TOOL_PALM           2
+#define MT_TOOL_MAX            2
 
 /*
  * Values describing the status of a force-feedback effect
@@ -1167,6 +473,14 @@ struct ff_effect {
 #define FF_GAIN                0x60
 #define FF_AUTOCENTER  0x61
 
+/*
+ * ff->playback(effect_id = FF_GAIN) is the first effect_id to
+ * cause a collision with another ff method, in this case ff->set_gain().
+ * Therefore the greatest safe value for effect_id is FF_GAIN - 1,
+ * and thus the total number of effects should never exceed FF_GAIN.
+ */
+#define FF_MAX_EFFECTS FF_GAIN
+
 #define FF_MAX         0x7f
 #define FF_CNT         (FF_MAX+1)
 
diff --git a/include/linux/uinput.h b/include/linux/uinput.h
new file mode 100644 (file)
index 0000000..434f02d
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ *  User level driver support for input subsystem
+ *
+ * Heavily based on evdev.c by Vojtech Pavlik
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
+ *
+ * Changes/Revisions:
+ *     0.5     08/13/2015 (David Herrmann <dh.herrmann@gmail.com> &
+ *                         Benjamin Tissoires <benjamin.tissoires@redhat.com>)
+ *             - add UI_DEV_SETUP ioctl
+ *             - add UI_ABS_SETUP ioctl
+ *             - add UI_GET_VERSION ioctl
+ *     0.4     01/09/2014 (Benjamin Tissoires <benjamin.tissoires@redhat.com>)
+ *             - add UI_GET_SYSNAME ioctl
+ *     0.3     24/05/2006 (Anssi Hannula <anssi.hannulagmail.com>)
+ *             - update ff support for the changes in kernel interface
+ *             - add UINPUT_VERSION
+ *     0.2     16/10/2004 (Micah Dowty <micah@navi.cx>)
+ *             - added force feedback support
+ *             - added UI_SET_PHYS
+ *     0.1     20/06/2002
+ *             - first public version
+ */
+#ifndef __UINPUT_H_
+#define __UINPUT_H_
+
+#include <linux/types.h>
+#include <linux/input.h>
+
+#define UINPUT_VERSION         5
+#define UINPUT_MAX_NAME_SIZE   80
+
+struct uinput_ff_upload {
+       __u32                   request_id;
+       __s32                   retval;
+       struct ff_effect        effect;
+       struct ff_effect        old;
+};
+
+struct uinput_ff_erase {
+       __u32                   request_id;
+       __s32                   retval;
+       __u32                   effect_id;
+};
+
+/* ioctl */
+#define UINPUT_IOCTL_BASE      'U'
+#define UI_DEV_CREATE          _IO(UINPUT_IOCTL_BASE, 1)
+#define UI_DEV_DESTROY         _IO(UINPUT_IOCTL_BASE, 2)
+
+struct uinput_setup {
+       struct input_id id;
+       char name[UINPUT_MAX_NAME_SIZE];
+       __u32 ff_effects_max;
+};
+
+/**
+ * UI_DEV_SETUP - Set device parameters for setup
+ *
+ * This ioctl sets parameters for the input device to be created.  It
+ * supersedes the old "struct uinput_user_dev" method, which wrote this data
+ * via write(). To actually set the absolute axes UI_ABS_SETUP should be
+ * used.
+ *
+ * The ioctl takes a "struct uinput_setup" object as argument. The fields of
+ * this object are as follows:
+ *              id: See the description of "struct input_id". This field is
+ *                  copied unchanged into the new device.
+ *            name: This is used unchanged as name for the new device.
+ *  ff_effects_max: This limits the maximum numbers of force-feedback effects.
+ *                  See below for a description of FF with uinput.
+ *
+ * This ioctl can be called multiple times and will overwrite previous values.
+ * If this ioctl fails with -EINVAL, it is recommended to use the old
+ * "uinput_user_dev" method via write() as a fallback, in case you run on an
+ * old kernel that does not support this ioctl.
+ *
+ * This ioctl may fail with -EINVAL if it is not supported or if you passed
+ * incorrect values, -ENOMEM if the kernel runs out of memory or -EFAULT if the
+ * passed uinput_setup object cannot be read/written.
+ * If this call fails, partial data may have already been applied to the
+ * internal device.
+ */
+#define UI_DEV_SETUP _IOW(UINPUT_IOCTL_BASE, 3, struct uinput_setup)
+
+struct uinput_abs_setup {
+       __u16  code; /* axis code */
+       /* __u16 filler; */
+       struct input_absinfo absinfo;
+};
+
+/**
+ * UI_ABS_SETUP - Set absolute axis information for the device to setup
+ *
+ * This ioctl sets one absolute axis information for the input device to be
+ * created. It supersedes the old "struct uinput_user_dev" method, which wrote
+ * part of this data and the content of UI_DEV_SETUP via write().
+ *
+ * The ioctl takes a "struct uinput_abs_setup" object as argument. The fields
+ * of this object are as follows:
+ *            code: The corresponding input code associated with this axis
+ *                  (ABS_X, ABS_Y, etc...)
+ *         absinfo: See "struct input_absinfo" for a description of this field.
+ *                  This field is copied unchanged into the kernel for the
+ *                  specified axis. If the axis is not enabled via
+ *                  UI_SET_ABSBIT, this ioctl will enable it.
+ *
+ * This ioctl can be called multiple times and will overwrite previous values.
+ * If this ioctl fails with -EINVAL, it is recommended to use the old
+ * "uinput_user_dev" method via write() as a fallback, in case you run on an
+ * old kernel that does not support this ioctl.
+ *
+ * This ioctl may fail with -EINVAL if it is not supported or if you passed
+ * incorrect values, -ENOMEM if the kernel runs out of memory or -EFAULT if the
+ * passed uinput_setup object cannot be read/written.
+ * If this call fails, partial data may have already been applied to the
+ * internal device.
+ */
+#define UI_ABS_SETUP _IOW(UINPUT_IOCTL_BASE, 4, struct uinput_abs_setup)
+
+#define UI_SET_EVBIT           _IOW(UINPUT_IOCTL_BASE, 100, int)
+#define UI_SET_KEYBIT          _IOW(UINPUT_IOCTL_BASE, 101, int)
+#define UI_SET_RELBIT          _IOW(UINPUT_IOCTL_BASE, 102, int)
+#define UI_SET_ABSBIT          _IOW(UINPUT_IOCTL_BASE, 103, int)
+#define UI_SET_MSCBIT          _IOW(UINPUT_IOCTL_BASE, 104, int)
+#define UI_SET_LEDBIT          _IOW(UINPUT_IOCTL_BASE, 105, int)
+#define UI_SET_SNDBIT          _IOW(UINPUT_IOCTL_BASE, 106, int)
+#define UI_SET_FFBIT           _IOW(UINPUT_IOCTL_BASE, 107, int)
+#define UI_SET_PHYS            _IOW(UINPUT_IOCTL_BASE, 108, char*)
+#define UI_SET_SWBIT           _IOW(UINPUT_IOCTL_BASE, 109, int)
+#define UI_SET_PROPBIT         _IOW(UINPUT_IOCTL_BASE, 110, int)
+
+#define UI_BEGIN_FF_UPLOAD     _IOWR(UINPUT_IOCTL_BASE, 200, struct uinput_ff_upload)
+#define UI_END_FF_UPLOAD       _IOW(UINPUT_IOCTL_BASE, 201, struct uinput_ff_upload)
+#define UI_BEGIN_FF_ERASE      _IOWR(UINPUT_IOCTL_BASE, 202, struct uinput_ff_erase)
+#define UI_END_FF_ERASE                _IOW(UINPUT_IOCTL_BASE, 203, struct uinput_ff_erase)
+
+/**
+ * UI_GET_SYSNAME - get the sysfs name of the created uinput device
+ *
+ * @return the sysfs name of the created virtual input device.
+ * The complete sysfs path is then /sys/devices/virtual/input/--NAME--
+ * Usually, it is in the form "inputN"
+ */
+#define UI_GET_SYSNAME(len)    _IOC(_IOC_READ, UINPUT_IOCTL_BASE, 44, len)
+
+/**
+ * UI_GET_VERSION - Return version of uinput protocol
+ *
+ * This writes uinput protocol version implemented by the kernel into
+ * the integer pointed to by the ioctl argument. The protocol version
+ * is hard-coded in the kernel and is independent of the uinput device.
+ */
+#define UI_GET_VERSION         _IOR(UINPUT_IOCTL_BASE, 45, unsigned int)
+
+/*
+ * To write a force-feedback-capable driver, the upload_effect
+ * and erase_effect callbacks in input_dev must be implemented.
+ * The uinput driver will generate a fake input event when one of
+ * these callbacks are invoked. The userspace code then uses
+ * ioctls to retrieve additional parameters and send the return code.
+ * The callback blocks until this return code is sent.
+ *
+ * The described callback mechanism is only used if ff_effects_max
+ * is set.
+ *
+ * To implement upload_effect():
+ *   1. Wait for an event with type == EV_UINPUT and code == UI_FF_UPLOAD.
+ *      A request ID will be given in 'value'.
+ *   2. Allocate a uinput_ff_upload struct, fill in request_id with
+ *      the 'value' from the EV_UINPUT event.
+ *   3. Issue a UI_BEGIN_FF_UPLOAD ioctl, giving it the
+ *      uinput_ff_upload struct. It will be filled in with the
+ *      ff_effects passed to upload_effect().
+ *   4. Perform the effect upload, and place a return code back into
+        the uinput_ff_upload struct.
+ *   5. Issue a UI_END_FF_UPLOAD ioctl, also giving it the
+ *      uinput_ff_upload_effect struct. This will complete execution
+ *      of our upload_effect() handler.
+ *
+ * To implement erase_effect():
+ *   1. Wait for an event with type == EV_UINPUT and code == UI_FF_ERASE.
+ *      A request ID will be given in 'value'.
+ *   2. Allocate a uinput_ff_erase struct, fill in request_id with
+ *      the 'value' from the EV_UINPUT event.
+ *   3. Issue a UI_BEGIN_FF_ERASE ioctl, giving it the
+ *      uinput_ff_erase struct. It will be filled in with the
+ *      effect ID passed to erase_effect().
+ *   4. Perform the effect erasure, and place a return code back
+ *      into the uinput_ff_erase struct.
+ *   5. Issue a UI_END_FF_ERASE ioctl, also giving it the
+ *      uinput_ff_erase_effect struct. This will complete execution
+ *      of our erase_effect() handler.
+ */
+
+/*
+ * This is the new event type, used only by uinput.
+ * 'code' is UI_FF_UPLOAD or UI_FF_ERASE, and 'value'
+ * is the unique request ID. This number was picked
+ * arbitrarily, above EV_MAX (since the input system
+ * never sees it) but in the range of a 16-bit int.
+ */
+#define EV_UINPUT              0x0101
+#define UI_FF_UPLOAD           1
+#define UI_FF_ERASE            2
+
+struct uinput_user_dev {
+       char name[UINPUT_MAX_NAME_SIZE];
+       struct input_id id;
+       __u32 ff_effects_max;
+       __s32 absmax[ABS_CNT];
+       __s32 absmin[ABS_CNT];
+       __s32 absfuzz[ABS_CNT];
+       __s32 absflat[ABS_CNT];
+};
+#endif /* __UINPUT_H_ */
index c83a2251749c381d25f037ee67481c40aaa8b2eb..512cdefd29198b6d6070d15a7ca1f9e9944ebcee 100644 (file)
@@ -11,7 +11,9 @@ libevdev_la_SOURCES = \
                    libevdev-uinput-int.h \
                    libevdev.c \
                    libevdev-names.c \
-                  ../include/linux/input.h
+                  ../include/linux/input-event-codes.h \
+                  ../include/linux/input.h \
+                  ../include/linux/uinput.h
 
 libevdev_la_LDFLAGS = \
        -version-info $(LIBEVDEV_LT_VERSION) \
@@ -24,7 +26,8 @@ libevdevincludedir = $(includedir)/libevdev-1.0/libevdev
 libevdevinclude_HEADERS = libevdev.h libevdev-uinput.h
 
 event-names.h: Makefile make-event-names.py
-       $(PYTHON) $(srcdir)/make-event-names.py $(top_srcdir)/include/linux/input.h  > $@
+       $(CAT) $(top_srcdir)/include/linux/input.h $(top_srcdir)/include/linux/input-event-codes.h | $(PYTHON) $(srcdir)/make-event-names.py  > $@
+
 
 EXTRA_DIST = make-event-names.py libevdev.sym
 CLEANFILES = event-names.h
index f587e76415725ae5fadaefb1c70343292deb0fe5..e1c7ec5b1e52b75bd8452699487558abadc29beb 100644 (file)
@@ -60,6 +60,20 @@ struct mt_sync_state {
        int val[];
 };
 
+/**
+ * Internal only: log data used to send messages to the respective log
+ * handler. We re-use the same struct for a global and inside
+ * struct libevdev.
+ * For the global, device_handler is NULL, for per-device instance
+ * global_handler is NULL.
+ */
+struct logdata {
+       enum libevdev_log_priority priority;            /** minimum logging priority */
+       libevdev_log_func_t global_handler;             /** global handler function */
+       libevdev_device_log_func_t device_handler;      /** per-device handler function */
+       void *userdata;                                 /** user-defined data pointer */
+};
+
 struct libevdev {
        int fd;
        bool initialized;
@@ -106,31 +120,28 @@ struct libevdev {
                unsigned long *tracking_id_changes;
                size_t tracking_id_changes_sz;   /* in bytes */
        } mt_sync;
-};
 
-struct logdata {
-       enum libevdev_log_priority priority;    /** minimum logging priority */
-       libevdev_log_func_t handler;            /** handler function */
-       void *userdata;                         /** user-defined data pointer */
+       struct logdata log;
 };
-extern struct logdata log_data;
 
-#define log_msg_cond(priority, ...) \
+#define log_msg_cond(dev, priority, ...) \
        do { \
-               if (libevdev_get_log_priority() >= priority) \
-                       log_msg(priority, log_data.userdata, __FILE__, __LINE__, __func__, __VA_ARGS__); \
+               if (_libevdev_log_priority(dev) >= priority) \
+                       _libevdev_log_msg(dev, priority, __FILE__, __LINE__, __func__, __VA_ARGS__); \
        } while(0)
 
-#define log_error(...) log_msg_cond(LIBEVDEV_LOG_ERROR, __VA_ARGS__)
-#define log_info(...) log_msg_cond(LIBEVDEV_LOG_INFO, __VA_ARGS__)
-#define log_dbg(...) log_msg_cond(LIBEVDEV_LOG_DEBUG, __VA_ARGS__)
-#define log_bug(...) log_msg_cond(LIBEVDEV_LOG_ERROR, "BUG: "__VA_ARGS__)
+#define log_error(dev, ...) log_msg_cond(dev, LIBEVDEV_LOG_ERROR, __VA_ARGS__)
+#define log_info(dev, ...) log_msg_cond(dev, LIBEVDEV_LOG_INFO, __VA_ARGS__)
+#define log_dbg(dev, ...) log_msg_cond(dev, LIBEVDEV_LOG_DEBUG, __VA_ARGS__)
+#define log_bug(dev, ...) log_msg_cond(dev, LIBEVDEV_LOG_ERROR, "BUG: "__VA_ARGS__)
 
 extern void
-log_msg(enum libevdev_log_priority priority,
-       void *data,
-       const char *file, int line, const char *func,
-       const char *format, ...) LIBEVDEV_ATTRIBUTE_PRINTF(6, 7);
+_libevdev_log_msg(const struct libevdev *dev,
+                 enum libevdev_log_priority priority,
+                 const char *file, int line, const char *func,
+                 const char *format, ...) LIBEVDEV_ATTRIBUTE_PRINTF(6, 7);
+extern enum libevdev_log_priority
+_libevdev_log_priority(const struct libevdev *dev);
 
 /**
  * @return a pointer to the next element in the queue, or NULL if the queue
@@ -170,7 +181,6 @@ queue_peek(struct libevdev *dev, size_t idx, struct input_event *ev)
        return 0;
 }
 
-
 /**
  * Shift the first n elements into ev and return the number of elements
  * shifted.
@@ -182,22 +192,21 @@ queue_peek(struct libevdev *dev, size_t idx, struct input_event *ev)
 static inline int
 queue_shift_multiple(struct libevdev *dev, size_t n, struct input_event *ev)
 {
-       size_t i;
+       size_t remaining;
 
        if (dev->queue_next == 0)
                return 0;
 
-       n = min(n, dev->queue_next);
+       remaining = dev->queue_next;
+       n = min(n, remaining);
+       remaining -= n;
 
-       if (ev) {
-               for (i = 0; i < n; i++)
-                       ev[i] = dev->queue[i];
-       }
+       if (ev)
+               memcpy(ev, dev->queue, n * sizeof(*ev));
 
-       for (i = 0; i < dev->queue_next - n; i++)
-               dev->queue[i] = dev->queue[n + i];
+       memmove(dev->queue, &dev->queue[n], remaining * sizeof(*dev->queue));
 
-       dev->queue_next -= n;
+       dev->queue_next = remaining;
        return n;
 }
 
@@ -283,7 +292,6 @@ queue_set_num_elements(struct libevdev *dev, size_t nelem)
                        max = libevdev_event_type_get_max(type); \
                break;
 
-
 static inline int
 type_to_mask_const(const struct libevdev *dev, unsigned int type, const unsigned long **mask)
 {
@@ -332,4 +340,3 @@ type_to_mask(struct libevdev *dev, unsigned int type, unsigned long **mask)
 
 #undef max_mask
 #endif
-
index 10669a33f74104867579a40b95f248af722153f9..ad318dee812a17b2bbeaf7d455cd445135b43fee 100644 (file)
@@ -141,3 +141,23 @@ libevdev_event_code_from_name_n(unsigned int type, const char *name, size_t len)
 
        return entry ? (int)entry->value : -1;
 }
+
+LIBEVDEV_EXPORT int
+libevdev_property_from_name(const char *name)
+{
+       return libevdev_property_from_name_n(name, strlen(name));
+}
+
+LIBEVDEV_EXPORT int
+libevdev_property_from_name_n(const char *name, size_t len)
+{
+       struct name_lookup lookup;
+       const struct name_entry *entry;
+
+       lookup.name = name;
+       lookup.len = len;
+
+       entry = lookup_name(prop_names, ARRAY_LENGTH(prop_names), &lookup);
+
+       return entry ? (int)entry->value : -1;
+}
index fbc1c2905dd192e8eda0e357cc5184628f8e321c..22d1684ba691c8d6d02f19333b9783499f06f566 100644 (file)
@@ -20,7 +20,6 @@
  * OF THIS SOFTWARE.
  */
 
-
 struct libevdev_uinput {
        int fd; /**< file descriptor to uinput */
        int fd_is_managed; /**< do we need to close it? */
index f176a004d6771a7b7c7a944f204e70cf242dc35e..893d169c6fa95d020df61370d51d3eaf1798bb2d 100644 (file)
@@ -62,6 +62,19 @@ alloc_uinput_device(const char *name)
        return uinput_dev;
 }
 
+static inline int
+set_abs(const struct libevdev *dev, int fd, unsigned int code)
+{
+       const struct input_absinfo *abs = libevdev_get_abs_info(dev, code);
+       struct uinput_abs_setup abs_setup = {0};
+       int rc;
+
+       abs_setup.code = code;
+       abs_setup.absinfo = *abs;
+       rc = ioctl(fd, UI_ABS_SETUP, &abs_setup);
+       return rc;
+}
+
 static int
 set_evbits(const struct libevdev *dev, int fd, struct uinput_user_dev *uidev)
 {
@@ -113,13 +126,21 @@ set_evbits(const struct libevdev *dev, int fd, struct uinput_user_dev *uidev)
                                goto out;
 
                        if (type == EV_ABS) {
-                               const struct input_absinfo *abs = libevdev_get_abs_info(dev, code);
-                               uidev->absmin[code] = abs->minimum;
-                               uidev->absmax[code] = abs->maximum;
-                               uidev->absfuzz[code] = abs->fuzz;
-                               uidev->absflat[code] = abs->flat;
-                               /* uinput has no resolution in the device struct, this needs
-                                * to be fixed in the kernel */
+                               if (uidev == NULL) {
+                                       rc = set_abs(dev, fd, code);
+                                       if (rc != 0)
+                                               goto out;
+                               } else {
+                                       const struct input_absinfo *abs =
+                                               libevdev_get_abs_info(dev, code);
+
+                                       uidev->absmin[code] = abs->minimum;
+                                       uidev->absmax[code] = abs->maximum;
+                                       uidev->absfuzz[code] = abs->fuzz;
+                                       uidev->absflat[code] = abs->flat;
+                                       /* uinput has no resolution in the
+                                        * device struct */
+                               }
                        }
                }
 
@@ -130,7 +151,7 @@ out:
 }
 
 static int
-set_props(const struct libevdev *dev, int fd, struct uinput_user_dev *uidev)
+set_props(const struct libevdev *dev, int fd)
 {
        unsigned int prop;
        int rc = 0;
@@ -147,7 +168,7 @@ set_props(const struct libevdev *dev, int fd, struct uinput_user_dev *uidev)
                         * ioctl is called on an already created device. The
                         * last two can't happen here.
                         */
-                       if (errno == -EINVAL)
+                       if (errno == EINVAL)
                                rc = 0;
                        break;
                }
@@ -198,8 +219,17 @@ fetch_syspath_and_devnode(struct libevdev_uinput *uinput_dev)
 {
        struct dirent **namelist;
        int ndev, i;
-
-       /* FIXME: use new ioctl() here once kernel supports it */
+       int rc;
+       char buf[sizeof(SYS_INPUT_DIR) + 64] = SYS_INPUT_DIR;
+
+       rc = ioctl(uinput_dev->fd,
+                  UI_GET_SYSNAME(sizeof(buf) - strlen(SYS_INPUT_DIR)),
+                  &buf[strlen(SYS_INPUT_DIR)]);
+       if (rc != -1) {
+               uinput_dev->syspath = strdup(buf);
+               uinput_dev->devnode = fetch_device_node(buf);
+               return 0;
+       }
 
        ndev = scandir(SYS_INPUT_DIR, &namelist, is_input_device, alphasort);
        if (ndev <= 0)
@@ -207,26 +237,28 @@ fetch_syspath_and_devnode(struct libevdev_uinput *uinput_dev)
 
        for (i = 0; i < ndev; i++) {
                int fd, len;
-               char buf[sizeof(SYS_INPUT_DIR) + 64];
                struct stat st;
 
-               strcpy(buf, SYS_INPUT_DIR);
-               strcat(buf, namelist[i]->d_name);
-
-               if (stat(buf, &st) == -1)
-                       continue;
-
-               /* created before UI_DEV_CREATE, or after it finished */
-               if (st.st_ctime < uinput_dev->ctime[0] ||
-                   st.st_ctime > uinput_dev->ctime[1])
+               rc = snprintf(buf, sizeof(buf), "%s%s/name",
+                             SYS_INPUT_DIR,
+                             namelist[i]->d_name);
+               if (rc < 0 || (size_t)rc >= sizeof(buf)) {
                        continue;
+               }
 
                /* created within time frame */
-               strcat(buf, "/name");
                fd = open(buf, O_RDONLY);
                if (fd < 0)
                        continue;
 
+               /* created before UI_DEV_CREATE, or after it finished */
+               if (fstat(fd, &st) == -1 ||
+                   st.st_ctime < uinput_dev->ctime[0] ||
+                   st.st_ctime > uinput_dev->ctime[1]) {
+                       close(fd);
+                       continue;
+               }
+
                len = read(fd, buf, sizeof(buf));
                close(fd);
                if (len <= 0)
@@ -236,11 +268,17 @@ fetch_syspath_and_devnode(struct libevdev_uinput *uinput_dev)
                if (strcmp(buf, uinput_dev->name) == 0) {
                        if (uinput_dev->syspath) {
                                /* FIXME: could descend into bit comparison here */
-                               log_info("multiple identical devices found. syspath is unreliable\n");
+                               log_info(NULL, "multiple identical devices found. syspath is unreliable\n");
                                break;
                        } else {
-                               strcpy(buf, SYS_INPUT_DIR);
-                               strcat(buf, namelist[i]->d_name);
+                               rc = snprintf(buf, sizeof(buf), "%s%s",
+                                             SYS_INPUT_DIR,
+                                             namelist[i]->d_name);
+                               if (rc < 0 || (size_t)rc >= sizeof(buf)) {
+                                       log_error(NULL, "Invalid syspath, syspath is unreliable\n");
+                                       break;
+                               }
+
                                uinput_dev->syspath = strdup(buf);
                                uinput_dev->devnode = fetch_device_node(buf);
                        }
@@ -254,14 +292,74 @@ fetch_syspath_and_devnode(struct libevdev_uinput *uinput_dev)
        return uinput_dev->devnode ? 0 : -1;
 }
 
+static int
+uinput_create_write(const struct libevdev *dev, int fd,
+                   struct libevdev_uinput *new_device)
+{
+       int rc;
+       struct uinput_user_dev uidev;
+
+       memset(&uidev, 0, sizeof(uidev));
+
+       strncpy(uidev.name, libevdev_get_name(dev), UINPUT_MAX_NAME_SIZE - 1);
+       uidev.id.vendor = libevdev_get_id_vendor(dev);
+       uidev.id.product = libevdev_get_id_product(dev);
+       uidev.id.bustype = libevdev_get_id_bustype(dev);
+       uidev.id.version = libevdev_get_id_version(dev);
+
+       if (set_evbits(dev, fd, &uidev) != 0)
+               goto error;
+       if (set_props(dev, fd) != 0)
+               goto error;
+
+       rc = write(fd, &uidev, sizeof(uidev));
+       if (rc < 0)
+               goto error;
+       else if ((size_t)rc < sizeof(uidev)) {
+               errno = EINVAL;
+               goto error;
+       }
+
+       errno = 0;
+
+error:
+       return -errno;
+}
+
+static int
+uinput_create_DEV_SETUP(const struct libevdev *dev, int fd,
+                       struct libevdev_uinput *new_device)
+{
+       int rc;
+       struct uinput_setup setup;
+
+       if (set_evbits(dev, fd, NULL) != 0)
+               goto error;
+       if (set_props(dev, fd) != 0)
+               goto error;
 
+       memset(&setup, 0, sizeof(setup));
+       strncpy(setup.name, libevdev_get_name(dev), UINPUT_MAX_NAME_SIZE - 1);
+       setup.id.vendor = libevdev_get_id_vendor(dev);
+       setup.id.product = libevdev_get_id_product(dev);
+       setup.id.bustype = libevdev_get_id_bustype(dev);
+       setup.id.version = libevdev_get_id_version(dev);
+       setup.ff_effects_max = libevdev_has_event_type(dev, EV_FF) ? 10 : 0;
+
+       rc = ioctl(fd, UI_DEV_SETUP, &setup);
+       if (rc == 0)
+               errno = 0;
+error:
+       return -errno;
+}
 
 LIBEVDEV_EXPORT int
 libevdev_uinput_create_from_device(const struct libevdev *dev, int fd, struct libevdev_uinput** uinput_dev)
 {
        int rc;
-       struct uinput_user_dev uidev;
        struct libevdev_uinput *new_device;
+       int close_fd_on_error = (fd == LIBEVDEV_UINPUT_OPEN_MANAGED);
+       unsigned int uinput_version = 0;
 
        new_device = alloc_uinput_device(libevdev_get_name(dev));
        if (!new_device)
@@ -274,31 +372,19 @@ libevdev_uinput_create_from_device(const struct libevdev *dev, int fd, struct li
 
                new_device->fd_is_managed = 1;
        } else if (fd < 0) {
-               log_bug("Invalid fd %d\n", fd);
+               log_bug(NULL, "Invalid fd %d\n", fd);
                errno = EBADF;
                goto error;
        }
 
-       memset(&uidev, 0, sizeof(uidev));
-
-       strncpy(uidev.name, libevdev_get_name(dev), UINPUT_MAX_NAME_SIZE - 1);
-       uidev.id.vendor = libevdev_get_id_vendor(dev);
-       uidev.id.product = libevdev_get_id_product(dev);
-       uidev.id.bustype = libevdev_get_id_bustype(dev);
-       uidev.id.version = libevdev_get_id_version(dev);
-
-       if (set_evbits(dev, fd, &uidev) != 0)
-               goto error;
-       if (set_props(dev, fd, &uidev) != 0)
-               goto error;
+       if (ioctl(fd, UI_GET_VERSION, &uinput_version) == 0 &&
+           uinput_version >= 5)
+               rc = uinput_create_DEV_SETUP(dev, fd, new_device);
+       else
+               rc = uinput_create_write(dev, fd, new_device);
 
-       rc = write(fd, &uidev, sizeof(uidev));
-       if (rc < 0)
-               goto error;
-       else if ((size_t)rc < sizeof(uidev)) {
-               errno = EINVAL;
+       if (rc != 0)
                goto error;
-       }
 
        /* ctime notes time before/after ioctl to help us filter out devices
           when traversing /sys/devices/virtual/input to find the device
@@ -317,7 +403,7 @@ libevdev_uinput_create_from_device(const struct libevdev *dev, int fd, struct li
        new_device->fd = fd;
 
        if (fetch_syspath_and_devnode(new_device) == -1) {
-               log_error("unable to fetch syspath or device node.\n");
+               log_error(NULL, "unable to fetch syspath or device node.\n");
                errno = ENODEV;
                goto error;
        }
@@ -327,8 +413,11 @@ libevdev_uinput_create_from_device(const struct libevdev *dev, int fd, struct li
        return 0;
 
 error:
+       rc = -errno;
        libevdev_uinput_destroy(new_device);
-       return -errno;
+       if (fd != -1 && close_fd_on_error)
+               close(fd);
+       return rc;
 }
 
 LIBEVDEV_EXPORT void
@@ -337,9 +426,11 @@ libevdev_uinput_destroy(struct libevdev_uinput *uinput_dev)
        if (!uinput_dev)
                return;
 
-       ioctl(uinput_dev->fd, UI_DEV_DESTROY, NULL);
-       if (uinput_dev->fd_is_managed)
-               close(uinput_dev->fd);
+       if (uinput_dev->fd >= 0) {
+               (void)ioctl(uinput_dev->fd, UI_DEV_DESTROY, NULL);
+               if (uinput_dev->fd_is_managed)
+                       close(uinput_dev->fd);
+       }
        free(uinput_dev->syspath);
        free(uinput_dev->devnode);
        free(uinput_dev->name);
index f5b8df47aa2a9bfc5559f9f8359a3197ac02793e..0cf33a9403f82edcb8d94861fb2ce786732116cb 100644 (file)
@@ -38,66 +38,72 @@ struct libevdev_uinput;
  * help to create uinput devices that emulate libevdev devices. In the simplest
  * form it serves to duplicate an existing device:
  *
- @code
- int err;
- int new_fd;
- struct libevdev *dev;
- struct libevdev_uinput *uidev;
- struct input_event ev[2];
-
- err = libevdev_new_from_fd(&dev, fd);
- if (err != 0)
-     return err;
-
- uifd = open("/dev/uinput", O_RDWR);
- if (uidev < 0)
-     return -errno;
-
- err = libevdev_uinput_create_from_device(dev, uifd, &uidev);
- if (err != 0)
-     return err;
-
- // post a REL_X event
- err = libevdev_uinput_write_event(uidev, EV_REL, REL_X, -1);
- if (err != 0)
-     return err;
- libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0);
- if (err != 0)
-     return err;
-
- libevdev_uinput_destroy(uidev);
- close(uifd);
-
- @endcode
+ * @code
+ * int err;
+ * int fd, new_fd, uifd;
+ * struct libevdev *dev;
+ * struct libevdev_uinput *uidev;
+ * struct input_event ev[2];
+ *
+ * fd = open("/dev/input/event0", O_RDONLY);
+ * if (fd < 0)
+ *     return err;
+ *
+ * err = libevdev_new_from_fd(fd, &dev);
+ * if (err != 0)
+ *     return err;
+ *
+ * uifd = open("/dev/uinput", O_RDWR);
+ * if (uidev < 0)
+ *     return -errno;
+ *
+ * err = libevdev_uinput_create_from_device(dev, uifd, &uidev);
+ * if (err != 0)
+ *     return err;
+ *
+ * // post a REL_X event
+ * err = libevdev_uinput_write_event(uidev, EV_REL, REL_X, -1);
+ * if (err != 0)
+ *     return err;
+ * libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0);
+ * if (err != 0)
+ *     return err;
+ *
+ * libevdev_uinput_destroy(uidev);
+ * libevdev_free(dev);
+ * close(uifd);
+ * close(fd);
+ *
+ * @endcode
  *
  * Alternatively, a device can be constructed from scratch:
  *
- @code
- int err;
- struct libevdev *dev;
- struct libevdev_uinput *uidev;
-
- dev = libevdev_new();
- libevdev_set_name(dev, "test device");
- libevdev_enable_event_type(dev, EV_REL);
libevdev_enable_event_code(dev, EV_REL, REL_X);
libevdev_enable_event_code(dev, EV_REL, REL_Y);
- libevdev_enable_event_type(dev, EV_KEY);
libevdev_enable_event_code(dev, EV_KEY, BTN_LEFT);
libevdev_enable_event_code(dev, EV_KEY, BTN_MIDDLE);
libevdev_enable_event_code(dev, EV_KEY, BTN_RIGHT);
-
- err = libevdev_uinput_create_from_device(dev,
-                                          LIBEVDEV_UINPUT_OPEN_MANAGED,
-                                          &uidev);
- if (err != 0)
-     return err;
-
- // ... do something ...
-
- libevdev_uinput_destroy(uidev);
-
- @endcode
@code
int err;
struct libevdev *dev;
struct libevdev_uinput *uidev;
+ *
dev = libevdev_new();
libevdev_set_name(dev, "test device");
libevdev_enable_event_type(dev, EV_REL);
* libevdev_enable_event_code(dev, EV_REL, REL_X, NULL);
* libevdev_enable_event_code(dev, EV_REL, REL_Y, NULL);
libevdev_enable_event_type(dev, EV_KEY);
* libevdev_enable_event_code(dev, EV_KEY, BTN_LEFT, NULL);
* libevdev_enable_event_code(dev, EV_KEY, BTN_MIDDLE, NULL);
* libevdev_enable_event_code(dev, EV_KEY, BTN_RIGHT, NULL);
+ *
err = libevdev_uinput_create_from_device(dev,
                                         LIBEVDEV_UINPUT_OPEN_MANAGED,
                                         &uidev);
if (err != 0)
    return err;
+ *
// ... do something ...
+ *
libevdev_uinput_destroy(uidev);
+ *
@endcode
  */
 
 enum libevdev_uinput_open_mode {
@@ -176,23 +182,20 @@ int libevdev_uinput_get_fd(const struct libevdev_uinput *uinput_dev);
 /**
  * @ingroup uinput
  *
- * Return the syspath representing this uinput device.
- * At the time of writing, the uinput kernel device does not
- * provide a way to get the syspath directly through uinput so libevdev must guess.
- * In some cases libevdev is unable to derive the syspath. If the running kernel
- * supports the UI_GET_SYSNAME ioctl, the syspath is retrieved through that and will
- * be reliable and not be NULL. The UI_GET_SYSNAME ioctl is currently
- * scheduled for 3.15.
- *
- * @note This function may return NULL. libevdev currently uses ctime and
- * the device name to guess devices. To avoid false positives, wait at least
- * wait at least 1.5s between creating devices that have the same name.
+ * Return the syspath representing this uinput device. If the UI_GET_SYSNAME
+ * ioctl not available, libevdev makes an educated guess.
+ * The UI_GET_SYSNAME ioctl is available since Linux 3.15.
+ *
+ * @note This function may return NULL if UI_GET_SYSNAME is not available.
+ * In that case, libevdev uses ctime and the device name to guess devices.
+ * To avoid false positives, wait at least wait at least 1.5s between
+ * creating devices that have the same name.
  * @param uinput_dev A previously created uinput device.
  * @return The syspath for this device, including the preceding /sys
  *
  * @see libevdev_uinput_get_devnode
  */
-const char*libevdev_uinput_get_syspath(struct libevdev_uinput *uinput_dev);
+const char* libevdev_uinput_get_syspath(struct libevdev_uinput *uinput_dev);
 
 /**
  * @ingroup uinput
@@ -202,7 +205,7 @@ const char*libevdev_uinput_get_syspath(struct libevdev_uinput *uinput_dev);
  * This relies on libevdev_uinput_get_syspath() to provide a valid syspath.
  * See libevdev_uinput_get_syspath() for more details.
  *
- * @note This function may return NULL. libevdev currently has to guess the
+ * @note This function may return NULL. libevdev may have to guess the
  * syspath and the device node. See libevdev_uinput_get_syspath() for details.
  * @param uinput_dev A previously created uinput device.
  * @return The device node for this device, in the form of /dev/input/eventN
index 31c1a14a894815991e943392cd258005dcf453e3..c6e11976011aed6371d10f607bb8621ed8f5a575 100644 (file)
@@ -45,7 +45,6 @@
                _a > _b ? _a : _b; \
                })
 
-
 static inline bool
 startswith(const char *str, size_t len, const char *prefix, size_t plen)
 {
index a3168317d2e883900ddec784187d26c430bc7818..43a095cf6c5e8de29d103201c2992f919b3c3ece 100644 (file)
@@ -25,6 +25,7 @@
 #include <poll.h>
 #include <stdlib.h>
 #include <string.h>
+#include <limits.h>
 #include <unistd.h>
 #include <stdarg.h>
 #include <stdbool.h>
@@ -48,11 +49,11 @@ static inline int*
 slot_value(const struct libevdev *dev, int slot, int axis)
 {
        if (unlikely(slot > dev->num_slots)) {
-               log_bug("Slot %d exceeds number of slots (%d)\n", slot, dev->num_slots);
+               log_bug(dev, "Slot %d exceeds number of slots (%d)\n", slot, dev->num_slots);
                slot = 0;
        }
        if (unlikely(axis < ABS_MT_MIN || axis > ABS_MT_MAX)) {
-               log_bug("MT axis %d is outside the valid range [%d,%d]\n",
+               log_bug(dev, "MT axis %d is outside the valid range [%d,%d]\n",
                        axis, ABS_MT_MIN, ABS_MT_MAX);
                axis = ABS_MT_MIN;
        }
@@ -70,7 +71,7 @@ init_event_queue(struct libevdev *dev)
        /* count the number of axes, keys, etc. to get a better idea at how
           many events per EV_SYN we could possibly get. That's the max we
           may get during SYN_DROPPED too. Use double that, just so we have
-          room for events while syncing an event.
+          room for events while syncing a device.
         */
        for (type = EV_KEY; type < EV_MAX; type++) {
                int max = libevdev_event_type_get_max(type);
@@ -84,7 +85,7 @@ init_event_queue(struct libevdev *dev)
        if (nslots > 1) {
                int num_mt_axes = 0;
 
-               for (code = ABS_MT_SLOT; code < ABS_MAX; code++) {
+               for (code = ABS_MT_SLOT; code <= ABS_MAX; code++) {
                        if (libevdev_has_event_code(dev, EV_ABS, code))
                                num_mt_axes++;
                }
@@ -126,34 +127,74 @@ libevdev_dflt_log_func(enum libevdev_log_priority priority,
        vfprintf(stderr, format, args);
 }
 
+static void
+fix_invalid_absinfo(const struct libevdev *dev,
+                   int axis,
+                   struct input_absinfo* abs_info)
+{
+       /*
+        * The reported absinfo for ABS_MT_TRACKING_ID is sometimes
+        * uninitialized for certain mtk-soc, due to init code mangling
+        * in the vendor kernel.
+        */
+       if (axis == ABS_MT_TRACKING_ID &&
+           abs_info->maximum == abs_info->minimum) {
+               abs_info->minimum = -1;
+               abs_info->maximum = 0xFFFF;
+               log_bug(dev,
+                       "Device \"%s\" has invalid ABS_MT_TRACKING_ID range",
+                       dev->name);
+       }
+}
+
 /*
  * Global logging settings.
  */
-struct logdata log_data = {
-       LIBEVDEV_LOG_INFO,
-       libevdev_dflt_log_func,
-       NULL,
+static struct logdata log_data = {
+       .priority = LIBEVDEV_LOG_INFO,
+       .global_handler = libevdev_dflt_log_func,
+       .userdata = NULL,
 };
 
 void
-log_msg(enum libevdev_log_priority priority,
-       void *data,
-       const char *file, int line, const char *func,
-       const char *format, ...)
+_libevdev_log_msg(const struct libevdev *dev,
+                 enum libevdev_log_priority priority,
+                 const char *file, int line, const char *func,
+                 const char *format, ...)
 {
        va_list args;
 
-       if (!log_data.handler || priority > log_data.priority)
+       if (dev && dev->log.device_handler) {
+               /**
+                * if both global handler and device handler are set
+                * we've set up the handlers wrong.  And that means we'll
+                * likely get the printf args wrong and cause all sorts of
+                * mayhem. Seppuku is called for.
+                */
+               if (unlikely(dev->log.global_handler))
+                       abort();
+
+               if (priority > dev->log.priority)
+                       return;
+       } else if (!log_data.global_handler || priority > log_data.priority)
                return;
+       else if (unlikely(log_data.device_handler))
+               abort(); /* Seppuku, see above */
 
        va_start(args, format);
-       log_data.handler(priority, data, file, line, func, format, args);
+       if (dev && dev->log.device_handler)
+               dev->log.device_handler(dev, priority, dev->log.userdata, file, line, func, format, args);
+       else
+               log_data.global_handler(priority, log_data.userdata, file, line, func, format, args);
        va_end(args);
 }
 
 static void
 libevdev_reset(struct libevdev *dev)
 {
+       enum libevdev_log_priority pri = dev->log.priority;
+       libevdev_device_log_func_t handler = dev->log.device_handler;
+
        free(dev->name);
        free(dev->phys);
        free(dev->uniq);
@@ -168,6 +209,8 @@ libevdev_reset(struct libevdev *dev)
        dev->current_slot = -1;
        dev->grabbed = LIBEVDEV_UNGRAB;
        dev->sync_state = SYNC_NONE;
+       dev->log.priority = pri;
+       dev->log.device_handler = handler;
        libevdev_enable_event_type(dev, EV_SYN);
 }
 
@@ -217,7 +260,7 @@ libevdev_free(struct libevdev *dev)
 LIBEVDEV_EXPORT void
 libevdev_set_log_function(libevdev_log_func_t logfunc, void *data)
 {
-       log_data.handler = logfunc;
+       log_data.global_handler = logfunc;
        log_data.userdata = data;
 }
 
@@ -235,11 +278,36 @@ libevdev_get_log_priority(void)
        return log_data.priority;
 }
 
+LIBEVDEV_EXPORT void
+libevdev_set_device_log_function(struct libevdev *dev,
+                                libevdev_device_log_func_t logfunc,
+                                enum libevdev_log_priority priority,
+                                void *data)
+{
+       if (!dev) {
+               log_bug(NULL, "device must not be NULL\n");
+               return;
+       }
+
+       dev->log.priority = priority;
+       dev->log.device_handler = logfunc;
+       dev->log.userdata = data;
+}
+
+enum libevdev_log_priority
+_libevdev_log_priority(const struct libevdev *dev)
+{
+       if (dev && dev->log.device_handler)
+               return dev->log.priority;
+       else
+               return libevdev_get_log_priority();
+}
+
 LIBEVDEV_EXPORT int
 libevdev_change_fd(struct libevdev *dev, int fd)
 {
        if (!dev->initialized) {
-               log_bug("device not initialized. call libevdev_set_fd() first\n");
+               log_bug(dev, "device not initialized. call libevdev_set_fd() first\n");
                return -1;
        }
        dev->fd = fd;
@@ -254,7 +322,7 @@ libevdev_set_fd(struct libevdev* dev, int fd)
        char buf[256];
 
        if (dev->initialized) {
-               log_bug("device already initialized.\n");
+               log_bug(dev, "device already initialized.\n");
                return -EBADF;
        } else if (fd < 0)
                return -EBADF;
@@ -384,6 +452,8 @@ libevdev_set_fd(struct libevdev* dev, int fd)
                        if (rc < 0)
                                goto out;
 
+                       fix_invalid_absinfo(dev, i, &abs_info);
+
                        dev->abs_info[i] = abs_info;
                }
        }
@@ -634,7 +704,6 @@ sync_mt_state(struct libevdev *dev, int create_events)
                                set_bit(slot_update, AXISBIT(slot, ABS_MT_SLOT));
                        }
 
-
                }
        }
 
@@ -743,7 +812,7 @@ drain_events(struct libevdev *dev)
                        return;
 
                if (rc < 0) {
-                       log_error("Failed to drain events before sync.\n");
+                       log_error(dev, "Failed to drain events before sync.\n");
                        return;
                }
 
@@ -758,7 +827,7 @@ drain_events(struct libevdev *dev)
           we can drain them.
         */
        if (iterations >= max_iterations)
-               log_info("Unable to drain events, buffer size mismatch.\n");
+               log_info(dev, "Unable to drain events, buffer size mismatch.\n");
 }
 
 static int
@@ -910,10 +979,13 @@ sanitize_event(const struct libevdev *dev,
               struct input_event *ev,
               enum SyncState sync_state)
 {
+       if (!libevdev_has_event_code(dev, ev->type, ev->code))
+               return EVENT_FILTER_DISCARD;
+
        if (unlikely(dev->num_slots > -1 &&
                     libevdev_event_is_code(ev, EV_ABS, ABS_MT_SLOT) &&
                     (ev->value < 0 || ev->value >= dev->num_slots))) {
-               log_bug("Device \"%s\" received an invalid slot index %d."
+               log_bug(dev, "Device \"%s\" received an invalid slot index %d."
                                "Capping to announced max slot number %d.\n",
                                dev->name, ev->value, dev->num_slots - 1);
                ev->value = dev->num_slots - 1;
@@ -930,7 +1002,7 @@ sanitize_event(const struct libevdev *dev,
                             *slot_value(dev, dev->current_slot, ABS_MT_TRACKING_ID) == -1) ||
                             (ev->value != -1 &&
                             *slot_value(dev, dev->current_slot, ABS_MT_TRACKING_ID) != -1)))) {
-               log_bug("Device \"%s\" received a double tracking ID %d in slot %d.\n",
+               log_bug(dev, "Device \"%s\" received a double tracking ID %d in slot %d.\n",
                        dev->name, ev->value, dev->current_slot);
                return EVENT_FILTER_DISCARD;
        }
@@ -943,15 +1015,19 @@ libevdev_next_event(struct libevdev *dev, unsigned int flags, struct input_event
 {
        int rc = LIBEVDEV_READ_STATUS_SUCCESS;
        enum event_filter_status filter_status;
+       const unsigned int valid_flags = LIBEVDEV_READ_FLAG_NORMAL |
+                                        LIBEVDEV_READ_FLAG_SYNC |
+                                        LIBEVDEV_READ_FLAG_FORCE_SYNC |
+                                        LIBEVDEV_READ_FLAG_BLOCKING;
 
        if (!dev->initialized) {
-               log_bug("device not initialized. call libevdev_set_fd() first\n");
+               log_bug(dev, "device not initialized. call libevdev_set_fd() first\n");
                return -EBADF;
        } else if (dev->fd < 0)
                return -EBADF;
 
-       if (!(flags & (LIBEVDEV_READ_FLAG_NORMAL|LIBEVDEV_READ_FLAG_SYNC|LIBEVDEV_READ_FLAG_FORCE_SYNC))) {
-               log_bug("invalid flags %#x\n.\n", flags);
+       if ((flags & valid_flags) == 0) {
+               log_bug(dev, "invalid flags %#x.\n", flags);
                return -EINVAL;
        }
 
@@ -1002,7 +1078,6 @@ libevdev_next_event(struct libevdev *dev, unsigned int flags, struct input_event
                        goto out;
                }
 
-
                if (queue_shift(dev, ev) != 0)
                        return -EAGAIN;
 
@@ -1029,7 +1104,7 @@ libevdev_next_event(struct libevdev *dev, unsigned int flags, struct input_event
 
                        if (queue_peek(dev, 0, &next) == 0 &&
                            next.type == EV_SYN && next.code == SYN_DROPPED)
-                               log_info("SYN_DROPPED received after finished "
+                               log_info(dev, "SYN_DROPPED received after finished "
                                         "sync - you're not keeping up\n");
                }
        }
@@ -1045,7 +1120,7 @@ libevdev_has_event_pending(struct libevdev *dev)
        int rc;
 
        if (!dev->initialized) {
-               log_bug("device not initialized. call libevdev_set_fd() first\n");
+               log_bug(dev, "device not initialized. call libevdev_set_fd() first\n");
                return -EBADF;
        } else if (dev->fd < 0)
                return -EBADF;
@@ -1088,7 +1163,6 @@ STRING_SETTER(name)
 STRING_SETTER(phys)
 STRING_SETTER(uniq)
 
-
 #define PRODUCT_GETTER(name) \
 LIBEVDEV_EXPORT int libevdev_get_id_##name(const struct libevdev *dev) \
 { \
@@ -1451,7 +1525,7 @@ libevdev_kernel_set_abs_info(struct libevdev *dev, unsigned int code, const stru
        int rc;
 
        if (!dev->initialized) {
-               log_bug("device not initialized. call libevdev_set_fd() first\n");
+               log_bug(dev, "device not initialized. call libevdev_set_fd() first\n");
                return -EBADF;
        } else if (dev->fd < 0)
                return -EBADF;
@@ -1474,13 +1548,13 @@ libevdev_grab(struct libevdev *dev, enum libevdev_grab_mode grab)
        int rc = 0;
 
        if (!dev->initialized) {
-               log_bug("device not initialized. call libevdev_set_fd() first\n");
+               log_bug(dev, "device not initialized. call libevdev_set_fd() first\n");
                return -EBADF;
        } else if (dev->fd < 0)
                return -EBADF;
 
        if (grab != LIBEVDEV_GRAB && grab != LIBEVDEV_UNGRAB) {
-               log_bug("invalid grab parameter %#x\n", grab);
+               log_bug(dev, "invalid grab parameter %#x\n", grab);
                return -EINVAL;
        }
 
@@ -1585,7 +1659,7 @@ libevdev_kernel_set_led_values(struct libevdev *dev, ...)
        size_t nleds = 0;
 
        if (!dev->initialized) {
-               log_bug("device not initialized. call libevdev_set_fd() first\n");
+               log_bug(dev, "device not initialized. call libevdev_set_fd() first\n");
                return -EBADF;
        } else if (dev->fd < 0)
                return -EBADF;
@@ -1641,7 +1715,7 @@ LIBEVDEV_EXPORT int
 libevdev_set_clock_id(struct libevdev *dev, int clockid)
 {
        if (!dev->initialized) {
-               log_bug("device not initialized. call libevdev_set_fd() first\n");
+               log_bug(dev, "device not initialized. call libevdev_set_fd() first\n");
                return -EBADF;
        } else if (dev->fd < 0)
                return -EBADF;
index 6c03cce0fe1d7523fe63695f2ca954c8dbc3422c..3edc3ae66cced07be1668c4d4aec3085171cdbb4 100644 (file)
@@ -78,7 +78,8 @@ extern "C" {
  *
  * libevdev does not handle the file descriptors directly, it merely uses
  * them. The caller is responsible for opening the file descriptors, setting
- * them to O_NONBLOCK and handling permissions.
+ * them to O_NONBLOCK and handling permissions. A caller should drain any
+ * events pending on the file descriptor before passing it to libevdev.
  *
  * Where does libevdev sit?
  * ========================
@@ -108,37 +109,37 @@ extern "C" {
  * finds them monitors the device to print the event.
  *
  * @code
-       struct libevdev *dev = NULL;
-       int fd;
-       int rc = 1;
-
-       fd = open("/dev/input/event0", O_RDONLY|O_NONBLOCK);
-       rc = libevdev_new_from_fd(fd, &dev);
-       if (rc < 0) {
-               fprintf(stderr, "Failed to init libevdev (%s)\n", strerror(-rc));
-               exit(1);
-       }
-       printf("Input device name: \"%s\"\n", libevdev_get_name(dev));
-       printf("Input device ID: bus %#x vendor %#x product %#x\n",
-              libevdev_get_id_bustype(dev),
-              libevdev_get_id_vendor(dev),
-              libevdev_get_id_product(dev));
-       if (!libevdev_has_event_type(dev, EV_REL) ||
-           !libevdev_has_event_code(dev, EV_KEY, BTN_LEFT)) {
-               printf("This device does not look like a mouse\n");
-               exit(1);
-       }
-
-       do {
-               struct input_event ev;
-               rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);
-               if (rc == 0)
-                       printf("Event: %s %s %d\n",
-                              libevdev_get_event_type_name(ev.type),
-                              libevdev_get_event_code_name(ev.type, ev.code),
-                              ev.value);
-       } while (rc == 1 || rc == 0 || rc == -EAGAIN);
-  @endcode
*      struct libevdev *dev = NULL;
*      int fd;
*      int rc = 1;
+ *
*      fd = open("/dev/input/event0", O_RDONLY|O_NONBLOCK);
*      rc = libevdev_new_from_fd(fd, &dev);
*      if (rc < 0) {
*              fprintf(stderr, "Failed to init libevdev (%s)\n", strerror(-rc));
*              exit(1);
*      }
*      printf("Input device name: \"%s\"\n", libevdev_get_name(dev));
*      printf("Input device ID: bus %#x vendor %#x product %#x\n",
*             libevdev_get_id_bustype(dev),
*             libevdev_get_id_vendor(dev),
*             libevdev_get_id_product(dev));
*      if (!libevdev_has_event_type(dev, EV_REL) ||
*          !libevdev_has_event_code(dev, EV_KEY, BTN_LEFT)) {
*              printf("This device does not look like a mouse\n");
*              exit(1);
*      }
+ *
*      do {
*              struct input_event ev;
*              rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);
*              if (rc == 0)
*                      printf("Event: %s %s %d\n",
*                             libevdev_get_event_type_name(ev.type),
*                             libevdev_get_event_code_name(ev.type, ev.code),
*                             ev.value);
*      } while (rc == 1 || rc == 0 || rc == -EAGAIN);
* @endcode
  *
  * A more complete example is available with the libevdev-events tool here:
  * http://cgit.freedesktop.org/libevdev/tree/tools/libevdev-events.c
@@ -173,17 +174,17 @@ extern "C" {
  * events. The number of events between SYN_REPORT events is arbitrary and
  * depends on the hardware. An example event sequence may look like this:
  * @code
-   EV_ABS   ABS_X        9
-   EV_ABS   ABS_Y        8
-   EV_SYN   SYN_REPORT   0
-   ------------------------
-   EV_ABS   ABS_X        10
-   EV_ABS   ABS_Y        10
-   EV_KEY   BTN_TOUCH    1
-   EV_SYN   SYN_REPORT   0
-   ------------------------
-   EV_ABS   ABS_X        11
-   EV_SYN   SYN_REPORT   0
*  EV_ABS   ABS_X        9
*  EV_ABS   ABS_Y        8
*  EV_SYN   SYN_REPORT   0
*  ------------------------
*  EV_ABS   ABS_X        10
*  EV_ABS   ABS_Y        10
*  EV_KEY   BTN_TOUCH    1
*  EV_SYN   SYN_REPORT   0
*  ------------------------
*  EV_ABS   ABS_X        11
*  EV_SYN   SYN_REPORT   0
  * @endcode
  *
  * Events are handed to the client buffer as they appear, the kernel adjusts
@@ -194,19 +195,19 @@ extern "C" {
  * the client that some events were lost. The above example event sequence
  * may look like this (note the missing/repeated events):
  * @code
-   EV_ABS   ABS_X        9
-   EV_ABS   ABS_Y        8
-   EV_SYN   SYN_REPORT   0
-   ------------------------
-   EV_ABS   ABS_X        10
-   EV_ABS   ABS_Y        10
-   EV_SYN   SYN_DROPPED  0
-   EV_ABS   ABS_Y        15
-   EV_SYN   SYN_REPORT   0
-   ------------------------
-   EV_ABS   ABS_X        11
-   EV_KEY   BTN_TOUCH    0
-   EV_SYN   SYN_REPORT   0
*  EV_ABS   ABS_X        9
*  EV_ABS   ABS_Y        8
*  EV_SYN   SYN_REPORT   0
*  ------------------------
*  EV_ABS   ABS_X        10
*  EV_ABS   ABS_Y        10
*  EV_SYN   SYN_DROPPED  0
*  EV_ABS   ABS_Y        15
*  EV_SYN   SYN_REPORT   0
*  ------------------------
*  EV_ABS   ABS_X        11
*  EV_KEY   BTN_TOUCH    0
*  EV_SYN   SYN_REPORT   0
  * @endcode
  *
  * A SYN_DROPPED event may be recieved at any time in the event sequence.
@@ -239,11 +240,11 @@ extern "C" {
  * active slot.
  * Thus, an event sequence from a slot-capable device may look like this:
  * @code
-   EV_ABS   ABS_MT_POSITION_Y   10
-   EV_ABS   ABS_MT_SLOT         1
-   EV_ABS   ABS_MT_POSITION_X   100
-   EV_ABS   ABS_MT_POSITION_Y   80
-   EV_SYN   SYN_REPORT          0
*  EV_ABS   ABS_MT_POSITION_Y   10
*  EV_ABS   ABS_MT_SLOT         1
*  EV_ABS   ABS_MT_POSITION_X   100
*  EV_ABS   ABS_MT_POSITION_Y   80
*  EV_SYN   SYN_REPORT          0
  * @endcode
  * Note the lack of ABS_MT_SLOT: the first ABS_MT_POSITION_Y applies to
  * a slot opened previously, and is the only axis that changed for that
@@ -266,16 +267,16 @@ extern "C" {
  *
  * An example event sequence for such a sync may look like this:
  * @code
-   EV_ABS   ABS_MT_SLOT         0
-   EV_ABS   ABS_MT_POSITION_Y   10
-   EV_ABS   ABS_MT_SLOT         1
-   EV_ABS   ABS_MT_POSITION_X   100
-   EV_ABS   ABS_MT_POSITION_Y   80
-   EV_ABS   ABS_MT_SLOT         2
-   EV_ABS   ABS_MT_POSITION_Y   8
-   EV_ABS   ABS_MT_PRESSURE     12
-   EV_ABS   ABS_MT_SLOT         1
-   EV_SYN   SYN_REPORT          0
*  EV_ABS   ABS_MT_SLOT         0
*  EV_ABS   ABS_MT_POSITION_Y   10
*  EV_ABS   ABS_MT_SLOT         1
*  EV_ABS   ABS_MT_POSITION_X   100
*  EV_ABS   ABS_MT_POSITION_Y   80
*  EV_ABS   ABS_MT_SLOT         2
*  EV_ABS   ABS_MT_POSITION_Y   8
*  EV_ABS   ABS_MT_PRESSURE     12
*  EV_ABS   ABS_MT_SLOT         1
*  EV_SYN   SYN_REPORT          0
  * @endcode
  * Note the terminating ABS_MT_SLOT event, this indicates that the kernel
  * currently has slot 1 active.
@@ -300,21 +301,21 @@ extern "C" {
  *
  * An example event sequence for such a sync may look like this:
  * @code
-   EV_ABS   ABS_MT_SLOT         0
-   EV_ABS   ABS_MT_TRACKING_ID  -1
-   EV_ABS   ABS_MT_SLOT         2
-   EV_ABS   ABS_MT_TRACKING_ID  -1
-   EV_SYN   SYN_REPORT          0
-   ------------------------
-   EV_ABS   ABS_MT_SLOT         1
-   EV_ABS   ABS_MT_POSITION_X   100
-   EV_ABS   ABS_MT_POSITION_Y   80
-   EV_ABS   ABS_MT_SLOT         2
-   EV_ABS   ABS_MT_TRACKING_ID  45
-   EV_ABS   ABS_MT_POSITION_Y   8
-   EV_ABS   ABS_MT_PRESSURE     12
-   EV_ABS   ABS_MT_SLOT         1
-   EV_SYN   SYN_REPORT          0
*  EV_ABS   ABS_MT_SLOT         0
*  EV_ABS   ABS_MT_TRACKING_ID  -1
*  EV_ABS   ABS_MT_SLOT         2
*  EV_ABS   ABS_MT_TRACKING_ID  -1
*  EV_SYN   SYN_REPORT          0
*  ------------------------
*  EV_ABS   ABS_MT_SLOT         1
*  EV_ABS   ABS_MT_POSITION_X   100
*  EV_ABS   ABS_MT_POSITION_Y   80
*  EV_ABS   ABS_MT_SLOT         2
*  EV_ABS   ABS_MT_TRACKING_ID  45
*  EV_ABS   ABS_MT_POSITION_Y   8
*  EV_ABS   ABS_MT_PRESSURE     12
*  EV_ABS   ABS_MT_SLOT         1
*  EV_SYN   SYN_REPORT          0
  * @endcode
  * Note how the touchpoint in slot 0 was terminated, the touchpoint in slot
  * 2 was terminated and then started with a new ABS_MT_TRACKING_ID. The touchpoint
@@ -326,46 +327,46 @@ extern "C" {
  * handles events again. The below example shows an example event sequence
  * and what libevdev sees in the case of a SYN_DROPPED event:
  * @code
-
-             kernel                  |              userspace
-                                     |
-   EV_ABS   ABS_MT_SLOT         0    |    EV_ABS   ABS_MT_SLOT         0
-   EV_ABS   ABS_MT_TRACKING_ID  -1   |    EV_ABS   ABS_MT_TRACKING_ID  -1
-   EV_SYN   SYN_REPORT          0    |    EV_SYN   SYN_REPORT          0
-   ------------------------          |    ------------------------
-   EV_ABS   ABS_MT_TRACKING_ID  30   |
-   EV_ABS   ABS_MT_POSITION_X   100  |
-   EV_ABS   ABS_MT_POSITION_Y   80   |
-   EV_SYN   SYN_REPORT          0    |           SYN_DROPPED
-   ------------------------          |
-   EV_ABS   ABS_MT_TRACKING_ID  -1   |
-   EV_SYN   SYN_REPORT          0    |
-   ------------------------          |    ------------------------
-   EV_ABS   ABS_MT_SLOT         1    |    EV_ABS   ABS_MT_SLOT         1
-   EV_ABS   ABS_MT_POSITION_X   90   |    EV_ABS   ABS_MT_POSITION_X   90
-   EV_ABS   ABS_MT_POSITION_Y   10   |    EV_ABS   ABS_MT_POSITION_Y   10
-   EV_SYN   SYN_REPORT          0    |    EV_SYN   SYN_REPORT          0
+ *
*            kernel                  |              userspace
*                                    |
*  EV_ABS   ABS_MT_SLOT         0    |    EV_ABS   ABS_MT_SLOT         0
*  EV_ABS   ABS_MT_TRACKING_ID  -1   |    EV_ABS   ABS_MT_TRACKING_ID  -1
*  EV_SYN   SYN_REPORT          0    |    EV_SYN   SYN_REPORT          0
*  ------------------------          |    ------------------------
*  EV_ABS   ABS_MT_TRACKING_ID  30   |
*  EV_ABS   ABS_MT_POSITION_X   100  |
*  EV_ABS   ABS_MT_POSITION_Y   80   |
*  EV_SYN   SYN_REPORT          0    |           SYN_DROPPED
*  ------------------------          |
*  EV_ABS   ABS_MT_TRACKING_ID  -1   |
*  EV_SYN   SYN_REPORT          0    |
*  ------------------------          |    ------------------------
*  EV_ABS   ABS_MT_SLOT         1    |    EV_ABS   ABS_MT_SLOT         1
*  EV_ABS   ABS_MT_POSITION_X   90   |    EV_ABS   ABS_MT_POSITION_X   90
*  EV_ABS   ABS_MT_POSITION_Y   10   |    EV_ABS   ABS_MT_POSITION_Y   10
*  EV_SYN   SYN_REPORT          0    |    EV_SYN   SYN_REPORT          0
  * @endcode
  * If such an event sequence occurs, libevdev will send all updated axes
  * during the sync process. Axis events may thus be generated for devices
  * without a currently valid ABS_MT_TRACKING_ID. Specifically for the above
  * example, the client would receive the following event sequence:
  * @code
-   EV_ABS   ABS_MT_SLOT         0       ← LIBEVDEV_READ_FLAG_NORMAL
-   EV_ABS   ABS_MT_TRACKING_ID  -1
-   EV_SYN   SYN_REPORT          0
-   ------------------------
-   EV_SYN   SYN_DROPPED         0       → LIBEVDEV_READ_STATUS_SYNC
-   ------------------------
-   EV_ABS   ABS_MT_POSITION_X   100     ← LIBEVDEV_READ_FLAG_SYNC
-   EV_ABS   ABS_MT_POSITION_Y   80
-   EV_SYN   SYN_REPORT          0
-   -----------------------------        → -EGAIN
-   EV_ABS   ABS_MT_SLOT         1       ← LIBEVDEV_READ_FLAG_NORMAL
-   EV_ABS   ABS_MT_POSITION_X   90
-   EV_ABS   ABS_MT_POSITION_Y   10
-   EV_SYN   SYN_REPORT          0
-   -------------------
*  EV_ABS   ABS_MT_SLOT         0       ← LIBEVDEV_READ_FLAG_NORMAL
*  EV_ABS   ABS_MT_TRACKING_ID  -1
*  EV_SYN   SYN_REPORT          0
*  ------------------------
*  EV_SYN   SYN_DROPPED         0       → LIBEVDEV_READ_STATUS_SYNC
*  ------------------------
*  EV_ABS   ABS_MT_POSITION_X   100     ← LIBEVDEV_READ_FLAG_SYNC
*  EV_ABS   ABS_MT_POSITION_Y   80
*  EV_SYN   SYN_REPORT          0
*  -----------------------------        → -EGAIN
*  EV_ABS   ABS_MT_SLOT         1       ← LIBEVDEV_READ_FLAG_NORMAL
*  EV_ABS   ABS_MT_POSITION_X   90
*  EV_ABS   ABS_MT_POSITION_Y   10
*  EV_SYN   SYN_REPORT          0
*  -------------------
  * @endcode
  * The axis events do not reflect the position of a current touch point, a
  * client must take care not to generate a new touch point based on those
@@ -388,19 +389,19 @@ extern "C" {
  * assume the buffer contains the following sequence:
  *
  * @code
-   EV_SYN   SYN_DROPPED
-   EV_ABS   ABS_X               1
-   EV_SYN   SYN_REPORT          0
-   EV_ABS   ABS_X               2
-   EV_SYN   SYN_REPORT          0
-   EV_ABS   ABS_X               3
-   EV_SYN   SYN_REPORT          0
-   EV_ABS   ABS_X               4
-   EV_SYN   SYN_REPORT          0
-   EV_ABS   ABS_X               5
-   EV_SYN   SYN_REPORT          0
-   EV_ABS   ABS_X               6
-   EV_SYN   SYN_REPORT          0
*  EV_SYN   SYN_DROPPED
*  EV_ABS   ABS_X               1
*  EV_SYN   SYN_REPORT          0
*  EV_ABS   ABS_X               2
*  EV_SYN   SYN_REPORT          0
*  EV_ABS   ABS_X               3
*  EV_SYN   SYN_REPORT          0
*  EV_ABS   ABS_X               4
*  EV_SYN   SYN_REPORT          0
*  EV_ABS   ABS_X               5
*  EV_SYN   SYN_REPORT          0
*  EV_ABS   ABS_X               6
*  EV_SYN   SYN_REPORT          0
  * @endcode
  * An ioctl at any time in this sequence will return a value of 6 for ABS_X.
  *
@@ -411,10 +412,10 @@ extern "C" {
  * avoid spurious cursor movements. In the above example, the event sequence
  * by libevdev is:
  * @code
-   EV_SYN   SYN_DROPPED
-   EV_ABS   ABS_X               6
-   EV_SYN   SYN_REPORT          0
-   @endcode
*  EV_SYN   SYN_DROPPED
*  EV_ABS   ABS_X               6
*  EV_SYN   SYN_REPORT          0
*  @endcode
  */
 
 /**
@@ -540,6 +541,20 @@ extern "C" {
  * @include linux/input.h
  */
 
+/**
+ * @page static_linking Statically linking libevdev
+ *
+ * Statically linking libevdev.a is not recommended. Symbol visibility is
+ * difficult to control in a static library, so extra care must be taken to
+ * only use symbols that are explicitly exported. libevdev's API stability
+ * guarantee only applies to those symbols.
+ *
+ * If you do link libevdev statically, note that in addition to the exported
+ * symbols, libevdev reserves the <b>_libevdev_*</b> namespace. Do not use
+ * or create symbols with that prefix, they are subject to change at any
+ * time.
+ */
+
 /**
  * @page testing libevdev-internal test suite
  *
@@ -614,6 +629,29 @@ extern "C" {
  * before libevdev_set_fd() unless documented otherwise.
  */
 
+/**
+ * @defgroup logging Library logging facilities
+ *
+ * libevdev provides two methods of logging library-internal messages. The
+ * old method is to provide a global log handler in
+ * libevdev_set_log_function(). The new method is to provide a per-context
+ * log handler in libevdev_set_device_log_function(). Developers are encouraged
+ * to use the per-context logging facilities over the global log handler as
+ * it provides access to the libevdev instance that caused a message, and is
+ * more flexible when libevdev is used from within a shared library.
+ *
+ * If a caller sets both the global log handler and a per-context log
+ * handler, each device with a per-context log handler will only invoke that
+ * log handler.
+ *
+ * @note To set a context-specific log handler, a context is needed.
+ * Thus developers are discouraged from using libevdev_new_from_fd() as
+ * important messages from the device initialization process may get lost.
+ *
+ * @note A context-specific handler cannot be used for libevdev's uinput
+ * devices. @ref uinput must use the global log handler.
+ */
+
 /**
  * @defgroup bits Querying device capabilities
  *
@@ -734,11 +772,11 @@ struct libevdev* libevdev_new(void);
  *
  * This is a shortcut for
  *
- @code
- int err;
- struct libevdev *dev = libevdev_new();
- err = libevdev_set_fd(dev, fd);
- @endcode
@code
int err;
struct libevdev *dev = libevdev_new();
err = libevdev_set_fd(dev, fd);
@endcode
  *
  * @param fd A file descriptor to the device in O_RDWR or O_RDONLY mode.
  * @param[out] dev The newly initialized evdev device.
@@ -757,6 +795,9 @@ int libevdev_new_from_fd(int fd, struct libevdev **dev);
  * Clean up and free the libevdev struct. After completion, the <code>struct
  * libevdev</code> is invalid and must not be used.
  *
+ * Note that calling libevdev_free() does not close the file descriptor
+ * currently asssociated with this instance.
+ *
  * @param dev The evdev device
  *
  * @note This function may be called before libevdev_set_fd().
@@ -764,7 +805,7 @@ int libevdev_new_from_fd(int fd, struct libevdev **dev);
 void libevdev_free(struct libevdev *dev);
 
 /**
- * @ingroup init
+ * @ingroup logging
  */
 enum libevdev_log_priority {
        LIBEVDEV_LOG_ERROR = 10,        /**< critical errors and application bugs */
@@ -773,7 +814,7 @@ enum libevdev_log_priority {
 };
 
 /**
- * @ingroup init
+ * @ingroup logging
  *
  * Logging function called by library-internal logging.
  * This function is expected to treat its input like printf would.
@@ -796,21 +837,27 @@ typedef void (*libevdev_log_func_t)(enum libevdev_log_priority priority,
        LIBEVDEV_ATTRIBUTE_PRINTF(6, 0);
 
 /**
- * @ingroup init
+ * @ingroup logging
  *
  * Set a printf-style logging handler for library-internal logging. The default
  * logging function is to stdout.
  *
+ * @note The global log handler is only called if no context-specific log
+ * handler has been set with libevdev_set_device_log_function().
+ *
  * @param logfunc The logging function for this device. If NULL, the current
  * logging function is unset and no logging is performed.
  * @param data User-specific data passed to the log handler.
  *
  * @note This function may be called before libevdev_set_fd().
+ *
+ * @deprecated Use per-context logging instead, see
+ * libevdev_set_device_log_function().
  */
 void libevdev_set_log_function(libevdev_log_func_t logfunc, void *data);
 
 /**
- * @ingroup init
+ * @ingroup logging
  *
  * Define the minimum level to be printed to the log handler.
  * Messages higher than this level are printed, others are discarded. This
@@ -818,19 +865,77 @@ void libevdev_set_log_function(libevdev_log_func_t logfunc, void *data);
  *
  * @param priority Minimum priority to be printed to the log.
  *
+ * @deprecated Use per-context logging instead, see
+ * libevdev_set_device_log_function().
  */
 void libevdev_set_log_priority(enum libevdev_log_priority priority);
 
 /**
- * @ingroup init
+ * @ingroup logging
  *
  * Return the current log priority level. Messages higher than this level
  * are printed, others are discarded. This is a global setting.
  *
  * @return the current log level
+ *
+ * @deprecated Use per-context logging instead, see
+ * libevdev_set_device_log_function().
  */
 enum libevdev_log_priority libevdev_get_log_priority(void);
 
+/**
+ * @ingroup logging
+ *
+ * Logging function called by library-internal logging for a specific
+ * libevdev context. This function is expected to treat its input like
+ * printf would.
+ *
+ * @param dev The evdev device
+ * @param priority Log priority of this message
+ * @param data User-supplied data pointer (see libevdev_set_log_function())
+ * @param file libevdev source code file generating this message
+ * @param line libevdev source code line generating this message
+ * @param func libevdev source code function generating this message
+ * @param format printf-style format string
+ * @param args List of arguments
+ *
+ * @see libevdev_set_log_function
+ * @since 1.3
+ */
+typedef void (*libevdev_device_log_func_t)(const struct libevdev *dev,
+                                          enum libevdev_log_priority priority,
+                                          void *data,
+                                          const char *file, int line,
+                                          const char *func,
+                                          const char *format, va_list args)
+       LIBEVDEV_ATTRIBUTE_PRINTF(7, 0);
+
+/**
+ * @ingroup logging
+ *
+ * Set a printf-style logging handler for library-internal logging for this
+ * device context. The default logging function is NULL, i.e. the global log
+ * handler is invoked. If a context-specific log handler is set, the global
+ * log handler is not invoked for this device.
+ *
+ * @note This log function applies for this device context only, even if
+ * another context exists for the same fd.
+ *
+ * @param dev The evdev device
+ * @param logfunc The logging function for this device. If NULL, the current
+ * logging function is unset and logging falls back to the global log
+ * handler, if any.
+ * @param priority Minimum priority to be printed to the log.
+ * @param data User-specific data passed to the log handler.
+ *
+ * @note This function may be called before libevdev_set_fd().
+ * @since 1.3
+ */
+void libevdev_set_device_log_function(struct libevdev *dev,
+                                     libevdev_device_log_func_t logfunc,
+                                     enum libevdev_log_priority priority,
+                                     void *data);
+
 /**
  * @ingroup init
  */
@@ -870,6 +975,15 @@ int libevdev_grab(struct libevdev *dev, enum libevdev_grab_mode grab);
  * you need to change the fd after closing and re-opening the same device, use
  * libevdev_change_fd().
  *
+ * A caller should ensure that any events currently pending on the fd are
+ * drained before the file descriptor is passed to libevdev for
+ * initialization. Due to how the kernel's ioctl handling works, the initial
+ * device state will reflect the current device state *after* applying all
+ * events currently pending on the fd. Thus, if the fd is not drained, the
+ * state visible to the caller will be inconsistent with the events
+ * immediately available on the device. This does not affect state-less
+ * events like EV_REL.
+ *
  * Unless otherwise specified, libevdev function behavior is undefined until
  * a successfull call to libevdev_set_fd().
  *
@@ -900,13 +1014,13 @@ int libevdev_set_fd(struct libevdev* dev, int fd);
  * The example code below illustrates how to force a re-sync of the
  * library-internal state. Note that this code doesn't handle the events in
  * the caller, it merely forces an update of the internal library state.
- @code
-     struct input_event ev;
-     libevdev_change_fd(dev, new_fd);
-     libevdev_next_event(dev, LIBEVDEV_READ_FLAG_FORCE_SYNC, &ev);
-     while (libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev) == LIBEVDEV_READ_STATUS_SYNC)
-                            ; // noop
- @endcode
@code
    struct input_event ev;
    libevdev_change_fd(dev, new_fd);
    libevdev_next_event(dev, LIBEVDEV_READ_FLAG_FORCE_SYNC, &ev);
    while (libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev) == LIBEVDEV_READ_STATUS_SYNC)
*                             ; // noop
@endcode
  *
  * The fd may be open in O_RDONLY or O_RDWR.
  *
@@ -931,7 +1045,6 @@ int libevdev_change_fd(struct libevdev* dev, int fd);
  */
 int libevdev_get_fd(const struct libevdev* dev);
 
-
 /**
  * @ingroup events
  */
@@ -953,6 +1066,7 @@ enum libevdev_read_status {
         */
        LIBEVDEV_READ_STATUS_SYNC = 1
 };
+
 /**
  * @ingroup events
  *
@@ -1284,6 +1398,7 @@ int libevdev_has_event_code(const struct libevdev *dev, unsigned int type, unsig
  * @note This function is signal-safe.
  */
 int libevdev_get_abs_minimum(const struct libevdev *dev, unsigned int code);
+
 /**
  * @ingroup bits
  *
@@ -1297,6 +1412,7 @@ int libevdev_get_abs_minimum(const struct libevdev *dev, unsigned int code);
  * @note This function is signal-safe.
  */
 int libevdev_get_abs_maximum(const struct libevdev *dev, unsigned int code);
+
 /**
  * @ingroup bits
  *
@@ -1310,6 +1426,7 @@ int libevdev_get_abs_maximum(const struct libevdev *dev, unsigned int code);
  * @note This function is signal-safe.
  */
 int libevdev_get_abs_fuzz(const struct libevdev *dev, unsigned int code);
+
 /**
  * @ingroup bits
  *
@@ -1323,6 +1440,7 @@ int libevdev_get_abs_fuzz(const struct libevdev *dev, unsigned int code);
  * @note This function is signal-safe.
  */
 int libevdev_get_abs_flat(const struct libevdev *dev, unsigned int code);
+
 /**
  * @ingroup bits
  *
@@ -1414,10 +1532,10 @@ int libevdev_set_event_value(struct libevdev *dev, unsigned int type, unsigned i
  *
  * Fetch the current value of the event type. This is a shortcut for
  *
- @code
-   if (libevdev_has_event_type(dev, t) && libevdev_has_event_code(dev, t, c))
-        val = libevdev_get_event_value(dev, t, c);
- @endcode
@code
  if (libevdev_has_event_type(dev, t) && libevdev_has_event_code(dev, t, c))
       val = libevdev_get_event_value(dev, t, c);
@endcode
  *
  * @param dev The evdev device, already initialized with libevdev_set_fd()
  * @param type The event type for the code to query (EV_SYN, EV_REL, etc.)
@@ -1491,12 +1609,12 @@ int libevdev_set_slot_value(struct libevdev *dev, unsigned int slot, unsigned in
  *
  * Fetch the current value of the code for the given slot. This is a shortcut for
  *
- @code
-   if (libevdev_has_event_type(dev, EV_ABS) &&
-       libevdev_has_event_code(dev, EV_ABS, c) &&
-       slot < device->number_of_slots)
-       val = libevdev_get_slot_value(dev, slot, c);
- @endcode
@code
  if (libevdev_has_event_type(dev, EV_ABS) &&
      libevdev_has_event_code(dev, EV_ABS, c) &&
      slot < device->number_of_slots)
      val = libevdev_get_slot_value(dev, slot, c);
@endcode
  *
  * @param dev The evdev device, already initialized with libevdev_set_fd()
  * @param slot The numerical slot number, must be smaller than the total number
@@ -1673,14 +1791,14 @@ int libevdev_disable_event_type(struct libevdev *dev, unsigned int type);
 /**
  * @ingroup kernel
  *
- * Forcibly enable an event type on this device, even if the underlying
+ * Forcibly enable an event code on this device, even if the underlying
  * device does not support it. While this cannot make the device actually
  * report such events, it will now return true for libevdev_has_event_code().
  *
  * The last argument depends on the type and code:
  * - If type is EV_ABS, data must be a pointer to a struct input_absinfo
  *   containing the data for this axis.
- * - If type is EV_REP, daat must be a pointer to a int containing the data
+ * - If type is EV_REP, data must be a pointer to a int containing the data
  *   for this axis
  * - For all other types, the argument must be NULL.
  *
@@ -1720,8 +1838,8 @@ int libevdev_enable_event_code(struct libevdev *dev, unsigned int type, unsigned
  * This is a local modification only affecting only this representation of
  * this device.
  *
- * Disabling EV_SYN will not work. Don't shoot yourself in the foot.
- * It hurts.
+ * Disabling codes of type EV_SYN will not work. Don't shoot yourself in the
+ * foot. It hurts.
  *
  * @param dev The evdev device, already initialized with libevdev_set_fd()
  * @param type The event type to disable (EV_ABS, EV_KEY, ...)
@@ -1750,7 +1868,6 @@ int libevdev_disable_event_code(struct libevdev *dev, unsigned int type, unsigne
  */
 int libevdev_kernel_set_abs_info(struct libevdev *dev, unsigned int code, const struct input_absinfo *abs);
 
-
 /**
  * @ingroup kernel
  */
@@ -1781,11 +1898,11 @@ int libevdev_kernel_set_led_value(struct libevdev *dev, unsigned int code, enum
  * of LED codes and values to set them to, terminated by a -1. For example, to
  * switch the NumLock LED on but the CapsLock LED off, use:
  *
- @code
-     libevdev_kernel_set_led_values(dev, LED_NUML, LIBEVDEV_LED_ON,
-                                         LED_CAPSL, LIBEVDEV_LED_OFF,
-                                         -1);
- @endcode
@code
    libevdev_kernel_set_led_values(dev, LED_NUML, LIBEVDEV_LED_ON,
                                        LED_CAPSL, LIBEVDEV_LED_OFF,
                                        -1);
@endcode
  *
  * If any LED code or value is invalid, this function returns -EINVAL and no
  * LEDs are modified.
@@ -1997,6 +2114,36 @@ int libevdev_event_code_from_name(unsigned int type, const char *name);
 int libevdev_event_code_from_name_n(unsigned int type, const char *name,
                                    size_t len);
 
+/**
+ * @ingroup misc
+ *
+ * Look up an input property by its name. Properties start with the fixed
+ * prefix "INPUT_PROP_" followed by their name (eg., "INPUT_PROP_POINTER").
+ * The prefix must be included in the name. It returns the constant assigned
+ * to the property or -1 if not found.
+ *
+ * @param name A non-NULL string describing an input property
+ *
+ * @return The given code constant for the name or -1 if not found.
+ */
+int libevdev_property_from_name(const char *name);
+
+/**
+ * @ingroup misc
+ *
+ * Look up an input property by its name. Properties start with the fixed
+ * prefix "INPUT_PROP_" followed by their name (eg., "INPUT_PROP_POINTER").
+ * The prefix must be included in the name. It returns the constant assigned
+ * to the property or -1 if not found.
+ *
+ * @param name A non-NULL string describing an input property
+ * @param len The length of the string in @p name excluding any terminating 0
+ * character.
+ *
+ * @return The given code constant for the name or -1 if not found.
+ */
+int libevdev_property_from_name_n(const char *name, size_t len);
+
 /**
  * @ingroup bits
  *
@@ -2016,7 +2163,6 @@ int libevdev_event_code_from_name_n(unsigned int type, const char *name,
  */
 int libevdev_get_repeat(const struct libevdev *dev, int *delay, int *period);
 
-
 /********* DEPRECATED SECTION *********/
 #if defined(__GNUC__) && __GNUC__ >= 4
 #define LIBEVDEV_DEPRECATED __attribute__ ((deprecated))
index ef4f06b710a749ea88c38cbaa1f41d9db4dc1ceb..374712f16e5eea0e9703b2e710c3cdcef5ba02da 100644 (file)
@@ -102,3 +102,13 @@ global:
 local:
        *;
 };
+
+LIBEVDEV_1_3 {
+global:
+       libevdev_set_device_log_function;
+       libevdev_property_from_name;
+       libevdev_property_from_name_n;
+
+local:
+       *;
+} LIBEVDEV_1;
index 149f0934f42772571a719915d836f7a155b851f9..b3c2acf26804001df47511338c5a508b8bbc0d27 100755 (executable)
@@ -82,8 +82,13 @@ def print_map(bits):
        print("};")
        print("")
 
+       print("#if __clang__")
+       print("#pragma clang diagnostic push")
+       print("#pragma clang diagnostic ignored \"-Winitializer-overrides\"")
+       print("#else")
        print("#pragma GCC diagnostic push")
        print("#pragma GCC diagnostic ignored \"-Woverride-init\"")
+       print("#endif")
        print("static const int ev_max[EV_MAX + 1] = {")
        print(" [0 ... EV_MAX] = -1,")
        for prefix in prefixes:
@@ -91,7 +96,11 @@ def print_map(bits):
                        continue
                print(" [EV_%s] = %s_MAX," % (prefix[:-1], prefix[:-1]))
        print("};")
+       print("#if __clang__")
+       print("#pragma clang diagnostic pop /* \"-Winitializer-overrides\" */")
+       print("#else")
        print("#pragma GCC diagnostic pop /* \"-Woverride-init\" */")
+       print("#endif");
        print("")
 
 def print_python_map(bits):
@@ -133,7 +142,10 @@ def print_lookup_table(bits):
                print_lookup(bits, prefix[:-1].lower())
        print("};")
        print("")
-
+       print("static const struct name_entry prop_names[] = {")
+       print_lookup(bits, "input_prop")
+       print("};")
+       print("")
 
 def print_mapping_table(bits):
        print("/* THIS FILE IS GENERATED, DO NOT EDIT */")
@@ -190,13 +202,12 @@ def parse(fp):
        return bits
 
 def usage(prog):
-       print("Usage: %s /path/to/linux/input.h" % prog)
+       print("Usage: cat <files> | %s" % prog)
 
 if __name__ == "__main__":
-       if len(sys.argv) != 2:
+       if len(sys.argv) != 1:
                usage(sys.argv[0])
                sys.exit(2)
 
-       with open(sys.argv[1]) as f:
-               bits = parse(f)
-               print_mapping_table(bits)
+       bits = parse(sys.stdin)
+       print_mapping_table(bits)
index aa53ef238027826b3f8d2d24fea27cc18c6aee71..5fbd43d1009af6099a9fd319b8da8e49e3305114 100644 (file)
@@ -109,13 +109,14 @@ dnl
 dnl Other compilers don't support -Werror per se, but they support
 dnl an equivalent flag:
 dnl  - Sun Studio compiler supports -errwarn=%all
+dnl we don't test for that, it gives us false positives when gcc doesn't
+dnl actually complain about it. If someone wants to compile this on sun, let
+dnl them fix it.
 AC_DEFUN([CC_CHECK_WERROR], [
   AC_CACHE_CHECK(
     [for $CC way to treat warnings as errors],
     [cc_cv_werror],
-    [CC_CHECK_CFLAGS_SILENT([-Werror], [cc_cv_werror=-Werror],
-      [CC_CHECK_CFLAGS_SILENT([-errwarn=%all], [cc_cv_werror=-errwarn=%all])])
-    ])
+    [CC_CHECK_FLAG_APPEND([cc_cv_werror], [CFLAGS], [-Werror])])
 ])
 
 AC_DEFUN([CC_CHECK_ATTRIBUTE], [
@@ -225,17 +226,11 @@ AC_DEFUN([CC_ATTRIBUTE_CONST], [
 ])
 
 AC_DEFUN([CC_FLAG_VISIBILITY], [
-  AC_REQUIRE([CC_CHECK_WERROR])
   AC_CACHE_CHECK([if $CC supports -fvisibility=hidden],
     [cc_cv_flag_visibility],
-    [cc_flag_visibility_save_CFLAGS="$CFLAGS"
-     CFLAGS="$CFLAGS $cc_cv_werror"
-     CC_CHECK_CFLAGS_SILENT([-fvisibility=hidden],
-     cc_cv_flag_visibility='yes',
-     cc_cv_flag_visibility='no')
-     CFLAGS="$cc_flag_visibility_save_CFLAGS"])
+    [CC_CHECK_FLAG_APPEND([cc_cv_flag_visibility], [CFLAGS], [-fvisibility=hidden])])
 
-  AS_IF([test "x$cc_cv_flag_visibility" = "xyes"],
+  AS_IF([test "x$cc_cv_flag_visibility" != "x"],
     [AC_DEFINE([SUPPORT_FLAG_VISIBILITY], 1,
        [Define this if the compiler supports the -fvisibility flag])
      $1],
index 541b0f2307596faee22ccb65c9e12546ae6b334c..cf3e55cdbff3b378253d5a985bc7e7082dd92940 100644 (file)
@@ -1,5 +1,5 @@
 Name:           libevdev
-Version:        1.2.2
+Version:        1.5.4
 Release:        0
 License:        MIT
 Summary:        wrapper library for evdev input devices
@@ -55,7 +55,7 @@ cp -a %{_builddir}/%{buildsubdir}/COPYING %{buildroot}/%{TZ_SYS_RO_SHARE}/licens
 %manifest %{name}.manifest
 %defattr(-,root,root)
 %{TZ_SYS_RO_SHARE}/license/%{name}
-%{_bindir}/touchpad-edge-detector
+%{_bindir}/*
 %{_libdir}/*.so.*
 %{_datadir}/*
 
index 7b195fb299db20c109a6e3e4451a63fbfd8101fc..e06aa4b43534658e14d8171a179455a862f96877 100644 (file)
@@ -1,10 +1,35 @@
-if BUILD_TESTS
-run_tests = test-libevdev test-kernel
 build_tests = test-compile-pedantic test-link
 
+if ENABLE_STATIC_LINK_TEST
+build_tests += test-static-link
+endif
+
+noinst_PROGRAMS = $(build_tests)
+
+AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_builddir)/libevdev
+AM_LDFLAGS =
+
+test_compile_pedantic_SOURCES = test-compile-pedantic.c
+test_compile_pedantic_CFLAGS = $(AM_CPPFLAGS) -pedantic -Werror -std=c89
+
+test_link_SOURCES = test-link.c
+test_link_CFLAGS = -I$(top_srcdir)
+test_link_LDADD = $(top_builddir)/libevdev/libevdev.la
+
+test_static_link_SOURCES = test-link.c
+test_static_link_CFLAGS = -I$(top_srcdir)
+test_static_link_LDADD = $(top_builddir)/libevdev/libevdev.la
+test_static_link_LDFLAGS = $(AM_LDFLAGS) -static
+
+check_local_deps =
+clean_local_deps =
+
+if ENABLE_RUNTIME_TESTS
+run_tests = test-libevdev test-kernel
+
 .NOTPARALLEL:
 
-noinst_PROGRAMS = $(run_tests) $(build_tests)
+noinst_PROGRAMS += $(run_tests)
 
 TESTS = $(run_tests)
 
@@ -23,7 +48,8 @@ common_sources = $(libevdev_sources) \
                 test-common.h
 
 # include builddir for event-names.h
-AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_builddir)/libevdev $(CHECK_CFLAGS) $(GCOV_CFLAGS)
+AM_CPPFLAGS += $(CHECK_CFLAGS) $(GCOV_CFLAGS)
+AM_LDFLAGS += $(GCOV_LDFLAGS)
 
 test_libevdev_SOURCES = \
                        test-main.c \
@@ -36,14 +62,7 @@ test_libevdev_SOURCES = \
                        test-uinput.c \
                        $(common_sources)
 
-test_libevdev_LDADD =  $(CHECK_LIBS) $(GCOV_LDFLAGS)
-
-test_compile_pedantic_SOURCES = test-compile-pedantic.c
-test_compile_pedantic_CFLAGS = $(AM_CPPFLAGS) -pedantic -Werror -std=c90
-
-test_link_SOURCES = test-link.c
-test_link_CFLAGS = -I$(top_srcdir)
-test_link_LDADD = $(top_builddir)/libevdev/libevdev.la
+test_libevdev_LDADD =  $(CHECK_LIBS)
 
 test_kernel_SOURCES = \
                      test-kernel.c \
@@ -60,7 +79,7 @@ VALGRIND_FLAGS=--leak-check=full \
 valgrind:
                $(MAKE) check-TESTS LOG_COMPILER="$(VALGRIND)" LOG_FLAGS="$(VALGRIND_FLAGS)"
 
-check: valgrind
+check_local_deps += valgrind
 
 endif
 
@@ -91,7 +110,8 @@ gcov-report.txt: gcov-clean check-TESTS
 gcov: gcov-report.txt
        @cat gcov-report.txt
 
-check-local: gcov
+check_local_deps += gcov
+clean_local_deps += gcov-clean
 
 else
 
@@ -104,11 +124,34 @@ gcov:
 gcov-clean:
        @true
 
-endif
+endif # HAVE_VALGRIND
 
 .PHONY: gcov gcov-clean gcov-report.txt
 
-clean-local: gcov-clean
-       rm -f *.gcno *.gcda
+endif # ENABLE_RUNTIME_TESTS
+
+if ENABLE_STATIC_SYMBOL_LEAKS_TEST
+# Hack to check for leaking symbols in the static library.
+# See https://bugs.freedesktop.org/show_bug.cgi?id=82785
+# Note the spaces in the expressions! After the first grep, each line
+# is " T symbol_name"
+static-symbol-leaks: test-static-link
+       $(AM_V_GEN)(\
+               $(NM) --extern-only $(builddir)/test-static-link | \
+                       grep -o -e " T .*" | \
+                       grep -v -e " main$$" \
+                               -e " atexit" \
+                               -e " *gcov.*" \
+                               -e " _.*" \
+                               -e " libevdev_*" && \
+                               echo "Leaking symbols found" && \
+                               exit 1 || exit 0 \
+       )
 
-endif
+check_local_deps += static-symbol-leaks
+endif # HAVE_NM
+
+check-local: $(check_local_deps)
+
+clean-local: $(clean_local_deps)
+       rm -f *.gcno *.gcda
index 617b8e22cc9f553be9e065dc75c65b10036b92fa..48200b6b73c916dbbf0a95d2121c361127d3a3a3 100644 (file)
@@ -113,7 +113,7 @@ uinput_device_free(struct uinput_device *dev)
                return;
 
        if (dev->uinput_fd != -1) {
-               ioctl(dev->uinput_fd, UI_DEV_DESTROY, NULL);
+               (void)ioctl(dev->uinput_fd, UI_DEV_DESTROY, NULL);
                close(dev->uinput_fd);
        }
        if (dev->dev_fd != -1)
index 6273a6d1417aaa2b98e8c499f4c37813bdfce8bd..29411347d63aa833f89fe2b137cc0930210946fa 100644 (file)
@@ -25,7 +25,6 @@
 
 #define DEFAULT_IDS NULL
 
-
 struct uinput_device* uinput_device_new(const char *name);
 int uinput_device_new_with_events(struct uinput_device **dev, const char *name, const struct input_id *ids, ...);
 int uinput_device_new_with_events_v(struct uinput_device **dev, const char *name, const struct input_id *ids, va_list args);
index 6449d46497c999d7179b728c0b22f09ebde9e8e0..339b278848b4a040561923b066e0d0ed9ef9dce4 100644 (file)
@@ -46,9 +46,9 @@ void test_logfunc_ignore_error(enum libevdev_log_priority priority,
 {
 }
 
-int test_create_device(struct uinput_device **uidev_return,
-                      struct libevdev **dev_return,
-                      ...)
+void test_create_device(struct uinput_device **uidev_return,
+                       struct libevdev **dev_return,
+                       ...)
 {
        int rc, fd;
        struct uinput_device *uidev;
@@ -71,15 +71,13 @@ int test_create_device(struct uinput_device **uidev_return,
 
        *uidev_return = uidev;
        *dev_return = dev;
-
-       return rc == 0 ? rc : -errno;
 }
 
-int test_create_abs_device(struct uinput_device **uidev_return,
-                          struct libevdev **dev_return,
-                          int nabs,
-                          const struct input_absinfo *abs,
-                          ...)
+void test_create_abs_device(struct uinput_device **uidev_return,
+                           struct libevdev **dev_return,
+                           int nabs,
+                           const struct input_absinfo *abs,
+                           ...)
 {
        int rc, fd;
        struct uinput_device *uidev;
@@ -117,6 +115,4 @@ int test_create_abs_device(struct uinput_device **uidev_return,
 
        *uidev_return = uidev;
        *dev_return = dev;
-
-       return rc == 0 ? rc : -errno;
 }
index d7a33d04b4ea21a4278d3be5bb51b75124bb89d4..47ad4765e6797a54fd157ef004460e4fe1c24dbe 100644 (file)
 
 #include "test-common-uinput.h"
 
-
-int test_create_device(struct uinput_device **uidev,
-                      struct libevdev **dev,
-                      ...);
-int test_create_abs_device(struct uinput_device **uidev,
-                          struct libevdev **dev,
-                          int nabs,
-                          const struct input_absinfo *abs,
-                          ...);
+void test_create_device(struct uinput_device **uidev,
+                       struct libevdev **dev,
+                       ...);
+void test_create_abs_device(struct uinput_device **uidev,
+                           struct libevdev **dev,
+                           int nabs,
+                           const struct input_absinfo *abs,
+                           ...);
 
 void test_logfunc_abort_on_error(enum libevdev_log_priority priority,
                                 void *data,
index 3a57973b3852d518653090f4104e61d6d4b1f115..b64940ebb3a0098a82b5a54ade8b57993098f17a 100644 (file)
  */
 
 #include <config.h>
-#include <libevdev/libevdev-int.h>
 #include "test-common.h"
 
 START_TEST(test_type_codes)
 {
-       ck_assert(libevdev_event_type_from_name("EV_SYN") == EV_SYN);
-       ck_assert(libevdev_event_type_from_name("EV_KEY") == EV_KEY);
-       ck_assert(libevdev_event_type_from_name("EV_REL") == EV_REL);
-       ck_assert(libevdev_event_type_from_name("EV_ABS") == EV_ABS);
-       ck_assert(libevdev_event_type_from_name("EV_MSC") == EV_MSC);
-       ck_assert(libevdev_event_type_from_name("EV_SND") == EV_SND);
-       ck_assert(libevdev_event_type_from_name("EV_SW") == EV_SW);
-       ck_assert(libevdev_event_type_from_name("EV_LED") == EV_LED);
-       ck_assert(libevdev_event_type_from_name("EV_REP") == EV_REP);
-       ck_assert(libevdev_event_type_from_name("EV_FF") == EV_FF);
-       ck_assert(libevdev_event_type_from_name("EV_FF_STATUS") == EV_FF_STATUS);
-       ck_assert(libevdev_event_type_from_name("EV_MAX") == EV_MAX);
-
-       ck_assert(libevdev_event_type_from_name_n("EV_SYNTAX", 6) == EV_SYN);
-       ck_assert(libevdev_event_type_from_name_n("EV_REPTILE", 6) == EV_REP);
+       ck_assert_int_eq(libevdev_event_type_from_name("EV_SYN"), EV_SYN);
+       ck_assert_int_eq(libevdev_event_type_from_name("EV_KEY"), EV_KEY);
+       ck_assert_int_eq(libevdev_event_type_from_name("EV_REL"), EV_REL);
+       ck_assert_int_eq(libevdev_event_type_from_name("EV_ABS"), EV_ABS);
+       ck_assert_int_eq(libevdev_event_type_from_name("EV_MSC"), EV_MSC);
+       ck_assert_int_eq(libevdev_event_type_from_name("EV_SND"), EV_SND);
+       ck_assert_int_eq(libevdev_event_type_from_name("EV_SW"), EV_SW);
+       ck_assert_int_eq(libevdev_event_type_from_name("EV_LED"), EV_LED);
+       ck_assert_int_eq(libevdev_event_type_from_name("EV_REP"), EV_REP);
+       ck_assert_int_eq(libevdev_event_type_from_name("EV_FF"), EV_FF);
+       ck_assert_int_eq(libevdev_event_type_from_name("EV_FF_STATUS"), EV_FF_STATUS);
+       ck_assert_int_eq(libevdev_event_type_from_name("EV_MAX"), EV_MAX);
+
+       ck_assert_int_eq(libevdev_event_type_from_name_n("EV_SYNTAX", 6), EV_SYN);
+       ck_assert_int_eq(libevdev_event_type_from_name_n("EV_REPTILE", 6), EV_REP);
 }
 END_TEST
 
 START_TEST(test_type_invalid)
 {
-       ck_assert(libevdev_event_type_from_name("EV_Syn") == -1);
-       ck_assert(libevdev_event_type_from_name("ev_SYN") == -1);
-       ck_assert(libevdev_event_type_from_name("SYN") == -1);
-       ck_assert(libevdev_event_type_from_name("EV_SYNTAX") == -1);
+       ck_assert_int_eq(libevdev_event_type_from_name("EV_Syn"), -1);
+       ck_assert_int_eq(libevdev_event_type_from_name("ev_SYN"), -1);
+       ck_assert_int_eq(libevdev_event_type_from_name("SYN"), -1);
+       ck_assert_int_eq(libevdev_event_type_from_name("EV_SYNTAX"), -1);
 
-       ck_assert(libevdev_event_type_from_name_n("EV_SYN", 5) == -1);
-       ck_assert(libevdev_event_type_from_name_n("EV_REPTILE", 7) == -1);
+       ck_assert_int_eq(libevdev_event_type_from_name_n("EV_SYN", 5), -1);
+       ck_assert_int_eq(libevdev_event_type_from_name_n("EV_REPTILE", 7), -1);
 }
 END_TEST
 
 START_TEST(test_key_codes)
 {
-       ck_assert(libevdev_event_code_from_name(EV_SYN, "SYN_REPORT") == SYN_REPORT);
-       ck_assert(libevdev_event_code_from_name(EV_ABS, "ABS_X") == ABS_X);
-       ck_assert(libevdev_event_code_from_name(EV_KEY, "BTN_A") == BTN_A);
-       ck_assert(libevdev_event_code_from_name(EV_KEY, "KEY_A") == KEY_A);
-       ck_assert(libevdev_event_code_from_name(EV_REL, "REL_X") == REL_X);
-       ck_assert(libevdev_event_code_from_name(EV_MSC, "MSC_RAW") == MSC_RAW);
-       ck_assert(libevdev_event_code_from_name(EV_LED, "LED_KANA") == LED_KANA);
-       ck_assert(libevdev_event_code_from_name(EV_SND, "SND_BELL") == SND_BELL);
-       ck_assert(libevdev_event_code_from_name(EV_REP, "REP_DELAY") == REP_DELAY);
-       ck_assert(libevdev_event_code_from_name(EV_SYN, "SYN_DROPPED") == SYN_DROPPED);
-       ck_assert(libevdev_event_code_from_name(EV_KEY, "KEY_RESERVED") == KEY_RESERVED);
-       ck_assert(libevdev_event_code_from_name(EV_KEY, "BTN_0") == BTN_0);
-       ck_assert(libevdev_event_code_from_name(EV_KEY, "KEY_0") == KEY_0);
-       ck_assert(libevdev_event_code_from_name(EV_FF, "FF_GAIN") == FF_GAIN);
-       ck_assert(libevdev_event_code_from_name(EV_FF_STATUS, "FF_STATUS_MAX") == FF_STATUS_MAX);
-       ck_assert(libevdev_event_code_from_name(EV_SW, "SW_MAX") == SW_MAX);
-
-       ck_assert(libevdev_event_code_from_name_n(EV_ABS, "ABS_YXZ", 5) == ABS_Y);
+       ck_assert_int_eq(libevdev_event_code_from_name(EV_SYN, "SYN_REPORT"), SYN_REPORT);
+       ck_assert_int_eq(libevdev_event_code_from_name(EV_ABS, "ABS_X"), ABS_X);
+       ck_assert_int_eq(libevdev_event_code_from_name(EV_KEY, "BTN_A"), BTN_A);
+       ck_assert_int_eq(libevdev_event_code_from_name(EV_KEY, "KEY_A"), KEY_A);
+       ck_assert_int_eq(libevdev_event_code_from_name(EV_REL, "REL_X"), REL_X);
+       ck_assert_int_eq(libevdev_event_code_from_name(EV_MSC, "MSC_RAW"), MSC_RAW);
+       ck_assert_int_eq(libevdev_event_code_from_name(EV_LED, "LED_KANA"), LED_KANA);
+       ck_assert_int_eq(libevdev_event_code_from_name(EV_SND, "SND_BELL"), SND_BELL);
+       ck_assert_int_eq(libevdev_event_code_from_name(EV_REP, "REP_DELAY"), REP_DELAY);
+       ck_assert_int_eq(libevdev_event_code_from_name(EV_SYN, "SYN_DROPPED"), SYN_DROPPED);
+       ck_assert_int_eq(libevdev_event_code_from_name(EV_KEY, "KEY_RESERVED"), KEY_RESERVED);
+       ck_assert_int_eq(libevdev_event_code_from_name(EV_KEY, "BTN_0"), BTN_0);
+       ck_assert_int_eq(libevdev_event_code_from_name(EV_KEY, "KEY_0"), KEY_0);
+       ck_assert_int_eq(libevdev_event_code_from_name(EV_FF, "FF_GAIN"), FF_GAIN);
+       ck_assert_int_eq(libevdev_event_code_from_name(EV_FF_STATUS, "FF_STATUS_MAX"), FF_STATUS_MAX);
+       ck_assert_int_eq(libevdev_event_code_from_name(EV_SW, "SW_MAX"), SW_MAX);
+
+       ck_assert_int_eq(libevdev_event_code_from_name_n(EV_ABS, "ABS_YXZ", 5), ABS_Y);
 }
 END_TEST
 
 START_TEST(test_key_invalid)
 {
-       ck_assert(libevdev_event_code_from_name(EV_MAX, "MAX_FAKE") == -1);
-       ck_assert(libevdev_event_code_from_name(EV_CNT, "CNT_FAKE") == -1);
-       ck_assert(libevdev_event_code_from_name(EV_PWR, "PWR_SOMETHING") == -1);
-       ck_assert(libevdev_event_code_from_name(EV_ABS, "EV_ABS") == -1);
-       ck_assert(libevdev_event_code_from_name(EV_ABS, "ABS_XY") == -1);
-       ck_assert(libevdev_event_code_from_name(EV_KEY, "BTN_GAMEPAD") == -1);
-       ck_assert(libevdev_event_code_from_name(EV_KEY, "BUS_PCI") == -1);
-       ck_assert(libevdev_event_code_from_name(EV_FF_STATUS, "FF_STATUS") == -1);
-       ck_assert(libevdev_event_code_from_name(EV_FF_STATUS, "FF_STATUS_") == -1);
-       ck_assert(libevdev_event_code_from_name(EV_FF, "FF_STATUS") == -1);
-       ck_assert(libevdev_event_code_from_name(EV_FF, "FF_STATUS_") == -1);
-       ck_assert(libevdev_event_code_from_name(EV_KEY, "ID_BUS") == -1);
-       ck_assert(libevdev_event_code_from_name(EV_SND, "SND_CNT") == -1);
-       ck_assert(libevdev_event_code_from_name(EV_SW, "SW_CNT") == -1);
-
-       ck_assert(libevdev_event_code_from_name_n(EV_ABS, "ABS_X", 4) == -1);
+       ck_assert_int_eq(libevdev_event_code_from_name(EV_MAX, "MAX_FAKE"), -1);
+       ck_assert_int_eq(libevdev_event_code_from_name(EV_CNT, "CNT_FAKE"), -1);
+       ck_assert_int_eq(libevdev_event_code_from_name(EV_PWR, "PWR_SOMETHING"), -1);
+       ck_assert_int_eq(libevdev_event_code_from_name(EV_ABS, "EV_ABS"), -1);
+       ck_assert_int_eq(libevdev_event_code_from_name(EV_ABS, "ABS_XY"), -1);
+       ck_assert_int_eq(libevdev_event_code_from_name(EV_KEY, "BTN_GAMEPAD"), -1);
+       ck_assert_int_eq(libevdev_event_code_from_name(EV_KEY, "BUS_PCI"), -1);
+       ck_assert_int_eq(libevdev_event_code_from_name(EV_FF_STATUS, "FF_STATUS"), -1);
+       ck_assert_int_eq(libevdev_event_code_from_name(EV_FF_STATUS, "FF_STATUS_"), -1);
+       ck_assert_int_eq(libevdev_event_code_from_name(EV_FF, "FF_STATUS"), -1);
+       ck_assert_int_eq(libevdev_event_code_from_name(EV_FF, "FF_STATUS_"), -1);
+       ck_assert_int_eq(libevdev_event_code_from_name(EV_KEY, "ID_BUS"), -1);
+       ck_assert_int_eq(libevdev_event_code_from_name(EV_SND, "SND_CNT"), -1);
+       ck_assert_int_eq(libevdev_event_code_from_name(EV_SW, "SW_CNT"), -1);
+
+       ck_assert_int_eq(libevdev_event_code_from_name_n(EV_ABS, "ABS_X", 4), -1);
+}
+END_TEST
+
+START_TEST(test_properties)
+{
+       struct prop {
+               int val;
+               const char *name;
+       } lut[] = {
+               { INPUT_PROP_DIRECT, "INPUT_PROP_DIRECT" },
+               { INPUT_PROP_POINTER, "INPUT_PROP_POINTER" },
+               { INPUT_PROP_MAX, "INPUT_PROP_MAX" },
+               { -1, NULL}
+       };
+       struct prop *p = lut;
+       while (p->val != -1) {
+               ck_assert_int_eq(libevdev_property_from_name(p->name), p->val);
+               p++;
+       }
+}
+END_TEST
+
+START_TEST(test_properties_invalid)
+{
+       ck_assert_int_eq(libevdev_property_from_name("EV_ABS"), -1);
+       ck_assert_int_eq(libevdev_property_from_name("INPUT_PROP"), -1);
+       ck_assert_int_eq(libevdev_property_from_name("INPUT_PROP_"), -1);
+       ck_assert_int_eq(libevdev_property_from_name("INPUT_PROP_FOO"), -1);
+
+       ck_assert_int_eq(libevdev_property_from_name_n("INPUT_PROP_POINTER", 11), -1);
+       ck_assert_int_eq(libevdev_property_from_name_n("INPUT_PROP_POINTER",
+                                               strlen("INPUT_PROP_POINTER") - 1), -1);
 }
 END_TEST
 
@@ -115,5 +146,10 @@ event_code_suite(void)
        tcase_add_test(tc, test_key_invalid);
        suite_add_tcase(s, tc);
 
+       tc = tcase_create("property tests");
+       tcase_add_test(tc, test_properties);
+       tcase_add_test(tc, test_properties_invalid);
+       suite_add_tcase(s, tc);
+
        return s;
 }
index 8d7e6d643364cb14a212c812ee2cf9dcf711e76f..10a59ead077c15e0d0d7806cb770f30abe32da81 100644 (file)
@@ -298,4 +298,3 @@ event_name_suite(void)
 
        return s;
 }
-
index d45fee064ebbb6789393784496b4f1e9423c07f3..501dc085ef35186d5b1351b4bd2c81d418ff41ca 100644 (file)
@@ -357,4 +357,3 @@ queue_suite(void)
 
        return s;
 }
-
index f3bc7e028c7ddefdb5c7fa063a58cbe832e308fd..6fba6054680e615bdb7b0f3f2f8c738308f31f96 100644 (file)
@@ -75,7 +75,7 @@ START_TEST(test_revoke)
        dev_fd = libevdev_get_fd(dev);
        ck_assert_int_ge(dev_fd, 0);
        rc = ioctl(dev_fd, EVIOCREVOKE, NULL);
-       if (rc == -1 && errno == -EINVAL) {
+       if (rc == -1 && errno == EINVAL) {
                fprintf(stderr, "WARNING: skipping EVIOCREVOKE test, not suported by current kernel\n");
                goto out;
        }
@@ -144,7 +144,7 @@ START_TEST(test_revoke_fail_after)
        ck_assert_int_gt(fd, -1);
 
        rc = ioctl(fd, EVIOCREVOKE, NULL);
-       if (rc == -1 && errno == -EINVAL) {
+       if (rc == -1 && errno == EINVAL) {
                fprintf(stderr, "WARNING: skipping EVIOCREVOKE test, not suported by current kernel\n");
                goto out;
        }
index 6ef0bf93281ac82039ccc7ce0fe106a7c87ea734..dd2face5d34c928242074aac30d6e59f209f470c 100644 (file)
@@ -60,6 +60,75 @@ START_TEST(test_next_event)
 }
 END_TEST
 
+START_TEST(test_next_event_invalid_fd)
+{
+       struct uinput_device* uidev;
+       struct libevdev *dev;
+       int rc;
+       struct input_event ev;
+
+       libevdev_set_log_function(test_logfunc_ignore_error, NULL);
+
+       dev = libevdev_new();
+       rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);
+       ck_assert_int_eq(rc, -EBADF);
+       libevdev_free(dev);
+
+       test_create_device(&uidev, &dev,
+                          EV_REL, REL_X,
+                          EV_REL, REL_Y,
+                          EV_KEY, BTN_LEFT,
+                          -1);
+
+       /* invalid (missing) flag */
+       rc = libevdev_next_event(dev, 0x10, &ev);
+       ck_assert_int_eq(rc, -EINVAL);
+
+       /* set an invalid fd */
+       rc = libevdev_change_fd(dev, -3);
+       ck_assert_int_eq(rc, 0);
+       rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);
+       ck_assert_int_eq(rc, -EBADF);
+
+       libevdev_set_log_function(test_logfunc_abort_on_error, NULL);
+
+       libevdev_free(dev);
+       uinput_device_free(uidev);
+}
+END_TEST
+
+START_TEST(test_next_event_blocking)
+{
+       struct uinput_device* uidev;
+       struct libevdev *dev;
+       int fd, flags;
+       int rc;
+       struct input_event ev;
+
+       test_create_device(&uidev, &dev,
+                          EV_REL, REL_X,
+                          EV_REL, REL_Y,
+                          EV_KEY, BTN_LEFT,
+                          -1);
+
+       fd = libevdev_get_fd(dev);
+       flags = fcntl(fd, F_GETFL) & ~O_NONBLOCK;
+       rc = fcntl(fd, F_SETFL, flags);
+       ck_assert_int_eq(rc, 0);
+
+       uinput_device_event(uidev, EV_KEY, BTN_LEFT, 1);
+       uinput_device_event(uidev, EV_SYN, SYN_REPORT, 0);
+       rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_BLOCKING, &ev);
+       ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS);
+       ck_assert_int_eq(ev.type, EV_KEY);
+       ck_assert_int_eq(ev.code, BTN_LEFT);
+       ck_assert_int_eq(ev.value, 1);
+
+       libevdev_free(dev);
+       uinput_device_free(uidev);
+}
+END_TEST
+
 START_TEST(test_syn_dropped_event)
 {
        struct uinput_device* uidev;
@@ -342,6 +411,23 @@ START_TEST(test_has_event_pending)
 }
 END_TEST
 
+START_TEST(test_has_event_pending_invalid_fd)
+{
+       struct libevdev *dev;
+       int rc;
+
+       libevdev_set_log_function(test_logfunc_ignore_error, NULL);
+
+       dev = libevdev_new();
+       rc = libevdev_has_event_pending(dev);
+       ck_assert_int_eq(rc, -EBADF);
+
+       libevdev_set_log_function(test_logfunc_abort_on_error, NULL);
+
+       libevdev_free(dev);
+}
+END_TEST
+
 START_TEST(test_syn_delta_button)
 {
        struct uinput_device* uidev;
@@ -479,7 +565,6 @@ START_TEST(test_syn_delta_mt)
        abs[3].value = ABS_MT_POSITION_Y;
        abs[3].maximum = 1000;
 
-
        abs[4].value = ABS_MT_SLOT;
        abs[4].maximum = 1;
        abs[5].value = ABS_MT_TRACKING_ID;
@@ -594,7 +679,6 @@ START_TEST(test_syn_delta_mt_reset_slot)
        abs[3].value = ABS_MT_POSITION_Y;
        abs[3].maximum = 1000;
 
-
        abs[4].value = ABS_MT_SLOT;
        abs[4].maximum = 1;
        abs[5].value = ABS_MT_TRACKING_ID;
@@ -1055,7 +1139,6 @@ START_TEST(test_syn_delta_late_sync)
                }
        }
 
-
        /* Now we basically re-do the exact same test, just with the
           tracking ID order inverted */
 
@@ -1139,7 +1222,6 @@ START_TEST(test_syn_delta_late_sync)
                }
        }
 
-
        uinput_device_free(uidev);
        libevdev_free(dev);
 }
@@ -1446,7 +1528,6 @@ START_TEST(test_event_values_invalid)
        ck_assert_int_eq(libevdev_fetch_event_value(dev, EV_REL, REL_Z, &value), 0);
        ck_assert_int_eq(value, 0xab);
 
-
        uinput_device_free(uidev);
        libevdev_free(dev);
 
@@ -1667,10 +1748,10 @@ START_TEST(test_mt_tracking_id_discard)
        abs[5].value = ABS_MT_TRACKING_ID;
        abs[5].maximum = 500;
 
-       rc = test_create_abs_device(&uidev, &dev,
-                                   6, abs,
-                                   EV_SYN, SYN_REPORT,
-                                   -1);
+       test_create_abs_device(&uidev, &dev,
+                              6, abs,
+                              EV_SYN, SYN_REPORT,
+                              -1);
 
        uinput_device_event(uidev, EV_ABS, ABS_MT_SLOT, 1);
        uinput_device_event(uidev, EV_ABS, ABS_MT_TRACKING_ID, 1);
@@ -1750,10 +1831,10 @@ START_TEST(test_mt_tracking_id_discard_neg_1)
        abs[5].value = ABS_MT_TRACKING_ID;
        abs[5].maximum = 500;
 
-       rc = test_create_abs_device(&uidev, &dev,
-                                   6, abs,
-                                   EV_SYN, SYN_REPORT,
-                                   -1);
+       test_create_abs_device(&uidev, &dev,
+                              6, abs,
+                              EV_SYN, SYN_REPORT,
+                              -1);
        uinput_device_event(uidev, EV_ABS, ABS_MT_SLOT, 1);
        uinput_device_event(uidev, EV_ABS, ABS_MT_TRACKING_ID, 1);
        uinput_device_event(uidev, EV_SYN, SYN_REPORT, 0);
@@ -2066,11 +2147,14 @@ libevdev_events(void)
 
        TCase *tc = tcase_create("event polling");
        tcase_add_test(tc, test_next_event);
+       tcase_add_test(tc, test_next_event_invalid_fd);
+       tcase_add_test(tc, test_next_event_blocking);
        tcase_add_test(tc, test_syn_dropped_event);
        tcase_add_test(tc, test_double_syn_dropped_event);
        tcase_add_test(tc, test_event_type_filtered);
        tcase_add_test(tc, test_event_code_filtered);
        tcase_add_test(tc, test_has_event_pending);
+       tcase_add_test(tc, test_has_event_pending_invalid_fd);
        suite_add_tcase(s, tc);
 
        tc = tcase_create("SYN_DROPPED deltas");
@@ -2112,4 +2196,3 @@ libevdev_events(void)
 
        return s;
 }
-
index 3ac41f10e6f9b66a46491212b8bceede49193b2d..77032069682645a1144e1369e626436e1f89049e 100644 (file)
@@ -262,7 +262,6 @@ START_TEST(test_input_props)
        rc = libevdev_new_from_fd(uinput_device_get_fd(uidev), &dev);
        ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc));
 
-
        for (i = 0; i < INPUT_PROP_CNT; i++) {
                if (i == INPUT_PROP_DIRECT || i == INPUT_PROP_BUTTONPAD)
                        ck_assert_int_eq(libevdev_has_property(dev, i), 1);
@@ -577,7 +576,6 @@ START_TEST(test_device_get_abs_info)
        uidev = uinput_device_new(TEST_DEVICE_NAME);
        ck_assert(uidev != NULL);
 
-
        abs.minimum = 0;
        abs.maximum = 1000;
        abs.fuzz = 1;
@@ -961,6 +959,44 @@ START_TEST(test_device_kernel_change_axis_invalid)
 }
 END_TEST
 
+START_TEST(test_device_kernel_set_abs_invalid_fd)
+{
+       struct uinput_device* uidev;
+       struct libevdev *dev;
+       struct input_absinfo abs[2];
+       struct input_absinfo a;
+       int rc;
+
+       libevdev_set_log_function(test_logfunc_ignore_error, NULL);
+
+       memset(abs, 0, sizeof(abs));
+       abs[0].value = ABS_X;
+       abs[0].maximum = 1000;
+
+       abs[1].value = ABS_Y;
+       abs[1].maximum = 1000;
+
+       dev = libevdev_new();
+       rc = libevdev_kernel_set_abs_info(dev, ABS_X, &a);
+       ck_assert_int_eq(rc, -EBADF);
+       libevdev_free(dev);
+
+       test_create_abs_device(&uidev, &dev,
+                              2, abs,
+                              EV_SYN,
+                              -1);
+
+       libevdev_change_fd(dev, -2);
+       rc = libevdev_kernel_set_abs_info(dev, ABS_X, &a);
+       ck_assert_int_eq(rc, -EBADF);
+
+       libevdev_set_log_function(test_logfunc_abort_on_error, NULL);
+
+       uinput_device_free(uidev);
+       libevdev_free(dev);
+}
+END_TEST
+
 START_TEST(test_led_valid)
 {
        struct uinput_device* uidev;
@@ -1153,6 +1189,7 @@ libevdev_has_event_test(void)
        tcase_add_test(tc, test_device_disable_bit_invalid);
        tcase_add_test(tc, test_device_kernel_change_axis);
        tcase_add_test(tc, test_device_kernel_change_axis_invalid);
+       tcase_add_test(tc, test_device_kernel_set_abs_invalid_fd);
        suite_add_tcase(s, tc);
 
        tc = tcase_create("led manipulation");
@@ -1163,4 +1200,3 @@ libevdev_has_event_test(void)
 
        return s;
 }
-
index 61fea4ba0ced5fbea26b88264e5b7960822835a7..f673a5890eca22f436becdad06f92e97617ed60b 100644 (file)
@@ -271,6 +271,79 @@ START_TEST(test_log_data)
 }
 END_TEST
 
+struct libevdev *devlogdata;
+static int dev_log_fn_called = 0;
+static void devlogfunc(const struct libevdev *dev,
+                   enum libevdev_log_priority priority,
+                   void *data,
+                   const char *file, int line, const char *func,
+                   const char *f, va_list args)
+{
+       ck_assert(dev == data);
+       dev_log_fn_called++;
+}
+
+START_TEST(test_device_log_init)
+{
+       struct libevdev *dev = NULL;
+       enum libevdev_log_priority old;
+
+       old = libevdev_get_log_priority();
+       libevdev_set_log_priority(LIBEVDEV_LOG_DEBUG);
+       libevdev_set_log_function(logfunc, logdata);
+
+       /* error for NULL device */
+       libevdev_set_device_log_function(NULL, NULL,
+                                        LIBEVDEV_LOG_ERROR, NULL);
+       ck_assert_int_eq(log_fn_called, 1);
+
+       /* error for NULL device */
+       libevdev_set_device_log_function(NULL, devlogfunc,
+                                        LIBEVDEV_LOG_ERROR, NULL);
+       ck_assert_int_eq(log_fn_called, 2);
+
+       log_fn_called = 0;
+
+       dev = libevdev_new();
+       ck_assert(dev != NULL);
+
+       libevdev_set_device_log_function(dev, NULL,
+                                        LIBEVDEV_LOG_ERROR, NULL);
+
+       /* libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, NULL) should
+          trigger a log message. */
+
+       /* expect global handler triggered */
+       libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, NULL);
+       ck_assert_int_eq(log_fn_called, 1);
+       ck_assert_int_eq(dev_log_fn_called, 0);
+
+       /* expect device handler triggered */
+       libevdev_set_device_log_function(dev, devlogfunc,
+                                        LIBEVDEV_LOG_ERROR, dev);
+       libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, NULL);
+       ck_assert_int_eq(log_fn_called, 1);
+       ck_assert_int_eq(dev_log_fn_called, 1);
+
+       /* device handler set, but priority filters. don't expect any log
+          handler to be called.
+          we don't have any log msgs > ERROR at the moment, so test it by
+          setting an invalid priority. */
+       libevdev_set_device_log_function(dev, devlogfunc,
+                                        LIBEVDEV_LOG_ERROR - 1, dev);
+       libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, NULL);
+       ck_assert_int_eq(log_fn_called, 1);
+       ck_assert_int_eq(dev_log_fn_called, 1);
+
+       libevdev_free(dev);
+
+       log_fn_called = 0;
+       libevdev_set_log_priority(old);
+       libevdev_set_log_function(test_logfunc_abort_on_error, NULL);
+
+}
+END_TEST
+
 START_TEST(test_device_init)
 {
        struct uinput_device* uidev;
@@ -362,6 +435,39 @@ START_TEST(test_device_grab)
 }
 END_TEST
 
+START_TEST(test_device_grab_invalid_fd)
+{
+       struct uinput_device* uidev;
+       struct libevdev *dev;
+       int rc;
+
+       libevdev_set_log_function(test_logfunc_ignore_error, NULL);
+
+       dev = libevdev_new();
+       rc = libevdev_grab(dev, 0);
+       ck_assert_int_eq(rc, -EBADF);
+       libevdev_free(dev);
+
+       test_create_device(&uidev, &dev,
+                          EV_SYN, SYN_REPORT,
+                          EV_REL, REL_X,
+                          EV_REL, REL_Y,
+                          EV_REL, REL_WHEEL,
+                          EV_KEY, BTN_LEFT,
+                          EV_KEY, BTN_MIDDLE,
+                          EV_KEY, BTN_RIGHT,
+                          -1);
+       libevdev_change_fd(dev, -2);
+       rc = libevdev_grab(dev, 0);
+       ck_assert_int_eq(rc, -EBADF);
+
+       libevdev_set_log_function(test_logfunc_abort_on_error, NULL);
+
+       uinput_device_free(uidev);
+       libevdev_free(dev);
+}
+END_TEST
+
 START_TEST(test_set_clock_id)
 {
        struct uinput_device* uidev;
@@ -392,6 +498,37 @@ START_TEST(test_set_clock_id)
 }
 END_TEST
 
+START_TEST(test_set_clock_id_invalid_fd)
+{
+       struct uinput_device* uidev;
+       struct libevdev *dev;
+       int rc;
+
+       libevdev_set_log_function(test_logfunc_ignore_error, NULL);
+
+       dev = libevdev_new();
+       rc = libevdev_set_clock_id(dev, CLOCK_MONOTONIC);
+       ck_assert_int_eq(rc, -EBADF);
+       libevdev_free(dev);
+
+       test_create_device(&uidev, &dev,
+                          EV_SYN, SYN_REPORT,
+                          EV_REL, REL_X,
+                          EV_REL, REL_Y,
+                          EV_REL, REL_WHEEL,
+                          EV_KEY, BTN_LEFT,
+                          EV_KEY, BTN_MIDDLE,
+                          EV_KEY, BTN_RIGHT,
+                          -1);
+       libevdev_change_fd(dev, -2);
+       rc = libevdev_set_clock_id(dev, CLOCK_MONOTONIC);
+       ck_assert_int_eq(rc, -EBADF);
+
+       uinput_device_free(uidev);
+       libevdev_free(dev);
+}
+END_TEST
+
 START_TEST(test_clock_id_events)
 {
        struct uinput_device* uidev;
@@ -477,6 +614,7 @@ libevdev_init_test(void)
        tcase_add_test(tc, test_log_set_get_priority);
        tcase_add_test(tc, test_log_default_priority);
        tcase_add_test(tc, test_log_data);
+       tcase_add_test(tc, test_device_log_init);
        suite_add_tcase(s, tc);
 
        tc = tcase_create("device fd init");
@@ -486,10 +624,12 @@ libevdev_init_test(void)
 
        tc = tcase_create("device grab");
        tcase_add_test(tc, test_device_grab);
+       tcase_add_test(tc, test_device_grab_invalid_fd);
        suite_add_tcase(s, tc);
 
        tc = tcase_create("clock id");
        tcase_add_test(tc, test_set_clock_id);
+       tcase_add_test(tc, test_set_clock_id_invalid_fd);
        tcase_add_test(tc, test_clock_id_events);
        suite_add_tcase(s, tc);
 
index 07fae53c2c60a736de6ddb00299bd3dac0af6697..536b2f18ddca8883d58f6a5ce4a22071f68a7df5 100644 (file)
@@ -3,8 +3,6 @@
    Memcheck:Param
    timer_create(evp)
    fun:timer_create@@GLIBC_2.3.3
-   fun:srunner_run
-   fun:main
 }
 {
    <ioctl_EVIOCGRAB_unaddressable_bytes>
index 8084fed086f216c14cc740df3784c270bc385809..c2a26459e06816a3066471921640afc04d5a9baf 100644 (file)
@@ -1,2 +1,4 @@
 libevdev-events
 touchpad-edge-detector
+mouse-dpi-tool
+libevdev-tweak-device
index 5d3600d9d576ccf5f75f588e9cbe21b6158b4b37..d699c5cb10f4d7c16673d572dc1323e571f21009 100644 (file)
@@ -1,5 +1,8 @@
 noinst_PROGRAMS = libevdev-events
-bin_PROGRAMS = touchpad-edge-detector
+bin_PROGRAMS = \
+              touchpad-edge-detector \
+              mouse-dpi-tool \
+              libevdev-tweak-device
 
 AM_CPPFLAGS = $(GCC_CFLAGS) -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/libevdev
 libevdev_ldadd = $(top_builddir)/libevdev/libevdev.la
@@ -10,3 +13,9 @@ libevdev_events_LDADD = $(libevdev_ldadd)
 touchpad_edge_detector_SOURCES = touchpad-edge-detector.c
 touchpad_edge_detector_LDADD = $(libevdev_ldadd)
 
+mouse_dpi_tool_SOURCES = mouse-dpi-tool.c
+mouse_dpi_tool_LDADD = $(libevdev_ldadd)
+
+libevdev_tweak_device_SOURCES = libevdev-tweak-device.c
+libevdev_tweak_device_LDADD = $(libevdev_ldadd)
+libevdev_tweak_device_MANS = libevdev-tweak-device.1
index 0711c78eefc66e25946ce16ddb2de88a43a80e93..3ce23f14697b2b93d5a5daa3336ad670672ec37d 100644 (file)
@@ -185,7 +185,7 @@ main(int argc, char **argv)
        } while (rc == LIBEVDEV_READ_STATUS_SYNC || rc == LIBEVDEV_READ_STATUS_SUCCESS || rc == -EAGAIN);
 
        if (rc != LIBEVDEV_READ_STATUS_SUCCESS && rc != -EAGAIN)
-               fprintf(stderr, "Failed to handle events: %s\n", strerror(rc));
+               fprintf(stderr, "Failed to handle events: %s\n", strerror(-rc));
 
        rc = 0;
 out:
diff --git a/tools/libevdev-tweak-device.c b/tools/libevdev-tweak-device.c
new file mode 100644 (file)
index 0000000..a051e08
--- /dev/null
@@ -0,0 +1,482 @@
+/*
+ * Copyright © 2014 Red Hat, Inc.
+ *
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <config.h>
+
+#include <getopt.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <linux/input.h>
+
+#include "libevdev.h"
+
+static void
+usage(void)
+{
+       printf("%s --abs <axis> [--min min] [--max max] [--res res] [--fuzz fuzz] [--flat flat] /dev/input/eventXYZ\n"
+              "\tChange the absinfo struct for the named axis\n"
+              "%s --resolution res[,yres] /dev/input/eventXYZ\n"
+              "\tChange the x/y resolution on the given device\n"
+              "%s --led <led> --on|--off /dev/input/eventXYZ\n"
+              "\tEnable or disable the named LED\n",
+              program_invocation_short_name,
+              program_invocation_short_name,
+              program_invocation_short_name);
+}
+
+enum mode {
+       MODE_NONE = 0,
+       MODE_ABS,
+       MODE_LED,
+       MODE_RESOLUTION,
+       MODE_HELP,
+};
+
+enum opts {
+       OPT_ABS = 1 << 0,
+       OPT_MIN = 1 << 1,
+       OPT_MAX = 1 << 2,
+       OPT_FUZZ = 1 << 3,
+       OPT_FLAT = 1 << 4,
+       OPT_RES = 1 << 5,
+       OPT_LED = 1 << 6,
+       OPT_ON = 1 << 7,
+       OPT_OFF = 1 << 8,
+       OPT_RESOLUTION = 1 << 9,
+       OPT_HELP = 1 << 10,
+};
+
+static bool
+parse_resolution_argument(const char *arg, int *xres, int *yres)
+{
+       int matched;
+
+       matched = sscanf(arg, "%d,%d", xres, yres);
+
+       switch(matched) {
+               case 2:
+                       break;
+               case 1:
+                       *yres = *xres;
+                       break;
+               default:
+                       return false;
+       }
+
+       return true;
+}
+
+static inline bool
+safe_atoi(const char *str, int *val)
+{
+        char *endptr;
+        long v;
+
+        v = strtol(str, &endptr, 10);
+        if (str == endptr)
+                return false;
+        if (*str != '\0' && *endptr != '\0')
+                return false;
+
+        if (v > INT_MAX || v < INT_MIN)
+                return false;
+
+        *val = v;
+        return true;
+}
+
+static int
+parse_event_code(int type, const char *str)
+{
+       int code;
+
+       code = libevdev_event_code_from_name(type, str);
+       if (code != -1)
+               return code;
+
+       if (safe_atoi(str, &code))
+               return code;
+
+       return -1;
+}
+
+static int
+parse_options_abs(int argc, char **argv, unsigned int *changes,
+                 int *axis, struct input_absinfo *absinfo)
+{
+       int rc = 1;
+       int c;
+       int option_index = 0;
+       static struct option opts[] = {
+               { "abs", 1, 0, OPT_ABS },
+               { "min", 1, 0, OPT_MIN },
+               { "max", 1, 0, OPT_MAX },
+               { "fuzz", 1, 0, OPT_FUZZ },
+               { "flat", 1, 0, OPT_FLAT },
+               { "res", 1, 0, OPT_RES },
+               { NULL, 0, 0, 0 },
+       };
+
+       if (argc < 2)
+               goto error;
+
+       optind = 1;
+       while (1) {
+               c = getopt_long(argc, argv, "h", opts, &option_index);
+               if (c == -1)
+                       break;
+
+               switch (c) {
+                       case OPT_ABS:
+                               *axis = parse_event_code(EV_ABS, optarg);
+                               if (*axis == -1)
+                                       goto error;
+                               break;
+                       case OPT_MIN:
+                               absinfo->minimum = atoi(optarg);
+                               break;
+                       case OPT_MAX:
+                               absinfo->maximum = atoi(optarg);
+                               break;
+                       case OPT_FUZZ:
+                               absinfo->fuzz = atoi(optarg);
+                               break;
+                       case OPT_FLAT:
+                               absinfo->flat = atoi(optarg);
+                               break;
+                       case OPT_RES:
+                               absinfo->resolution = atoi(optarg);
+                               break;
+                       default:
+                               goto error;
+               }
+               *changes |= c;
+       }
+       rc = 0;
+error:
+       return rc;
+}
+
+static int
+parse_options_led(int argc, char **argv, int *led, int *led_state)
+{
+       int rc = 1;
+       int c;
+       int option_index = 0;
+       static struct option opts[] = {
+               { "led", 1, 0, OPT_LED },
+               { "on", 0, 0, OPT_ON },
+               { "off", 0, 0, OPT_OFF },
+               { NULL, 0, 0, 0 },
+       };
+
+       if (argc < 2)
+               goto error;
+
+       optind = 1;
+       while (1) {
+               c = getopt_long(argc, argv, "h", opts, &option_index);
+               if (c == -1)
+                       break;
+
+               switch (c) {
+                       case OPT_LED:
+                               *led = parse_event_code(EV_LED, optarg);
+                               if (*led == -1)
+                                       goto error;
+                               break;
+                       case OPT_ON:
+                               if (*led_state != -1)
+                                       goto error;
+                               *led_state = 1;
+                               break;
+                       case OPT_OFF:
+                               if (*led_state != -1)
+                                       goto error;
+                               *led_state = 0;
+                               break;
+                       default:
+                               goto error;
+               }
+       }
+
+       rc = 0;
+error:
+       return rc;
+}
+
+static int
+parse_options_resolution(int argc, char **argv, int *xres, int *yres)
+{
+       int rc = 1;
+       int c;
+       int option_index = 0;
+       static struct option opts[] = {
+               { "resolution", 1, 0, OPT_RESOLUTION },
+               { NULL, 0, 0, 0 },
+       };
+
+       if (argc < 2)
+               goto error;
+
+       optind = 1;
+       while (1) {
+               c = getopt_long(argc, argv, "h", opts, &option_index);
+               if (c == -1)
+                       break;
+
+               switch (c) {
+                       case OPT_RESOLUTION:
+                               if (!parse_resolution_argument(optarg,
+                                                              xres, yres))
+                                       goto error;
+                               break;
+                       default:
+                               goto error;
+               }
+       }
+
+       rc = 0;
+error:
+       return rc;
+}
+
+static enum mode
+parse_options_mode(int argc, char **argv)
+{
+       int c;
+       int option_index = 0;
+       static const struct option opts[] = {
+               { "abs", 1, 0, OPT_ABS },
+               { "led", 1, 0, OPT_LED },
+               { "resolution", 1, 0, OPT_RESOLUTION },
+               { "help", 0, 0, OPT_HELP },
+               { NULL, 0, 0, 0 },
+       };
+       enum mode mode = MODE_NONE;
+
+       if (argc < 2)
+               return mode;
+
+       while (mode == MODE_NONE) {
+               c = getopt_long(argc, argv, "h", opts, &option_index);
+               if (c == -1)
+                       break;
+
+               switch (c) {
+                       case 'h':
+                       case OPT_HELP:
+                               mode = MODE_HELP;
+                               break;
+                       case OPT_ABS:
+                               mode = MODE_ABS;
+                               break;
+                       case OPT_LED:
+                               mode = MODE_LED;
+                               break;
+                       case OPT_RESOLUTION:
+                               mode = MODE_RESOLUTION;
+                               break;
+                       default:
+                               break;
+               }
+       }
+
+       if (optind >= argc && mode != MODE_HELP)
+               return MODE_NONE;
+
+       return mode;
+}
+
+static void
+set_abs(struct libevdev *dev, unsigned int changes,
+       unsigned int axis, struct input_absinfo *absinfo)
+{
+       int rc;
+       struct input_absinfo abs;
+       const struct input_absinfo *a;
+
+       if ((a = libevdev_get_abs_info(dev, axis)) == NULL) {
+               fprintf(stderr,
+                       "Device '%s' doesn't have axis %s\n",
+                       libevdev_get_name(dev),
+                       libevdev_event_code_get_name(EV_ABS, axis));
+               return;
+       }
+
+       abs = *a;
+       if (changes & OPT_MIN)
+               abs.minimum = absinfo->minimum;
+       if (changes & OPT_MAX)
+               abs.maximum = absinfo->maximum;
+       if (changes & OPT_FUZZ)
+               abs.fuzz = absinfo->fuzz;
+       if (changes & OPT_FLAT)
+               abs.flat = absinfo->flat;
+       if (changes & OPT_RES)
+               abs.resolution = absinfo->resolution;
+
+       rc = libevdev_kernel_set_abs_info(dev, axis, &abs);
+       if (rc != 0)
+               fprintf(stderr,
+                       "Failed to set absinfo %s: %s",
+                       libevdev_event_code_get_name(EV_ABS, axis),
+                       strerror(-rc));
+}
+
+static void
+set_led(struct libevdev *dev, unsigned int led, int led_state)
+{
+       int rc;
+       enum libevdev_led_value state =
+               led_state ? LIBEVDEV_LED_ON : LIBEVDEV_LED_OFF;
+
+       if (!libevdev_has_event_code(dev, EV_LED, led)) {
+               fprintf(stderr,
+                       "Device '%s' doesn't have %s\n",
+                       libevdev_get_name(dev),
+                       libevdev_event_code_get_name(EV_LED, led));
+               return;
+       }
+
+       rc = libevdev_kernel_set_led_value(dev, led, state);
+       if (rc != 0)
+               fprintf(stderr,
+                       "Failed to set LED %s: %s",
+                       libevdev_event_code_get_name(EV_LED, led),
+                       strerror(-rc));
+}
+
+static void
+set_resolution(struct libevdev *dev, int xres, int yres)
+{
+       struct input_absinfo abs;
+
+       abs.resolution = xres;
+       if (libevdev_has_event_code(dev, EV_ABS, ABS_X))
+               set_abs(dev, OPT_RES, ABS_X, &abs);
+       if (libevdev_has_event_code(dev, EV_ABS, ABS_MT_POSITION_X))
+               set_abs(dev, OPT_RES, ABS_MT_POSITION_X, &abs);
+
+       abs.resolution = yres;
+       if (libevdev_has_event_code(dev, EV_ABS, ABS_Y))
+               set_abs(dev, OPT_RES, ABS_Y, &abs);
+       if (libevdev_has_event_code(dev, EV_ABS, ABS_MT_POSITION_Y))
+               set_abs(dev, OPT_RES, ABS_MT_POSITION_Y, &abs);
+}
+
+int
+main(int argc, char **argv)
+{
+       struct libevdev *dev = NULL;
+       int fd = -1;
+       int rc = EXIT_FAILURE;
+       enum mode mode;
+       const char *path;
+       struct input_absinfo absinfo;
+       int axis = -1;
+       int led = -1;
+       int led_state = -1;
+       unsigned int changes = 0; /* bitmask of changes */
+       int xres = 0,
+           yres = 0;
+
+       mode = parse_options_mode(argc, argv);
+       switch (mode) {
+               case MODE_HELP:
+                       rc = EXIT_SUCCESS;
+                       /* fallthrough */
+               case MODE_NONE:
+                       usage();
+                       goto out;
+               case MODE_ABS:
+                       rc = parse_options_abs(argc, argv, &changes, &axis,
+                                              &absinfo);
+                       break;
+               case MODE_LED:
+                       rc = parse_options_led(argc, argv, &led, &led_state);
+                       break;
+               case MODE_RESOLUTION:
+                       rc = parse_options_resolution(argc, argv, &xres,
+                                                     &yres);
+                       break;
+               default:
+                       fprintf(stderr,
+                               "++?????++ Out of Cheese Error. Redo From Start.\n");
+                       goto out;
+       }
+
+       if (rc != EXIT_SUCCESS)
+               goto out;
+
+       if (optind >= argc) {
+               rc = EXIT_FAILURE;
+               usage();
+               goto out;
+       }
+
+       path = argv[optind];
+
+       fd = open(path, O_RDWR);
+       if (fd < 0) {
+               rc = EXIT_FAILURE;
+               perror("Failed to open device");
+               goto out;
+       }
+
+       rc = libevdev_new_from_fd(fd, &dev);
+       if (rc < 0) {
+               fprintf(stderr, "Failed to init libevdev (%s)\n", strerror(-rc));
+               goto out;
+       }
+
+       switch (mode) {
+               case MODE_ABS:
+                       set_abs(dev, changes, axis, &absinfo);
+                       break;
+               case MODE_LED:
+                       set_led(dev, led, led_state);
+                       break;
+               case MODE_RESOLUTION:
+                       set_resolution(dev, xres, yres);
+                       break;
+               default:
+                       break;
+       }
+
+out:
+       libevdev_free(dev);
+       if (fd != -1)
+               close(fd);
+
+       return rc;
+}
diff --git a/tools/mouse-dpi-tool.c b/tools/mouse-dpi-tool.c
new file mode 100644 (file)
index 0000000..7f0e7be
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ * Copyright © 2014 Red Hat, Inc.
+ *
+ * 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 Red Hat
+ * not be used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.  Red
+ * Hat makes no representations about the suitability of this software
+ * for any purpose.  It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL THE AUTHORS 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <libevdev/libevdev.h>
+#include <sys/signalfd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#define min(a, b) (((a) < (b)) ? (a) : (b))
+#define max(a, b) (((a) > (b)) ? (a) : (b))
+
+struct measurements {
+       int distance;
+       double frequency;
+       uint64_t us;
+};
+
+static int
+usage(void) {
+       printf("Usage: %s /dev/input/event0\n", program_invocation_short_name);
+       printf("\n");
+       printf("This tool reads relative events from the kernel and calculates\n"
+              "the distance covered and maximum frequency of the incoming events.\n"
+              "Some mouse devices provide dynamic frequencies, it is\n"
+              "recommended to measure multiple times to obtain the highest value.\n");
+       return 1;
+}
+
+static inline uint64_t
+tv2us(const struct timeval *tv)
+{
+       return tv->tv_sec * 1000000 + tv->tv_usec;
+}
+
+static inline double
+get_frequency(double last, double current)
+{
+       return 1000000.0/(current - last);
+}
+
+static int
+print_current_values(const struct measurements *m)
+{
+       static int progress = 0;
+       char status = 0;
+
+       switch (progress) {
+               case 0: status = '|'; break;
+               case 1: status = '/'; break;
+               case 2: status = '-'; break;
+               case 3: status = '\\'; break;
+               default:
+                       status = '?';
+                       break;
+       }
+
+       progress = (progress + 1) % 4;
+
+       printf("\rCovered distance in device units: %8d at frequency %3.1fHz    %c",
+              abs(m->distance), m->frequency, status);
+
+       return 0;
+}
+
+static int
+handle_event(struct measurements *m, const struct input_event *ev)
+{
+       if (ev->type == EV_SYN) {
+               const int idle_reset = 3000000; /* us */
+               uint64_t last_us = m->us;
+
+               m->us = tv2us(&ev->time);
+
+               /* reset after pause */
+               if (last_us + idle_reset < m->us) {
+                       m->frequency = 0.0;
+                       m->distance = 0;
+               } else {
+                       double freq = get_frequency(last_us, m->us);
+                       m->frequency = max(freq, m->frequency);
+                       return print_current_values(m);
+               }
+
+               return 0;
+       } else if (ev->type != EV_REL)
+               return 0;
+
+       switch(ev->code) {
+               case REL_X:
+                       m->distance += ev->value;
+                       break;
+       }
+
+       return 0;
+}
+
+static int
+mainloop(struct libevdev *dev, struct measurements *m) {
+       struct pollfd fds[2];
+       sigset_t mask;
+
+       fds[0].fd = libevdev_get_fd(dev);
+       fds[0].events = POLLIN;
+
+       sigemptyset(&mask);
+       sigaddset(&mask, SIGINT);
+       fds[1].fd = signalfd(-1, &mask, SFD_NONBLOCK);
+       fds[1].events = POLLIN;
+
+       sigprocmask(SIG_BLOCK, &mask, NULL);
+
+       while (poll(fds, 2, -1)) {
+               struct input_event ev;
+               int rc;
+
+               if (fds[1].revents)
+                       break;
+
+               do {
+                       rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);
+                       if (rc == LIBEVDEV_READ_STATUS_SYNC) {
+                               fprintf(stderr, "Error: cannot keep up\n");
+                               return 1;
+                       } else if (rc != -EAGAIN && rc < 0) {
+                               fprintf(stderr, "Error: %s\n", strerror(-rc));
+                               return 1;
+                       } else if (rc == LIBEVDEV_READ_STATUS_SUCCESS) {
+                               handle_event(m, &ev);
+                       }
+               } while (rc != -EAGAIN);
+       }
+
+       return 0;
+}
+
+static void
+print_summary(struct measurements *m)
+{
+       int res;
+
+       printf("Estimated sampling frequency: %dHz\n", (int)m->frequency);
+       printf("To calculate resolution, measure physical distance covered\n"
+              "and look up the matching resolution in the table below\n");
+
+       m->distance = abs(m->distance);
+
+       /* If the mouse has more than 2500dpi, the manufacturer usually
+          shows off on their website anyway */
+       for (res = 400; res <= 2500; res += 200) {
+               double inch = m->distance/(double)res;
+               printf("%8dmm   %8.2fin %8ddpi\n",
+                      (int)(inch * 25.4), inch, res);
+       }
+       printf("If your resolution is not in the list, calculate it with:\n"
+              "\tresolution=%d/inches, or\n"
+              "\tresolution=%d * 25.4/mm\n", m->distance, m->distance);
+}
+
+static inline const char*
+bustype(int bustype)
+{
+       const char *bus;
+
+       switch(bustype) {
+               case BUS_PCI: bus = "pci"; break;
+               case BUS_ISAPNP: bus = "isapnp"; break;
+               case BUS_USB: bus = "usb"; break;
+               case BUS_HIL: bus = "hil"; break;
+               case BUS_BLUETOOTH: bus = "bluetooth"; break;
+               case BUS_VIRTUAL: bus = "virtual"; break;
+               default: bus = "unknown bus type"; break;
+       }
+
+       return bus;
+}
+
+int
+main (int argc, char **argv) {
+       int rc;
+       int fd;
+       const char *path;
+       struct libevdev *dev;
+       struct measurements measurements = {0, 0, 0};
+
+       if (argc < 2)
+               return usage();
+
+       path = argv[1];
+       if (path[0] == '-')
+               return usage();
+
+       fd = open(path, O_RDONLY|O_NONBLOCK);
+       if (fd < 0) {
+               fprintf(stderr, "Error opening the device: %s\n", strerror(errno));
+               return 1;
+       }
+
+       rc = libevdev_new_from_fd(fd, &dev);
+       if (rc != 0) {
+               fprintf(stderr, "Error fetching the device info: %s\n", strerror(-rc));
+               return 1;
+       }
+
+       if (libevdev_grab(dev, LIBEVDEV_GRAB) != 0) {
+               fprintf(stderr, "Error: cannot grab the device, something else is grabbing it.\n");
+               fprintf(stderr, "Use 'fuser -v %s' to find processes with an open fd\n", path);
+               return 1;
+       }
+       libevdev_grab(dev, LIBEVDEV_UNGRAB);
+
+       printf("Mouse %s on %s\n", libevdev_get_name(dev), path);
+       printf("Move the device 250mm/10in or more along the x-axis.\n");
+       printf("Pause 3 seconds before movement to reset, Ctrl+C to exit.\n");
+       setbuf(stdout, NULL);
+
+       rc = mainloop(dev, &measurements);
+
+       printf("\n");
+
+       print_summary(&measurements);
+
+       printf("\n");
+       printf("Entry for hwdb match (replace XXX with the resolution in DPI):\n"
+              "mouse:%s:v%04xp%04x:name:%s:\n"
+              " MOUSE_DPI=XXX@%d\n",
+              bustype(libevdev_get_id_bustype(dev)),
+              libevdev_get_id_vendor(dev),
+              libevdev_get_id_product(dev),
+              libevdev_get_name(dev),
+              (int)measurements.frequency);
+
+       libevdev_free(dev);
+       close(fd);
+
+       return rc;
+}
index b857934d9d670759990825f2254b0a64c43a2357..ca34414d728d36ca1e42776642ff975fa8fcdb80 100644 (file)
@@ -30,6 +30,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <limits.h>
+#include <math.h>
 #include <poll.h>
 #include <signal.h>
 #include <stdint.h>
 
 static int
 usage(void) {
-       printf("Usage: %s /dev/input/event0\n", program_invocation_short_name);
+       printf("Usage: %s 12x34 /dev/input/event0\n", program_invocation_short_name);
        printf("\n");
        printf("This tool reads the touchpad events from the kernel and calculates\n "
-              "the minimum and maximum for the x and y coordinates, respectively.\n");
+              "the minimum and maximum for the x and y coordinates, respectively.\n"
+              "The first argument is the physical size of the touchpad in mm.\n");
        return 1;
 }
 
@@ -54,6 +56,10 @@ struct dimensions {
        int top, bottom, left, right;
 };
 
+struct size {
+       int w, h;
+};
+
 static int
 print_current_values(const struct dimensions *d)
 {
@@ -136,17 +142,113 @@ mainloop(struct libevdev *dev, struct dimensions *dim) {
        return 0;
 }
 
+static inline void
+pid_vid_matchstr(struct libevdev *dev, char *match, size_t sz)
+{
+       snprintf(match, sz, "input:b%04Xv%04Xp%04X",
+               libevdev_get_id_bustype(dev),
+               libevdev_get_id_vendor(dev),
+               libevdev_get_id_product(dev));
+}
+
+static inline void
+dmi_matchstr(struct libevdev *dev, char *match, size_t sz)
+{
+       char modalias[PATH_MAX];
+       FILE *fp;
+
+       fp = fopen("/sys/class/dmi/id/modalias", "r");
+       if (!fp || fgets(modalias, sizeof(modalias), fp) == NULL) {
+               sprintf(match, "ERROR READING DMI MODALIAS");
+               if (fp)
+                       fclose(fp);
+               return;
+       }
+
+       fclose(fp);
+
+       modalias[strlen(modalias) - 1] = '\0'; /* drop \n */
+       snprintf(match, sz, "name:%s:%s", libevdev_get_name(dev), modalias);
+
+       return;
+}
+
+static void
+print_udev_override_rule(struct libevdev *dev,
+                        const struct dimensions *dim,
+                        const struct size *size) {
+       const struct input_absinfo *x, *y;
+       char match[PATH_MAX];
+       int w, h;
+       int xres, yres;
+
+       x = libevdev_get_abs_info(dev, ABS_X);
+       y = libevdev_get_abs_info(dev, ABS_Y);
+       w = dim->right - dim->left;
+       h = dim->bottom - dim->top;
+       xres = round((double)w/size->w);
+       yres = round((double)h/size->h);
+
+       if (x->resolution && y->resolution) {
+               printf("Touchpad size as listed by the kernel: %dx%dmm\n",
+                      w/x->resolution, h/y->resolution);
+       } else {
+               printf("Touchpad has no resolution, size unknown\n");
+       }
+
+       printf("User-specified touchpad size: %dx%dmm\n", size->w, size->h);
+       printf("Calculated ranges: %d/%d\n", w, h);
+       printf("\n");
+       printf("Suggested udev rule:\n");
+
+       switch(libevdev_get_id_bustype(dev)) {
+       case BUS_USB:
+       case BUS_BLUETOOTH:
+               pid_vid_matchstr(dev, match, sizeof(match));
+               break;
+       default:
+               dmi_matchstr(dev, match, sizeof(match));
+               break;
+       }
+
+       printf("# <Laptop model description goes here>\n"
+              "evdev:%s*\n"
+              " EVDEV_ABS_00=%d:%d:%d\n"
+              " EVDEV_ABS_01=%d:%d:%d\n",
+              match,
+              dim->left, dim->right, xres,
+              dim->top, dim->bottom, yres);
+       if (libevdev_has_event_code(dev, EV_ABS, ABS_MT_POSITION_X))
+               printf(" EVDEV_ABS_35=%d:%d:%d\n"
+                      " EVDEV_ABS_36=%d:%d:%d\n",
+                      dim->left, dim->right, xres,
+                      dim->top, dim->bottom, yres);
+}
+
 int main (int argc, char **argv) {
        int rc;
        int fd;
        const char *path;
        struct libevdev *dev;
        struct dimensions dim;
+       struct size size;
+
+       if (argc < 3)
+               return usage();
 
-       if (argc < 2)
+       if (sscanf(argv[1], "%dx%d", &size.w, &size.h) != 2 ||
+           size.w <= 0 || size.h <= 0)
                return usage();
 
-       path = argv[1];
+       if (size.w < 30 || size.h < 30) {
+               fprintf(stderr,
+                       "%dx%dmm is too small for a touchpad.\n"
+                       "Please specify the touchpad size in mm.\n",
+                       size.w, size.h);
+               return 1;
+       }
+
+       path = argv[2];
        if (path[0] == '-')
                return usage();
 
@@ -169,6 +271,13 @@ int main (int argc, char **argv) {
        }
        libevdev_grab(dev, LIBEVDEV_UNGRAB);
 
+       if (!libevdev_has_event_code(dev, EV_ABS, ABS_X) ||
+           !libevdev_has_event_code(dev, EV_ABS, ABS_Y)) {
+               fprintf(stderr, "Error: this device does not have abs axes\n");
+               rc = EXIT_FAILURE;
+               goto out;
+       }
+
        dim.left = INT_MAX;
        dim.right = INT_MIN;
        dim.top = INT_MAX;
@@ -185,12 +294,13 @@ int main (int argc, char **argv) {
        setbuf(stdout, NULL);
 
        rc = mainloop(dev, &dim);
+       printf("\n\n");
 
-       printf("\n");
+       print_udev_override_rule(dev, &dim, &size);
 
+out:
        libevdev_free(dev);
        close(fd);
 
        return rc;
 }
-