From 728b51253949bc0e5265c9335ed970dcdcb2774f Mon Sep 17 00:00:00 2001 From: JengHyun Kang Date: Tue, 22 Nov 2016 18:31:47 +0900 Subject: [PATCH] libevdev 1.5.4 --- .gitignore | 3 + configure.ac | 43 +- doc/libevdev.doxygen.in | 1837 +---------------------------- include/linux/input-event-codes.h | 804 +++++++++++++ include/linux/input.h | 824 ++----------- include/linux/uinput.h | 231 ++++ libevdev/Makefile.am | 7 +- libevdev/libevdev-int.h | 65 +- libevdev/libevdev-names.c | 20 + libevdev/libevdev-uinput-int.h | 1 - libevdev/libevdev-uinput.c | 191 ++- libevdev/libevdev-uinput.h | 143 +-- libevdev/libevdev-util.h | 1 - libevdev/libevdev.c | 142 ++- libevdev/libevdev.h | 498 +++++--- libevdev/libevdev.sym | 10 + libevdev/make-event-names.py | 23 +- m4/attributes.m4 | 17 +- packaging/libevdev.spec | 4 +- test/Makefile.am | 79 +- test/test-common-uinput.c | 2 +- test/test-common-uinput.h | 1 - test/test-common.c | 20 +- test/test-common.h | 17 +- test/test-event-codes.c | 148 ++- test/test-event-names.c | 1 - test/test-int-queue.c | 1 - test/test-kernel.c | 4 +- test/test-libevdev-events.c | 111 +- test/test-libevdev-has-event.c | 42 +- test/test-libevdev-init.c | 140 +++ test/valgrind.suppressions | 2 - tools/.gitignore | 2 + tools/Makefile.am | 11 +- tools/libevdev-events.c | 2 +- tools/libevdev-tweak-device.c | 482 ++++++++ tools/mouse-dpi-tool.c | 268 +++++ tools/touchpad-edge-detector.c | 122 +- 38 files changed, 3209 insertions(+), 3110 deletions(-) create mode 100644 include/linux/input-event-codes.h create mode 100644 include/linux/uinput.h create mode 100644 tools/libevdev-tweak-device.c create mode 100644 tools/mouse-dpi-tool.c diff --git a/.gitignore b/.gitignore index 957e4c0..9fd134f 100644 --- a/.gitignore +++ b/.gitignore @@ -68,3 +68,6 @@ texinfo.tex .vimdir ylwrap # Application Specific Files +*.trs +*.log +*.sig diff --git a/configure.ac b/configure.ac index dc17109..ee68614 100644 --- a/configure.ac +++ b/configure.ac @@ -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} ]) diff --git a/doc/libevdev.doxygen.in b/doc/libevdev.doxygen.in index 853c47d..d64efa9 100644 --- a/doc/libevdev.doxygen.in +++ b/doc/libevdev.doxygen.in @@ -1,1854 +1,19 @@ -# 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 , where is the value of -# the FILE_VERSION_FILTER tag, and 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 , where -# is the value of the INPUT_FILTER tag, and 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 -# -# Qt Help Project / Custom Filters. - -QHP_CUST_FILTER_ATTRS = - -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this -# project's -# filter section matches. -# -# Qt Help Project / Filter Attributes. - -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 index 0000000..49f75c8 --- /dev/null +++ b/include/linux/input-event-codes.h @@ -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 + * + * 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 diff --git a/include/linux/input.h b/include/linux/input.h index e37293b..fbc968f 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -14,6 +14,7 @@ #include #include +#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 index 0000000..434f02d --- /dev/null +++ b/include/linux/uinput.h @@ -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 + * + * Changes/Revisions: + * 0.5 08/13/2015 (David Herrmann & + * Benjamin Tissoires ) + * - add UI_DEV_SETUP ioctl + * - add UI_ABS_SETUP ioctl + * - add UI_GET_VERSION ioctl + * 0.4 01/09/2014 (Benjamin Tissoires ) + * - add UI_GET_SYSNAME ioctl + * 0.3 24/05/2006 (Anssi Hannula ) + * - update ff support for the changes in kernel interface + * - add UINPUT_VERSION + * 0.2 16/10/2004 (Micah Dowty ) + * - added force feedback support + * - added UI_SET_PHYS + * 0.1 20/06/2002 + * - first public version + */ +#ifndef __UINPUT_H_ +#define __UINPUT_H_ + +#include +#include + +#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_ */ diff --git a/libevdev/Makefile.am b/libevdev/Makefile.am index c83a225..512cdef 100644 --- a/libevdev/Makefile.am +++ b/libevdev/Makefile.am @@ -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 diff --git a/libevdev/libevdev-int.h b/libevdev/libevdev-int.h index f587e76..e1c7ec5 100644 --- a/libevdev/libevdev-int.h +++ b/libevdev/libevdev-int.h @@ -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 - diff --git a/libevdev/libevdev-names.c b/libevdev/libevdev-names.c index 10669a3..ad318de 100644 --- a/libevdev/libevdev-names.c +++ b/libevdev/libevdev-names.c @@ -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; +} diff --git a/libevdev/libevdev-uinput-int.h b/libevdev/libevdev-uinput-int.h index fbc1c29..22d1684 100644 --- a/libevdev/libevdev-uinput-int.h +++ b/libevdev/libevdev-uinput-int.h @@ -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? */ diff --git a/libevdev/libevdev-uinput.c b/libevdev/libevdev-uinput.c index f176a00..893d169 100644 --- a/libevdev/libevdev-uinput.c +++ b/libevdev/libevdev-uinput.c @@ -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); diff --git a/libevdev/libevdev-uinput.h b/libevdev/libevdev-uinput.h index f5b8df4..0cf33a9 100644 --- a/libevdev/libevdev-uinput.h +++ b/libevdev/libevdev-uinput.h @@ -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 diff --git a/libevdev/libevdev-util.h b/libevdev/libevdev-util.h index 31c1a14..c6e1197 100644 --- a/libevdev/libevdev-util.h +++ b/libevdev/libevdev-util.h @@ -45,7 +45,6 @@ _a > _b ? _a : _b; \ }) - static inline bool startswith(const char *str, size_t len, const char *prefix, size_t plen) { diff --git a/libevdev/libevdev.c b/libevdev/libevdev.c index a316831..43a095c 100644 --- a/libevdev/libevdev.c +++ b/libevdev/libevdev.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -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; diff --git a/libevdev/libevdev.h b/libevdev/libevdev.h index 6c03cce..3edc3ae 100644 --- a/libevdev/libevdev.h +++ b/libevdev/libevdev.h @@ -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 _libevdev_* 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 struct * libevdev 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)) diff --git a/libevdev/libevdev.sym b/libevdev/libevdev.sym index ef4f06b..374712f 100644 --- a/libevdev/libevdev.sym +++ b/libevdev/libevdev.sym @@ -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; diff --git a/libevdev/make-event-names.py b/libevdev/make-event-names.py index 149f093..b3c2acf 100755 --- a/libevdev/make-event-names.py +++ b/libevdev/make-event-names.py @@ -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 | %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) diff --git a/m4/attributes.m4 b/m4/attributes.m4 index aa53ef2..5fbd43d 100644 --- a/m4/attributes.m4 +++ b/m4/attributes.m4 @@ -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], diff --git a/packaging/libevdev.spec b/packaging/libevdev.spec index 541b0f2..cf3e55c 100644 --- a/packaging/libevdev.spec +++ b/packaging/libevdev.spec @@ -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}/* diff --git a/test/Makefile.am b/test/Makefile.am index 7b195fb..e06aa4b 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -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 diff --git a/test/test-common-uinput.c b/test/test-common-uinput.c index 617b8e2..48200b6 100644 --- a/test/test-common-uinput.c +++ b/test/test-common-uinput.c @@ -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) diff --git a/test/test-common-uinput.h b/test/test-common-uinput.h index 6273a6d..2941134 100644 --- a/test/test-common-uinput.h +++ b/test/test-common-uinput.h @@ -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); diff --git a/test/test-common.c b/test/test-common.c index 6449d46..339b278 100644 --- a/test/test-common.c +++ b/test/test-common.c @@ -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; } diff --git a/test/test-common.h b/test/test-common.h index d7a33d0..47ad476 100644 --- a/test/test-common.h +++ b/test/test-common.h @@ -32,15 +32,14 @@ #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, diff --git a/test/test-event-codes.c b/test/test-event-codes.c index 3a57973..b64940e 100644 --- a/test/test-event-codes.c +++ b/test/test-event-codes.c @@ -21,82 +21,113 @@ */ #include -#include #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; } diff --git a/test/test-event-names.c b/test/test-event-names.c index 8d7e6d6..10a59ea 100644 --- a/test/test-event-names.c +++ b/test/test-event-names.c @@ -298,4 +298,3 @@ event_name_suite(void) return s; } - diff --git a/test/test-int-queue.c b/test/test-int-queue.c index d45fee0..501dc08 100644 --- a/test/test-int-queue.c +++ b/test/test-int-queue.c @@ -357,4 +357,3 @@ queue_suite(void) return s; } - diff --git a/test/test-kernel.c b/test/test-kernel.c index f3bc7e0..6fba605 100644 --- a/test/test-kernel.c +++ b/test/test-kernel.c @@ -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; } diff --git a/test/test-libevdev-events.c b/test/test-libevdev-events.c index 6ef0bf9..dd2face 100644 --- a/test/test-libevdev-events.c +++ b/test/test-libevdev-events.c @@ -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; } - diff --git a/test/test-libevdev-has-event.c b/test/test-libevdev-has-event.c index 3ac41f1..7703206 100644 --- a/test/test-libevdev-has-event.c +++ b/test/test-libevdev-has-event.c @@ -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; } - diff --git a/test/test-libevdev-init.c b/test/test-libevdev-init.c index 61fea4b..f673a58 100644 --- a/test/test-libevdev-init.c +++ b/test/test-libevdev-init.c @@ -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); diff --git a/test/valgrind.suppressions b/test/valgrind.suppressions index 07fae53..536b2f1 100644 --- a/test/valgrind.suppressions +++ b/test/valgrind.suppressions @@ -3,8 +3,6 @@ Memcheck:Param timer_create(evp) fun:timer_create@@GLIBC_2.3.3 - fun:srunner_run - fun:main } { diff --git a/tools/.gitignore b/tools/.gitignore index 8084fed..c2a2645 100644 --- a/tools/.gitignore +++ b/tools/.gitignore @@ -1,2 +1,4 @@ libevdev-events touchpad-edge-detector +mouse-dpi-tool +libevdev-tweak-device diff --git a/tools/Makefile.am b/tools/Makefile.am index 5d3600d..d699c5c 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -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 diff --git a/tools/libevdev-events.c b/tools/libevdev-events.c index 0711c78..3ce23f1 100644 --- a/tools/libevdev-events.c +++ b/tools/libevdev-events.c @@ -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 index 0000000..a051e08 --- /dev/null +++ b/tools/libevdev-tweak-device.c @@ -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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libevdev.h" + +static void +usage(void) +{ + printf("%s --abs [--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 --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 index 0000000..7f0e7be --- /dev/null +++ b/tools/mouse-dpi-tool.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +} diff --git a/tools/touchpad-edge-detector.c b/tools/touchpad-edge-detector.c index b857934..ca34414 100644 --- a/tools/touchpad-edge-detector.c +++ b/tools/touchpad-edge-detector.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -43,10 +44,11 @@ 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("# \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; } - -- 2.34.1