summaryrefslogtreecommitdiff
path: root/Source/DirectFB/inputdrivers/linux_input
diff options
context:
space:
mode:
Diffstat (limited to 'Source/DirectFB/inputdrivers/linux_input')
-rwxr-xr-xSource/DirectFB/inputdrivers/linux_input/Makefile.am34
-rwxr-xr-xSource/DirectFB/inputdrivers/linux_input/Makefile.in601
-rwxr-xr-xSource/DirectFB/inputdrivers/linux_input/input_fake.h84
-rwxr-xr-xSource/DirectFB/inputdrivers/linux_input/linux_input.c1994
4 files changed, 2713 insertions, 0 deletions
diff --git a/Source/DirectFB/inputdrivers/linux_input/Makefile.am b/Source/DirectFB/inputdrivers/linux_input/Makefile.am
new file mode 100755
index 0000000..eb4265a
--- /dev/null
+++ b/Source/DirectFB/inputdrivers/linux_input/Makefile.am
@@ -0,0 +1,34 @@
+## Makefile.am for DirectFB/inputdrivers/linux_input
+
+INCLUDES = \
+ -I$(top_builddir)/include \
+ -I$(top_srcdir)/include \
+ -I$(top_builddir)/lib \
+ -I$(top_srcdir)/lib \
+ -I$(top_srcdir)/src \
+ -I$(top_srcdir)/systems
+
+linux_input_LTLIBRARIES = libdirectfb_linux_input.la
+
+if BUILD_STATIC
+linux_input_DATA = $(linux_input_LTLIBRARIES:.la=.o)
+endif
+
+linux_inputdir = $(MODULEDIR)/inputdrivers
+
+libdirectfb_linux_input_la_SOURCES = \
+ input_fake.h \
+ linux_input.c
+
+libdirectfb_linux_input_la_LDFLAGS = \
+ -module \
+ -avoid-version \
+ $(DFB_LDFLAGS)
+
+libdirectfb_linux_input_la_LIBADD = \
+ $(top_builddir)/lib/direct/libdirect.la \
+ $(top_builddir)/src/libdirectfb.la
+
+
+include $(top_srcdir)/rules/libobject.make
+
diff --git a/Source/DirectFB/inputdrivers/linux_input/Makefile.in b/Source/DirectFB/inputdrivers/linux_input/Makefile.in
new file mode 100755
index 0000000..8f54db6
--- /dev/null
+++ b/Source/DirectFB/inputdrivers/linux_input/Makefile.in
@@ -0,0 +1,601 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(top_srcdir)/rules/libobject.make
+subdir = inputdrivers/linux_input
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/as-ac-expand.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(linux_inputdir)" \
+ "$(DESTDIR)$(linux_inputdir)"
+linux_inputLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(linux_input_LTLIBRARIES)
+libdirectfb_linux_input_la_DEPENDENCIES = \
+ $(top_builddir)/lib/direct/libdirect.la \
+ $(top_builddir)/src/libdirectfb.la
+am_libdirectfb_linux_input_la_OBJECTS = linux_input.lo
+libdirectfb_linux_input_la_OBJECTS = \
+ $(am_libdirectfb_linux_input_la_OBJECTS)
+libdirectfb_linux_input_la_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(libdirectfb_linux_input_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libdirectfb_linux_input_la_SOURCES)
+DIST_SOURCES = $(libdirectfb_linux_input_la_SOURCES)
+linux_inputDATA_INSTALL = $(INSTALL_DATA)
+DATA = $(linux_input_DATA)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+ASFLAGS = @ASFLAGS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIR = @DATADIR@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DFB_CFLAGS_OMIT_FRAME_POINTER = @DFB_CFLAGS_OMIT_FRAME_POINTER@
+DFB_INTERNAL_CFLAGS = @DFB_INTERNAL_CFLAGS@
+DFB_LDFLAGS = @DFB_LDFLAGS@
+DFB_SMOOTH_SCALING = @DFB_SMOOTH_SCALING@
+DIRECTFB_BINARY_AGE = @DIRECTFB_BINARY_AGE@
+DIRECTFB_CSOURCE = @DIRECTFB_CSOURCE@
+DIRECTFB_INTERFACE_AGE = @DIRECTFB_INTERFACE_AGE@
+DIRECTFB_MAJOR_VERSION = @DIRECTFB_MAJOR_VERSION@
+DIRECTFB_MICRO_VERSION = @DIRECTFB_MICRO_VERSION@
+DIRECTFB_MINOR_VERSION = @DIRECTFB_MINOR_VERSION@
+DIRECTFB_VERSION = @DIRECTFB_VERSION@
+DIRECT_BUILD_DEBUG = @DIRECT_BUILD_DEBUG@
+DIRECT_BUILD_DEBUGS = @DIRECT_BUILD_DEBUGS@
+DIRECT_BUILD_GETTID = @DIRECT_BUILD_GETTID@
+DIRECT_BUILD_NETWORK = @DIRECT_BUILD_NETWORK@
+DIRECT_BUILD_STDBOOL = @DIRECT_BUILD_STDBOOL@
+DIRECT_BUILD_TEXT = @DIRECT_BUILD_TEXT@
+DIRECT_BUILD_TRACE = @DIRECT_BUILD_TRACE@
+DSYMUTIL = @DSYMUTIL@
+DYNLIB = @DYNLIB@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+FREETYPE_CFLAGS = @FREETYPE_CFLAGS@
+FREETYPE_LIBS = @FREETYPE_LIBS@
+FREETYPE_PROVIDER = @FREETYPE_PROVIDER@
+FUSION_BUILD_KERNEL = @FUSION_BUILD_KERNEL@
+FUSION_BUILD_MULTI = @FUSION_BUILD_MULTI@
+FUSION_MESSAGE_SIZE = @FUSION_MESSAGE_SIZE@
+GIF_PROVIDER = @GIF_PROVIDER@
+GREP = @GREP@
+HAVE_LINUX = @HAVE_LINUX@
+INCLUDEDIR = @INCLUDEDIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTERNALINCLUDEDIR = @INTERNALINCLUDEDIR@
+JPEG_PROVIDER = @JPEG_PROVIDER@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBJPEG = @LIBJPEG@
+LIBOBJS = @LIBOBJS@
+LIBPNG = @LIBPNG@
+LIBPNG_CONFIG = @LIBPNG_CONFIG@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_AGE = @LT_AGE@
+LT_BINARY = @LT_BINARY@
+LT_CURRENT = @LT_CURRENT@
+LT_RELEASE = @LT_RELEASE@
+LT_REVISION = @LT_REVISION@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAN2HTML = @MAN2HTML@
+MKDIR_P = @MKDIR_P@
+MODULEDIR = @MODULEDIR@
+MODULEDIRNAME = @MODULEDIRNAME@
+NMEDIT = @NMEDIT@
+OBJEXT = @OBJEXT@
+OSX_LIBS = @OSX_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PNG_PROVIDER = @PNG_PROVIDER@
+RANLIB = @RANLIB@
+RUNTIME_SYSROOT = @RUNTIME_SYSROOT@
+SDL_CFLAGS = @SDL_CFLAGS@
+SDL_LIBS = @SDL_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOPATH = @SOPATH@
+STRIP = @STRIP@
+SYSCONFDIR = @SYSCONFDIR@
+SYSFS_LIBS = @SYSFS_LIBS@
+THREADFLAGS = @THREADFLAGS@
+THREADLIB = @THREADLIB@
+TSLIB_CFLAGS = @TSLIB_CFLAGS@
+TSLIB_LIBS = @TSLIB_LIBS@
+VERSION = @VERSION@
+VNC_CFLAGS = @VNC_CFLAGS@
+VNC_CONFIG = @VNC_CONFIG@
+VNC_LIBS = @VNC_LIBS@
+X11_CFLAGS = @X11_CFLAGS@
+X11_LIBS = @X11_LIBS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+INCLUDES = \
+ -I$(top_builddir)/include \
+ -I$(top_srcdir)/include \
+ -I$(top_builddir)/lib \
+ -I$(top_srcdir)/lib \
+ -I$(top_srcdir)/src \
+ -I$(top_srcdir)/systems
+
+linux_input_LTLIBRARIES = libdirectfb_linux_input.la
+@BUILD_STATIC_TRUE@linux_input_DATA = $(linux_input_LTLIBRARIES:.la=.o)
+linux_inputdir = $(MODULEDIR)/inputdrivers
+libdirectfb_linux_input_la_SOURCES = \
+ input_fake.h \
+ linux_input.c
+
+libdirectfb_linux_input_la_LDFLAGS = \
+ -module \
+ -avoid-version \
+ $(DFB_LDFLAGS)
+
+libdirectfb_linux_input_la_LIBADD = \
+ $(top_builddir)/lib/direct/libdirect.la \
+ $(top_builddir)/src/libdirectfb.la
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/libobject.make $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu inputdrivers/linux_input/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu inputdrivers/linux_input/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-linux_inputLTLIBRARIES: $(linux_input_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(linux_inputdir)" || $(MKDIR_P) "$(DESTDIR)$(linux_inputdir)"
+ @list='$(linux_input_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(linux_inputLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(linux_inputdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(linux_inputLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(linux_inputdir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-linux_inputLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(linux_input_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(linux_inputdir)/$$p'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(linux_inputdir)/$$p"; \
+ done
+
+clean-linux_inputLTLIBRARIES:
+ -test -z "$(linux_input_LTLIBRARIES)" || rm -f $(linux_input_LTLIBRARIES)
+ @list='$(linux_input_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libdirectfb_linux_input.la: $(libdirectfb_linux_input_la_OBJECTS) $(libdirectfb_linux_input_la_DEPENDENCIES)
+ $(libdirectfb_linux_input_la_LINK) -rpath $(linux_inputdir) $(libdirectfb_linux_input_la_OBJECTS) $(libdirectfb_linux_input_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/linux_input.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-linux_inputDATA: $(linux_input_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(linux_inputdir)" || $(MKDIR_P) "$(DESTDIR)$(linux_inputdir)"
+ @list='$(linux_input_DATA)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(linux_inputDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(linux_inputdir)/$$f'"; \
+ $(linux_inputDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(linux_inputdir)/$$f"; \
+ done
+
+uninstall-linux_inputDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(linux_input_DATA)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(linux_inputdir)/$$f'"; \
+ rm -f "$(DESTDIR)$(linux_inputdir)/$$f"; \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(linux_inputdir)" "$(DESTDIR)$(linux_inputdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-linux_inputLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-linux_inputDATA \
+ install-linux_inputLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-linux_inputDATA \
+ uninstall-linux_inputLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-linux_inputLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am \
+ install-linux_inputDATA install-linux_inputLTLIBRARIES \
+ install-man install-pdf install-pdf-am install-ps \
+ install-ps-am install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
+ uninstall-am uninstall-linux_inputDATA \
+ uninstall-linux_inputLTLIBRARIES
+
+%.o: .libs/%.a %.la
+ rm -f $<.tmp/*.o
+ if test -d $<.tmp; then rmdir $<.tmp; fi
+ mkdir $<.tmp
+ (cd $<.tmp && $(AR) x ../../$<)
+ $(LD) -o $@ -r $<.tmp/*.o
+ rm -f $<.tmp/*.o && rmdir $<.tmp
+
+.PHONY: $(LTLIBRARIES:%.la=.libs/%.a)
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Source/DirectFB/inputdrivers/linux_input/input_fake.h b/Source/DirectFB/inputdrivers/linux_input/input_fake.h
new file mode 100755
index 0000000..7aecc9f
--- /dev/null
+++ b/Source/DirectFB/inputdrivers/linux_input/input_fake.h
@@ -0,0 +1,84 @@
+#ifndef _INPUT_FAKE_H
+#define _INPUT_FAKE_H
+
+#include <linux/input.h>
+
+
+#if !defined(KEY_OK)
+
+/**
+ * define some additional remote control keys in case they
+ * were not already defined above in <linux/input.h>
+ */
+
+#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
+#define KEY_TIME 0x167
+#define KEY_VENDOR 0x168
+#define KEY_ARCHIVE 0x169
+#define KEY_PROGRAM 0x16a
+#define KEY_CHANNEL 0x16b
+#define KEY_FAVORITES 0x16c
+#define KEY_EPG 0x16d
+#define KEY_PVR 0x16e
+#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
+#define KEY_TV 0x179
+#define KEY_TV2 0x17a
+#define KEY_VCR 0x17b
+#define KEY_VCR2 0x17c
+#define KEY_SAT 0x17d
+#define KEY_SAT2 0x17e
+#define KEY_CD 0x17f
+#define KEY_TAPE 0x180
+#define KEY_RADIO 0x181
+#define KEY_TUNER 0x182
+#define KEY_PLAYER 0x183
+#define KEY_TEXT 0x184
+#define KEY_DVD 0x185
+#define KEY_AUX 0x186
+#define KEY_MP3 0x187
+#define KEY_AUDIO 0x188
+#define KEY_VIDEO 0x189
+#define KEY_DIRECTORY 0x18a
+#define KEY_LIST 0x18b
+#define KEY_MEMO 0x18c
+#define KEY_CALENDAR 0x18d
+#define KEY_RED 0x18e
+#define KEY_GREEN 0x18f
+#define KEY_YELLOW 0x190
+#define KEY_BLUE 0x191
+#define KEY_CHANNELUP 0x192
+#define KEY_CHANNELDOWN 0x193
+#define KEY_FIRST 0x194
+#define KEY_LAST 0x195
+#define KEY_AB 0x196
+#define KEY_PLAY 0x197
+#define KEY_RESTART 0x198
+#define KEY_SLOW 0x199
+#define KEY_SHUFFLE 0x19a
+#define KEY_FASTFORWARD 0x19b
+#define KEY_PREVIOUS 0x19c
+#define KEY_NEXT 0x19d
+#define KEY_DIGITS 0x19e
+#define KEY_TEEN 0x19f
+#define KEY_TWEN 0x1a0
+#define KEY_BREAK 0x1a1
+
+
+#endif /* !defined(KEY_OK) */
+#endif /* _INPUT_FAKE_H */
+
diff --git a/Source/DirectFB/inputdrivers/linux_input/linux_input.c b/Source/DirectFB/inputdrivers/linux_input/linux_input.c
new file mode 100755
index 0000000..9294ef7
--- /dev/null
+++ b/Source/DirectFB/inputdrivers/linux_input/linux_input.c
@@ -0,0 +1,1994 @@
+/*
+ (c) Copyright 2001-2008 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+
+#include <linux/version.h>
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
+typedef unsigned long kernel_ulong_t;
+#define BITS_PER_LONG (sizeof(long)*8)
+#endif
+
+#include <linux/input.h>
+
+#ifndef KEY_OK
+/* Linux kernel 2.5.42+ defines additional keys in linux/input.h */
+#include "input_fake.h"
+#endif
+
+#ifndef EV_CNT
+#define EV_CNT (EV_MAX+1)
+#define KEY_CNT (KEY_MAX+1)
+#define REL_CNT (REL_MAX+1)
+#define ABS_CNT (ABS_MAX+1)
+#define LED_CNT (LED_MAX+1)
+#endif
+
+/* compat defines for older kernel like 2.4.x */
+#ifndef EV_SYN
+#define EV_SYN 0x00
+#define SYN_REPORT 0
+#define SYN_CONFIG 1
+#define ABS_TOOL_WIDTH 0x1c
+#define BTN_TOOL_DOUBLETAP 0x14d
+#define BTN_TOOL_TRIPLETAP 0x14e
+#endif
+
+#ifndef EVIOCGLED
+#define EVIOCGLED(len) _IOC(_IOC_READ, 'E', 0x19, len)
+#endif
+
+#ifndef EVIOCGRAB
+#define EVIOCGRAB _IOW('E', 0x90, int)
+#endif
+
+#include <linux/keyboard.h>
+
+
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <dfb_types.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/kd.h>
+#include <stdlib.h>
+
+#define DFB_INPUTDRIVER_HAS_AXIS_INFO
+#define DFB_INPUTDRIVER_HAS_SENSITIVITY
+
+#include <directfb.h>
+#include <directfb_keyboard.h>
+
+#include <core/coredefs.h>
+#include <core/coretypes.h>
+#include <core/input.h>
+#include <core/system.h>
+
+#include <direct/debug.h>
+#include <direct/mem.h>
+#include <direct/messages.h>
+#include <direct/thread.h>
+#include <direct/util.h>
+
+#include <misc/conf.h>
+#include <misc/util.h>
+
+#ifdef LINUX_INPUT_USE_FBDEV
+#include <fbdev/fbdev.h>
+#endif
+
+#include <core/input_driver.h>
+
+
+DFB_INPUT_DRIVER( linux_input )
+
+#ifndef BITS_PER_LONG
+#define BITS_PER_LONG (sizeof(long) * 8)
+#endif
+#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
+#define OFF(x) ((x)%BITS_PER_LONG)
+#define BIT(x) (1UL<<OFF(x))
+#define LONG(x) ((x)/BITS_PER_LONG)
+#undef test_bit
+#define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1)
+
+/* compat for 2.4.x kernel - just a compile fix */
+#ifndef HAVE_INPUT_ABSINFO
+struct input_absinfo {
+ s32 value;
+ s32 minimum;
+ s32 maximum;
+ s32 fuzz;
+ s32 flat;
+};
+#endif
+
+
+D_DEBUG_DOMAIN( LinuxInput_Driver, "LinuxInput/Driver", "Linux Input Driver" );
+
+
+/*
+ * Touchpads related stuff
+ */
+typedef enum {
+ TOUCHPAD_FSM_START,
+ TOUCHPAD_FSM_MAIN,
+ TOUCHPAD_FSM_DRAG_START,
+ TOUCHPAD_FSM_DRAG_MAIN,
+} TouchPadState;
+
+struct touchpad_axis {
+ int old, min, max;
+};
+
+struct touchpad_fsm_state {
+ TouchPadState fsm_state;
+
+ struct touchpad_axis x;
+ struct touchpad_axis y;
+ struct timeval timeout;
+};
+
+typedef enum {
+ EVENT_NONE = 0x00000000,
+
+ EVENT_BUTTON = 0x00000001,
+ EVENT_KEY = 0x00000002,
+ EVENT_AXES = 0x00000004,
+
+ EVENT_ALL = 0x00000007,
+} EventFlags;
+
+/*
+ * declaration of private data
+ */
+typedef struct {
+ unsigned int index;
+
+ CoreInputDevice *device;
+ DirectThread *thread;
+
+ InputDeviceInfo info;
+
+ int fd;
+
+ bool has_leds;
+ unsigned long led_state[NBITS(LED_CNT)];
+ DFBInputDeviceLockState locks;
+
+#ifdef LINUX_INPUT_USE_FBDEV
+ VirtualTerminal *vt;
+#endif
+
+ bool touchpad;
+ struct touchpad_fsm_state fsm_state;
+
+ struct {
+ EventFlags added;
+
+ DFBInputEvent button;
+ DFBInputEvent key;
+
+ DFBInputEvent axes[DIAI_LAST+1];
+ } events;
+
+ struct timeval timeout;
+
+ int sensitivity;
+} LinuxInputData;
+
+
+typedef struct {
+ char *device;
+ InputDeviceInfo info;
+ LinuxInputData *data;
+} InputDevice;
+
+
+static bool check_device( const char *device,
+ InputDeviceInfo *ret_info );
+
+
+#define MAX_LINUX_INPUT_DEVICES 16
+
+static int num_devices = 0;
+static InputDevice devices[MAX_LINUX_INPUT_DEVICES];
+
+
+static const
+int basic_keycodes [] = {
+ DIKI_UNKNOWN, DIKI_ESCAPE, DIKI_1, DIKI_2, DIKI_3, DIKI_4, DIKI_5,
+ DIKI_6, DIKI_7, DIKI_8, DIKI_9, DIKI_0, DIKI_MINUS_SIGN,
+ DIKI_EQUALS_SIGN, DIKI_BACKSPACE,
+
+ DIKI_TAB, DIKI_Q, DIKI_W, DIKI_E, DIKI_R, DIKI_T, DIKI_Y, DIKI_U,
+ DIKI_I, DIKI_O, DIKI_P, DIKI_BRACKET_LEFT, DIKI_BRACKET_RIGHT,
+ DIKI_ENTER,
+
+ DIKI_CONTROL_L, DIKI_A, DIKI_S, DIKI_D, DIKI_F, DIKI_G, DIKI_H, DIKI_J,
+ DIKI_K, DIKI_L, DIKI_SEMICOLON, DIKI_QUOTE_RIGHT, DIKI_QUOTE_LEFT,
+
+ DIKI_SHIFT_L, DIKI_BACKSLASH, DIKI_Z, DIKI_X, DIKI_C, DIKI_V, DIKI_B,
+ DIKI_N, DIKI_M, DIKI_COMMA, DIKI_PERIOD, DIKI_SLASH, DIKI_SHIFT_R,
+ DIKI_KP_MULT, DIKI_ALT_L, DIKI_SPACE, DIKI_CAPS_LOCK,
+
+ DIKI_F1, DIKI_F2, DIKI_F3, DIKI_F4, DIKI_F5, DIKI_F6, DIKI_F7, DIKI_F8,
+ DIKI_F9, DIKI_F10, DIKI_NUM_LOCK, DIKI_SCROLL_LOCK,
+
+ DIKI_KP_7, DIKI_KP_8, DIKI_KP_9, DIKI_KP_MINUS,
+ DIKI_KP_4, DIKI_KP_5, DIKI_KP_6, DIKI_KP_PLUS,
+ DIKI_KP_1, DIKI_KP_2, DIKI_KP_3, DIKI_KP_0, DIKI_KP_DECIMAL,
+
+ /*KEY_103RD,*/ DIKI_BACKSLASH,
+ /*KEY_F13,*/ DFB_FUNCTION_KEY(13),
+ /*KEY_102ND*/ DIKI_LESS_SIGN,
+
+ DIKI_F11, DIKI_F12, DIKI_PRINT, DFB_FUNCTION_KEY(15),
+ DFB_FUNCTION_KEY(16), DFB_FUNCTION_KEY(17), DFB_FUNCTION_KEY(18),
+ DFB_FUNCTION_KEY(19), DFB_FUNCTION_KEY(20),
+
+ DIKI_KP_ENTER, DIKI_CONTROL_R, DIKI_KP_DIV, DIKI_PRINT, DIKS_ALTGR,
+
+ /*KEY_LINEFEED*/ DIKI_UNKNOWN,
+
+ DIKI_HOME, DIKI_UP, DIKI_PAGE_UP, DIKI_LEFT, DIKI_RIGHT,
+ DIKI_END, DIKI_DOWN, DIKI_PAGE_DOWN, DIKI_INSERT, DIKI_DELETE,
+
+ /*KEY_MACRO,*/ DIKI_UNKNOWN,
+
+ DIKS_MUTE, DIKS_VOLUME_DOWN, DIKS_VOLUME_UP, DIKS_POWER, DIKI_KP_EQUAL,
+
+ /*KEY_KPPLUSMINUS,*/ DIKI_UNKNOWN,
+
+ DIKS_PAUSE, DFB_FUNCTION_KEY(21), DFB_FUNCTION_KEY(22),
+ DFB_FUNCTION_KEY(23), DFB_FUNCTION_KEY(24),
+
+ DIKI_KP_SEPARATOR, DIKI_META_L, DIKI_META_R, DIKI_SUPER_L,
+
+ DIKS_STOP,
+
+ /*DIKS_AGAIN, DIKS_PROPS, DIKS_UNDO, DIKS_FRONT, DIKS_COPY,
+ DIKS_OPEN, DIKS_PASTE, DIKS_FIND, DIKS_CUT,*/
+ DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN,
+ DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN,
+
+ DIKS_HELP, DIKS_MENU, DIKS_CALCULATOR, DIKS_SETUP,
+
+ /*KEY_SLEEP, KEY_WAKEUP, KEY_FILE, KEY_SENDFILE, KEY_DELETEFILE,
+ KEY_XFER,*/
+ DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN,
+ DIKI_UNKNOWN,
+
+ /*KEY_PROG1, KEY_PROG2,*/
+ DIKS_CUSTOM1, DIKS_CUSTOM2,
+
+ DIKS_INTERNET,
+
+ /*KEY_MSDOS, KEY_COFFEE, KEY_DIRECTION, KEY_CYCLEWINDOWS,*/
+ DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN,
+
+ DIKS_MAIL,
+
+ /*KEY_BOOKMARKS, KEY_COMPUTER, */
+ DIKI_UNKNOWN, DIKI_UNKNOWN,
+
+ DIKS_BACK, DIKS_FORWARD,
+
+ /*KEY_CLOSECD, KEY_EJECTCD, KEY_EJECTCLOSECD,*/
+ DIKS_EJECT, DIKS_EJECT, DIKS_EJECT,
+
+ DIKS_NEXT, DIKS_PLAYPAUSE, DIKS_PREVIOUS, DIKS_STOP, DIKS_RECORD,
+ DIKS_REWIND, DIKS_PHONE,
+
+ /*KEY_ISO,*/ DIKI_UNKNOWN,
+ /*KEY_CONFIG,*/ DIKS_SETUP,
+ /*KEY_HOMEPAGE, KEY_REFRESH,*/ DIKI_UNKNOWN, DIKS_SHUFFLE,
+
+ DIKS_EXIT, /*KEY_MOVE,*/ DIKI_UNKNOWN, DIKS_EDITOR,
+
+ /*KEY_SCROLLUP,*/ DIKS_PAGE_UP,
+ /*KEY_SCROLLDOWN,*/ DIKS_PAGE_DOWN,
+ /*KEY_KPLEFTPAREN,*/ DIKI_UNKNOWN,
+ /*KEY_KPRIGHTPAREN,*/ DIKI_UNKNOWN,
+
+ /* unused codes 181-182: */
+ DIKI_UNKNOWN, DIKI_UNKNOWN,
+
+ DFB_FUNCTION_KEY(13), DFB_FUNCTION_KEY(14), DFB_FUNCTION_KEY(15),
+ DFB_FUNCTION_KEY(16), DFB_FUNCTION_KEY(17), DFB_FUNCTION_KEY(18),
+ DFB_FUNCTION_KEY(19), DFB_FUNCTION_KEY(20), DFB_FUNCTION_KEY(21),
+ DFB_FUNCTION_KEY(22), DFB_FUNCTION_KEY(23), DFB_FUNCTION_KEY(24),
+
+ /* unused codes 195-199: */
+ DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN, DIKI_UNKNOWN,
+
+ /* KEY_PLAYCD, KEY_PAUSECD */
+ DIKS_PLAY, DIKS_PAUSE,
+
+ /*KEY_PROG3, KEY_PROG4,*/
+ DIKS_CUSTOM3, DIKS_CUSTOM4,
+
+ DIKI_UNKNOWN,
+
+ /*KEY_SUSPEND, KEY_CLOSE*/
+ DIKI_UNKNOWN, DIKI_UNKNOWN,
+
+ /* KEY_PLAY */
+ DIKS_PLAY,
+
+ /* KEY_FASTFORWARD */
+ DIKS_FASTFORWARD,
+
+ /* KEY_BASSBOOST */
+ DIKI_UNKNOWN,
+
+ /* KEY_PRINT */
+ DIKS_PRINT,
+
+ /* KEY_HP */ DIKI_UNKNOWN,
+ /* KEY_CAMERA */ DIKI_UNKNOWN,
+ /* KEY_SOUND */ DIKS_AUDIO,
+ /* KEY_QUESTION */ DIKS_HELP,
+ /* KEY_EMAIL */ DIKS_MAIL,
+ /* KEY_CHAT */ DIKI_UNKNOWN,
+ /* KEY_SEARCH */ DIKI_UNKNOWN,
+ /* KEY_CONNECT */ DIKI_UNKNOWN,
+ /* KEY_FINANCE */ DIKI_UNKNOWN,
+ /* KEY_SPORT */ DIKI_UNKNOWN,
+ /* KEY_SHOP */ DIKI_UNKNOWN,
+ /* KEY_ALTERASE */ DIKI_UNKNOWN,
+ /* KEY_CANCEL */ DIKS_CANCEL,
+ /* KEY_BRIGHTNESSDOWN */ DIKI_UNKNOWN,
+ /* KEY_BRIGHTNESSUP */ DIKI_UNKNOWN,
+ /* KEY_MEDIA */ DIKI_UNKNOWN,
+};
+
+static const
+int ext_keycodes [] = {
+ DIKS_OK, DIKS_SELECT, DIKS_GOTO, DIKS_CLEAR, DIKS_POWER2, DIKS_OPTION,
+ DIKS_INFO, DIKS_TIME, DIKS_VENDOR, DIKS_ARCHIVE, DIKS_PROGRAM,
+ DIKS_CHANNEL, DIKS_FAVORITES, DIKS_EPG, DIKS_PVR, DIKS_MHP,
+ DIKS_LANGUAGE, DIKS_TITLE, DIKS_SUBTITLE, DIKS_ANGLE, DIKS_ZOOM,
+ DIKS_MODE, DIKS_KEYBOARD, DIKS_SCREEN, DIKS_PC, DIKS_TV, DIKS_TV2,
+ DIKS_VCR, DIKS_VCR2, DIKS_SAT, DIKS_SAT2, DIKS_CD, DIKS_TAPE,
+ DIKS_RADIO, DIKS_TUNER, DIKS_PLAYER, DIKS_TEXT, DIKS_DVD, DIKS_AUX,
+ DIKS_MP3, DIKS_AUDIO, DIKS_VIDEO, DIKS_DIRECTORY, DIKS_LIST, DIKS_MEMO,
+ DIKS_CALENDAR, DIKS_RED, DIKS_GREEN, DIKS_YELLOW, DIKS_BLUE,
+ DIKS_CHANNEL_UP, DIKS_CHANNEL_DOWN, DIKS_FIRST, DIKS_LAST, DIKS_AB,
+ DIKS_NEXT, DIKS_RESTART, DIKS_SLOW, DIKS_SHUFFLE, DIKS_FASTFORWARD,
+ DIKS_PREVIOUS, DIKS_NEXT, DIKS_DIGITS, DIKS_TEEN, DIKS_TWEN, DIKS_BREAK
+};
+
+/**********************************************************************************************************************/
+
+static void touchpad_fsm_init( struct touchpad_fsm_state *state );
+static int touchpad_fsm( struct touchpad_fsm_state *state,
+ const struct input_event *levt,
+ DFBInputEvent *devt );
+
+/**********************************************************************************************************************/
+
+static bool timeout_passed( const struct timeval *timeout, const struct timeval *current );
+static bool timeout_is_set( const struct timeval *timeout );
+static void timeout_add( struct timeval *timeout, const struct timeval *sub );
+static void timeout_sub( struct timeval *timeout, const struct timeval *sub );
+
+/**********************************************************************************************************************/
+/**********************************************************************************************************************/
+
+/*
+ * Translates a Linux input keycode into a DirectFB keycode.
+ */
+static int
+translate_key( unsigned short code )
+{
+ if (code < D_ARRAY_SIZE( basic_keycodes ))
+ return basic_keycodes[code];
+
+ if (code >= KEY_OK)
+ if (code - KEY_OK < D_ARRAY_SIZE( ext_keycodes ))
+ return ext_keycodes[code-KEY_OK];
+
+ return DIKI_UNKNOWN;
+}
+
+#ifdef LINUX_INPUT_USE_FBDEV
+static DFBInputDeviceKeySymbol
+keyboard_get_symbol( int code,
+ unsigned short value,
+ DFBInputDeviceKeymapSymbolIndex level )
+{
+ unsigned char type = KTYP(value);
+ unsigned char index = KVAL(value);
+ int base = (level == DIKSI_BASE);
+
+ switch (type) {
+ case KT_FN:
+ if (index < 20)
+ return DFB_FUNCTION_KEY( index + 1 );
+ break;
+ case KT_LETTER:
+ case KT_LATIN:
+ switch (index) {
+ case 0x1c:
+ return DIKS_PRINT;
+ case 0x7f:
+ return DIKS_BACKSPACE;
+ case 0xa4:
+ return 0x20ac; /* euro currency sign */
+ default:
+ return index;
+ }
+ break;
+ case KT_DEAD:
+ switch (value) {
+ case K_DGRAVE:
+ return DIKS_DEAD_GRAVE;
+
+ case K_DACUTE:
+ return DIKS_DEAD_ACUTE;
+
+ case K_DCIRCM:
+ return DIKS_DEAD_CIRCUMFLEX;
+
+ case K_DTILDE:
+ return DIKS_DEAD_TILDE;
+
+ case K_DDIERE:
+ return DIKS_DEAD_DIAERESIS;
+
+ case K_DCEDIL:
+ return DIKS_DEAD_CEDILLA;
+
+ default:
+ break;
+ }
+ break;
+ case KT_PAD:
+ if (index <= 9 && level != DIKSI_BASE)
+ return DIKS_0 + index;
+ break;
+ case 0xe: /* special IPAQ H3600 case - AH */
+ switch (index) {
+ case 0x20: return DIKS_CALENDAR;
+ case 0x1a: return DIKS_BACK;
+ case 0x1c: return DIKS_MEMO;
+ case 0x21: return DIKS_POWER;
+ }
+ break;
+ case 0xd: /* another special IPAQ H3600 case - AH */
+ switch (index) {
+ case 0x2: return DIKS_DIRECTORY;
+ case 0x1: return DIKS_MAIL; /* Q on older iPaqs */
+ }
+ break;
+ }
+
+ switch (value) {
+ case K_LEFT: return DIKS_CURSOR_LEFT;
+ case K_RIGHT: return DIKS_CURSOR_RIGHT;
+ case K_UP: return DIKS_CURSOR_UP;
+ case K_DOWN: return DIKS_CURSOR_DOWN;
+ case K_ENTER: return DIKS_ENTER;
+ case K_CTRL: return DIKS_CONTROL;
+ case K_SHIFT: return DIKS_SHIFT;
+ case K_ALT: return DIKS_ALT;
+ case K_ALTGR: return DIKS_ALTGR;
+ case K_INSERT: return DIKS_INSERT;
+ case K_REMOVE: return DIKS_DELETE;
+ case K_FIND: return DIKS_HOME;
+ case K_SELECT: return DIKS_END;
+ case K_PGUP: return DIKS_PAGE_UP;
+ case K_PGDN: return DIKS_PAGE_DOWN;
+ case K_NUM: return DIKS_NUM_LOCK;
+ case K_HOLD: return DIKS_SCROLL_LOCK;
+ case K_PAUSE: return DIKS_PAUSE;
+ case K_BREAK: return DIKS_BREAK;
+ case K_CAPS: return DIKS_CAPS_LOCK;
+
+ case K_P0: return DIKS_INSERT;
+ case K_P1: return DIKS_END;
+ case K_P2: return DIKS_CURSOR_DOWN;
+ case K_P3: return DIKS_PAGE_DOWN;
+ case K_P4: return DIKS_CURSOR_LEFT;
+ case K_P5: return DIKS_BEGIN;
+ case K_P6: return DIKS_CURSOR_RIGHT;
+ case K_P7: return DIKS_HOME;
+ case K_P8: return DIKS_CURSOR_UP;
+ case K_P9: return DIKS_PAGE_UP;
+ case K_PPLUS: return DIKS_PLUS_SIGN;
+ case K_PMINUS: return DIKS_MINUS_SIGN;
+ case K_PSTAR: return DIKS_ASTERISK;
+ case K_PSLASH: return DIKS_SLASH;
+ case K_PENTER: return DIKS_ENTER;
+ case K_PCOMMA: return base ? DIKS_DELETE : DIKS_COMMA;
+ case K_PDOT: return base ? DIKS_DELETE : DIKS_PERIOD;
+ case K_PPARENL: return DIKS_PARENTHESIS_LEFT;
+ case K_PPARENR: return DIKS_PARENTHESIS_RIGHT;
+ }
+
+ /* special keys not in the map, hack? */
+ if (code == 99)
+ return DIKS_PRINT;
+
+ if (code == 124) /* keypad equal key */
+ return DIKS_EQUALS_SIGN;
+
+ if (code == 125) /* left windows key */
+ return DIKS_META;
+
+ if (code == 126) /* right windows key */
+ return DIKS_META;
+
+ if (code == 127) /* context menu key */
+ return DIKS_SUPER;
+
+ return DIKS_NULL;
+}
+
+static DFBInputDeviceKeyIdentifier
+keyboard_get_identifier( int code, unsigned short value )
+{
+ unsigned char type = KTYP(value);
+ unsigned char index = KVAL(value);
+
+ if (type == KT_PAD) {
+ if (index <= 9)
+ return DIKI_KP_0 + index;
+
+ switch (value) {
+ case K_PSLASH: return DIKI_KP_DIV;
+ case K_PSTAR: return DIKI_KP_MULT;
+ case K_PMINUS: return DIKI_KP_MINUS;
+ case K_PPLUS: return DIKI_KP_PLUS;
+ case K_PENTER: return DIKI_KP_ENTER;
+ case K_PCOMMA:
+ case K_PDOT: return DIKI_KP_DECIMAL;
+ }
+ }
+
+ /* Looks like a hack, but don't know a better way yet. */
+ switch (code) {
+ case 12: return DIKI_MINUS_SIGN;
+ case 13: return DIKI_EQUALS_SIGN;
+ case 26: return DIKI_BRACKET_LEFT;
+ case 27: return DIKI_BRACKET_RIGHT;
+ case 39: return DIKI_SEMICOLON;
+ case 40: return DIKI_QUOTE_RIGHT;
+ case 41: return DIKI_QUOTE_LEFT;
+ case 43: return DIKI_BACKSLASH;
+ case 51: return DIKI_COMMA;
+ case 52: return DIKI_PERIOD;
+ case 53: return DIKI_SLASH;
+ case 54: return DIKI_SHIFT_R;
+ case 97: return DIKI_CONTROL_R;
+ case 100: return DIKI_ALT_R;
+ default:
+ ;
+ }
+
+ /* special keys not in the map, hack? */
+ if (code == 124) /* keypad equal key */
+ return DIKI_KP_EQUAL;
+
+ if (code == 125) /* left windows key */
+ return DIKI_META_L;
+
+ if (code == 126) /* right windows key */
+ return DIKI_META_R;
+
+ if (code == 127) /* context menu key */
+ return DIKI_SUPER_R;
+
+ return DIKI_UNKNOWN;
+}
+
+static unsigned short
+keyboard_read_value( const LinuxInputData *data,
+ unsigned char table, unsigned char index )
+{
+ struct kbentry entry;
+
+ if (!data->vt)
+ return 0;
+
+ entry.kb_table = table;
+ entry.kb_index = index;
+ entry.kb_value = 0;
+
+ if (ioctl( data->vt->fd, KDGKBENT, &entry )) {
+ D_PERROR("DirectFB/keyboard: KDGKBENT (table: %d, index: %d) "
+ "failed!\n", table, index);
+ return 0;
+ }
+
+ return entry.kb_value;
+}
+#endif /* LINUX_INPUT_USE_FBDEV */
+
+/**********************************************************************************************************************/
+
+/*
+ * Translates key and button events.
+ */
+static bool
+key_event( const struct input_event *levt,
+ DFBInputEvent *devt )
+{
+ int code = levt->code;
+
+ /* map touchscreen and smartpad events to button mouse */
+ if (code == BTN_TOUCH || code == BTN_TOOL_FINGER)
+ code = BTN_MOUSE;
+
+ if ((code >= BTN_MOUSE && code < BTN_JOYSTICK) || code == BTN_TOUCH) {
+ /* ignore repeat events for buttons */
+ if (levt->value == 2)
+ return false;
+
+ devt->type = levt->value ? DIET_BUTTONPRESS : DIET_BUTTONRELEASE;
+ /* don't set DIEF_BUTTONS, it will be set by the input core */
+ devt->button = DIBI_FIRST + code - BTN_MOUSE;
+ }
+ else {
+ int key = translate_key( code );
+
+ if (key == DIKI_UNKNOWN)
+ return false;
+
+ devt->type = levt->value ? DIET_KEYPRESS : DIET_KEYRELEASE;
+
+ if (DFB_KEY_TYPE(key) == DIKT_IDENTIFIER) {
+ devt->key_id = key;
+ devt->flags |= DIEF_KEYID;
+ }
+ else {
+ devt->key_symbol = key;
+ devt->flags |= DIEF_KEYSYMBOL;
+ }
+
+ devt->flags |= DIEF_KEYCODE;
+ devt->key_code = code;
+ }
+
+ if (levt->value == 2)
+ devt->flags |= DIEF_REPEAT;
+
+ return true;
+}
+
+/*
+ * Translates relative axis events.
+ */
+static bool
+rel_event( const LinuxInputData *data,
+ const struct input_event *levt,
+ DFBInputEvent *devt )
+{
+ switch (levt->code) {
+ case REL_X:
+ devt->axis = DIAI_X;
+ devt->axisrel = levt->value * data->sensitivity;
+ break;
+
+ case REL_Y:
+ devt->axis = DIAI_Y;
+ devt->axisrel = levt->value * data->sensitivity;
+ break;
+
+ case REL_Z:
+ case REL_WHEEL:
+ devt->axis = DIAI_Z;
+ devt->axisrel = -levt->value * data->sensitivity;
+ break;
+
+ default:
+ if (levt->code > REL_MAX || levt->code > DIAI_LAST)
+ return false;
+ devt->axis = levt->code;
+ devt->axisrel = levt->value * data->sensitivity;
+ }
+
+ devt->type = DIET_AXISMOTION;
+ devt->flags |= DIEF_AXISREL;
+
+ return true;
+}
+
+/*
+ * Translates absolute axis events.
+ */
+static bool
+abs_event( const struct input_event *levt,
+ DFBInputEvent *devt )
+{
+ switch (levt->code) {
+ case ABS_X:
+ devt->axis = DIAI_X;
+ break;
+
+ case ABS_Y:
+ devt->axis = DIAI_Y;
+ break;
+
+ case ABS_Z:
+ case ABS_WHEEL:
+ devt->axis = DIAI_Z;
+ break;
+
+ default:
+ if (levt->code >= ABS_PRESSURE || levt->code > DIAI_LAST)
+ return false;
+ devt->axis = levt->code;
+ }
+
+ devt->type = DIET_AXISMOTION;
+ devt->flags |= DIEF_AXISABS;
+ devt->axisabs = levt->value;
+
+ return true;
+}
+
+/*
+ * Translates a Linux input event into a DirectFB input event.
+ */
+static bool
+translate_event( const LinuxInputData *data,
+ const struct input_event *levt,
+ DFBInputEvent *devt )
+{
+ devt->flags = DIEF_TIMESTAMP;
+ devt->timestamp = levt->time;
+
+ switch (levt->type) {
+ case EV_KEY:
+ return key_event( levt, devt );
+
+ case EV_REL:
+ return rel_event( data, levt, devt );
+
+ case EV_ABS:
+ return abs_event( levt, devt );
+
+ default:
+ ;
+ }
+
+ return false;
+}
+
+static void
+set_led( const LinuxInputData *data, int led, int state )
+{
+ struct input_event levt;
+
+ levt.type = EV_LED;
+ levt.code = led;
+ levt.value = !!state;
+
+ write( data->fd, &levt, sizeof(levt) );
+}
+
+/**********************************************************************************************************************/
+/**********************************************************************************************************************/
+
+static void
+LinuxInput_Initialize( LinuxInputData *data )
+{
+ /* Query min/max coordinates. */
+ if (data->touchpad) {
+ struct input_absinfo absinfo;
+
+ touchpad_fsm_init( &data->fsm_state );
+
+ ioctl( data->fd, EVIOCGABS(ABS_X), &absinfo );
+ data->fsm_state.x.min = absinfo.minimum;
+ data->fsm_state.x.max = absinfo.maximum;
+
+ ioctl( data->fd, EVIOCGABS(ABS_Y), &absinfo );
+ data->fsm_state.y.min = absinfo.minimum;
+ data->fsm_state.y.max = absinfo.maximum;
+ }
+}
+
+static void
+LinuxInput_FlushEvents( LinuxInputData *data )
+{
+ int i;
+ int num = 0;
+ DFBInputEvent *events[DIAI_LAST+1+2];
+
+ D_DEBUG_AT( LinuxInput_Driver, "%s( %p )\n", __FUNCTION__, data );
+
+ /* Flush axis events first */
+ if (data->events.added & EVENT_AXES) {
+ for (i=0; i<D_ARRAY_SIZE(data->events.axes); i++) {
+ if (data->events.axes[i].type)
+ events[num++] = &data->events.axes[i];
+ }
+ }
+
+ /* Flush button */
+ if (data->events.added & EVENT_BUTTON) {
+ events[num++] = &data->events.button;
+ }
+
+ /* Flush key */
+ if (data->events.added & EVENT_KEY) {
+ events[num++] = &data->events.key;
+ }
+
+ /* Clear event mask */
+ data->events.added = EVENT_NONE;
+
+ /*
+ * Dispatch all events
+ */
+ for (i=0; i<num; i++) {
+ /* Add DIEF_FOLLOW to all but last event */
+ if (i < num-1)
+ events[i]->flags |= DIEF_FOLLOW;
+
+ dfb_input_dispatch( data->device, events[i] );
+
+ if (data->has_leds && (events[i]->locks != data->locks)) {
+ set_led( data, LED_SCROLLL, events[i]->locks & DILS_SCROLL );
+ set_led( data, LED_NUML, events[i]->locks & DILS_NUM );
+ set_led( data, LED_CAPSL, events[i]->locks & DILS_CAPS );
+
+ data->locks = events[i]->locks;
+ }
+
+ events[i]->type = DIET_UNKNOWN;
+ events[i]->flags = DIEF_NONE;
+ }
+}
+
+static void
+LinuxInput_AddEvent( LinuxInputData *data,
+ DFBInputEvent *event )
+{
+ D_DEBUG_AT( LinuxInput_Driver, "%s( %p, %p )\n", __FUNCTION__, data, event );
+ D_DEBUG_AT( LinuxInput_Driver, " =-> type %d, flags 0x%04x\n", event->type, event->flags );
+
+ if (!data->events.added && dfb_config->max_axis_rate) {
+ struct timeval time;
+
+ gettimeofday( &time, NULL );
+
+ data->timeout.tv_sec = 0;
+ data->timeout.tv_usec = 1000000 / dfb_config->max_axis_rate;
+
+ timeout_add( &data->timeout, &time );
+ }
+
+ switch (event->type) {
+ case DIET_BUTTONPRESS:
+ case DIET_BUTTONRELEASE:
+ if (data->events.button.type) {
+ D_BUG( "previous button event not flushed" );
+ LinuxInput_FlushEvents( data );
+ }
+
+ data->events.added |= EVENT_BUTTON;
+ data->events.button = *event;
+ break;
+
+ case DIET_KEYPRESS:
+ case DIET_KEYRELEASE:
+ if (data->events.key.type) {
+ D_BUG( "previous key event not flushed" );
+ LinuxInput_FlushEvents( data );
+ }
+
+ data->events.added |= EVENT_KEY;
+ data->events.key = *event;
+ break;
+
+ case DIET_AXISMOTION:
+ if (event->axis < DIAI_FIRST || event->axis > DIAI_LAST) {
+ D_BUG( "axis %d out of range", event->axis );
+ return;
+ }
+
+ if (data->events.axes[event->axis].type) {
+ if (dfb_config->mouse_motion_compression || dfb_config->max_axis_rate) {
+ if (D_FLAGS_IS_SET( event->flags, DIEF_AXISREL )) {
+ if (D_FLAGS_IS_SET( data->events.axes[event->axis].flags, DIEF_AXISREL ))
+ event->axisrel += data->events.axes[event->axis].axisrel;
+ else
+ D_WARN( "previous axis event with different abs/rel flag" );
+ }
+ else {
+ if (D_FLAGS_IS_SET( data->events.axes[event->axis].flags, DIEF_AXISREL ))
+ D_WARN( "previous axis event with different abs/rel flag" );
+ }
+ }
+ else {
+ D_BUG( "previous axis event not flushed" );
+ LinuxInput_FlushEvents( data );
+ }
+ }
+
+ data->events.added |= EVENT_AXES;
+ data->events.axes[event->axis] = *event;
+ break;
+
+ default:
+ D_ONCE( "unknown event type %d", event->type );
+ }
+}
+
+static void
+LinuxInput_HandleEvent( LinuxInputData *data,
+ const struct input_event *levt )
+{
+ int status = -1;
+ DFBInputEvent temp = { .type = DIET_UNKNOWN };
+
+ D_DEBUG_AT( LinuxInput_Driver, "%s( %p, %p )\n", __FUNCTION__, data, levt );
+ D_DEBUG_AT( LinuxInput_Driver, " =-> 0x%02x 0x%03x\n", levt->type, levt->code );
+
+ if (levt->type == EV_SYN && levt->code == SYN_REPORT) {
+ /* With mouse motion compression wait as long as only axis events are added */
+ if ((dfb_config->mouse_motion_compression || dfb_config->max_axis_rate) && data->events.added == EVENT_AXES)
+ return;
+
+ LinuxInput_FlushEvents( data );
+
+ return;
+ }
+
+ if (data->touchpad) {
+ status = touchpad_fsm( &data->fsm_state, levt, &temp );
+ if (!status)
+ /* Handled but no further processing is necessary. */
+ return;
+ }
+
+ if (status < 0) {
+ /* Not handled. Try the direct approach. */
+ if (!translate_event( data, levt, &temp ))
+ return;
+ }
+
+ D_ASSERT( temp.type != DIET_UNKNOWN );
+
+ LinuxInput_AddEvent( data, &temp );
+}
+
+static void
+LinuxInput_HandleTimeout( LinuxInputData *data )
+{
+ D_DEBUG_AT( LinuxInput_Driver, "%s( %p )\n", __FUNCTION__, data );
+
+ if (data->touchpad) {
+ DFBInputEvent event;
+
+ if (touchpad_fsm( &data->fsm_state, NULL, &event ) > 0)
+ dfb_input_dispatch( data->device, &event );
+ }
+
+ LinuxInput_FlushEvents( data );
+}
+
+static DFBResult
+LinuxInput_GetTimeout( LinuxInputData *data,
+ struct timeval *ret_timeout )
+{
+ D_DEBUG_AT( LinuxInput_Driver, "%s( %p )\n", __FUNCTION__, data );
+
+ if (data->events.added && dfb_config->max_axis_rate) {
+ *ret_timeout = data->timeout;
+
+ return DFB_OK;
+ }
+
+ if (data->touchpad && timeout_is_set( &data->fsm_state.timeout )) {
+ *ret_timeout = data->fsm_state.timeout;
+
+ return DFB_OK;
+ }
+
+ return DFB_TEMPUNAVAIL;
+}
+
+/**********************************************************************************************************************/
+/**********************************************************************************************************************/
+
+static void
+LinuxInput_CloseDevice( LinuxInputData *data )
+{
+ int fd = data->fd;
+
+ D_INFO( "LinuxInput: Disconnected '%s'\n", data->info.desc.name );
+
+ dfb_input_device_disconnected( data->device );
+
+ data->fd = -1;
+
+ close( fd );
+}
+
+static void
+LinuxInput_ProbeDevice( const char *device )
+{
+ DFBResult ret;
+ int i, fd;
+ InputDeviceInfo info;
+
+ D_DEBUG_AT( LinuxInput_Driver, "%s( %s )\n", __FUNCTION__, device );
+
+ for (i=0; i<num_devices; i++) {
+ if (!strcmp( devices[i].device, device )) {
+ if (devices[i].data && devices[i].data->fd != -1)
+ return;
+
+ break;
+ }
+ }
+
+ if (!check_device( device, &info ))
+ return;
+
+ for (i=0; i<num_devices; i++) {
+ if (!memcmp( &info, &devices[i].info, sizeof(InputDeviceInfo) )) {
+ if (devices[i].data && devices[i].data->fd == -1) {
+ D_INFO( "LinuxInput: Reconnected '%s'\n", info.desc.name );
+
+ dfb_input_device_reconnected( devices[i].data->device );
+
+ /* reopen device */
+ fd = open( device, O_RDWR );
+ if (fd < 0) {
+ D_PERROR( "DirectFB/linux_input: could not reopen device" );
+ return;
+ }
+
+ /* grab device */
+ if (dfb_config->linux_input_grab) {
+ ret = ioctl( fd, EVIOCGRAB, 1 );
+ /* 2.4 kernels don't have EVIOCGRAB so ignore EINVAL */
+ if (ret && errno != EINVAL) {
+ D_PERROR( "DirectFB/linux_input: could not grab device" );
+ close( fd );
+ return;
+ }
+ }
+
+ devices[i].data->fd = fd;
+
+ D_FREE( devices[i].device );
+
+ devices[i].device = D_STRDUP( device );
+ }
+
+ return;
+ }
+ }
+
+ D_INFO( "LinuxInput: Added '%s'\n", info.desc.name );
+
+ devices[num_devices].device = D_STRDUP( device );
+ devices[num_devices].info = info;
+
+ num_devices++;
+}
+
+static void
+LinuxInput_UpdateDevices()
+{
+ int i;
+
+ D_DEBUG_AT( LinuxInput_Driver, "%s()\n", __FUNCTION__ );
+
+ /* Use the devices specified in the configuration. */
+ if (fusion_vector_has_elements( &dfb_config->linux_input_devices )) {
+ const char *device;
+
+ fusion_vector_foreach (device, i, dfb_config->linux_input_devices) {
+ if (num_devices >= MAX_LINUX_INPUT_DEVICES)
+ break;
+
+ LinuxInput_ProbeDevice( device );
+ }
+ }
+ else {
+ char *tsdev;
+
+ /* Check for tslib device being used. */
+ tsdev = getenv( "TSLIB_TSDEVICE" );
+
+ /* No devices specified. Try to guess some. */
+ for (i=0; i<MAX_LINUX_INPUT_DEVICES; i++) {
+ char buf[32];
+
+ snprintf( buf, 32, "/dev/input/event%d", i );
+
+ /* Let tslib driver handle its device. */
+ if (tsdev && !strcmp( tsdev, buf ))
+ continue;
+
+ LinuxInput_ProbeDevice( buf );
+ }
+ }
+}
+
+/**********************************************************************************************************************/
+
+/*
+ * Input thread reading from device.
+ * Generates events on incoming data.
+ */
+static void*
+linux_input_EventThread( DirectThread *thread, void *driver_data )
+{
+ DFBResult ret;
+ LinuxInputData *data = (LinuxInputData*) driver_data;
+
+ LinuxInput_Initialize( data );
+
+ while (true) {
+ int status;
+ fd_set set;
+ struct timeval timeout;
+ bool handle = false;
+
+ if (data->fd < 0) {
+ usleep( 100000 );
+
+ if (data->index == 0)
+ LinuxInput_UpdateDevices();
+
+ continue;
+ }
+
+ FD_ZERO( &set );
+ FD_SET( data->fd, &set );
+
+ ret = LinuxInput_GetTimeout( data, &timeout );
+ switch (ret) {
+ case DFB_TEMPUNAVAIL:
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 2000000;
+
+ status = select( data->fd + 1, &set, NULL, NULL, &timeout );
+ break;
+
+ case DFB_OK: {
+ struct timeval time;
+
+ handle = true;
+
+ gettimeofday( &time, NULL );
+
+ if (!timeout_passed( &timeout, &time )) {
+ timeout_sub( &timeout, &time );
+
+ status = select( data->fd + 1, &set, NULL, NULL, &timeout );
+ break;
+ }
+ }
+
+ default:
+ status = 0;
+ break;
+ }
+
+ /* timeout? */
+ if (status == 0) {
+ if (handle)
+ LinuxInput_HandleTimeout( data );
+
+ if (data->index == 0)
+ LinuxInput_UpdateDevices();
+
+ continue;
+ }
+
+ if (status < 0) {
+ direct_thread_testcancel( thread );
+
+ if (errno != EINTR)
+ break;
+ }
+ else if (FD_ISSET( data->fd, &set )) {
+ int i;
+ int readlen;
+ struct input_event levt[64];
+
+ readlen = read( data->fd, levt, sizeof(levt) );
+ if (readlen < 0) {
+ direct_thread_testcancel( thread );
+
+ if (errno != EINTR) {
+ if (errno != ENODEV)
+ D_PERROR( "LinuxInput: Error during read()!\n" );
+
+ LinuxInput_CloseDevice( data );
+ }
+ }
+ else if (readlen > 0) {
+ D_DEBUG_AT( LinuxInput_Driver, "%s( '%s' )\n", __FUNCTION__, data->info.desc.name );
+
+ for (i=0; i<readlen / sizeof(levt[0]); i++)
+ LinuxInput_HandleEvent( data, &levt[i] );
+ }
+ else
+ LinuxInput_CloseDevice( data );
+ }
+
+ /* Handle mouse motion compression, though this might break the SYN_REPORT semantics */
+ if (dfb_config->mouse_motion_compression && data->events.added && !dfb_config->max_axis_rate)
+ LinuxInput_FlushEvents( data );
+ }
+
+ D_PERROR( "linux_input thread died\n" );
+
+ return NULL;
+}
+
+/**********************************************************************************************************************/
+
+/*
+ * Fill device information.
+ * Queries the input device and tries to classify it.
+ */
+static void
+get_device_info( int fd,
+ InputDeviceInfo *info,
+ bool *touchpad )
+{
+ unsigned int num_keys = 0;
+ unsigned int num_ext_keys = 0;
+ unsigned int num_buttons = 0;
+ unsigned int num_rels = 0;
+ unsigned int num_abs = 0;
+
+ unsigned long evbit[NBITS(EV_CNT)];
+ unsigned long keybit[NBITS(KEY_CNT)];
+ unsigned long relbit[NBITS(REL_CNT)];
+ unsigned long absbit[NBITS(ABS_CNT)];
+
+ struct input_id devinfo;
+
+ /* get device name */
+ ioctl( fd, EVIOCGNAME(DFB_INPUT_DEVICE_DESC_NAME_LENGTH - 1), info->desc.name );
+
+ /* set device vendor */
+ snprintf( info->desc.vendor,
+ DFB_INPUT_DEVICE_DESC_VENDOR_LENGTH, "Linux" );
+
+ /* get event type bits */
+ ioctl( fd, EVIOCGBIT(0, sizeof(evbit)), evbit );
+
+ if (test_bit( EV_KEY, evbit )) {
+ int i;
+
+ /* get keyboard bits */
+ ioctl( fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit );
+
+ /** count typical keyboard keys only */
+ for (i=KEY_Q; i<=KEY_M; i++)
+ if (test_bit( i, keybit ))
+ num_keys++;
+
+ for (i=KEY_OK; i<KEY_CNT; i++)
+ if (test_bit( i, keybit ))
+ num_ext_keys++;
+
+ for (i=BTN_MOUSE; i<BTN_JOYSTICK; i++)
+ if (test_bit( i, keybit ))
+ num_buttons++;
+ }
+
+ if (test_bit( EV_REL, evbit )) {
+ int i;
+
+ /* get bits for relative axes */
+ ioctl( fd, EVIOCGBIT(EV_REL, sizeof(relbit)), relbit );
+
+ for (i=0; i<REL_CNT; i++)
+ if (test_bit( i, relbit ))
+ num_rels++;
+ }
+
+ if (test_bit( EV_ABS, evbit )) {
+ int i;
+
+ /* get bits for absolute axes */
+ ioctl( fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit );
+
+ for (i=0; i<ABS_PRESSURE; i++)
+ if (test_bit( i, absbit ))
+ num_abs++;
+ }
+
+ /* Touchpad? */
+ /* FIXME: can we rely on BTN_TOUCH? xorg synaptics driver doesn't use it. */
+ if (test_bit( EV_KEY, evbit ) &&
+ test_bit( BTN_TOUCH, keybit ) &&
+ test_bit( BTN_TOOL_FINGER, keybit) &&
+ test_bit( EV_ABS, evbit ) &&
+ test_bit( ABS_X, absbit ) &&
+ test_bit( ABS_Y, absbit ) &&
+ test_bit( ABS_PRESSURE, absbit ))
+ *touchpad = true;
+ else
+ *touchpad = false;
+
+ /* Mouse, Touchscreen or Smartpad ? */
+ if ((test_bit( EV_KEY, evbit ) &&
+ (test_bit( BTN_TOUCH, keybit ) || test_bit( BTN_TOOL_FINGER, keybit ))) ||
+ ((num_rels >= 2 && num_buttons) || (num_abs == 2 && (num_buttons == 1))))
+ info->desc.type |= DIDTF_MOUSE;
+ else if (num_abs && num_buttons) /* Or a Joystick? */
+ info->desc.type |= DIDTF_JOYSTICK;
+
+ /* A Keyboard, do we have at least some letters? */
+ if (num_keys > 20) {
+ info->desc.type |= DIDTF_KEYBOARD;
+ info->desc.caps |= DICAPS_KEYS;
+ }
+
+ info->desc.min_keycode = 0;
+ info->desc.max_keycode = 127;
+
+ /* A Remote Control? */
+ if (num_ext_keys) {
+ info->desc.type |= DIDTF_REMOTE;
+ info->desc.caps |= DICAPS_KEYS;
+ }
+
+ /* Buttons */
+ if (num_buttons) {
+ info->desc.caps |= DICAPS_BUTTONS;
+ info->desc.max_button = DIBI_FIRST + num_buttons - 1;
+ }
+
+ /* Axes */
+ if (num_rels || num_abs) {
+ info->desc.caps |= DICAPS_AXES;
+ info->desc.max_axis = DIAI_FIRST + MAX(num_rels, num_abs) - 1;
+ }
+
+ /* Decide which primary input device to be. */
+ if (info->desc.type & DIDTF_KEYBOARD)
+ info->prefered_id = DIDID_KEYBOARD;
+ else if (info->desc.type & DIDTF_REMOTE)
+ info->prefered_id = DIDID_REMOTE;
+ else if (info->desc.type & DIDTF_JOYSTICK)
+ info->prefered_id = DIDID_JOYSTICK;
+ else if (info->desc.type & DIDTF_MOUSE)
+ info->prefered_id = DIDID_MOUSE;
+ else
+ info->prefered_id = DIDID_ANY;
+
+ /* Get VID and PID information */
+ ioctl( fd, EVIOCGID, &devinfo );
+
+ info->desc.vendor_id = devinfo.vendor;
+ info->desc.product_id = devinfo.product;
+}
+
+static bool
+check_device( const char *device,
+ InputDeviceInfo *ret_info )
+{
+ int fd;
+
+ D_DEBUG_AT( LinuxInput_Driver, "%s( %s )\n", __FUNCTION__, device );
+
+ /* Check if we are able to open the device */
+ fd = open( device, O_RDWR );
+ if (fd < 0) {
+ return false;
+ }
+ else {
+ bool touchpad;
+
+ /* try to grab the device */
+ if (dfb_config->linux_input_grab) {
+ /* 2.4 kernels don't have EVIOCGRAB so ignore EINVAL */
+ if (ioctl( fd, EVIOCGRAB, 1 ) && errno != EINVAL) {
+ close( fd );
+ return false;
+ }
+ }
+
+ memset( ret_info, 0, sizeof(InputDeviceInfo) );
+
+ get_device_info( fd, ret_info, &touchpad );
+
+ if (dfb_config->linux_input_grab)
+ ioctl( fd, EVIOCGRAB, 0 );
+ close( fd );
+
+ if (!dfb_config->linux_input_ir_only ||
+ (ret_info->desc.type & DIDTF_REMOTE))
+ return true;
+ }
+
+ return false;
+}
+
+/**********************************************************************************************************************/
+/**********************************************************************************************************************/
+
+/*
+ * Return the number of available devices.
+ * Called once during initialization of DirectFB.
+ */
+static int
+driver_get_available( void )
+{
+ D_DEBUG_AT( LinuxInput_Driver, "%s()\n", __FUNCTION__ );
+
+#ifdef LINUX_INPUT_USE_FBDEV
+ if (dfb_system_type() != CORE_FBDEV)
+ return 0;
+#endif
+
+ LinuxInput_UpdateDevices();
+
+ printf("================JK: get_available returns %d\n", num_devices);
+ return num_devices;
+}
+
+/*
+ * Fill out general information about this driver.
+ * Called once during initialization of DirectFB.
+ */
+static void
+driver_get_info( InputDriverInfo *info )
+{
+ /* fill driver info structure */
+ snprintf ( info->name,
+ DFB_INPUT_DRIVER_INFO_NAME_LENGTH, "Linux Input Driver" );
+ snprintf ( info->vendor,
+ DFB_INPUT_DRIVER_INFO_VENDOR_LENGTH, "directfb.org" );
+
+ info->version.major = 0;
+ info->version.minor = 1;
+}
+
+/*
+ * Open the device, fill out information about it,
+ * allocate and fill private data, start input thread.
+ * Called during initialization, resuming or taking over mastership.
+ */
+static DFBResult
+driver_open_device( CoreInputDevice *device,
+ unsigned int number,
+ InputDeviceInfo *info,
+ void **driver_data )
+{
+ int fd, ret;
+ unsigned long ledbit[NBITS(LED_CNT)];
+ LinuxInputData *data;
+#ifdef LINUX_INPUT_USE_FBDEV
+ FBDev *dfb_fbdev = dfb_system_data();
+#endif
+ bool touchpad;
+
+ D_DEBUG_AT( LinuxInput_Driver, "%s( %d ) <- %s\n", __FUNCTION__, number, devices[number].device );
+
+ /* open device */
+ fd = open( devices[number].device, O_RDWR );
+ if (fd < 0) {
+ D_PERROR( "DirectFB/linux_input: could not open device" );
+ return DFB_INIT;
+ }
+
+ /* grab device */
+ if (dfb_config->linux_input_grab) {
+ ret = ioctl( fd, EVIOCGRAB, 1 );
+ /* 2.4 kernels don't have EVIOCGRAB so ignore EINVAL */
+ if (ret && errno != EINVAL) {
+ D_PERROR( "DirectFB/linux_input: could not grab device" );
+ close( fd );
+ return DFB_INIT;
+ }
+ }
+
+ /* fill device info structure */
+ get_device_info( fd, info, &touchpad );
+
+ /* allocate and fill private data */
+ data = D_CALLOC( 1, sizeof(LinuxInputData) );
+ if (!data) {
+ if (dfb_config->linux_input_grab)
+ ioctl( fd, EVIOCGRAB, 0 );
+ close( fd );
+ return D_OOM();
+ }
+
+ data->index = number;
+ data->fd = fd;
+ data->device = device;
+ data->info = *info;
+#ifdef LINUX_INPUT_USE_FBDEV
+ if (dfb_system_type() == CORE_FBDEV)
+ data->vt = dfb_fbdev->vt;
+#endif
+ data->touchpad = touchpad;
+
+ /* check if the device has LEDs */
+ ret = ioctl( fd, EVIOCGBIT(EV_LED, sizeof(ledbit)), ledbit );
+ if (ret < 0)
+ D_PERROR( "DirectFB/linux_input: could not get LED bits" );
+ else
+ data->has_leds = test_bit( LED_SCROLLL, ledbit ) ||
+ test_bit( LED_NUML, ledbit ) ||
+ test_bit( LED_CAPSL, ledbit );
+
+ if (data->has_leds) {
+ /* get LED state */
+ ret = ioctl( fd, EVIOCGLED(sizeof(data->led_state)), data->led_state );
+ if (ret < 0) {
+ D_PERROR( "DirectFB/linux_input: could not get LED state" );
+ if (dfb_config->linux_input_grab)
+ ioctl( fd, EVIOCGRAB, 0 );
+ close( fd );
+ D_FREE( data );
+ return DFB_INIT;
+ }
+
+ /* turn off LEDs */
+ set_led( data, LED_SCROLLL, 0 );
+ set_led( data, LED_NUML, 0 );
+ set_led( data, LED_CAPSL, 0 );
+ }
+
+ data->sensitivity = 0x10000;
+
+ devices[number].data = data;
+
+ /* start input thread */
+ data->thread = direct_thread_create( DTT_INPUT, linux_input_EventThread, data, "Linux Input" );
+
+ /* set private data pointer */
+ *driver_data = data;
+
+ return DFB_OK;
+}
+
+/*
+ * Obtain information about an axis (only absolute axis so far).
+ */
+static DFBResult
+driver_get_axis_info( CoreInputDevice *device,
+ void *driver_data,
+ DFBInputDeviceAxisIdentifier axis,
+ DFBInputDeviceAxisInfo *ret_info )
+{
+ LinuxInputData *data = (LinuxInputData*) driver_data;
+
+ if (data->touchpad)
+ return DFB_OK;
+
+ if (axis <= ABS_PRESSURE && axis < DIAI_LAST) {
+ unsigned long absbit[NBITS(ABS_CNT)];
+
+ /* check if we have an absolute axes */
+ ioctl( data->fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit );
+
+ if (test_bit (axis, absbit)) {
+ struct input_absinfo absinfo;
+
+ if (ioctl( data->fd, EVIOCGABS(axis), &absinfo ) == 0 &&
+ (absinfo.minimum || absinfo.maximum)) {
+ ret_info->flags |= DIAIF_ABS_MIN | DIAIF_ABS_MAX;
+ ret_info->abs_min = absinfo.minimum;
+ ret_info->abs_max = absinfo.maximum;
+ }
+ }
+ }
+
+ return DFB_OK;
+}
+
+/*
+ * Fetch one entry from the kernel keymap.
+ */
+static DFBResult
+driver_get_keymap_entry( CoreInputDevice *device,
+ void *driver_data,
+ DFBInputDeviceKeymapEntry *entry )
+{
+#ifdef LINUX_INPUT_USE_FBDEV
+ LinuxInputData *data = (LinuxInputData*) driver_data;
+ int code = entry->code;
+ unsigned short value;
+ DFBInputDeviceKeyIdentifier identifier;
+
+ if (!data->vt)
+ return DFB_UNSUPPORTED;
+
+ /* fetch the base level */
+ value = keyboard_read_value( driver_data, K_NORMTAB, code );
+
+ /* get the identifier for basic mapping */
+ identifier = keyboard_get_identifier( code, value );
+
+ /* is CapsLock effective? */
+ if (KTYP(value) == KT_LETTER)
+ entry->locks |= DILS_CAPS;
+
+ /* is NumLock effective? */
+ if (identifier >= DIKI_KP_DECIMAL && identifier <= DIKI_KP_9)
+ entry->locks |= DILS_NUM;
+
+ /* write identifier to entry */
+ entry->identifier = identifier;
+
+ /* write base level symbol to entry */
+ entry->symbols[DIKSI_BASE] = keyboard_get_symbol( code, value, DIKSI_BASE );
+
+
+ /* fetch the shifted base level */
+ value = keyboard_read_value( driver_data, K_SHIFTTAB, entry->code );
+
+ /* write shifted base level symbol to entry */
+ entry->symbols[DIKSI_BASE_SHIFT] = keyboard_get_symbol( code, value,
+ DIKSI_BASE_SHIFT );
+
+
+ /* fetch the alternative level */
+ value = keyboard_read_value( driver_data, K_ALTTAB, entry->code );
+
+ /* write alternative level symbol to entry */
+ entry->symbols[DIKSI_ALT] = keyboard_get_symbol( code, value, DIKSI_ALT );
+
+
+ /* fetch the shifted alternative level */
+ value = keyboard_read_value( driver_data, K_ALTSHIFTTAB, entry->code );
+
+ /* write shifted alternative level symbol to entry */
+ entry->symbols[DIKSI_ALT_SHIFT] = keyboard_get_symbol( code, value,
+ DIKSI_ALT_SHIFT );
+
+ return DFB_OK;
+#else
+ return DFB_UNSUPPORTED;
+#endif
+}
+
+/*
+ * Obtain information about an axis (only absolute axis so far).
+ */
+static DFBResult
+driver_set_sensitivity( CoreInputDevice *device,
+ void *driver_data,
+ int sensitivity )
+{
+ LinuxInputData *data = (LinuxInputData*) driver_data;
+
+ data->sensitivity = sensitivity;
+
+ return DFB_OK;
+}
+
+/*
+ * End thread, close device and free private data.
+ */
+static void
+driver_close_device( void *driver_data )
+{
+ LinuxInputData *data = (LinuxInputData*) driver_data;
+
+ /* stop input thread */
+ direct_thread_cancel( data->thread );
+ direct_thread_join( data->thread );
+ direct_thread_destroy( data->thread );
+
+ if (data->has_leds) {
+ /* restore LED state */
+ set_led( data, LED_SCROLLL, test_bit( LED_SCROLLL, data->led_state ) );
+ set_led( data, LED_NUML, test_bit( LED_NUML, data->led_state ) );
+ set_led( data, LED_CAPSL, test_bit( LED_CAPSL, data->led_state ) );
+ }
+
+ /* release device */
+ if (dfb_config->linux_input_grab)
+ ioctl( data->fd, EVIOCGRAB, 0 );
+
+ /* close file */
+ close( data->fd );
+
+ /* free private data */
+ D_FREE( data );
+}
+
+/**********************************************************************************************************************/
+
+static bool
+timeout_is_set( const struct timeval *timeout )
+{
+ return timeout->tv_sec || timeout->tv_usec;
+}
+
+static bool
+timeout_passed( const struct timeval *timeout, const struct timeval *current )
+{
+ return !timeout_is_set( timeout ) ||
+ current->tv_sec > timeout->tv_sec ||
+ (current->tv_sec == timeout->tv_sec && current->tv_usec > timeout->tv_usec);
+}
+
+static void
+timeout_clear( struct timeval *timeout )
+{
+ timeout->tv_sec = 0;
+ timeout->tv_usec = 0;
+}
+
+static void
+timeout_add( struct timeval *timeout, const struct timeval *add )
+{
+ timeout->tv_sec += add->tv_sec;
+ timeout->tv_usec += add->tv_usec;
+ while (timeout->tv_usec >= 1000000) {
+ timeout->tv_sec++;
+ timeout->tv_usec -= 1000000;
+ }
+}
+
+static void
+timeout_sub( struct timeval *timeout, const struct timeval *sub )
+{
+ timeout->tv_sec -= sub->tv_sec;
+ timeout->tv_usec -= sub->tv_usec;
+ while (timeout->tv_usec < 0) {
+ timeout->tv_sec--;
+ timeout->tv_usec += 1000000;
+ }
+}
+
+/**********************************************************************************************************************/
+
+static void
+touchpad_fsm_init( struct touchpad_fsm_state *state )
+{
+ state->x.old = -1;
+ state->y.old = -1;
+ state->fsm_state = TOUCHPAD_FSM_START;
+ timeout_clear( &state->timeout );
+}
+
+static int
+touchpad_normalize( const struct touchpad_axis *axis, int value )
+{
+ return ((value - axis->min) << 9) / (axis->max - axis->min);
+}
+
+static int
+touchpad_translate( struct touchpad_fsm_state *state,
+ const struct input_event *levt,
+ DFBInputEvent *devt )
+{
+ struct touchpad_axis *axis = NULL;
+ int abs, rel;
+
+ devt->flags = DIEF_TIMESTAMP | DIEF_AXISREL;
+ devt->timestamp = levt->time;
+ devt->type = DIET_AXISMOTION;
+
+ switch (levt->code) {
+ case ABS_X:
+ axis = &state->x;
+ devt->axis = DIAI_X;
+ break;
+ case ABS_Y:
+ axis = &state->y;
+ devt->axis = DIAI_Y;
+ break;
+ default:
+ return 0;
+ }
+
+ abs = touchpad_normalize( axis, levt->value );
+ if (axis->old == -1)
+ axis->old = abs;
+ rel = abs - axis->old;
+
+#define ACCEL_THRESHOLD 25
+#define ACCEL_NUM 3
+#define ACCEL_DENOM 1
+
+ if (rel > ACCEL_THRESHOLD)
+ rel += (rel - ACCEL_THRESHOLD) * ACCEL_NUM / ACCEL_DENOM;
+ else if (rel < -ACCEL_THRESHOLD)
+ rel += (rel + ACCEL_THRESHOLD) * ACCEL_NUM / ACCEL_DENOM;
+
+ axis->old = abs;
+ devt->axisrel = rel;
+
+ return 1;
+}
+
+static bool
+touchpad_finger_landing( const struct input_event *levt )
+{
+ return levt->type == EV_KEY && levt->code == BTN_TOUCH && levt->value == 1;
+}
+
+static bool
+touchpad_finger_leaving( const struct input_event *levt )
+{
+ return levt->type == EV_KEY && levt->code == BTN_TOUCH && levt->value == 0;
+}
+
+static bool
+touchpad_finger_moving( const struct input_event *levt )
+{
+ return levt->type == EV_ABS && (levt->code == ABS_X || levt->code == ABS_Y);
+}
+
+/*
+ * This FSM takes into accout finger landing on touchpad and leaving and
+ * translates absolute DFBInputEvent into a relative one
+ */
+static int
+touchpad_fsm( struct touchpad_fsm_state *state,
+ const struct input_event *levt,
+ DFBInputEvent *devt )
+{
+ struct timeval timeout = { 0, 125000 };
+
+ /* select() timeout? */
+ if (!levt) {
+ /* Check if button release is due. */
+ if (state->fsm_state == TOUCHPAD_FSM_DRAG_START) {
+ devt->flags = DIEF_TIMESTAMP;
+ devt->timestamp = state->timeout; /* timeout of current time? */
+ devt->type = DIET_BUTTONRELEASE;
+ devt->button = DIBI_FIRST;
+
+ touchpad_fsm_init( state );
+ return 1;
+ }
+
+ /* Already passed, clear it so select() won't return until there is something to do. */
+ timeout_clear( &state->timeout );
+ return 0;
+ }
+
+ /* More or less ignore these events for now */
+ if ((levt->type == EV_SYN && levt->code == SYN_REPORT) ||
+ (levt->type == EV_ABS && levt->code == ABS_PRESSURE) ||
+ (levt->type == EV_ABS && levt->code == ABS_TOOL_WIDTH) ||
+ (levt->type == EV_KEY && levt->code == BTN_TOOL_FINGER) ||
+ (levt->type == EV_KEY && levt->code == BTN_TOOL_DOUBLETAP) ||
+ (levt->type == EV_KEY && levt->code == BTN_TOOL_TRIPLETAP)) {
+
+ /* Check if button release is due. */
+ if (state->fsm_state == TOUCHPAD_FSM_DRAG_START &&
+ timeout_passed( &state->timeout, &levt->time )) {
+ devt->flags = DIEF_TIMESTAMP;
+ devt->timestamp = state->timeout; /* timeout of levt->time? */
+ devt->type = DIET_BUTTONRELEASE;
+ devt->button = DIBI_FIRST;
+
+ touchpad_fsm_init( state );
+ return 1;
+ }
+
+ return 0;
+ }
+
+ /* Use translate_event() for other events. */
+ if (!(levt->type == EV_KEY && levt->code == BTN_TOUCH) &&
+ !(levt->type == EV_ABS && (levt->code == ABS_X || levt->code == ABS_Y)))
+ return -1;
+
+ switch (state->fsm_state) {
+ case TOUCHPAD_FSM_START:
+ if (touchpad_finger_landing( levt )) {
+ state->fsm_state = TOUCHPAD_FSM_MAIN;
+ state->timeout = levt->time;
+ timeout_add( &state->timeout, &timeout );
+ }
+ return 0;
+
+ case TOUCHPAD_FSM_MAIN:
+ if (touchpad_finger_moving( levt )) {
+ if (1){//timeout_passed( &state->timeout, &levt->time )) {
+ //timeout_clear( &state->timeout );
+ return touchpad_translate( state, levt, devt );
+ }
+ }
+ else if (touchpad_finger_leaving( levt )) {
+ if (!timeout_passed( &state->timeout, &levt->time )) {
+ devt->flags = DIEF_TIMESTAMP;
+ devt->timestamp = levt->time;
+ devt->type = DIET_BUTTONPRESS;
+ devt->button = DIBI_FIRST;
+
+ touchpad_fsm_init( state );
+ state->fsm_state = TOUCHPAD_FSM_DRAG_START;
+ state->timeout = levt->time;
+ timeout_add( &state->timeout, &timeout );
+ return 1;
+ }
+ else {
+ touchpad_fsm_init( state );
+ }
+ }
+ return 0;
+
+ case TOUCHPAD_FSM_DRAG_START:
+ if (timeout_passed( &state->timeout, &levt->time )){
+ devt->flags = DIEF_TIMESTAMP;
+ devt->timestamp = state->timeout; /* timeout of levt->time? */
+ devt->type = DIET_BUTTONRELEASE;
+ devt->button = DIBI_FIRST;
+
+ touchpad_fsm_init(state);
+ return 1;
+ }
+ else {
+ if (touchpad_finger_landing( levt )) {
+ state->fsm_state = TOUCHPAD_FSM_DRAG_MAIN;
+ state->timeout = levt->time;
+ timeout_add( &state->timeout, &timeout );
+ }
+ }
+ return 0;
+
+ case TOUCHPAD_FSM_DRAG_MAIN:
+ if (touchpad_finger_moving( levt )) {
+ if (1){//timeout_passed( &state->timeout, &levt->time )) {
+ //timeout_clear( &state->timeout );
+ return touchpad_translate( state, levt, devt );
+ }
+ }
+ else if (touchpad_finger_leaving( levt )) {
+ devt->flags = DIEF_TIMESTAMP;
+ devt->timestamp = levt->time;
+ devt->type = DIET_BUTTONRELEASE;
+ devt->button = DIBI_FIRST;
+
+ touchpad_fsm_init( state );
+ return 1;
+ }
+ return 0;
+
+ default:
+ return 0;
+ }
+
+ return 0;
+}