From 7fe60435bce6595a9c58a9bfd8244d74b5320e96 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Tue, 15 Jan 2013 08:46:13 +0100 Subject: Import DirectFB141_2k11R3_beta5 --- .../DirectFB/inputdrivers/linux_input/Makefile.am | 34 + .../DirectFB/inputdrivers/linux_input/Makefile.in | 601 ++++++ .../DirectFB/inputdrivers/linux_input/input_fake.h | 84 + .../inputdrivers/linux_input/linux_input.c | 1994 ++++++++++++++++++++ 4 files changed, 2713 insertions(+) create mode 100755 Source/DirectFB/inputdrivers/linux_input/Makefile.am create mode 100755 Source/DirectFB/inputdrivers/linux_input/Makefile.in create mode 100755 Source/DirectFB/inputdrivers/linux_input/input_fake.h create mode 100755 Source/DirectFB/inputdrivers/linux_input/linux_input.c (limited to 'Source/DirectFB/inputdrivers/linux_input') 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 + + +#if !defined(KEY_OK) + +/** + * define some additional remote control keys in case they + * were not already defined above in + */ + +#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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + + +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) +typedef unsigned long kernel_ulong_t; +#define BITS_PER_LONG (sizeof(long)*8) +#endif + +#include + +#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 + + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#define DFB_INPUTDRIVER_HAS_AXIS_INFO +#define DFB_INPUTDRIVER_HAS_SENSITIVITY + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#ifdef LINUX_INPUT_USE_FBDEV +#include +#endif + +#include + + +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(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; ievents.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; iflags |= 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; ifd != -1) + return; + + break; + } + } + + if (!check_device( device, &info )) + return; + + for (i=0; ifd == -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; ifd < 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; imouse_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= 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; +} -- cgit