mirror of
https://gitlab.freedesktop.org/libevdev/libevdev.git
synced 2026-01-04 00:20:15 +01:00
libevdev is a library to handle evdev devices
Two main goals of this library: - 'transparently' handle SYN_DROPPED events - avoid errors in ioctl handling by providing a simpler interface. Keeps a cached copy of the device for quick querying. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
commit
a3255d3ec7
15 changed files with 2434 additions and 0 deletions
45
.gitignore
vendored
Normal file
45
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
aclocal.m4
|
||||
autom4te.cache/
|
||||
autoscan.log
|
||||
ChangeLog
|
||||
compile
|
||||
config.guess
|
||||
config.h
|
||||
config.h.in
|
||||
config.log
|
||||
config-ml.in
|
||||
config.py
|
||||
config.status
|
||||
config.status.lineno
|
||||
config.sub
|
||||
configure
|
||||
configure.scan
|
||||
depcomp
|
||||
.deps/
|
||||
INSTALL
|
||||
install-sh
|
||||
.libs/
|
||||
libtool
|
||||
libtool.m4
|
||||
ltmain.sh
|
||||
lt~obsolete.m4
|
||||
ltoptions.m4
|
||||
ltsugar.m4
|
||||
ltversion.m4
|
||||
Makefile
|
||||
Makefile.in
|
||||
mdate-sh
|
||||
missing
|
||||
mkinstalldirs
|
||||
*.pc
|
||||
py-compile
|
||||
stamp-h?
|
||||
symlink-tree
|
||||
texinfo.tex
|
||||
ylwrap
|
||||
*.la
|
||||
*.lo
|
||||
*.o
|
||||
*~
|
||||
*.swp
|
||||
.vimdir
|
||||
19
COPYING
Normal file
19
COPYING
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
Copyright © 2013 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.
|
||||
6
Makefile.am
Normal file
6
Makefile.am
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
SUBDIRS = libevdev test
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = libevdev.pc
|
||||
|
||||
EXTRA_DIST = libevdev.pc.in
|
||||
33
README.md
Normal file
33
README.md
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
libevemu - wrapper library for evdev input devices
|
||||
==================================================
|
||||
|
||||
libevdevdev is a wrapper library for evdev devices. it moves the common
|
||||
tasks when dealing with evdev devices into a library and provides a library
|
||||
interface to the callers, thus avoiding erroneous ioctls, etc.
|
||||
|
||||
http://github.com/whot/libevdev
|
||||
|
||||
**libevdev is currently in early stages of development. Use at your own risk**
|
||||
|
||||
Device capabilities
|
||||
-------------------
|
||||
libevdev provides interfaces to query a device's capabilities. These
|
||||
interfaces are type-safe (as opposed to the ioctl bits) and protect against
|
||||
invalid codes, etc.
|
||||
|
||||
SYN_DROPPED handling
|
||||
--------------------
|
||||
SYN_DROPPED is sent by the kernel if userspace cannot keep up with the
|
||||
reporting rate of the device. Once the kernel's buffer is full, it will
|
||||
issue a SYN_DROPPED event signalling dropped event. The userspace process
|
||||
must re-sync the device.
|
||||
|
||||
libevdevdev semi-transparently handles SYN_DROPPED events, providing an
|
||||
interface to the caller to sync up device state without having to manually
|
||||
compare bitfields. Instead, libevdev sends the 'missing' events to the
|
||||
caller, allowing it to use the same event processing paths as it would
|
||||
otherwise.
|
||||
|
||||
Changing devices
|
||||
----------------
|
||||
libevdev provides interfaces to **modify** the kernel device.
|
||||
47
configure.ac
Normal file
47
configure.ac
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
AC_PREREQ([2.64])
|
||||
|
||||
AC_INIT([libevdev],
|
||||
[0.1],
|
||||
[],
|
||||
[libevdev],
|
||||
[])
|
||||
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz])
|
||||
|
||||
# Before making a release, the LIBEVDEV_LT_VERSION string should be
|
||||
# modified.
|
||||
# The string is of the form C:R:A.
|
||||
# - If interfaces have been changed or added, but binary compatibility has
|
||||
# been preserved, change to C+1:0:A+1
|
||||
# - 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=1:0:0
|
||||
AC_SUBST(LIBEVDEV_LT_VERSION)
|
||||
|
||||
|
||||
AM_SILENT_RULES([yes])
|
||||
|
||||
# Check for programs
|
||||
AC_PROG_CC
|
||||
|
||||
# Initialize libtool
|
||||
LT_PREREQ([2.2])
|
||||
LT_INIT
|
||||
|
||||
PKG_PROG_PKG_CONFIG()
|
||||
PKG_CHECK_MODULES(FFI, [libffi])
|
||||
|
||||
if test "x$GCC" = "xyes"; then
|
||||
GCC_CFLAGS="-Wall -Wextra -Wno-unused-parameter -g -Wstrict-prototypes -Wmissing-prototypes -fvisibility=hidden"
|
||||
fi
|
||||
AC_SUBST(GCC_CFLAGS)
|
||||
|
||||
AC_CONFIG_FILES([Makefile
|
||||
libevdev/Makefile
|
||||
test/Makefile
|
||||
libevdev.pc])
|
||||
AC_OUTPUT
|
||||
10
libevdev.pc.in
Normal file
10
libevdev.pc.in
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: evdev_read
|
||||
Description: Handler library for evdev events
|
||||
Version: @EVDEV_READ_VERSION@
|
||||
Cflags: -I${includedir}/libevdev-1.0/
|
||||
Libs: -L${libdir} -levdev
|
||||
11
libevdev/Makefile.am
Normal file
11
libevdev/Makefile.am
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
lib_LTLIBRARIES=libevdev.la
|
||||
|
||||
libevdev_la_SOURCES = \
|
||||
libevdev.h \
|
||||
libevdev-int.h \
|
||||
libevdev.c
|
||||
|
||||
libevdev_la_LDFLAGS = -version-info $(LIBEVDEV_LT_VERSION) -export-symbols-regex '^libevdev_'
|
||||
|
||||
libevdevincludedir = $(includedir)/libevdev-1.0/libevdev
|
||||
libevdevinclude_HEADERS = libevdev.h
|
||||
66
libevdev/libevdev-int.h
Normal file
66
libevdev/libevdev-int.h
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright © 2013 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.
|
||||
*/
|
||||
|
||||
#ifndef libevdev_INT_H
|
||||
#define libevdev_INT_H
|
||||
|
||||
#include <config.h>
|
||||
#include "libevdev.h"
|
||||
|
||||
#define LONG_BITS (sizeof(long) * 8)
|
||||
#define NLONGS(x) (((x) + LONG_BITS - 1) / LONG_BITS)
|
||||
#define ARRAY_LENGTH(a) (sizeof(a) / (sizeof((a)[0])))
|
||||
#define MAX_NAME 256
|
||||
#define MAX_SLOTS 32
|
||||
#define ABS_MT_MIN ABS_MT_SLOT
|
||||
#define ABS_MT_MAX ABS_MT_TOOL_Y
|
||||
#define ABS_MT_CNT (ABS_MT_MAX - ABS_MT_MIN + 1)
|
||||
|
||||
struct libevdev {
|
||||
int fd;
|
||||
libevdev_callback_proc callback;
|
||||
libevdev_callback_proc sync_callback;
|
||||
void *userdata;
|
||||
|
||||
char name[MAX_NAME];
|
||||
struct input_id ids;
|
||||
unsigned long bits[NLONGS(EV_CNT)];
|
||||
unsigned long props[NLONGS(INPUT_PROP_CNT)];
|
||||
unsigned long key_bits[NLONGS(KEY_CNT)];
|
||||
unsigned long rel_bits[NLONGS(REL_CNT)];
|
||||
unsigned long abs_bits[NLONGS(ABS_CNT)];
|
||||
unsigned long led_bits[NLONGS(LED_CNT)];
|
||||
unsigned long key_values[NLONGS(KEY_CNT)];
|
||||
struct input_absinfo abs_info[ABS_CNT];
|
||||
unsigned int mt_slot_vals[MAX_SLOTS][ABS_MT_CNT];
|
||||
int num_slots; /**< valid slots in mt_slot_vals */
|
||||
|
||||
int need_sync;
|
||||
int grabbed;
|
||||
|
||||
struct input_event *queue;
|
||||
size_t queue_size; /**< size of queue in elements */
|
||||
size_t queue_next; /**< next event index */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
790
libevdev/libevdev.c
Normal file
790
libevdev/libevdev.c
Normal file
|
|
@ -0,0 +1,790 @@
|
|||
/*
|
||||
* Copyright © 2013 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.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "libevdev.h"
|
||||
#include "libevdev-int.h"
|
||||
|
||||
#define MAXEVENTS 64
|
||||
|
||||
static inline int
|
||||
bit_is_set(const unsigned long *array, int bit)
|
||||
{
|
||||
return !!(array[bit / LONG_BITS] & (1LL << (bit % LONG_BITS)));
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_bit(unsigned long *array, int bit)
|
||||
{
|
||||
array[bit / LONG_BITS] |= (1LL << (bit % LONG_BITS));
|
||||
}
|
||||
|
||||
static inline void
|
||||
clear_bit(unsigned long *array, int bit)
|
||||
{
|
||||
array[bit / LONG_BITS] &= ~(1LL << (bit % LONG_BITS));
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_bit_state(unsigned long *array, int bit, int state)
|
||||
{
|
||||
if (state)
|
||||
set_bit(array, bit);
|
||||
else
|
||||
clear_bit(array, bit);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
type_to_mask_const(const struct libevdev *dev, unsigned int type, const unsigned long **mask)
|
||||
{
|
||||
unsigned int max;
|
||||
|
||||
switch(type) {
|
||||
case EV_ABS:
|
||||
*mask = dev->abs_bits;
|
||||
max = ABS_MAX;
|
||||
break;
|
||||
case EV_REL:
|
||||
*mask = dev->rel_bits;
|
||||
max = REL_MAX;
|
||||
break;
|
||||
case EV_KEY:
|
||||
*mask = dev->key_bits;
|
||||
max = KEY_MAX;
|
||||
break;
|
||||
case EV_LED:
|
||||
*mask = dev->led_bits;
|
||||
max = LED_MAX;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
type_to_mask(struct libevdev *dev, unsigned int type, unsigned long **mask)
|
||||
{
|
||||
unsigned int max;
|
||||
|
||||
switch(type) {
|
||||
case EV_ABS:
|
||||
*mask = dev->abs_bits;
|
||||
max = ABS_MAX;
|
||||
break;
|
||||
case EV_REL:
|
||||
*mask = dev->rel_bits;
|
||||
max = REL_MAX;
|
||||
break;
|
||||
case EV_KEY:
|
||||
*mask = dev->key_bits;
|
||||
max = KEY_MAX;
|
||||
break;
|
||||
case EV_LED:
|
||||
*mask = dev->led_bits;
|
||||
max = LED_MAX;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
static int
|
||||
init_event_queue(struct libevdev *dev)
|
||||
{
|
||||
/* FIXME: count the number of axes, keys, etc. to get a better idea at how many events per
|
||||
EV_SYN we could possibly get. Then multiply that by the actual buffer size we care about */
|
||||
|
||||
const int QUEUE_SIZE = 256;
|
||||
|
||||
dev->queue = calloc(QUEUE_SIZE, sizeof(struct input_event));
|
||||
if (!dev->queue)
|
||||
return -ENOSPC;
|
||||
|
||||
dev->queue_size = QUEUE_SIZE;
|
||||
dev->queue_next = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct libevdev*
|
||||
libevdev_new(int fd)
|
||||
{
|
||||
struct libevdev *dev;
|
||||
|
||||
dev = calloc(1, sizeof(*dev));
|
||||
dev->num_slots = -1;
|
||||
|
||||
if (fd >= 0)
|
||||
libevdev_set_fd(dev, fd);
|
||||
dev->fd = fd;
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
void
|
||||
libevdev_free(struct libevdev *dev)
|
||||
{
|
||||
free(dev);
|
||||
}
|
||||
|
||||
int
|
||||
libevdev_change_fd(struct libevdev *dev, int fd)
|
||||
{
|
||||
if (dev->fd == -1)
|
||||
return -1;
|
||||
dev->fd = fd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
libevdev_set_fd(struct libevdev* dev, int fd)
|
||||
{
|
||||
int rc;
|
||||
int i;
|
||||
|
||||
if (dev->fd == -1) {
|
||||
libevdev_callback_proc cb, scb;
|
||||
void *userdata;
|
||||
|
||||
/* these may be set before set_fd */
|
||||
cb = dev->callback;
|
||||
scb = dev->sync_callback;
|
||||
userdata = dev->userdata;
|
||||
|
||||
memset(dev, 0, sizeof(*dev));
|
||||
|
||||
dev->fd = -1;
|
||||
dev->callback = cb;
|
||||
dev->sync_callback = scb;
|
||||
dev->userdata = userdata;
|
||||
}
|
||||
|
||||
rc = ioctl(fd, EVIOCGBIT(0, sizeof(dev->bits)), dev->bits);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
rc = ioctl(fd, EVIOCGNAME(sizeof(dev->name) - 1), dev->name);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
rc = ioctl(fd, EVIOCGID, &dev->ids);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
rc = ioctl(fd, EVIOCGPROP(sizeof(dev->props)), dev->props);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
rc = ioctl(fd, EVIOCGBIT(EV_REL, sizeof(dev->rel_bits)), dev->rel_bits);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
rc = ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(dev->abs_bits)), dev->abs_bits);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
rc = ioctl(fd, EVIOCGBIT(EV_LED, sizeof(dev->led_bits)), dev->led_bits);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
rc = ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(dev->key_bits)), dev->key_bits);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
for (i = ABS_X; i <= ABS_MAX; i++) {
|
||||
if (bit_is_set(dev->abs_bits, i)) {
|
||||
struct input_absinfo abs_info;
|
||||
rc = ioctl(fd, EVIOCGABS(i), &dev->abs_info[i]);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
if (i == ABS_MT_SLOT)
|
||||
dev->num_slots = abs_info.maximum + 1; /* FIXME: non-zero min? */
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
rc = init_event_queue(dev);
|
||||
if (rc < 0)
|
||||
return -rc;
|
||||
|
||||
/* not copying key state because we won't know when we'll start to
|
||||
* use this fd and key's are likely to change state by then.
|
||||
* Same with the valuators, really, but they may not change.
|
||||
*/
|
||||
|
||||
dev->fd = fd;
|
||||
|
||||
out:
|
||||
return rc ? -errno : 0;
|
||||
}
|
||||
|
||||
int
|
||||
libevdev_get_fd(const struct libevdev* dev)
|
||||
{
|
||||
return dev->fd;
|
||||
}
|
||||
|
||||
int
|
||||
libevdev_set_callbacks(struct libevdev *dev,
|
||||
libevdev_callback_proc callback,
|
||||
libevdev_callback_proc sync_callback,
|
||||
void *userdata)
|
||||
{
|
||||
dev->callback = callback;
|
||||
dev->sync_callback = sync_callback;
|
||||
dev->userdata = userdata;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
init_event(struct input_event *ev, int type, int code, int value)
|
||||
{
|
||||
ev->time.tv_sec = 0; /* FIXME: blah! */
|
||||
ev->time.tv_usec = 0; /* FIXME: blah! */
|
||||
ev->type = type;
|
||||
ev->code = code;
|
||||
ev->value = value;
|
||||
}
|
||||
|
||||
static int
|
||||
sync_key_state(struct libevdev *dev)
|
||||
{
|
||||
int rc;
|
||||
int i;
|
||||
unsigned long keystate[NLONGS(KEY_MAX)];
|
||||
struct input_event ev;
|
||||
|
||||
rc = ioctl(dev->fd, EVIOCGKEY(sizeof(keystate)), keystate);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < KEY_MAX; i++) {
|
||||
int old, new;
|
||||
old = bit_is_set(dev->key_values, i);
|
||||
new = bit_is_set(keystate, i);
|
||||
if (old ^ new) {
|
||||
init_event(&ev, EV_KEY, i, new ? 1 : 0);
|
||||
dev->sync_callback(dev, &ev, dev->userdata);
|
||||
}
|
||||
set_bit_state(dev->key_values, i, new);
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
out:
|
||||
return rc ? -errno : 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sync_abs_state(struct libevdev *dev)
|
||||
{
|
||||
int rc;
|
||||
int i;
|
||||
struct input_event ev;
|
||||
|
||||
for (i = ABS_X; i <= ABS_MAX; i++) {
|
||||
if (i >= ABS_MT_MIN && i <= ABS_MT_MAX)
|
||||
continue;
|
||||
|
||||
if (bit_is_set(dev->abs_bits, i)) {
|
||||
struct input_absinfo abs_info;
|
||||
rc = ioctl(dev->fd, EVIOCGABS(i), &abs_info);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
if (dev->abs_info[i].value != abs_info.value) {
|
||||
init_event(&ev, EV_ABS, i, abs_info.value);
|
||||
dev->sync_callback(dev, &ev, dev->userdata);
|
||||
dev->abs_info[i].value = abs_info.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
out:
|
||||
return rc ? -errno : 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sync_mt_state(struct libevdev *dev)
|
||||
{
|
||||
int rc;
|
||||
int i;
|
||||
struct mt_state {
|
||||
int code;
|
||||
int val[MAX_SLOTS];
|
||||
} mt_state[ABS_MT_CNT];
|
||||
struct input_event ev;
|
||||
|
||||
for (i = ABS_MT_MIN; i < ABS_MT_MAX; i++) {
|
||||
if (i == ABS_MT_SLOT)
|
||||
continue;
|
||||
|
||||
mt_state[i].code = i;
|
||||
rc = ioctl(dev->fd, EVIOCGMTSLOTS(sizeof(struct mt_state)), &mt_state[i]);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < dev->num_slots; i++) {
|
||||
int j;
|
||||
init_event(&ev, EV_ABS, ABS_MT_SLOT, i);
|
||||
dev->sync_callback(dev, &ev, dev->userdata);
|
||||
for (j = ABS_MT_MIN; j < ABS_MT_MAX; j++) {
|
||||
if (dev->mt_slot_vals[i][j] != mt_state[j].val[i]) {
|
||||
init_event(&ev, EV_ABS, j, mt_state[j].val[i]);
|
||||
dev->sync_callback(dev, &ev, dev->userdata);
|
||||
dev->mt_slot_vals[i][j] = mt_state[j].val[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
out:
|
||||
return rc ? -errno : 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sync_state(struct libevdev *dev, unsigned int flags)
|
||||
{
|
||||
int rc = 0;
|
||||
struct input_event ev;
|
||||
|
||||
if (libevdev_has_event_type(dev, EV_KEY))
|
||||
rc = sync_key_state(dev); /* FIXME: handle ER_SINGLE */
|
||||
if (rc == 0 && libevdev_has_event_type(dev, EV_ABS))
|
||||
rc = sync_abs_state(dev);
|
||||
if (rc == 0 && libevdev_has_event_code(dev, EV_ABS, ABS_MT_SLOT))
|
||||
rc = sync_mt_state(dev);
|
||||
|
||||
init_event(&ev, EV_SYN, SYN_REPORT, 0);
|
||||
dev->sync_callback(dev, &ev, dev->userdata);
|
||||
|
||||
dev->need_sync = 0;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
update_key_state(struct libevdev *dev, const struct input_event *e)
|
||||
{
|
||||
if (!libevdev_has_event_type(dev, EV_KEY))
|
||||
return 1;
|
||||
|
||||
if (e->code > KEY_MAX)
|
||||
return 1;
|
||||
|
||||
if (e->value == 0)
|
||||
clear_bit(dev->key_values, e->code);
|
||||
else
|
||||
set_bit(dev->key_values, e->code);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
update_abs_state(struct libevdev *dev, const struct input_event *e)
|
||||
{
|
||||
if (!libevdev_has_event_type(dev, EV_ABS))
|
||||
return 1;
|
||||
|
||||
if (e->code > ABS_MAX)
|
||||
return 1;
|
||||
|
||||
dev->abs_info[e->code].value = e->value;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
update_state(struct libevdev *dev, const struct input_event *e)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
switch(e->type) {
|
||||
case EV_SYN:
|
||||
case EV_REL:
|
||||
break;
|
||||
case EV_KEY:
|
||||
rc = update_key_state(dev, e);
|
||||
break;
|
||||
case EV_ABS:
|
||||
rc = update_abs_state(dev, e);
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
read_more_events(struct libevdev *dev)
|
||||
{
|
||||
int free_elem;
|
||||
int len;
|
||||
|
||||
free_elem = dev->queue_size - dev->queue_next - 1;
|
||||
if (free_elem <= 0)
|
||||
return 0;
|
||||
|
||||
len = read(dev->fd, &dev->queue[dev->queue_next], free_elem * sizeof(struct input_event));
|
||||
if (len < 0) {
|
||||
if (errno != EAGAIN || dev->queue_next == 0)
|
||||
return -errno;
|
||||
} else if (len > 0 && len % sizeof(struct input_event) != 0)
|
||||
return -EINVAL;
|
||||
|
||||
dev->queue_next += len/sizeof(struct input_event);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int libevdev_read_events(struct libevdev *dev,
|
||||
unsigned int flags)
|
||||
{
|
||||
int nevents, processed;
|
||||
int i;
|
||||
int rc = 0;
|
||||
|
||||
if (dev->fd < 0)
|
||||
return -ENODEV;
|
||||
|
||||
if (flags & ER_SYNC) {
|
||||
if (!dev->need_sync)
|
||||
return 0;
|
||||
return sync_state(dev, flags);
|
||||
}
|
||||
|
||||
/* Always read in some more events. Best case this smoothes over a potential SYN_DROPPED,
|
||||
worst case we don't read fast enough and end up with SYN_DROPPED anyway */
|
||||
rc = read_more_events(dev);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
nevents = dev->queue_next;
|
||||
for (processed = 0; processed < nevents; processed++) {
|
||||
struct input_event *e = &dev->queue[processed];
|
||||
|
||||
update_state(dev, e);
|
||||
|
||||
if (e->type == EV_SYN && e->code == SYN_DROPPED) {
|
||||
dev->need_sync = 0;
|
||||
rc = 1;
|
||||
break;
|
||||
} else if (libevdev_has_event_code(dev, e->type, e->code)) {
|
||||
if (dev->callback(dev, e, dev->userdata) != 0) {
|
||||
rc = -ECANCELED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < nevents - processed; i++) {
|
||||
dev->queue[i] = dev->queue[i + processed];
|
||||
}
|
||||
|
||||
dev->queue_next -= processed;
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
const char *
|
||||
libevdev_get_name(const struct libevdev *dev)
|
||||
{
|
||||
return dev->name;
|
||||
}
|
||||
|
||||
int libevdev_get_pid(const struct libevdev *dev)
|
||||
{
|
||||
return dev->ids.product;
|
||||
}
|
||||
|
||||
int libevdev_get_vid(const struct libevdev *dev)
|
||||
{
|
||||
return dev->ids.vendor;
|
||||
}
|
||||
|
||||
int libevdev_get_bustype(const struct libevdev *dev)
|
||||
{
|
||||
return dev->ids.bustype;
|
||||
}
|
||||
|
||||
int
|
||||
libevdev_has_property(const struct libevdev *dev, unsigned int prop)
|
||||
{
|
||||
return (prop <= INPUT_PROP_MAX) && bit_is_set(dev->props, prop);
|
||||
}
|
||||
|
||||
int
|
||||
libevdev_has_event_type(const struct libevdev *dev, unsigned int type)
|
||||
{
|
||||
return (type <= EV_MAX) && bit_is_set(dev->bits, type);
|
||||
}
|
||||
|
||||
int
|
||||
libevdev_has_event_code(const struct libevdev *dev, unsigned int type, unsigned int code)
|
||||
{
|
||||
const unsigned long *mask;
|
||||
unsigned int max;
|
||||
|
||||
if (!libevdev_has_event_type(dev, type))
|
||||
return 0;
|
||||
|
||||
if (type == EV_SYN)
|
||||
return 1;
|
||||
|
||||
max = type_to_mask_const(dev, type, &mask);
|
||||
|
||||
if (code > max)
|
||||
return 0;
|
||||
|
||||
return bit_is_set(mask, code);
|
||||
}
|
||||
|
||||
int
|
||||
libevdev_get_event_value(const struct libevdev *dev, unsigned int type, unsigned int code)
|
||||
{
|
||||
int value;
|
||||
|
||||
if (!libevdev_has_event_type(dev, type) || !libevdev_has_event_code(dev, type, code))
|
||||
return 0;
|
||||
|
||||
switch (type) {
|
||||
case EV_ABS: value = dev->abs_info[code].value; break;
|
||||
case EV_KEY: value = bit_is_set(dev->key_values, code); break;
|
||||
default:
|
||||
value = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
int
|
||||
libevdev_fetch_event_value(const struct libevdev *dev, unsigned int type, unsigned int code, int *value)
|
||||
{
|
||||
if (libevdev_has_event_type(dev, type) &&
|
||||
libevdev_has_event_code(dev, type, code)) {
|
||||
*value = libevdev_get_event_value(dev, type, code);
|
||||
return 1;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
libevdev_get_slot_value(const struct libevdev *dev, unsigned int slot, unsigned int code)
|
||||
{
|
||||
if (!libevdev_has_event_type(dev, EV_ABS) || !libevdev_has_event_code(dev, EV_ABS, code))
|
||||
return 0;
|
||||
|
||||
if (slot >= dev->num_slots || slot >= MAX_SLOTS)
|
||||
return 0;
|
||||
|
||||
if (code > ABS_MT_MAX || code < ABS_MT_MIN)
|
||||
return 0;
|
||||
|
||||
return dev->mt_slot_vals[slot][code - ABS_MT_MIN];
|
||||
}
|
||||
|
||||
int
|
||||
libevdev_fetch_slot_value(const struct libevdev *dev, unsigned int slot, unsigned int code, int *value)
|
||||
{
|
||||
if (libevdev_has_event_type(dev, EV_ABS) &&
|
||||
libevdev_has_event_code(dev, EV_ABS, code) &&
|
||||
slot < dev->num_slots && slot < MAX_SLOTS) {
|
||||
*value = libevdev_get_slot_value(dev, slot, code);
|
||||
return 1;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
libevdev_get_num_slots(const struct libevdev *dev)
|
||||
{
|
||||
return dev->num_slots;
|
||||
}
|
||||
|
||||
const struct input_absinfo*
|
||||
libevdev_get_abs_info(const struct libevdev *dev, unsigned int code)
|
||||
{
|
||||
if (!libevdev_has_event_type(dev, EV_ABS) ||
|
||||
!libevdev_has_event_code(dev, EV_ABS, code))
|
||||
return NULL;
|
||||
|
||||
return &dev->abs_info[code];
|
||||
}
|
||||
|
||||
int
|
||||
libevdev_get_abs_min(const struct libevdev *dev, unsigned int code)
|
||||
{
|
||||
const struct input_absinfo *absinfo = libevdev_get_abs_info(dev, code);
|
||||
|
||||
return absinfo ? absinfo->minimum : 0;
|
||||
}
|
||||
|
||||
int
|
||||
libevdev_get_abs_max(const struct libevdev *dev, unsigned int code)
|
||||
{
|
||||
const struct input_absinfo *absinfo = libevdev_get_abs_info(dev, code);
|
||||
|
||||
return absinfo ? absinfo->maximum : 0;
|
||||
}
|
||||
|
||||
int
|
||||
libevdev_get_abs_fuzz(const struct libevdev *dev, unsigned int code)
|
||||
{
|
||||
const struct input_absinfo *absinfo = libevdev_get_abs_info(dev, code);
|
||||
|
||||
return absinfo ? absinfo->fuzz : 0;
|
||||
}
|
||||
|
||||
int
|
||||
libevdev_get_abs_flat(const struct libevdev *dev, unsigned int code)
|
||||
{
|
||||
const struct input_absinfo *absinfo = libevdev_get_abs_info(dev, code);
|
||||
|
||||
return absinfo ? absinfo->flat : 0;
|
||||
}
|
||||
|
||||
int
|
||||
libevdev_get_abs_resolution(const struct libevdev *dev, unsigned int code)
|
||||
{
|
||||
const struct input_absinfo *absinfo = libevdev_get_abs_info(dev, code);
|
||||
|
||||
return absinfo ? absinfo->resolution : 0;
|
||||
}
|
||||
|
||||
int
|
||||
libevdev_enable_event_type(struct libevdev *dev, unsigned int type)
|
||||
{
|
||||
if (type > EV_MAX)
|
||||
return 1;
|
||||
|
||||
set_bit(dev->bits, type);
|
||||
|
||||
/* FIXME: pass through to kernel */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
libevdev_disable_event_type(struct libevdev *dev, unsigned int type)
|
||||
{
|
||||
if (type > EV_MAX)
|
||||
return 1;
|
||||
|
||||
clear_bit(dev->bits, type);
|
||||
|
||||
/* FIXME: pass through to kernel */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
libevdev_enable_event_code(struct libevdev *dev, unsigned int type,
|
||||
unsigned int code, const void *data)
|
||||
{
|
||||
unsigned int max;
|
||||
unsigned long *mask;
|
||||
|
||||
if (libevdev_enable_event_type(dev, type))
|
||||
return 1;
|
||||
|
||||
max = type_to_mask(dev, type, &mask);
|
||||
|
||||
if (code > max)
|
||||
return 1;
|
||||
|
||||
set_bit(mask, code);
|
||||
|
||||
if (type == EV_ABS) {
|
||||
const struct input_absinfo *abs = data;
|
||||
dev->abs_info[code] = *abs;
|
||||
}
|
||||
|
||||
/* FIXME: pass through to kernel */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
libevdev_disable_event_code(struct libevdev *dev, unsigned int type, unsigned int code)
|
||||
{
|
||||
unsigned int max;
|
||||
unsigned long *mask;
|
||||
|
||||
if (type > EV_MAX)
|
||||
return 1;
|
||||
|
||||
max = type_to_mask(dev, type, &mask);
|
||||
|
||||
if (code > max)
|
||||
return 1;
|
||||
|
||||
clear_bit(mask, code);
|
||||
|
||||
/* FIXME: pass through to kernel */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
libevdev_kernel_set_abs_value(struct libevdev *dev, unsigned int code, const struct input_absinfo *abs)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (code > ABS_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
rc = ioctl(dev->fd, EVIOCSABS(code), *abs);
|
||||
if (rc < 0)
|
||||
rc = -errno;
|
||||
else
|
||||
rc = libevdev_enable_event_code(dev, EV_ABS, code, abs);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
libevdev_grab(struct libevdev *dev, int grab)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (grab && !dev->grabbed)
|
||||
rc = ioctl(dev->fd, EVIOCGRAB, (void *)1);
|
||||
else if (!grab && dev->grabbed)
|
||||
rc = ioctl(dev->fd, EVIOCGRAB, (void *)0);
|
||||
|
||||
if (rc == 0)
|
||||
dev->grabbed = grab;
|
||||
|
||||
return rc < 0 ? -errno : 0;
|
||||
}
|
||||
427
libevdev/libevdev.h
Normal file
427
libevdev/libevdev.h
Normal file
|
|
@ -0,0 +1,427 @@
|
|||
/*
|
||||
* Copyright © 2013 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.
|
||||
*/
|
||||
|
||||
#ifndef libevdev_H
|
||||
#define libevdev_H
|
||||
|
||||
#include <config.h>
|
||||
#include <linux/input.h>
|
||||
|
||||
struct libevdev;
|
||||
|
||||
enum EvdevReadFlags {
|
||||
ER_SINGLE = 1, /**< Read until including the first EV_SYN or EAGAIN */
|
||||
ER_SYNC = 2, /**< Process data in sync mode */
|
||||
ER_ALL = 4, /**< Read until EAGAIN */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Initialize a new libevdev struct.
|
||||
*
|
||||
* @param fd If fd >= 0, the device is initialised for the fd. Otherwise, a
|
||||
* caller must call evdev_set_fd() before attempting to read events.
|
||||
*
|
||||
* @see libevdev_set_fd
|
||||
*/
|
||||
struct libevdev* libevdev_new(int fd);
|
||||
|
||||
/**
|
||||
* Clean up and free the libevdev struct.
|
||||
*
|
||||
* @note This function may be called before libevdev_set_fd.
|
||||
*/
|
||||
void libevdev_free(struct libevdev *dev);
|
||||
|
||||
/**
|
||||
* Grab or ungrab the device through a kernel EVIOCGRAB. This prevents other
|
||||
* clients (including kernel-internal ones such as rfkill) from receiving
|
||||
* events from this device.
|
||||
*
|
||||
* This is generally a bad idea. Don't do this.
|
||||
*
|
||||
* Grabbing an already grabbed device, or ungrabbing an ungrabbed device is
|
||||
* a noop and always succeeds.
|
||||
*
|
||||
* @param grab If true, grab the device. Otherwise ungrab the device.
|
||||
*
|
||||
* @return 0 if the device was successfull grabbed or ungrabbed, or a
|
||||
* negative errno in case of failure.
|
||||
*/
|
||||
int libevdev_grab(struct libevdev *dev, int grab);
|
||||
|
||||
/**
|
||||
* Set the fd for this struct and initialize internal data.
|
||||
* The fd must be open for reading and ioctl.
|
||||
*
|
||||
* This function may only be called once per device. If you need to re-read
|
||||
* a device, use libevdev_free and libevdev_new. If you need to change the
|
||||
* fd, use libevdev_change_fd.
|
||||
*
|
||||
* Unless otherwise specified, libevdev function behavior is undefined until
|
||||
* a successfull call to libevdev_set_fd.
|
||||
*
|
||||
* @param fd The file descriptor for the device
|
||||
*
|
||||
* @return 0 on success, or a negative error code on failure
|
||||
*
|
||||
* @see libevdev_change_fd
|
||||
* @see libevdev_new
|
||||
* @see libevdev_free
|
||||
*/
|
||||
int libevdev_set_fd(struct libevdev* dev, int fd);
|
||||
|
||||
/**
|
||||
* Change the fd for this device, without re-reading the actual device.
|
||||
*
|
||||
* It is an error to call this function before calling libevdev_set_fd.
|
||||
*
|
||||
* @param fd The new fd
|
||||
*
|
||||
* @return 0 on success, or -1 on failure.
|
||||
*
|
||||
* @see libevdev_set_fd
|
||||
*/
|
||||
int libevdev_change_fd(struct libevdev* dev, int fd);
|
||||
|
||||
/**
|
||||
*
|
||||
* @return The previously set fd, or -1 if none had been set previously.
|
||||
* @note This function may be called before libevdev_set_fd.
|
||||
*/
|
||||
int libevdev_get_fd(const struct libevdev* dev);
|
||||
|
||||
/**
|
||||
* Event callback used to report events back to the client.
|
||||
*
|
||||
* If this function returns -1, event processing is interrupted and returned
|
||||
* to the caller of libevdev_read_events. A future call to
|
||||
* libevdev_read_events will continue with the next event in the queue.
|
||||
*
|
||||
* @param dev The device this callback was invoked on
|
||||
* @param ev The event read from the kernel
|
||||
* @param userdata Previously assigned caller-specific data
|
||||
*
|
||||
* @return 0 on success, or -1 on failure.
|
||||
*
|
||||
* @see libevdev_read_events
|
||||
*/
|
||||
typedef int (*libevdev_callback_proc)(struct libevdev *dev, struct input_event *ev, void *userdata);
|
||||
|
||||
/**
|
||||
* Set the callbacks to be used when reading events off the fd.
|
||||
* Two callbacks are used, one for reporting events during normal operation, one for
|
||||
* reporting events during an event sync. If either is NULL, no events are
|
||||
* reported for that mode.
|
||||
*
|
||||
* @param callback Callback used for regular events when read off the fd
|
||||
* @param sync_callback Callback used for events while re-syncing after a
|
||||
* SYN_DROPPED event.
|
||||
* @param userdata Caller-specific data, passed back through the callbacks.
|
||||
*
|
||||
* @return zero on success, -1 on failure
|
||||
*
|
||||
* @see libevdev_read_events
|
||||
* @note This function may be called before libevdev_set_fd.
|
||||
*/
|
||||
int libevdev_set_callbacks(struct libevdev *dev,
|
||||
libevdev_callback_proc callback,
|
||||
libevdev_callback_proc sync_callback,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* Read events off the fd and call the matching callback.
|
||||
*
|
||||
* Depending on the flags, the behaviour changes as follows:
|
||||
* - ER_SINGLE: read a single event off the fd (i.e. up to the next EV_SYN).
|
||||
* This should only be used if the caller is time-sensitive and event
|
||||
* processing of multiple events may prevent other computation.
|
||||
* - ER_ALL: read all the events off the fd until a read would block or
|
||||
* an SYN_DROPPED event is read.
|
||||
* - ER_SYNC: switch to sync mode and report all events that are required to
|
||||
* bring the device state back in sync with the kernel device state.
|
||||
*
|
||||
* @param fd The file descriptor previously set, open in non-blocking mode. If
|
||||
* the file descriptor differs from the previous one, -EBADF is returned.
|
||||
* @param flags The set of flags to decide how to handle events.
|
||||
*
|
||||
* @return On failure, a negative errno is returned.
|
||||
* @retval 0 One or more events where read of the fd
|
||||
* @retval -EAGAIN No events are currently on the fd
|
||||
* @retval -ECANCELLED The callback returned non-zero
|
||||
* @retval 1 A SYN_DROPPED event was received
|
||||
*
|
||||
* @see libevdev_set_callbacks
|
||||
*
|
||||
* @note This function is signal-safe.
|
||||
*/
|
||||
int libevdev_read_events(struct libevdev *dev, unsigned int flags);
|
||||
|
||||
/**
|
||||
* @return The device name as read off the kernel device
|
||||
*
|
||||
* @note This function is signal-safe.
|
||||
*/
|
||||
const char* libevdev_get_name(const struct libevdev *dev);
|
||||
|
||||
/**
|
||||
* @return The device's product ID
|
||||
*
|
||||
* @note This function is signal-safe.
|
||||
*/
|
||||
int libevdev_get_pid(const struct libevdev *dev);
|
||||
/**
|
||||
* @return The device's vendor ID
|
||||
*
|
||||
* @note This function is signal-safe.
|
||||
*/
|
||||
int libevdev_get_vid(const struct libevdev *dev);
|
||||
|
||||
/**
|
||||
* @return The device's bus type
|
||||
*
|
||||
* @note This function is signal-safe.
|
||||
*/
|
||||
int libevdev_get_bustype(const struct libevdev *dev);
|
||||
|
||||
/**
|
||||
* @return 1 if the device supports this event type, or 0 otherwise.
|
||||
*
|
||||
* @note This function is signal-safe
|
||||
*/
|
||||
int libevdev_has_property(const struct libevdev *dev, unsigned int prop);
|
||||
|
||||
/**
|
||||
* @return 1 if the device supports this event type, or 0 otherwise.
|
||||
*
|
||||
* @note This function is signal-safe.
|
||||
*/
|
||||
int libevdev_has_event_type(const struct libevdev *dev, unsigned int type);
|
||||
|
||||
/**
|
||||
* @return 1 if the device supports this event type, or 0 otherwise.
|
||||
*
|
||||
* @note This function is signal-safe.
|
||||
*/
|
||||
int libevdev_has_event_code(const struct libevdev *dev, unsigned int type, unsigned int code);
|
||||
|
||||
/**
|
||||
* @return axis minimum for the given axis or 0 if the axis is invalid
|
||||
*/
|
||||
int libevdev_get_abs_min(const struct libevdev *dev, unsigned int code);
|
||||
/**
|
||||
* @return axis maximum for the given axis or 0 if the axis is invalid
|
||||
*/
|
||||
int libevdev_get_abs_max(const struct libevdev *dev, unsigned int code);
|
||||
/**
|
||||
* @return axis fuzz for the given axis or 0 if the axis is invalid
|
||||
*/
|
||||
int libevdev_get_abs_fuzz(const struct libevdev *dev, unsigned int code);
|
||||
/**
|
||||
* @return axis flat for the given axis or 0 if the axis is invalid
|
||||
*/
|
||||
int libevdev_get_abs_flat(const struct libevdev *dev, unsigned int code);
|
||||
/**
|
||||
* @return axis resolution for the given axis or 0 if the axis is invalid
|
||||
*/
|
||||
int libevdev_get_abs_resolution(const struct libevdev *dev, unsigned int code);
|
||||
|
||||
/**
|
||||
* @return The input_absinfo for the given code, or NULL if the device does
|
||||
* not support this event code.
|
||||
*/
|
||||
const struct input_absinfo* libevdev_get_abs_info(const struct libevdev *dev, unsigned int code);
|
||||
|
||||
/**
|
||||
* Behaviour of this function is undefined if the device does not provide
|
||||
* the event.
|
||||
*
|
||||
* @return The current value of the event.
|
||||
*
|
||||
* @note This function is signal-safe.
|
||||
* @note The value for ABS_MT_ events is undefined, use
|
||||
* libevdev_get_slot_value instead
|
||||
*
|
||||
* @see libevdev_get_slot_value
|
||||
*/
|
||||
int libevdev_get_event_value(const struct libevdev *dev, unsigned int type, unsigned int code);
|
||||
|
||||
/**
|
||||
* Fetch the current value of the event type. This is a shortcut for
|
||||
*
|
||||
* <pre>
|
||||
* if (libevdev_has_event_type(dev, t) && libevdev_has_event_code(dev, t, c))
|
||||
* val = libevdev_get_event_value(dev, t, c);
|
||||
* </pre>
|
||||
*
|
||||
* @return non-zero if the device supports this event code, or zero
|
||||
* otherwise. On return of zero, value is unmodified.
|
||||
*
|
||||
* @note This function is signal-safe.
|
||||
* @note The value for ABS_MT_ events is undefined, use
|
||||
* libevdev_fetch_slot_value instead
|
||||
*
|
||||
* @see libevdev_fetch_slot_value
|
||||
*/
|
||||
int libevdev_fetch_event_value(const struct libevdev *dev, unsigned int type, unsigned int code, int *value);
|
||||
|
||||
/**
|
||||
* Return the current value of the code for the given slot.
|
||||
*
|
||||
* The return value is undefined for a slot exceeding the available slots on
|
||||
* the device, or for a device that does not have slots.
|
||||
*
|
||||
* @note This function is signal-safe.
|
||||
* @note The value for events other than ABS_MT_ is undefined, use
|
||||
* libevdev_fetch_value instead
|
||||
*
|
||||
* @see libevdev_get_value
|
||||
*/
|
||||
int libevdev_get_slot_value(const struct libevdev *dev, unsigned int slot, unsigned int code);
|
||||
|
||||
/**
|
||||
* Fetch the current value of the code for the given slot. This is a shortcut for
|
||||
*
|
||||
* <pre>
|
||||
* 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);
|
||||
* </pre>
|
||||
*
|
||||
* @return non-zero if the device supports this event code, or zero
|
||||
* otherwise. On return of zero, value is unmodified.
|
||||
*
|
||||
* @note This function is signal-safe.
|
||||
* @note The value for ABS_MT_ events is undefined, use
|
||||
* libevdev_fetch_slot_value instead
|
||||
*
|
||||
* @see libevdev_fetch_slot_value
|
||||
*/
|
||||
int libevdev_fetch_slot_value(const struct libevdev *dev, unsigned int slot, unsigned int code, int *value);
|
||||
|
||||
/**
|
||||
* Get the number of slots supported by this device.
|
||||
*
|
||||
* Note that the slot offset may be non-zero, use libevdev_get_abs_min() or
|
||||
* libevdev_get_abs_info() to get the minimum slot number.
|
||||
*
|
||||
* @return The number of slots supported, or -1
|
||||
*/
|
||||
int libevdev_get_num_slots(const struct libevdev *dev);
|
||||
|
||||
/**
|
||||
* Forcibly enable an event type 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_type.
|
||||
*
|
||||
* This is a local modification only affecting only this process and only
|
||||
* this device.
|
||||
*
|
||||
* @param type The event type to enable (EV_ABS, EV_KEY, ...)
|
||||
*
|
||||
* @return 0 on success or -1 otherwise
|
||||
*
|
||||
* @see libevdev_has_event_type
|
||||
*/
|
||||
int libevdev_enable_event_type(struct libevdev *dev, unsigned int type);
|
||||
|
||||
/**
|
||||
* Forcibly disable an event type on this device, even if the underlying
|
||||
* device provides it, effectively muting all keys or axes. libevdev will
|
||||
* filter any events matching this type and none will reach the caller.
|
||||
* libevdev_has_event_type will return false for this type.
|
||||
*
|
||||
* In most cases, a caller likely only wants to disable a single code, not
|
||||
* the whole type. Use libevdev_disable_event_code for that.
|
||||
*
|
||||
* This is a local modification only affecting only this process and only
|
||||
* this device.
|
||||
*
|
||||
* @param type The event type to enable (EV_ABS, EV_KEY, ...)
|
||||
*
|
||||
* @return 0 on success or -1 otherwise
|
||||
*
|
||||
* @see libevdev_has_event_type
|
||||
* @see libevdev_disable_event_type
|
||||
*/
|
||||
int libevdev_disable_event_type(struct libevdev *dev, unsigned int type);
|
||||
|
||||
/**
|
||||
* Forcibly enable an event type 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, the vararg must be a pointer to a struct input_absinfo
|
||||
* containing the data for this axis.
|
||||
* - For all other types, the argument is ignored.
|
||||
*
|
||||
* This function calls libevdev_enable_event_type if necessary.
|
||||
*
|
||||
* This is a local modification only affecting only this process and only
|
||||
* this device.
|
||||
*
|
||||
* @param type The event type to enable (EV_ABS, EV_KEY, ...)
|
||||
* @param code The event code to enable (ABS_X, REL_X, etc.)
|
||||
* @param data Axis/key data, depending on type and code
|
||||
*
|
||||
* @return 0 on success or -1 otherwise
|
||||
*
|
||||
* @see libevdev_enable_event_type
|
||||
*/
|
||||
int libevdev_enable_event_code(struct libevdev *dev, unsigned int type, unsigned int code, const void *data);
|
||||
|
||||
/**
|
||||
* Forcibly disable an event code on this device, even if the underlying
|
||||
* device provides it, effectively muting this key or axis. libevdev will
|
||||
* filter any events matching this type and code and none will reach the
|
||||
* caller.
|
||||
* libevdev_has_event_code will return false for this code combination.
|
||||
*
|
||||
* Disabling all event codes for a given type will not disable the event
|
||||
* type. Use libevdev_disable_event_type for that.
|
||||
*
|
||||
* This is a local modification only affecting only this process and only
|
||||
* this device.
|
||||
*
|
||||
* @param type The event type to enable (EV_ABS, EV_KEY, ...)
|
||||
* @param code The event code to enable (ABS_X, REL_X, etc.)
|
||||
*
|
||||
* @return 0 on success or -1 otherwise
|
||||
*
|
||||
* @see libevdev_has_event_code
|
||||
* @see libevdev_disable_event_type
|
||||
*/
|
||||
int libevdev_disable_event_code(struct libevdev *dev, unsigned int type, unsigned int code);
|
||||
|
||||
/**
|
||||
* Set the device's EV_ABS/<code> axis to the value defined in the abs
|
||||
* parameter. This will be written to the kernel.
|
||||
*
|
||||
* @return zero on success, or a negative errno on failure
|
||||
*
|
||||
* @see libevdev_enable_event_code
|
||||
*/
|
||||
int libevdev_kernel_set_abs_value(struct libevdev *dev, unsigned int code, const struct input_absinfo *abs);
|
||||
|
||||
#endif /* libevdev_H */
|
||||
2
test/.gitignore
vendored
Normal file
2
test/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
libevdev-print
|
||||
libevdev-events
|
||||
11
test/Makefile.am
Normal file
11
test/Makefile.am
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
noinst_PROGRAMS = libevdev-print libevdev-events
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/libevdev
|
||||
libevdev_ldadd = $(top_builddir)/libevdev/libevdev.la
|
||||
|
||||
libevdev_print_SOURCES = libevdev-print.c event-names.h
|
||||
libevdev_print_LDADD = $(libevdev_ldadd)
|
||||
|
||||
libevdev_events_SOURCES = libevdev-events.c event-names.h
|
||||
libevdev_events_LDADD = $(libevdev_ldadd)
|
||||
|
||||
704
test/event-names.h
Normal file
704
test/event-names.h
Normal file
|
|
@ -0,0 +1,704 @@
|
|||
/* THIS FILE IS GENERATED, DO NOT EDIT */
|
||||
/* to regenerate this file, get evemu from
|
||||
git://git.freedesktop.org/git/evemu
|
||||
*/
|
||||
|
||||
#ifndef EVENT_NAMES_H
|
||||
#define EVENT_NAMES_H
|
||||
|
||||
#define SYN_MAX 3 /* linux/input.h doesn't define that */
|
||||
|
||||
static const char * const ev_map[EV_MAX + 1] = {
|
||||
[0 ... EV_MAX] = NULL,
|
||||
[EV_SYN] = "EV_SYN",
|
||||
[EV_KEY] = "EV_KEY",
|
||||
[EV_REL] = "EV_REL",
|
||||
[EV_ABS] = "EV_ABS",
|
||||
[EV_MSC] = "EV_MSC",
|
||||
[EV_SW] = "EV_SW",
|
||||
[EV_LED] = "EV_LED",
|
||||
[EV_SND] = "EV_SND",
|
||||
[EV_REP] = "EV_REP",
|
||||
[EV_FF] = "EV_FF",
|
||||
[EV_PWR] = "EV_PWR",
|
||||
[EV_FF_STATUS] = "EV_FF_STATUS",
|
||||
[EV_MAX] = "EV_MAX",
|
||||
};
|
||||
|
||||
static const char * const rel_map[REL_MAX + 1] = {
|
||||
[0 ... REL_MAX] = NULL,
|
||||
[REL_X] = "REL_X",
|
||||
[REL_Y] = "REL_Y",
|
||||
[REL_Z] = "REL_Z",
|
||||
[REL_RX] = "REL_RX",
|
||||
[REL_RY] = "REL_RY",
|
||||
[REL_RZ] = "REL_RZ",
|
||||
[REL_HWHEEL] = "REL_HWHEEL",
|
||||
[REL_DIAL] = "REL_DIAL",
|
||||
[REL_WHEEL] = "REL_WHEEL",
|
||||
[REL_MISC] = "REL_MISC",
|
||||
[REL_MAX] = "REL_MAX",
|
||||
};
|
||||
|
||||
static const char * const abs_map[ABS_MAX + 1] = {
|
||||
[0 ... ABS_MAX] = NULL,
|
||||
[ABS_X] = "ABS_X",
|
||||
[ABS_Y] = "ABS_Y",
|
||||
[ABS_Z] = "ABS_Z",
|
||||
[ABS_RX] = "ABS_RX",
|
||||
[ABS_RY] = "ABS_RY",
|
||||
[ABS_RZ] = "ABS_RZ",
|
||||
[ABS_THROTTLE] = "ABS_THROTTLE",
|
||||
[ABS_RUDDER] = "ABS_RUDDER",
|
||||
[ABS_WHEEL] = "ABS_WHEEL",
|
||||
[ABS_GAS] = "ABS_GAS",
|
||||
[ABS_BRAKE] = "ABS_BRAKE",
|
||||
[ABS_HAT0X] = "ABS_HAT0X",
|
||||
[ABS_HAT0Y] = "ABS_HAT0Y",
|
||||
[ABS_HAT1X] = "ABS_HAT1X",
|
||||
[ABS_HAT1Y] = "ABS_HAT1Y",
|
||||
[ABS_HAT2X] = "ABS_HAT2X",
|
||||
[ABS_HAT2Y] = "ABS_HAT2Y",
|
||||
[ABS_HAT3X] = "ABS_HAT3X",
|
||||
[ABS_HAT3Y] = "ABS_HAT3Y",
|
||||
[ABS_PRESSURE] = "ABS_PRESSURE",
|
||||
[ABS_DISTANCE] = "ABS_DISTANCE",
|
||||
[ABS_TILT_X] = "ABS_TILT_X",
|
||||
[ABS_TILT_Y] = "ABS_TILT_Y",
|
||||
[ABS_TOOL_WIDTH] = "ABS_TOOL_WIDTH",
|
||||
[ABS_VOLUME] = "ABS_VOLUME",
|
||||
[ABS_MISC] = "ABS_MISC",
|
||||
[ABS_MT_SLOT] = "ABS_MT_SLOT",
|
||||
[ABS_MT_TOUCH_MAJOR] = "ABS_MT_TOUCH_MAJOR",
|
||||
[ABS_MT_TOUCH_MINOR] = "ABS_MT_TOUCH_MINOR",
|
||||
[ABS_MT_WIDTH_MAJOR] = "ABS_MT_WIDTH_MAJOR",
|
||||
[ABS_MT_WIDTH_MINOR] = "ABS_MT_WIDTH_MINOR",
|
||||
[ABS_MT_ORIENTATION] = "ABS_MT_ORIENTATION",
|
||||
[ABS_MT_POSITION_X] = "ABS_MT_POSITION_X",
|
||||
[ABS_MT_POSITION_Y] = "ABS_MT_POSITION_Y",
|
||||
[ABS_MT_TOOL_TYPE] = "ABS_MT_TOOL_TYPE",
|
||||
[ABS_MT_BLOB_ID] = "ABS_MT_BLOB_ID",
|
||||
[ABS_MT_TRACKING_ID] = "ABS_MT_TRACKING_ID",
|
||||
[ABS_MT_PRESSURE] = "ABS_MT_PRESSURE",
|
||||
[ABS_MT_DISTANCE] = "ABS_MT_DISTANCE",
|
||||
[ABS_MT_TOOL_X] = "ABS_MT_TOOL_X",
|
||||
[ABS_MT_TOOL_Y] = "ABS_MT_TOOL_Y",
|
||||
[ABS_MAX] = "ABS_MAX",
|
||||
};
|
||||
|
||||
static const char * const key_map[KEY_MAX + 1] = {
|
||||
[0 ... KEY_MAX] = NULL,
|
||||
[KEY_RESERVED] = "KEY_RESERVED",
|
||||
[KEY_ESC] = "KEY_ESC",
|
||||
[KEY_1] = "KEY_1",
|
||||
[KEY_2] = "KEY_2",
|
||||
[KEY_3] = "KEY_3",
|
||||
[KEY_4] = "KEY_4",
|
||||
[KEY_5] = "KEY_5",
|
||||
[KEY_6] = "KEY_6",
|
||||
[KEY_7] = "KEY_7",
|
||||
[KEY_8] = "KEY_8",
|
||||
[KEY_9] = "KEY_9",
|
||||
[KEY_0] = "KEY_0",
|
||||
[KEY_MINUS] = "KEY_MINUS",
|
||||
[KEY_EQUAL] = "KEY_EQUAL",
|
||||
[KEY_BACKSPACE] = "KEY_BACKSPACE",
|
||||
[KEY_TAB] = "KEY_TAB",
|
||||
[KEY_Q] = "KEY_Q",
|
||||
[KEY_W] = "KEY_W",
|
||||
[KEY_E] = "KEY_E",
|
||||
[KEY_R] = "KEY_R",
|
||||
[KEY_T] = "KEY_T",
|
||||
[KEY_Y] = "KEY_Y",
|
||||
[KEY_U] = "KEY_U",
|
||||
[KEY_I] = "KEY_I",
|
||||
[KEY_O] = "KEY_O",
|
||||
[KEY_P] = "KEY_P",
|
||||
[KEY_LEFTBRACE] = "KEY_LEFTBRACE",
|
||||
[KEY_RIGHTBRACE] = "KEY_RIGHTBRACE",
|
||||
[KEY_ENTER] = "KEY_ENTER",
|
||||
[KEY_LEFTCTRL] = "KEY_LEFTCTRL",
|
||||
[KEY_A] = "KEY_A",
|
||||
[KEY_S] = "KEY_S",
|
||||
[KEY_D] = "KEY_D",
|
||||
[KEY_F] = "KEY_F",
|
||||
[KEY_G] = "KEY_G",
|
||||
[KEY_H] = "KEY_H",
|
||||
[KEY_J] = "KEY_J",
|
||||
[KEY_K] = "KEY_K",
|
||||
[KEY_L] = "KEY_L",
|
||||
[KEY_SEMICOLON] = "KEY_SEMICOLON",
|
||||
[KEY_APOSTROPHE] = "KEY_APOSTROPHE",
|
||||
[KEY_GRAVE] = "KEY_GRAVE",
|
||||
[KEY_LEFTSHIFT] = "KEY_LEFTSHIFT",
|
||||
[KEY_BACKSLASH] = "KEY_BACKSLASH",
|
||||
[KEY_Z] = "KEY_Z",
|
||||
[KEY_X] = "KEY_X",
|
||||
[KEY_C] = "KEY_C",
|
||||
[KEY_V] = "KEY_V",
|
||||
[KEY_B] = "KEY_B",
|
||||
[KEY_N] = "KEY_N",
|
||||
[KEY_M] = "KEY_M",
|
||||
[KEY_COMMA] = "KEY_COMMA",
|
||||
[KEY_DOT] = "KEY_DOT",
|
||||
[KEY_SLASH] = "KEY_SLASH",
|
||||
[KEY_RIGHTSHIFT] = "KEY_RIGHTSHIFT",
|
||||
[KEY_KPASTERISK] = "KEY_KPASTERISK",
|
||||
[KEY_LEFTALT] = "KEY_LEFTALT",
|
||||
[KEY_SPACE] = "KEY_SPACE",
|
||||
[KEY_CAPSLOCK] = "KEY_CAPSLOCK",
|
||||
[KEY_F1] = "KEY_F1",
|
||||
[KEY_F2] = "KEY_F2",
|
||||
[KEY_F3] = "KEY_F3",
|
||||
[KEY_F4] = "KEY_F4",
|
||||
[KEY_F5] = "KEY_F5",
|
||||
[KEY_F6] = "KEY_F6",
|
||||
[KEY_F7] = "KEY_F7",
|
||||
[KEY_F8] = "KEY_F8",
|
||||
[KEY_F9] = "KEY_F9",
|
||||
[KEY_F10] = "KEY_F10",
|
||||
[KEY_NUMLOCK] = "KEY_NUMLOCK",
|
||||
[KEY_SCROLLLOCK] = "KEY_SCROLLLOCK",
|
||||
[KEY_KP7] = "KEY_KP7",
|
||||
[KEY_KP8] = "KEY_KP8",
|
||||
[KEY_KP9] = "KEY_KP9",
|
||||
[KEY_KPMINUS] = "KEY_KPMINUS",
|
||||
[KEY_KP4] = "KEY_KP4",
|
||||
[KEY_KP5] = "KEY_KP5",
|
||||
[KEY_KP6] = "KEY_KP6",
|
||||
[KEY_KPPLUS] = "KEY_KPPLUS",
|
||||
[KEY_KP1] = "KEY_KP1",
|
||||
[KEY_KP2] = "KEY_KP2",
|
||||
[KEY_KP3] = "KEY_KP3",
|
||||
[KEY_KP0] = "KEY_KP0",
|
||||
[KEY_KPDOT] = "KEY_KPDOT",
|
||||
[KEY_ZENKAKUHANKAKU] = "KEY_ZENKAKUHANKAKU",
|
||||
[KEY_102ND] = "KEY_102ND",
|
||||
[KEY_F11] = "KEY_F11",
|
||||
[KEY_F12] = "KEY_F12",
|
||||
[KEY_RO] = "KEY_RO",
|
||||
[KEY_KATAKANA] = "KEY_KATAKANA",
|
||||
[KEY_HIRAGANA] = "KEY_HIRAGANA",
|
||||
[KEY_HENKAN] = "KEY_HENKAN",
|
||||
[KEY_KATAKANAHIRAGANA] = "KEY_KATAKANAHIRAGANA",
|
||||
[KEY_MUHENKAN] = "KEY_MUHENKAN",
|
||||
[KEY_KPJPCOMMA] = "KEY_KPJPCOMMA",
|
||||
[KEY_KPENTER] = "KEY_KPENTER",
|
||||
[KEY_RIGHTCTRL] = "KEY_RIGHTCTRL",
|
||||
[KEY_KPSLASH] = "KEY_KPSLASH",
|
||||
[KEY_SYSRQ] = "KEY_SYSRQ",
|
||||
[KEY_RIGHTALT] = "KEY_RIGHTALT",
|
||||
[KEY_LINEFEED] = "KEY_LINEFEED",
|
||||
[KEY_HOME] = "KEY_HOME",
|
||||
[KEY_UP] = "KEY_UP",
|
||||
[KEY_PAGEUP] = "KEY_PAGEUP",
|
||||
[KEY_LEFT] = "KEY_LEFT",
|
||||
[KEY_RIGHT] = "KEY_RIGHT",
|
||||
[KEY_END] = "KEY_END",
|
||||
[KEY_DOWN] = "KEY_DOWN",
|
||||
[KEY_PAGEDOWN] = "KEY_PAGEDOWN",
|
||||
[KEY_INSERT] = "KEY_INSERT",
|
||||
[KEY_DELETE] = "KEY_DELETE",
|
||||
[KEY_MACRO] = "KEY_MACRO",
|
||||
[KEY_MUTE] = "KEY_MUTE",
|
||||
[KEY_VOLUMEDOWN] = "KEY_VOLUMEDOWN",
|
||||
[KEY_VOLUMEUP] = "KEY_VOLUMEUP",
|
||||
[KEY_POWER] = "KEY_POWER",
|
||||
[KEY_KPEQUAL] = "KEY_KPEQUAL",
|
||||
[KEY_KPPLUSMINUS] = "KEY_KPPLUSMINUS",
|
||||
[KEY_PAUSE] = "KEY_PAUSE",
|
||||
[KEY_SCALE] = "KEY_SCALE",
|
||||
[KEY_KPCOMMA] = "KEY_KPCOMMA",
|
||||
[KEY_HANGEUL] = "KEY_HANGEUL",
|
||||
[KEY_HANJA] = "KEY_HANJA",
|
||||
[KEY_YEN] = "KEY_YEN",
|
||||
[KEY_LEFTMETA] = "KEY_LEFTMETA",
|
||||
[KEY_RIGHTMETA] = "KEY_RIGHTMETA",
|
||||
[KEY_COMPOSE] = "KEY_COMPOSE",
|
||||
[KEY_STOP] = "KEY_STOP",
|
||||
[KEY_AGAIN] = "KEY_AGAIN",
|
||||
[KEY_PROPS] = "KEY_PROPS",
|
||||
[KEY_UNDO] = "KEY_UNDO",
|
||||
[KEY_FRONT] = "KEY_FRONT",
|
||||
[KEY_COPY] = "KEY_COPY",
|
||||
[KEY_OPEN] = "KEY_OPEN",
|
||||
[KEY_PASTE] = "KEY_PASTE",
|
||||
[KEY_FIND] = "KEY_FIND",
|
||||
[KEY_CUT] = "KEY_CUT",
|
||||
[KEY_HELP] = "KEY_HELP",
|
||||
[KEY_MENU] = "KEY_MENU",
|
||||
[KEY_CALC] = "KEY_CALC",
|
||||
[KEY_SETUP] = "KEY_SETUP",
|
||||
[KEY_SLEEP] = "KEY_SLEEP",
|
||||
[KEY_WAKEUP] = "KEY_WAKEUP",
|
||||
[KEY_FILE] = "KEY_FILE",
|
||||
[KEY_SENDFILE] = "KEY_SENDFILE",
|
||||
[KEY_DELETEFILE] = "KEY_DELETEFILE",
|
||||
[KEY_XFER] = "KEY_XFER",
|
||||
[KEY_PROG1] = "KEY_PROG1",
|
||||
[KEY_PROG2] = "KEY_PROG2",
|
||||
[KEY_WWW] = "KEY_WWW",
|
||||
[KEY_MSDOS] = "KEY_MSDOS",
|
||||
[KEY_COFFEE] = "KEY_COFFEE",
|
||||
[KEY_DIRECTION] = "KEY_DIRECTION",
|
||||
[KEY_CYCLEWINDOWS] = "KEY_CYCLEWINDOWS",
|
||||
[KEY_MAIL] = "KEY_MAIL",
|
||||
[KEY_BOOKMARKS] = "KEY_BOOKMARKS",
|
||||
[KEY_COMPUTER] = "KEY_COMPUTER",
|
||||
[KEY_BACK] = "KEY_BACK",
|
||||
[KEY_FORWARD] = "KEY_FORWARD",
|
||||
[KEY_CLOSECD] = "KEY_CLOSECD",
|
||||
[KEY_EJECTCD] = "KEY_EJECTCD",
|
||||
[KEY_EJECTCLOSECD] = "KEY_EJECTCLOSECD",
|
||||
[KEY_NEXTSONG] = "KEY_NEXTSONG",
|
||||
[KEY_PLAYPAUSE] = "KEY_PLAYPAUSE",
|
||||
[KEY_PREVIOUSSONG] = "KEY_PREVIOUSSONG",
|
||||
[KEY_STOPCD] = "KEY_STOPCD",
|
||||
[KEY_RECORD] = "KEY_RECORD",
|
||||
[KEY_REWIND] = "KEY_REWIND",
|
||||
[KEY_PHONE] = "KEY_PHONE",
|
||||
[KEY_ISO] = "KEY_ISO",
|
||||
[KEY_CONFIG] = "KEY_CONFIG",
|
||||
[KEY_HOMEPAGE] = "KEY_HOMEPAGE",
|
||||
[KEY_REFRESH] = "KEY_REFRESH",
|
||||
[KEY_EXIT] = "KEY_EXIT",
|
||||
[KEY_MOVE] = "KEY_MOVE",
|
||||
[KEY_EDIT] = "KEY_EDIT",
|
||||
[KEY_SCROLLUP] = "KEY_SCROLLUP",
|
||||
[KEY_SCROLLDOWN] = "KEY_SCROLLDOWN",
|
||||
[KEY_KPLEFTPAREN] = "KEY_KPLEFTPAREN",
|
||||
[KEY_KPRIGHTPAREN] = "KEY_KPRIGHTPAREN",
|
||||
[KEY_NEW] = "KEY_NEW",
|
||||
[KEY_REDO] = "KEY_REDO",
|
||||
[KEY_F13] = "KEY_F13",
|
||||
[KEY_F14] = "KEY_F14",
|
||||
[KEY_F15] = "KEY_F15",
|
||||
[KEY_F16] = "KEY_F16",
|
||||
[KEY_F17] = "KEY_F17",
|
||||
[KEY_F18] = "KEY_F18",
|
||||
[KEY_F19] = "KEY_F19",
|
||||
[KEY_F20] = "KEY_F20",
|
||||
[KEY_F21] = "KEY_F21",
|
||||
[KEY_F22] = "KEY_F22",
|
||||
[KEY_F23] = "KEY_F23",
|
||||
[KEY_F24] = "KEY_F24",
|
||||
[KEY_PLAYCD] = "KEY_PLAYCD",
|
||||
[KEY_PAUSECD] = "KEY_PAUSECD",
|
||||
[KEY_PROG3] = "KEY_PROG3",
|
||||
[KEY_PROG4] = "KEY_PROG4",
|
||||
[KEY_DASHBOARD] = "KEY_DASHBOARD",
|
||||
[KEY_SUSPEND] = "KEY_SUSPEND",
|
||||
[KEY_CLOSE] = "KEY_CLOSE",
|
||||
[KEY_PLAY] = "KEY_PLAY",
|
||||
[KEY_FASTFORWARD] = "KEY_FASTFORWARD",
|
||||
[KEY_BASSBOOST] = "KEY_BASSBOOST",
|
||||
[KEY_PRINT] = "KEY_PRINT",
|
||||
[KEY_HP] = "KEY_HP",
|
||||
[KEY_CAMERA] = "KEY_CAMERA",
|
||||
[KEY_SOUND] = "KEY_SOUND",
|
||||
[KEY_QUESTION] = "KEY_QUESTION",
|
||||
[KEY_EMAIL] = "KEY_EMAIL",
|
||||
[KEY_CHAT] = "KEY_CHAT",
|
||||
[KEY_SEARCH] = "KEY_SEARCH",
|
||||
[KEY_CONNECT] = "KEY_CONNECT",
|
||||
[KEY_FINANCE] = "KEY_FINANCE",
|
||||
[KEY_SPORT] = "KEY_SPORT",
|
||||
[KEY_SHOP] = "KEY_SHOP",
|
||||
[KEY_ALTERASE] = "KEY_ALTERASE",
|
||||
[KEY_CANCEL] = "KEY_CANCEL",
|
||||
[KEY_BRIGHTNESSDOWN] = "KEY_BRIGHTNESSDOWN",
|
||||
[KEY_BRIGHTNESSUP] = "KEY_BRIGHTNESSUP",
|
||||
[KEY_MEDIA] = "KEY_MEDIA",
|
||||
[KEY_SWITCHVIDEOMODE] = "KEY_SWITCHVIDEOMODE",
|
||||
[KEY_KBDILLUMTOGGLE] = "KEY_KBDILLUMTOGGLE",
|
||||
[KEY_KBDILLUMDOWN] = "KEY_KBDILLUMDOWN",
|
||||
[KEY_KBDILLUMUP] = "KEY_KBDILLUMUP",
|
||||
[KEY_SEND] = "KEY_SEND",
|
||||
[KEY_REPLY] = "KEY_REPLY",
|
||||
[KEY_FORWARDMAIL] = "KEY_FORWARDMAIL",
|
||||
[KEY_SAVE] = "KEY_SAVE",
|
||||
[KEY_DOCUMENTS] = "KEY_DOCUMENTS",
|
||||
[KEY_BATTERY] = "KEY_BATTERY",
|
||||
[KEY_BLUETOOTH] = "KEY_BLUETOOTH",
|
||||
[KEY_WLAN] = "KEY_WLAN",
|
||||
[KEY_UWB] = "KEY_UWB",
|
||||
[KEY_UNKNOWN] = "KEY_UNKNOWN",
|
||||
[KEY_VIDEO_NEXT] = "KEY_VIDEO_NEXT",
|
||||
[KEY_VIDEO_PREV] = "KEY_VIDEO_PREV",
|
||||
[KEY_BRIGHTNESS_CYCLE] = "KEY_BRIGHTNESS_CYCLE",
|
||||
[KEY_BRIGHTNESS_ZERO] = "KEY_BRIGHTNESS_ZERO",
|
||||
[KEY_DISPLAY_OFF] = "KEY_DISPLAY_OFF",
|
||||
[KEY_WIMAX] = "KEY_WIMAX",
|
||||
[KEY_RFKILL] = "KEY_RFKILL",
|
||||
[KEY_MICMUTE] = "KEY_MICMUTE",
|
||||
[BTN_0] = "BTN_0",
|
||||
[BTN_1] = "BTN_1",
|
||||
[BTN_2] = "BTN_2",
|
||||
[BTN_3] = "BTN_3",
|
||||
[BTN_4] = "BTN_4",
|
||||
[BTN_5] = "BTN_5",
|
||||
[BTN_6] = "BTN_6",
|
||||
[BTN_7] = "BTN_7",
|
||||
[BTN_8] = "BTN_8",
|
||||
[BTN_9] = "BTN_9",
|
||||
[BTN_LEFT] = "BTN_LEFT",
|
||||
[BTN_RIGHT] = "BTN_RIGHT",
|
||||
[BTN_MIDDLE] = "BTN_MIDDLE",
|
||||
[BTN_SIDE] = "BTN_SIDE",
|
||||
[BTN_EXTRA] = "BTN_EXTRA",
|
||||
[BTN_FORWARD] = "BTN_FORWARD",
|
||||
[BTN_BACK] = "BTN_BACK",
|
||||
[BTN_TASK] = "BTN_TASK",
|
||||
[BTN_TRIGGER] = "BTN_TRIGGER",
|
||||
[BTN_THUMB] = "BTN_THUMB",
|
||||
[BTN_THUMB2] = "BTN_THUMB2",
|
||||
[BTN_TOP] = "BTN_TOP",
|
||||
[BTN_TOP2] = "BTN_TOP2",
|
||||
[BTN_PINKIE] = "BTN_PINKIE",
|
||||
[BTN_BASE] = "BTN_BASE",
|
||||
[BTN_BASE2] = "BTN_BASE2",
|
||||
[BTN_BASE3] = "BTN_BASE3",
|
||||
[BTN_BASE4] = "BTN_BASE4",
|
||||
[BTN_BASE5] = "BTN_BASE5",
|
||||
[BTN_BASE6] = "BTN_BASE6",
|
||||
[BTN_DEAD] = "BTN_DEAD",
|
||||
[BTN_A] = "BTN_A",
|
||||
[BTN_B] = "BTN_B",
|
||||
[BTN_C] = "BTN_C",
|
||||
[BTN_X] = "BTN_X",
|
||||
[BTN_Y] = "BTN_Y",
|
||||
[BTN_Z] = "BTN_Z",
|
||||
[BTN_TL] = "BTN_TL",
|
||||
[BTN_TR] = "BTN_TR",
|
||||
[BTN_TL2] = "BTN_TL2",
|
||||
[BTN_TR2] = "BTN_TR2",
|
||||
[BTN_SELECT] = "BTN_SELECT",
|
||||
[BTN_START] = "BTN_START",
|
||||
[BTN_MODE] = "BTN_MODE",
|
||||
[BTN_THUMBL] = "BTN_THUMBL",
|
||||
[BTN_THUMBR] = "BTN_THUMBR",
|
||||
[BTN_TOOL_PEN] = "BTN_TOOL_PEN",
|
||||
[BTN_TOOL_RUBBER] = "BTN_TOOL_RUBBER",
|
||||
[BTN_TOOL_BRUSH] = "BTN_TOOL_BRUSH",
|
||||
[BTN_TOOL_PENCIL] = "BTN_TOOL_PENCIL",
|
||||
[BTN_TOOL_AIRBRUSH] = "BTN_TOOL_AIRBRUSH",
|
||||
[BTN_TOOL_FINGER] = "BTN_TOOL_FINGER",
|
||||
[BTN_TOOL_MOUSE] = "BTN_TOOL_MOUSE",
|
||||
[BTN_TOOL_LENS] = "BTN_TOOL_LENS",
|
||||
[BTN_TOOL_QUINTTAP] = "BTN_TOOL_QUINTTAP",
|
||||
[BTN_TOUCH] = "BTN_TOUCH",
|
||||
[BTN_STYLUS] = "BTN_STYLUS",
|
||||
[BTN_STYLUS2] = "BTN_STYLUS2",
|
||||
[BTN_TOOL_DOUBLETAP] = "BTN_TOOL_DOUBLETAP",
|
||||
[BTN_TOOL_TRIPLETAP] = "BTN_TOOL_TRIPLETAP",
|
||||
[BTN_TOOL_QUADTAP] = "BTN_TOOL_QUADTAP",
|
||||
[BTN_GEAR_DOWN] = "BTN_GEAR_DOWN",
|
||||
[BTN_GEAR_UP] = "BTN_GEAR_UP",
|
||||
[KEY_OK] = "KEY_OK",
|
||||
[KEY_SELECT] = "KEY_SELECT",
|
||||
[KEY_GOTO] = "KEY_GOTO",
|
||||
[KEY_CLEAR] = "KEY_CLEAR",
|
||||
[KEY_POWER2] = "KEY_POWER2",
|
||||
[KEY_OPTION] = "KEY_OPTION",
|
||||
[KEY_INFO] = "KEY_INFO",
|
||||
[KEY_TIME] = "KEY_TIME",
|
||||
[KEY_VENDOR] = "KEY_VENDOR",
|
||||
[KEY_ARCHIVE] = "KEY_ARCHIVE",
|
||||
[KEY_PROGRAM] = "KEY_PROGRAM",
|
||||
[KEY_CHANNEL] = "KEY_CHANNEL",
|
||||
[KEY_FAVORITES] = "KEY_FAVORITES",
|
||||
[KEY_EPG] = "KEY_EPG",
|
||||
[KEY_PVR] = "KEY_PVR",
|
||||
[KEY_MHP] = "KEY_MHP",
|
||||
[KEY_LANGUAGE] = "KEY_LANGUAGE",
|
||||
[KEY_TITLE] = "KEY_TITLE",
|
||||
[KEY_SUBTITLE] = "KEY_SUBTITLE",
|
||||
[KEY_ANGLE] = "KEY_ANGLE",
|
||||
[KEY_ZOOM] = "KEY_ZOOM",
|
||||
[KEY_MODE] = "KEY_MODE",
|
||||
[KEY_KEYBOARD] = "KEY_KEYBOARD",
|
||||
[KEY_SCREEN] = "KEY_SCREEN",
|
||||
[KEY_PC] = "KEY_PC",
|
||||
[KEY_TV] = "KEY_TV",
|
||||
[KEY_TV2] = "KEY_TV2",
|
||||
[KEY_VCR] = "KEY_VCR",
|
||||
[KEY_VCR2] = "KEY_VCR2",
|
||||
[KEY_SAT] = "KEY_SAT",
|
||||
[KEY_SAT2] = "KEY_SAT2",
|
||||
[KEY_CD] = "KEY_CD",
|
||||
[KEY_TAPE] = "KEY_TAPE",
|
||||
[KEY_RADIO] = "KEY_RADIO",
|
||||
[KEY_TUNER] = "KEY_TUNER",
|
||||
[KEY_PLAYER] = "KEY_PLAYER",
|
||||
[KEY_TEXT] = "KEY_TEXT",
|
||||
[KEY_DVD] = "KEY_DVD",
|
||||
[KEY_AUX] = "KEY_AUX",
|
||||
[KEY_MP3] = "KEY_MP3",
|
||||
[KEY_AUDIO] = "KEY_AUDIO",
|
||||
[KEY_VIDEO] = "KEY_VIDEO",
|
||||
[KEY_DIRECTORY] = "KEY_DIRECTORY",
|
||||
[KEY_LIST] = "KEY_LIST",
|
||||
[KEY_MEMO] = "KEY_MEMO",
|
||||
[KEY_CALENDAR] = "KEY_CALENDAR",
|
||||
[KEY_RED] = "KEY_RED",
|
||||
[KEY_GREEN] = "KEY_GREEN",
|
||||
[KEY_YELLOW] = "KEY_YELLOW",
|
||||
[KEY_BLUE] = "KEY_BLUE",
|
||||
[KEY_CHANNELUP] = "KEY_CHANNELUP",
|
||||
[KEY_CHANNELDOWN] = "KEY_CHANNELDOWN",
|
||||
[KEY_FIRST] = "KEY_FIRST",
|
||||
[KEY_LAST] = "KEY_LAST",
|
||||
[KEY_AB] = "KEY_AB",
|
||||
[KEY_NEXT] = "KEY_NEXT",
|
||||
[KEY_RESTART] = "KEY_RESTART",
|
||||
[KEY_SLOW] = "KEY_SLOW",
|
||||
[KEY_SHUFFLE] = "KEY_SHUFFLE",
|
||||
[KEY_BREAK] = "KEY_BREAK",
|
||||
[KEY_PREVIOUS] = "KEY_PREVIOUS",
|
||||
[KEY_DIGITS] = "KEY_DIGITS",
|
||||
[KEY_TEEN] = "KEY_TEEN",
|
||||
[KEY_TWEN] = "KEY_TWEN",
|
||||
[KEY_VIDEOPHONE] = "KEY_VIDEOPHONE",
|
||||
[KEY_GAMES] = "KEY_GAMES",
|
||||
[KEY_ZOOMIN] = "KEY_ZOOMIN",
|
||||
[KEY_ZOOMOUT] = "KEY_ZOOMOUT",
|
||||
[KEY_ZOOMRESET] = "KEY_ZOOMRESET",
|
||||
[KEY_WORDPROCESSOR] = "KEY_WORDPROCESSOR",
|
||||
[KEY_EDITOR] = "KEY_EDITOR",
|
||||
[KEY_SPREADSHEET] = "KEY_SPREADSHEET",
|
||||
[KEY_GRAPHICSEDITOR] = "KEY_GRAPHICSEDITOR",
|
||||
[KEY_PRESENTATION] = "KEY_PRESENTATION",
|
||||
[KEY_DATABASE] = "KEY_DATABASE",
|
||||
[KEY_NEWS] = "KEY_NEWS",
|
||||
[KEY_VOICEMAIL] = "KEY_VOICEMAIL",
|
||||
[KEY_ADDRESSBOOK] = "KEY_ADDRESSBOOK",
|
||||
[KEY_MESSENGER] = "KEY_MESSENGER",
|
||||
[KEY_DISPLAYTOGGLE] = "KEY_DISPLAYTOGGLE",
|
||||
[KEY_SPELLCHECK] = "KEY_SPELLCHECK",
|
||||
[KEY_LOGOFF] = "KEY_LOGOFF",
|
||||
[KEY_DOLLAR] = "KEY_DOLLAR",
|
||||
[KEY_EURO] = "KEY_EURO",
|
||||
[KEY_FRAMEBACK] = "KEY_FRAMEBACK",
|
||||
[KEY_FRAMEFORWARD] = "KEY_FRAMEFORWARD",
|
||||
[KEY_CONTEXT_MENU] = "KEY_CONTEXT_MENU",
|
||||
[KEY_MEDIA_REPEAT] = "KEY_MEDIA_REPEAT",
|
||||
[KEY_10CHANNELSUP] = "KEY_10CHANNELSUP",
|
||||
[KEY_10CHANNELSDOWN] = "KEY_10CHANNELSDOWN",
|
||||
[KEY_IMAGES] = "KEY_IMAGES",
|
||||
[KEY_DEL_EOL] = "KEY_DEL_EOL",
|
||||
[KEY_DEL_EOS] = "KEY_DEL_EOS",
|
||||
[KEY_INS_LINE] = "KEY_INS_LINE",
|
||||
[KEY_DEL_LINE] = "KEY_DEL_LINE",
|
||||
[KEY_FN] = "KEY_FN",
|
||||
[KEY_FN_ESC] = "KEY_FN_ESC",
|
||||
[KEY_FN_F1] = "KEY_FN_F1",
|
||||
[KEY_FN_F2] = "KEY_FN_F2",
|
||||
[KEY_FN_F3] = "KEY_FN_F3",
|
||||
[KEY_FN_F4] = "KEY_FN_F4",
|
||||
[KEY_FN_F5] = "KEY_FN_F5",
|
||||
[KEY_FN_F6] = "KEY_FN_F6",
|
||||
[KEY_FN_F7] = "KEY_FN_F7",
|
||||
[KEY_FN_F8] = "KEY_FN_F8",
|
||||
[KEY_FN_F9] = "KEY_FN_F9",
|
||||
[KEY_FN_F10] = "KEY_FN_F10",
|
||||
[KEY_FN_F11] = "KEY_FN_F11",
|
||||
[KEY_FN_F12] = "KEY_FN_F12",
|
||||
[KEY_FN_1] = "KEY_FN_1",
|
||||
[KEY_FN_2] = "KEY_FN_2",
|
||||
[KEY_FN_D] = "KEY_FN_D",
|
||||
[KEY_FN_E] = "KEY_FN_E",
|
||||
[KEY_FN_F] = "KEY_FN_F",
|
||||
[KEY_FN_S] = "KEY_FN_S",
|
||||
[KEY_FN_B] = "KEY_FN_B",
|
||||
[KEY_BRL_DOT1] = "KEY_BRL_DOT1",
|
||||
[KEY_BRL_DOT2] = "KEY_BRL_DOT2",
|
||||
[KEY_BRL_DOT3] = "KEY_BRL_DOT3",
|
||||
[KEY_BRL_DOT4] = "KEY_BRL_DOT4",
|
||||
[KEY_BRL_DOT5] = "KEY_BRL_DOT5",
|
||||
[KEY_BRL_DOT6] = "KEY_BRL_DOT6",
|
||||
[KEY_BRL_DOT7] = "KEY_BRL_DOT7",
|
||||
[KEY_BRL_DOT8] = "KEY_BRL_DOT8",
|
||||
[KEY_BRL_DOT9] = "KEY_BRL_DOT9",
|
||||
[KEY_BRL_DOT10] = "KEY_BRL_DOT10",
|
||||
[KEY_NUMERIC_0] = "KEY_NUMERIC_0",
|
||||
[KEY_NUMERIC_1] = "KEY_NUMERIC_1",
|
||||
[KEY_NUMERIC_2] = "KEY_NUMERIC_2",
|
||||
[KEY_NUMERIC_3] = "KEY_NUMERIC_3",
|
||||
[KEY_NUMERIC_4] = "KEY_NUMERIC_4",
|
||||
[KEY_NUMERIC_5] = "KEY_NUMERIC_5",
|
||||
[KEY_NUMERIC_6] = "KEY_NUMERIC_6",
|
||||
[KEY_NUMERIC_7] = "KEY_NUMERIC_7",
|
||||
[KEY_NUMERIC_8] = "KEY_NUMERIC_8",
|
||||
[KEY_NUMERIC_9] = "KEY_NUMERIC_9",
|
||||
[KEY_NUMERIC_STAR] = "KEY_NUMERIC_STAR",
|
||||
[KEY_NUMERIC_POUND] = "KEY_NUMERIC_POUND",
|
||||
[KEY_CAMERA_FOCUS] = "KEY_CAMERA_FOCUS",
|
||||
[KEY_WPS_BUTTON] = "KEY_WPS_BUTTON",
|
||||
[KEY_TOUCHPAD_TOGGLE] = "KEY_TOUCHPAD_TOGGLE",
|
||||
[KEY_TOUCHPAD_ON] = "KEY_TOUCHPAD_ON",
|
||||
[KEY_TOUCHPAD_OFF] = "KEY_TOUCHPAD_OFF",
|
||||
[KEY_CAMERA_ZOOMIN] = "KEY_CAMERA_ZOOMIN",
|
||||
[KEY_CAMERA_ZOOMOUT] = "KEY_CAMERA_ZOOMOUT",
|
||||
[KEY_CAMERA_UP] = "KEY_CAMERA_UP",
|
||||
[KEY_CAMERA_DOWN] = "KEY_CAMERA_DOWN",
|
||||
[KEY_CAMERA_LEFT] = "KEY_CAMERA_LEFT",
|
||||
[KEY_CAMERA_RIGHT] = "KEY_CAMERA_RIGHT",
|
||||
[BTN_TRIGGER_HAPPY1] = "BTN_TRIGGER_HAPPY1",
|
||||
[BTN_TRIGGER_HAPPY2] = "BTN_TRIGGER_HAPPY2",
|
||||
[BTN_TRIGGER_HAPPY3] = "BTN_TRIGGER_HAPPY3",
|
||||
[BTN_TRIGGER_HAPPY4] = "BTN_TRIGGER_HAPPY4",
|
||||
[BTN_TRIGGER_HAPPY5] = "BTN_TRIGGER_HAPPY5",
|
||||
[BTN_TRIGGER_HAPPY6] = "BTN_TRIGGER_HAPPY6",
|
||||
[BTN_TRIGGER_HAPPY7] = "BTN_TRIGGER_HAPPY7",
|
||||
[BTN_TRIGGER_HAPPY8] = "BTN_TRIGGER_HAPPY8",
|
||||
[BTN_TRIGGER_HAPPY9] = "BTN_TRIGGER_HAPPY9",
|
||||
[BTN_TRIGGER_HAPPY10] = "BTN_TRIGGER_HAPPY10",
|
||||
[BTN_TRIGGER_HAPPY11] = "BTN_TRIGGER_HAPPY11",
|
||||
[BTN_TRIGGER_HAPPY12] = "BTN_TRIGGER_HAPPY12",
|
||||
[BTN_TRIGGER_HAPPY13] = "BTN_TRIGGER_HAPPY13",
|
||||
[BTN_TRIGGER_HAPPY14] = "BTN_TRIGGER_HAPPY14",
|
||||
[BTN_TRIGGER_HAPPY15] = "BTN_TRIGGER_HAPPY15",
|
||||
[BTN_TRIGGER_HAPPY16] = "BTN_TRIGGER_HAPPY16",
|
||||
[BTN_TRIGGER_HAPPY17] = "BTN_TRIGGER_HAPPY17",
|
||||
[BTN_TRIGGER_HAPPY18] = "BTN_TRIGGER_HAPPY18",
|
||||
[BTN_TRIGGER_HAPPY19] = "BTN_TRIGGER_HAPPY19",
|
||||
[BTN_TRIGGER_HAPPY20] = "BTN_TRIGGER_HAPPY20",
|
||||
[BTN_TRIGGER_HAPPY21] = "BTN_TRIGGER_HAPPY21",
|
||||
[BTN_TRIGGER_HAPPY22] = "BTN_TRIGGER_HAPPY22",
|
||||
[BTN_TRIGGER_HAPPY23] = "BTN_TRIGGER_HAPPY23",
|
||||
[BTN_TRIGGER_HAPPY24] = "BTN_TRIGGER_HAPPY24",
|
||||
[BTN_TRIGGER_HAPPY25] = "BTN_TRIGGER_HAPPY25",
|
||||
[BTN_TRIGGER_HAPPY26] = "BTN_TRIGGER_HAPPY26",
|
||||
[BTN_TRIGGER_HAPPY27] = "BTN_TRIGGER_HAPPY27",
|
||||
[BTN_TRIGGER_HAPPY28] = "BTN_TRIGGER_HAPPY28",
|
||||
[BTN_TRIGGER_HAPPY29] = "BTN_TRIGGER_HAPPY29",
|
||||
[BTN_TRIGGER_HAPPY30] = "BTN_TRIGGER_HAPPY30",
|
||||
[BTN_TRIGGER_HAPPY31] = "BTN_TRIGGER_HAPPY31",
|
||||
[BTN_TRIGGER_HAPPY32] = "BTN_TRIGGER_HAPPY32",
|
||||
[BTN_TRIGGER_HAPPY33] = "BTN_TRIGGER_HAPPY33",
|
||||
[BTN_TRIGGER_HAPPY34] = "BTN_TRIGGER_HAPPY34",
|
||||
[BTN_TRIGGER_HAPPY35] = "BTN_TRIGGER_HAPPY35",
|
||||
[BTN_TRIGGER_HAPPY36] = "BTN_TRIGGER_HAPPY36",
|
||||
[BTN_TRIGGER_HAPPY37] = "BTN_TRIGGER_HAPPY37",
|
||||
[BTN_TRIGGER_HAPPY38] = "BTN_TRIGGER_HAPPY38",
|
||||
[BTN_TRIGGER_HAPPY39] = "BTN_TRIGGER_HAPPY39",
|
||||
[BTN_TRIGGER_HAPPY40] = "BTN_TRIGGER_HAPPY40",
|
||||
[KEY_MAX] = "KEY_MAX",
|
||||
};
|
||||
|
||||
static const char * const led_map[LED_MAX + 1] = {
|
||||
[0 ... LED_MAX] = NULL,
|
||||
[LED_NUML] = "LED_NUML",
|
||||
[LED_CAPSL] = "LED_CAPSL",
|
||||
[LED_SCROLLL] = "LED_SCROLLL",
|
||||
[LED_COMPOSE] = "LED_COMPOSE",
|
||||
[LED_KANA] = "LED_KANA",
|
||||
[LED_SLEEP] = "LED_SLEEP",
|
||||
[LED_SUSPEND] = "LED_SUSPEND",
|
||||
[LED_MUTE] = "LED_MUTE",
|
||||
[LED_MISC] = "LED_MISC",
|
||||
[LED_MAIL] = "LED_MAIL",
|
||||
[LED_CHARGING] = "LED_CHARGING",
|
||||
[LED_MAX] = "LED_MAX",
|
||||
};
|
||||
|
||||
static const char * const snd_map[SND_MAX + 1] = {
|
||||
[0 ... SND_MAX] = NULL,
|
||||
[SND_CLICK] = "SND_CLICK",
|
||||
[SND_BELL] = "SND_BELL",
|
||||
[SND_TONE] = "SND_TONE",
|
||||
[SND_MAX] = "SND_MAX",
|
||||
};
|
||||
|
||||
static const char * const msc_map[MSC_MAX + 1] = {
|
||||
[0 ... MSC_MAX] = NULL,
|
||||
[MSC_SERIAL] = "MSC_SERIAL",
|
||||
[MSC_PULSELED] = "MSC_PULSELED",
|
||||
[MSC_GESTURE] = "MSC_GESTURE",
|
||||
[MSC_RAW] = "MSC_RAW",
|
||||
[MSC_SCAN] = "MSC_SCAN",
|
||||
[MSC_TIMESTAMP] = "MSC_TIMESTAMP",
|
||||
[MSC_MAX] = "MSC_MAX",
|
||||
};
|
||||
|
||||
static const char * const sw_map[SW_MAX + 1] = {
|
||||
[0 ... SW_MAX] = NULL,
|
||||
[SW_LID] = "SW_LID",
|
||||
[SW_TABLET_MODE] = "SW_TABLET_MODE",
|
||||
[SW_HEADPHONE_INSERT] = "SW_HEADPHONE_INSERT",
|
||||
[SW_RFKILL_ALL] = "SW_RFKILL_ALL",
|
||||
[SW_MICROPHONE_INSERT] = "SW_MICROPHONE_INSERT",
|
||||
[SW_DOCK] = "SW_DOCK",
|
||||
[SW_LINEOUT_INSERT] = "SW_LINEOUT_INSERT",
|
||||
[SW_JACK_PHYSICAL_INSERT] = "SW_JACK_PHYSICAL_INSERT",
|
||||
[SW_VIDEOOUT_INSERT] = "SW_VIDEOOUT_INSERT",
|
||||
[SW_CAMERA_LENS_COVER] = "SW_CAMERA_LENS_COVER",
|
||||
[SW_KEYPAD_SLIDE] = "SW_KEYPAD_SLIDE",
|
||||
[SW_FRONT_PROXIMITY] = "SW_FRONT_PROXIMITY",
|
||||
[SW_ROTATE_LOCK] = "SW_ROTATE_LOCK",
|
||||
[SW_LINEIN_INSERT] = "SW_LINEIN_INSERT",
|
||||
[SW_MAX] = "SW_MAX",
|
||||
};
|
||||
|
||||
static const char * const ff_map[FF_MAX + 1] = {
|
||||
[0 ... FF_MAX] = NULL,
|
||||
[FF_STATUS_STOPPED] = "FF_STATUS_STOPPED",
|
||||
[FF_STATUS_MAX] = "FF_STATUS_MAX",
|
||||
[FF_AUTOCENTER] = "FF_AUTOCENTER",
|
||||
[FF_GAIN] = "FF_GAIN",
|
||||
[FF_RUMBLE] = "FF_RUMBLE",
|
||||
[FF_PERIODIC] = "FF_PERIODIC",
|
||||
[FF_CONSTANT] = "FF_CONSTANT",
|
||||
[FF_SPRING] = "FF_SPRING",
|
||||
[FF_FRICTION] = "FF_FRICTION",
|
||||
[FF_DAMPER] = "FF_DAMPER",
|
||||
[FF_INERTIA] = "FF_INERTIA",
|
||||
[FF_RAMP] = "FF_RAMP",
|
||||
[FF_SQUARE] = "FF_SQUARE",
|
||||
[FF_TRIANGLE] = "FF_TRIANGLE",
|
||||
[FF_SINE] = "FF_SINE",
|
||||
[FF_SAW_UP] = "FF_SAW_UP",
|
||||
[FF_SAW_DOWN] = "FF_SAW_DOWN",
|
||||
[FF_CUSTOM] = "FF_CUSTOM",
|
||||
[FF_MAX] = "FF_MAX",
|
||||
};
|
||||
|
||||
static const char * const syn_map[SYN_MAX + 1] = {
|
||||
[0 ... SYN_MAX] = NULL,
|
||||
[SYN_REPORT] = "SYN_REPORT",
|
||||
[SYN_CONFIG] = "SYN_CONFIG",
|
||||
[SYN_MT_REPORT] = "SYN_MT_REPORT",
|
||||
[SYN_DROPPED] = "SYN_DROPPED",
|
||||
};
|
||||
|
||||
static const char * const input_prop_map[INPUT_PROP_MAX + 1] = {
|
||||
[0 ... INPUT_PROP_MAX] = NULL,
|
||||
[INPUT_PROP_POINTER] = "INPUT_PROP_POINTER",
|
||||
[INPUT_PROP_DIRECT] = "INPUT_PROP_DIRECT",
|
||||
[INPUT_PROP_BUTTONPAD] = "INPUT_PROP_BUTTONPAD",
|
||||
[INPUT_PROP_SEMI_MT] = "INPUT_PROP_SEMI_MT",
|
||||
[INPUT_PROP_MAX] = "INPUT_PROP_MAX",
|
||||
};
|
||||
|
||||
static const char * const * const map[EV_MAX + 1] = {
|
||||
[0 ... EV_MAX] = NULL,
|
||||
[EV_REL] = rel_map,
|
||||
[EV_ABS] = abs_map,
|
||||
[EV_KEY] = key_map,
|
||||
[EV_LED] = led_map,
|
||||
[EV_SND] = snd_map,
|
||||
[EV_MSC] = msc_map,
|
||||
[EV_SW] = sw_map,
|
||||
[EV_FF] = ff_map,
|
||||
[EV_SYN] = syn_map,
|
||||
};
|
||||
|
||||
static const char * event_get_type_name(int type) {
|
||||
return ev_map[type];
|
||||
}
|
||||
|
||||
static const char * event_get_code_name(int type, int code) {
|
||||
return map[type] ? map[type][code] : NULL;
|
||||
}
|
||||
|
||||
#endif /* EVENT_NAMES_H */
|
||||
120
test/libevdev-events.c
Normal file
120
test/libevdev-events.c
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* Copyright © 2013 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.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
#include <linux/input.h>
|
||||
|
||||
#include "libevdev.h"
|
||||
#include "event-names.h"
|
||||
|
||||
void
|
||||
print_code_bits(struct libevdev *dev, unsigned int type, unsigned int max)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i <= max; i++) {
|
||||
if (libevdev_has_event_code(dev, type, i))
|
||||
printf("%s: %s\n",
|
||||
event_get_type_name(type),
|
||||
event_get_code_name(type, i));
|
||||
}
|
||||
}
|
||||
|
||||
int callback(struct libevdev *dev, struct input_event *ev, void *userdata)
|
||||
{
|
||||
if (ev->type == EV_SYN)
|
||||
printf("Event: time %ld.%06ld, ++++++++++++++++++++ %s +++++++++++++++\n",
|
||||
ev->time.tv_sec,
|
||||
ev->time.tv_usec,
|
||||
event_get_type_name(ev->type));
|
||||
else
|
||||
printf("Event: time %ld.%06ld, type %d (%s), code %d (%s), value %d\n",
|
||||
ev->time.tv_sec,
|
||||
ev->time.tv_usec,
|
||||
ev->type,
|
||||
event_get_type_name(ev->type),
|
||||
ev->code,
|
||||
event_get_code_name(ev->type, ev->code),
|
||||
ev->value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sync_callback(struct libevdev *dev, struct input_event *ev, void *userdata)
|
||||
{
|
||||
printf("SYNC: ");
|
||||
callback(dev, ev, userdata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct libevdev *dev = NULL;
|
||||
const char *file;
|
||||
int fd;
|
||||
int rc = 1;
|
||||
|
||||
if (argc < 2)
|
||||
goto out;
|
||||
|
||||
file = argv[1];
|
||||
fd = open(file, O_RDONLY | O_NONBLOCK);
|
||||
if (fd < 0) {
|
||||
perror("Failed to open device");
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev = libevdev_new(fd);
|
||||
if (!dev) {
|
||||
fprintf(stderr, "Failed to init libevdev\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (libevdev_set_callbacks(dev, &callback, &sync_callback, NULL) != 0) {
|
||||
fprintf(stderr, "Failed to set callbacks");
|
||||
goto out;
|
||||
}
|
||||
|
||||
do {
|
||||
rc = libevdev_read_events(dev, ER_ALL);
|
||||
if (rc == 1) {
|
||||
printf("::::::::::::::::::::: dropped ::::::::::::::::::::::\n");
|
||||
rc = libevdev_read_events(dev, ER_ALL | ER_SYNC);
|
||||
}
|
||||
} while (rc == 1 || rc == 0 || rc == -EAGAIN);
|
||||
|
||||
if (rc != 0 && rc != -EAGAIN)
|
||||
fprintf(stderr, "Failed to handle events: %s\n", strerror(rc));
|
||||
|
||||
rc = 0;
|
||||
out:
|
||||
libevdev_free(dev);
|
||||
|
||||
return rc;
|
||||
}
|
||||
143
test/libevdev-print.c
Normal file
143
test/libevdev-print.c
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* Copyright © 2013 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.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
#include <linux/input.h>
|
||||
|
||||
#include "libevdev.h"
|
||||
#include "event-names.h"
|
||||
|
||||
static void
|
||||
print_abs_bits(struct libevdev *dev, int axis)
|
||||
{
|
||||
const struct input_absinfo *abs;
|
||||
|
||||
if (!libevdev_has_event_code(dev, EV_ABS, axis))
|
||||
return;
|
||||
|
||||
abs = libevdev_get_abs_info(dev, axis);
|
||||
|
||||
printf(" Value %6d\n", abs->value);
|
||||
printf(" Min %6d\n", abs->minimum);
|
||||
printf(" Max %6d\n", abs->maximum);
|
||||
if (abs->fuzz)
|
||||
printf(" Fuzz %6d\n", abs->fuzz);
|
||||
if (abs->flat)
|
||||
printf(" Flat %6d\n", abs->flat);
|
||||
if (abs->resolution)
|
||||
printf(" Resolution %6d\n", abs->resolution);
|
||||
}
|
||||
|
||||
static void
|
||||
print_code_bits(struct libevdev *dev, unsigned int type, unsigned int max)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i <= max; i++) {
|
||||
if (!libevdev_has_event_code(dev, type, i))
|
||||
continue;
|
||||
|
||||
printf(" Event code %i (%s)\n", i, event_get_code_name(type, i));
|
||||
if (type == EV_ABS)
|
||||
print_abs_bits(dev, i);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_bits(struct libevdev *dev)
|
||||
{
|
||||
unsigned int i;
|
||||
printf("Supported events:\n");
|
||||
|
||||
for (i = 0; i <= EV_MAX; i++) {
|
||||
if (libevdev_has_event_type(dev, i))
|
||||
printf(" Event type %d (%s)\n", i, event_get_type_name(i));
|
||||
switch(i) {
|
||||
case EV_KEY:
|
||||
print_code_bits(dev, EV_KEY, KEY_MAX);
|
||||
break;
|
||||
case EV_REL:
|
||||
print_code_bits(dev, EV_REL, REL_MAX);
|
||||
break;
|
||||
case EV_ABS:
|
||||
print_code_bits(dev, EV_ABS, ABS_MAX);
|
||||
break;
|
||||
case EV_LED:
|
||||
print_code_bits(dev, EV_LED, LED_MAX);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_props(struct libevdev *dev)
|
||||
{
|
||||
unsigned int i;
|
||||
printf("Properties:\n");
|
||||
|
||||
for (i = 0; i <= INPUT_PROP_MAX; i++) {
|
||||
if (libevdev_has_property(dev, i))
|
||||
printf(" Property type %d (%s)\n", i, input_prop_map[i]);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct libevdev *dev;
|
||||
const char *file;
|
||||
int fd;
|
||||
|
||||
|
||||
if (argc < 2)
|
||||
return 1;
|
||||
|
||||
file = argv[1];
|
||||
fd = open(file, O_RDONLY | O_NONBLOCK);
|
||||
if (fd < 0) {
|
||||
perror("Failed to open device");
|
||||
return 1;
|
||||
}
|
||||
|
||||
dev = libevdev_new(fd);
|
||||
if (!dev) {
|
||||
fprintf(stderr, "Failed to init libevdev\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Input device ID: bus %#x vendor %#x product %#x\n",
|
||||
libevdev_get_bustype(dev),
|
||||
libevdev_get_vid(dev),
|
||||
libevdev_get_pid(dev));
|
||||
printf("Input device name: \"%s\"\n", libevdev_get_name(dev));
|
||||
print_bits(dev);
|
||||
print_props(dev);
|
||||
|
||||
libevdev_free(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue