diff options
Diffstat (limited to 'config')
-rw-r--r-- | config/10-evdev.conf | 40 | ||||
-rw-r--r-- | config/Makefile.am | 41 | ||||
-rw-r--r-- | config/Makefile.in | 804 | ||||
-rw-r--r-- | config/config-backends.h | 70 | ||||
-rw-r--r-- | config/config.c | 139 | ||||
-rw-r--r-- | config/dbus-core.c | 247 | ||||
-rw-r--r-- | config/dbus.c | 439 | ||||
-rwxr-xr-x | config/fdi2iclass.py | 202 | ||||
-rw-r--r-- | config/hal.c | 654 | ||||
-rw-r--r-- | config/udev.c | 325 | ||||
-rw-r--r-- | config/x11-input.fdi | 93 | ||||
-rw-r--r-- | config/xorg-server.conf | 13 |
12 files changed, 3067 insertions, 0 deletions
diff --git a/config/10-evdev.conf b/config/10-evdev.conf new file mode 100644 index 0000000..cc83ab2 --- /dev/null +++ b/config/10-evdev.conf @@ -0,0 +1,40 @@ +# +# Catch-all evdev loader for udev-based systems +# We don't simply match on any device since that also adds accelerometers +# and other devices that we don't really want to use. The list below +# matches everything but joysticks. + +Section "InputClass" + Identifier "evdev pointer catchall" + MatchIsPointer "on" + MatchDevicePath "/dev/input/event*" + Driver "evdev" +EndSection + +Section "InputClass" + Identifier "evdev keyboard catchall" + MatchIsKeyboard "on" + MatchDevicePath "/dev/input/event*" + Driver "evdev" +EndSection + +Section "InputClass" + Identifier "evdev touchpad catchall" + MatchIsTouchpad "on" + MatchDevicePath "/dev/input/event*" + Driver "evdev" +EndSection + +Section "InputClass" + Identifier "evdev tablet catchall" + MatchIsTablet "on" + MatchDevicePath "/dev/input/event*" + Driver "evdev" +EndSection + +Section "InputClass" + Identifier "evdev touchscreen catchall" + MatchIsTouchscreen "on" + MatchDevicePath "/dev/input/event*" + Driver "evdev" +EndSection diff --git a/config/Makefile.am b/config/Makefile.am new file mode 100644 index 0000000..4a2e873 --- /dev/null +++ b/config/Makefile.am @@ -0,0 +1,41 @@ +AM_CFLAGS = $(DIX_CFLAGS) + +noinst_LTLIBRARIES = libconfig.la +libconfig_la_SOURCES = config.c config-backends.h + +if CONFIG_UDEV + +AM_CFLAGS += $(UDEV_CFLAGS) +libconfig_la_SOURCES += udev.c +libconfig_la_LIBADD = $(UDEV_LIBS) + +if XORG +xorgconfddir = $(datadir)/X11/$(XF86CONFIGDIR) +xorgconfd_DATA = 10-evdev.conf +endif + +else + +if CONFIG_NEED_DBUS +AM_CFLAGS += $(DBUS_CFLAGS) +libconfig_la_SOURCES += dbus-core.c +libconfig_la_LIBADD = $(DBUS_LIBS) + +if CONFIG_DBUS_API +dbusconfigdir = $(sysconfdir)/dbus-1/system.d +dbusconfig_DATA = xorg-server.conf + +libconfig_la_SOURCES += dbus.c +endif + +if CONFIG_HAL +AM_CFLAGS += $(HAL_CFLAGS) +libconfig_la_SOURCES += hal.c +libconfig_la_LIBADD += $(HAL_LIBS) +endif + +endif # CONFIG_NEED_DBUS + +endif # !CONFIG_UDEV + +EXTRA_DIST = xorg-server.conf x11-input.fdi 10-evdev.conf fdi2iclass.py diff --git a/config/Makefile.in b/config/Makefile.in new file mode 100644 index 0000000..92a97b0 --- /dev/null +++ b/config/Makefile.in @@ -0,0 +1,804 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 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@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@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@ +@CONFIG_UDEV_TRUE@am__append_1 = $(UDEV_CFLAGS) +@CONFIG_UDEV_TRUE@am__append_2 = udev.c +@CONFIG_NEED_DBUS_TRUE@@CONFIG_UDEV_FALSE@am__append_3 = $(DBUS_CFLAGS) +@CONFIG_NEED_DBUS_TRUE@@CONFIG_UDEV_FALSE@am__append_4 = dbus-core.c +@CONFIG_DBUS_API_TRUE@@CONFIG_NEED_DBUS_TRUE@@CONFIG_UDEV_FALSE@am__append_5 = dbus.c +@CONFIG_HAL_TRUE@@CONFIG_NEED_DBUS_TRUE@@CONFIG_UDEV_FALSE@am__append_6 = $(HAL_CFLAGS) +@CONFIG_HAL_TRUE@@CONFIG_NEED_DBUS_TRUE@@CONFIG_UDEV_FALSE@am__append_7 = hal.c +@CONFIG_HAL_TRUE@@CONFIG_NEED_DBUS_TRUE@@CONFIG_UDEV_FALSE@am__append_8 = $(HAL_LIBS) +subdir = config +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_define_dir.m4 \ + $(top_srcdir)/m4/ax_tls.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/include/do-not-use-config.h \ + $(top_builddir)/include/xorg-server.h \ + $(top_builddir)/include/dix-config.h \ + $(top_builddir)/include/xorg-config.h \ + $(top_builddir)/include/xkb-config.h \ + $(top_builddir)/include/xwin-config.h \ + $(top_builddir)/include/kdrive-config.h \ + $(top_builddir)/include/version-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +am__DEPENDENCIES_1 = +@CONFIG_HAL_TRUE@@CONFIG_NEED_DBUS_TRUE@@CONFIG_UDEV_FALSE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) +@CONFIG_NEED_DBUS_TRUE@@CONFIG_UDEV_FALSE@libconfig_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ +@CONFIG_NEED_DBUS_TRUE@@CONFIG_UDEV_FALSE@ $(am__DEPENDENCIES_2) +@CONFIG_UDEV_TRUE@libconfig_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ +@CONFIG_UDEV_TRUE@ $(am__DEPENDENCIES_2) +am__libconfig_la_SOURCES_DIST = config.c config-backends.h udev.c \ + dbus-core.c dbus.c hal.c +@CONFIG_UDEV_TRUE@am__objects_1 = udev.lo +@CONFIG_NEED_DBUS_TRUE@@CONFIG_UDEV_FALSE@am__objects_2 = \ +@CONFIG_NEED_DBUS_TRUE@@CONFIG_UDEV_FALSE@ dbus-core.lo +@CONFIG_DBUS_API_TRUE@@CONFIG_NEED_DBUS_TRUE@@CONFIG_UDEV_FALSE@am__objects_3 = dbus.lo +@CONFIG_HAL_TRUE@@CONFIG_NEED_DBUS_TRUE@@CONFIG_UDEV_FALSE@am__objects_4 = hal.lo +am_libconfig_la_OBJECTS = config.lo $(am__objects_1) $(am__objects_2) \ + $(am__objects_3) $(am__objects_4) +libconfig_la_OBJECTS = $(am_libconfig_la_OBJECTS) +AM_V_lt = $(am__v_lt_$(V)) +am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) +am__v_lt_0 = --silent +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_$(V)) +am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) +am__v_CC_0 = @echo " CC " $@; +AM_V_at = $(am__v_at_$(V)) +am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +am__v_at_0 = @ +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_$(V)) +am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) +am__v_CCLD_0 = @echo " CCLD " $@; +AM_V_GEN = $(am__v_GEN_$(V)) +am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +am__v_GEN_0 = @echo " GEN " $@; +SOURCES = $(libconfig_la_SOURCES) +DIST_SOURCES = $(am__libconfig_la_SOURCES_DIST) +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 = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(dbusconfigdir)" \ + "$(DESTDIR)$(xorgconfddir)" +DATA = $(dbusconfig_DATA) $(xorgconfd_DATA) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ADMIN_MAN_DIR = @ADMIN_MAN_DIR@ +ADMIN_MAN_SUFFIX = @ADMIN_MAN_SUFFIX@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APPLE_APPLICATIONS_DIR = @APPLE_APPLICATIONS_DIR@ +APPLE_APPLICATION_NAME = @APPLE_APPLICATION_NAME@ +APP_MAN_DIR = @APP_MAN_DIR@ +APP_MAN_SUFFIX = @APP_MAN_SUFFIX@ +AR = @AR@ +ARM_BACKTRACE_CFLAGS = @ARM_BACKTRACE_CFLAGS@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASE_FONT_PATH = @BASE_FONT_PATH@ +BUILD_DATE = @BUILD_DATE@ +BUILD_TIME = @BUILD_TIME@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHANGELOG_CMD = @CHANGELOG_CMD@ +COMPILEDDEFAULTFONTPATH = @COMPILEDDEFAULTFONTPATH@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CWARNFLAGS = @CWARNFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DARWIN_LIBS = @DARWIN_LIBS@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_LIBS = @DBUS_LIBS@ +DEFAULT_LIBRARY_PATH = @DEFAULT_LIBRARY_PATH@ +DEFAULT_LOGDIR = @DEFAULT_LOGDIR@ +DEFAULT_LOGPREFIX = @DEFAULT_LOGPREFIX@ +DEFAULT_MODULE_PATH = @DEFAULT_MODULE_PATH@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DGA_CFLAGS = @DGA_CFLAGS@ +DGA_LIBS = @DGA_LIBS@ +DIX_CFLAGS = @DIX_CFLAGS@ +DIX_LIB = @DIX_LIB@ +DLLTOOL = @DLLTOOL@ +DLOPEN_LIBS = @DLOPEN_LIBS@ +DMXEXAMPLES_DEP_CFLAGS = @DMXEXAMPLES_DEP_CFLAGS@ +DMXEXAMPLES_DEP_LIBS = @DMXEXAMPLES_DEP_LIBS@ +DMXMODULES_CFLAGS = @DMXMODULES_CFLAGS@ +DMXMODULES_LIBS = @DMXMODULES_LIBS@ +DMXXIEXAMPLES_DEP_CFLAGS = @DMXXIEXAMPLES_DEP_CFLAGS@ +DMXXIEXAMPLES_DEP_LIBS = @DMXXIEXAMPLES_DEP_LIBS@ +DMXXMUEXAMPLES_DEP_CFLAGS = @DMXXMUEXAMPLES_DEP_CFLAGS@ +DMXXMUEXAMPLES_DEP_LIBS = @DMXXMUEXAMPLES_DEP_LIBS@ +DOXYGEN = @DOXYGEN@ +DRI2PROTO_CFLAGS = @DRI2PROTO_CFLAGS@ +DRI2PROTO_LIBS = @DRI2PROTO_LIBS@ +DRIPROTO_CFLAGS = @DRIPROTO_CFLAGS@ +DRIPROTO_LIBS = @DRIPROTO_LIBS@ +DRIVER_MAN_DIR = @DRIVER_MAN_DIR@ +DRIVER_MAN_SUFFIX = @DRIVER_MAN_SUFFIX@ +DRI_CFLAGS = @DRI_CFLAGS@ +DRI_DRIVER_PATH = @DRI_DRIVER_PATH@ +DRI_LIBS = @DRI_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DTRACE = @DTRACE@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILE_MAN_DIR = @FILE_MAN_DIR@ +FILE_MAN_SUFFIX = @FILE_MAN_SUFFIX@ +FONT100DPIDIR = @FONT100DPIDIR@ +FONT75DPIDIR = @FONT75DPIDIR@ +FONTMISCDIR = @FONTMISCDIR@ +FONTOTFDIR = @FONTOTFDIR@ +FONTROOTDIR = @FONTROOTDIR@ +FONTTTFDIR = @FONTTTFDIR@ +FONTTYPE1DIR = @FONTTYPE1DIR@ +FOP = @FOP@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_LIBS = @GLIB_LIBS@ +GLX_ARCH_DEFINES = @GLX_ARCH_DEFINES@ +GLX_DEFINES = @GLX_DEFINES@ +GLX_TLS = @GLX_TLS@ +GL_CFLAGS = @GL_CFLAGS@ +GL_LIBS = @GL_LIBS@ +GREP = @GREP@ +HAL_CFLAGS = @HAL_CFLAGS@ +HAL_LIBS = @HAL_LIBS@ +INSTALL = @INSTALL@ +INSTALL_CMD = @INSTALL_CMD@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KDRIVE_CFLAGS = @KDRIVE_CFLAGS@ +KDRIVE_INCS = @KDRIVE_INCS@ +KDRIVE_LIBS = @KDRIVE_LIBS@ +KDRIVE_LOCAL_LIBS = @KDRIVE_LOCAL_LIBS@ +KDRIVE_PURE_INCS = @KDRIVE_PURE_INCS@ +KDRIVE_PURE_LIBS = @KDRIVE_PURE_LIBS@ +LAUNCHD_ID_PREFIX = @LAUNCHD_ID_PREFIX@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LD_EXPORT_SYMBOLS_FLAG = @LD_EXPORT_SYMBOLS_FLAG@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBDRM_CFLAGS = @LIBDRM_CFLAGS@ +LIBDRM_LIBS = @LIBDRM_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSHA1_CFLAGS = @LIBSHA1_CFLAGS@ +LIBSHA1_LIBS = @LIBSHA1_LIBS@ +LIBTOOL = @LIBTOOL@ +LIB_MAN_DIR = @LIB_MAN_DIR@ +LIB_MAN_SUFFIX = @LIB_MAN_SUFFIX@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAIN_LIB = @MAIN_LIB@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MAN_SUBSTS = @MAN_SUBSTS@ +MISC_MAN_DIR = @MISC_MAN_DIR@ +MISC_MAN_SUFFIX = @MISC_MAN_SUFFIX@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCCLD = @OBJCCLD@ +OBJCDEPMODE = @OBJCDEPMODE@ +OBJCFLAGS = @OBJCFLAGS@ +OBJCLINK = @OBJCLINK@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OS_LIB = @OS_LIB@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PCIACCESS_CFLAGS = @PCIACCESS_CFLAGS@ +PCIACCESS_LIBS = @PCIACCESS_LIBS@ +PCI_TXT_IDS_PATH = @PCI_TXT_IDS_PATH@ +PERL = @PERL@ +PIXMAN_CFLAGS = @PIXMAN_CFLAGS@ +PIXMAN_LIBS = @PIXMAN_LIBS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROJECTROOT = @PROJECTROOT@ +RANLIB = @RANLIB@ +RAWCPP = @RAWCPP@ +RAWCPPFLAGS = @RAWCPPFLAGS@ +RELEASE_DATE = @RELEASE_DATE@ +SDK_REQUIRED_MODULES = @SDK_REQUIRED_MODULES@ +SED = @SED@ +SELINUX_CFLAGS = @SELINUX_CFLAGS@ +SELINUX_LIBS = @SELINUX_LIBS@ +SERVER_MISC_CONFIG_PATH = @SERVER_MISC_CONFIG_PATH@ +SET_MAKE = @SET_MAKE@ +SHA1_CFLAGS = @SHA1_CFLAGS@ +SHA1_LIBS = @SHA1_LIBS@ +SHELL = @SHELL@ +SOLARIS_ASM_CFLAGS = @SOLARIS_ASM_CFLAGS@ +SOLARIS_INOUT_ARCH = @SOLARIS_INOUT_ARCH@ +STRIP = @STRIP@ +STYLESHEET_SRCDIR = @STYLESHEET_SRCDIR@ +SYSCONFDIR = @SYSCONFDIR@ +TSLIB_CFLAGS = @TSLIB_CFLAGS@ +TSLIB_LIBS = @TSLIB_LIBS@ +UDEV_CFLAGS = @UDEV_CFLAGS@ +UDEV_LIBS = @UDEV_LIBS@ +UTILS_SYS_LIBS = @UTILS_SYS_LIBS@ +VENDOR_NAME_SHORT = @VENDOR_NAME_SHORT@ +VERSION = @VERSION@ +WINDOWSWM_CFLAGS = @WINDOWSWM_CFLAGS@ +WINDOWSWM_LIBS = @WINDOWSWM_LIBS@ +WINDRES = @WINDRES@ +X11EXAMPLES_DEP_CFLAGS = @X11EXAMPLES_DEP_CFLAGS@ +X11EXAMPLES_DEP_LIBS = @X11EXAMPLES_DEP_LIBS@ +XDMCP_CFLAGS = @XDMCP_CFLAGS@ +XDMCP_LIBS = @XDMCP_LIBS@ +XDMXCONFIG_DEP_CFLAGS = @XDMXCONFIG_DEP_CFLAGS@ +XDMXCONFIG_DEP_LIBS = @XDMXCONFIG_DEP_LIBS@ +XDMX_CFLAGS = @XDMX_CFLAGS@ +XDMX_LIBS = @XDMX_LIBS@ +XDMX_SYS_LIBS = @XDMX_SYS_LIBS@ +XEPHYR_CFLAGS = @XEPHYR_CFLAGS@ +XEPHYR_INCS = @XEPHYR_INCS@ +XEPHYR_LIBS = @XEPHYR_LIBS@ +XF86CONFIGDIR = @XF86CONFIGDIR@ +XF86CONFIGFILE = @XF86CONFIGFILE@ +XF86VIDMODE_CFLAGS = @XF86VIDMODE_CFLAGS@ +XF86VIDMODE_LIBS = @XF86VIDMODE_LIBS@ +XKB_BASE_DIRECTORY = @XKB_BASE_DIRECTORY@ +XKB_BIN_DIRECTORY = @XKB_BIN_DIRECTORY@ +XKB_COMPILED_DIR = @XKB_COMPILED_DIR@ +XKM_OUTPUT_DIR = @XKM_OUTPUT_DIR@ +XLIB_CFLAGS = @XLIB_CFLAGS@ +XLIB_LIBS = @XLIB_LIBS@ +XMLTO = @XMLTO@ +XNESTMODULES_CFLAGS = @XNESTMODULES_CFLAGS@ +XNESTMODULES_LIBS = @XNESTMODULES_LIBS@ +XNEST_LIBS = @XNEST_LIBS@ +XNEST_SYS_LIBS = @XNEST_SYS_LIBS@ +XORG_CFLAGS = @XORG_CFLAGS@ +XORG_INCS = @XORG_INCS@ +XORG_LIBS = @XORG_LIBS@ +XORG_MAN_PAGE = @XORG_MAN_PAGE@ +XORG_MODULES_CFLAGS = @XORG_MODULES_CFLAGS@ +XORG_MODULES_LIBS = @XORG_MODULES_LIBS@ +XORG_OS = @XORG_OS@ +XORG_OS_SUBDIR = @XORG_OS_SUBDIR@ +XORG_SGML_PATH = @XORG_SGML_PATH@ +XORG_SYS_LIBS = @XORG_SYS_LIBS@ +XPBPROXY_CFLAGS = @XPBPROXY_CFLAGS@ +XPBPROXY_LIBS = @XPBPROXY_LIBS@ +XQUARTZ_SPARKLE = @XQUARTZ_SPARKLE@ +XRESEXAMPLES_DEP_CFLAGS = @XRESEXAMPLES_DEP_CFLAGS@ +XRESEXAMPLES_DEP_LIBS = @XRESEXAMPLES_DEP_LIBS@ +XSERVERCFLAGS_CFLAGS = @XSERVERCFLAGS_CFLAGS@ +XSERVERCFLAGS_LIBS = @XSERVERCFLAGS_LIBS@ +XSERVERLIBS_CFLAGS = @XSERVERLIBS_CFLAGS@ +XSERVERLIBS_LIBS = @XSERVERLIBS_LIBS@ +XSERVER_LIBS = @XSERVER_LIBS@ +XSERVER_SYS_LIBS = @XSERVER_SYS_LIBS@ +XSL_STYLESHEET = @XSL_STYLESHEET@ +XTSTEXAMPLES_DEP_CFLAGS = @XTSTEXAMPLES_DEP_CFLAGS@ +XTSTEXAMPLES_DEP_LIBS = @XTSTEXAMPLES_DEP_LIBS@ +XVFB_LIBS = @XVFB_LIBS@ +XVFB_SYS_LIBS = @XVFB_SYS_LIBS@ +XWINMODULES_CFLAGS = @XWINMODULES_CFLAGS@ +XWINMODULES_LIBS = @XWINMODULES_LIBS@ +XWIN_LIBS = @XWIN_LIBS@ +XWIN_SERVER_NAME = @XWIN_SERVER_NAME@ +XWIN_SYS_LIBS = @XWIN_SYS_LIBS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +__XCONFIGDIR__ = @__XCONFIGDIR__@ +__XCONFIGFILE__ = @__XCONFIGFILE__@ +abi_ansic = @abi_ansic@ +abi_extension = @abi_extension@ +abi_videodrv = @abi_videodrv@ +abi_xinput = @abi_xinput@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +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@ +driverdir = @driverdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +extdir = @extdir@ +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@ +logdir = @logdir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sdkdir = @sdkdir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +symbol_visibility = @symbol_visibility@ +sysconfdir = @sysconfdir@ +sysconfigdir = @sysconfigdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CFLAGS = $(DIX_CFLAGS) $(am__append_1) $(am__append_3) \ + $(am__append_6) +noinst_LTLIBRARIES = libconfig.la +libconfig_la_SOURCES = config.c config-backends.h $(am__append_2) \ + $(am__append_4) $(am__append_5) $(am__append_7) +@CONFIG_NEED_DBUS_TRUE@@CONFIG_UDEV_FALSE@libconfig_la_LIBADD = \ +@CONFIG_NEED_DBUS_TRUE@@CONFIG_UDEV_FALSE@ $(DBUS_LIBS) \ +@CONFIG_NEED_DBUS_TRUE@@CONFIG_UDEV_FALSE@ $(am__append_8) +@CONFIG_UDEV_TRUE@libconfig_la_LIBADD = $(UDEV_LIBS) $(am__append_8) +@CONFIG_UDEV_TRUE@@XORG_TRUE@xorgconfddir = $(datadir)/X11/$(XF86CONFIGDIR) +@CONFIG_UDEV_TRUE@@XORG_TRUE@xorgconfd_DATA = 10-evdev.conf +@CONFIG_DBUS_API_TRUE@@CONFIG_NEED_DBUS_TRUE@@CONFIG_UDEV_FALSE@dbusconfigdir = $(sysconfdir)/dbus-1/system.d +@CONFIG_DBUS_API_TRUE@@CONFIG_NEED_DBUS_TRUE@@CONFIG_UDEV_FALSE@dbusconfig_DATA = xorg-server.conf +EXTRA_DIST = xorg-server.conf x11-input.fdi 10-evdev.conf fdi2iclass.py +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign config/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign config/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 +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_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 +libconfig.la: $(libconfig_la_OBJECTS) $(libconfig_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libconfig_la_OBJECTS) $(libconfig_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/config.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbus-core.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbus.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hal.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/udev.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@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@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@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@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@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-dbusconfigDATA: $(dbusconfig_DATA) + @$(NORMAL_INSTALL) + test -z "$(dbusconfigdir)" || $(MKDIR_P) "$(DESTDIR)$(dbusconfigdir)" + @list='$(dbusconfig_DATA)'; test -n "$(dbusconfigdir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(dbusconfigdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(dbusconfigdir)" || exit $$?; \ + done + +uninstall-dbusconfigDATA: + @$(NORMAL_UNINSTALL) + @list='$(dbusconfig_DATA)'; test -n "$(dbusconfigdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(dbusconfigdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(dbusconfigdir)" && rm -f $$files +install-xorgconfdDATA: $(xorgconfd_DATA) + @$(NORMAL_INSTALL) + test -z "$(xorgconfddir)" || $(MKDIR_P) "$(DESTDIR)$(xorgconfddir)" + @list='$(xorgconfd_DATA)'; test -n "$(xorgconfddir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(xorgconfddir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(xorgconfddir)" || exit $$?; \ + done + +uninstall-xorgconfdDATA: + @$(NORMAL_UNINSTALL) + @list='$(xorgconfd_DATA)'; test -n "$(xorgconfddir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(xorgconfddir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(xorgconfddir)" && rm -f $$files + +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; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + 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; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + 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)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__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 "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$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)$(dbusconfigdir)" "$(DESTDIR)$(xorgconfddir)"; 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) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_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-noinstLTLIBRARIES \ + 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 + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dbusconfigDATA install-xorgconfdDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +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-dbusconfigDATA uninstall-xorgconfdDATA + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES 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-dbusconfigDATA install-dvi install-dvi-am install-exec \ + 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 install-strip install-xorgconfdDATA \ + 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-dbusconfigDATA \ + uninstall-xorgconfdDATA + + +# 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/config/config-backends.h b/config/config-backends.h new file mode 100644 index 0000000..0a2a22a --- /dev/null +++ b/config/config-backends.h @@ -0,0 +1,70 @@ +/* + * Copyright © 2006-2007 Daniel Stone + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Daniel Stone <daniel@fooishbar.org> + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif +#include "input.h" + +void remove_devices(const char *backend, const char *config_info); +BOOL device_is_duplicate(const char *config_info); +void add_option(InputOption **options, const char *key, const char *value); + +#ifdef CONFIG_UDEV +int config_udev_init(void); +void config_udev_fini(void); +#else + +# ifdef CONFIG_NEED_DBUS +#include <dbus/dbus.h> + +typedef void (*config_dbus_core_connect_hook)(DBusConnection *connection, + void *data); +typedef void (*config_dbus_core_disconnect_hook)(void *data); + +struct config_dbus_core_hook { + config_dbus_core_connect_hook connect; + config_dbus_core_disconnect_hook disconnect; + void *data; + + struct config_dbus_core_hook *next; +}; + +int config_dbus_core_init(void); +void config_dbus_core_fini(void); +int config_dbus_core_add_hook(struct config_dbus_core_hook *hook); +void config_dbus_core_remove_hook(struct config_dbus_core_hook *hook); +# endif + +# ifdef CONFIG_DBUS_API +int config_dbus_init(void); +void config_dbus_fini(void); +# endif + +# ifdef CONFIG_HAL +int config_hal_init(void); +void config_hal_fini(void); +# endif +#endif diff --git a/config/config.c b/config/config.c new file mode 100644 index 0000000..d86f7c6 --- /dev/null +++ b/config/config.c @@ -0,0 +1,139 @@ +/* + * Copyright © 2006-2007 Daniel Stone + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Daniel Stone <daniel@fooishbar.org> + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "os.h" +#include "inputstr.h" +#include "hotplug.h" +#include "config-backends.h" + +void +config_init(void) +{ +#ifdef CONFIG_UDEV + if (!config_udev_init()) + ErrorF("[config] failed to initialise udev\n"); +#elif defined(CONFIG_NEED_DBUS) + if (config_dbus_core_init()) { +# ifdef CONFIG_DBUS_API + if (!config_dbus_init()) + ErrorF("[config] failed to initialise D-Bus API\n"); +# endif +# ifdef CONFIG_HAL + if (!config_hal_init()) + ErrorF("[config] failed to initialise HAL\n"); +# endif + } + else { + ErrorF("[config] failed to initialise D-Bus core\n"); + } +#endif +} + +void +config_fini(void) +{ +#if defined(CONFIG_UDEV) + config_udev_fini(); +#elif defined(CONFIG_NEED_DBUS) +# ifdef CONFIG_HAL + config_hal_fini(); +# endif +# ifdef CONFIG_DBUS_API + config_dbus_fini(); +# endif + config_dbus_core_fini(); +#endif +} + +static void +remove_device(const char *backend, DeviceIntPtr dev) +{ + /* this only gets called for devices that have already been added */ + LogMessage(X_INFO, "config/%s: removing device %s\n", backend, dev->name); + + /* Call PIE here so we don't try to dereference a device that's + * already been removed. */ + OsBlockSignals(); + ProcessInputEvents(); + DeleteInputDeviceRequest(dev); + OsReleaseSignals(); +} + +void +remove_devices(const char *backend, const char *config_info) +{ + DeviceIntPtr dev, next; + + for (dev = inputInfo.devices; dev; dev = next) { + next = dev->next; + if (dev->config_info && strcmp(dev->config_info, config_info) == 0) + remove_device(backend, dev); + } + for (dev = inputInfo.off_devices; dev; dev = next) { + next = dev->next; + if (dev->config_info && strcmp(dev->config_info, config_info) == 0) + remove_device(backend, dev); + } +} + +BOOL +device_is_duplicate(const char *config_info) +{ + DeviceIntPtr dev; + + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->config_info && (strcmp(dev->config_info, config_info) == 0)) + return TRUE; + } + + for (dev = inputInfo.off_devices; dev; dev = dev->next) + { + if (dev->config_info && (strcmp(dev->config_info, config_info) == 0)) + return TRUE; + } + + return FALSE; +} + +void +add_option(InputOption **options, const char *key, const char *value) +{ + if (!value || *value == '\0') + return; + + for (; *options; options = &(*options)->next) + ; + *options = calloc(sizeof(**options), 1); + if (!*options) /* Yeesh. */ + return; + (*options)->key = strdup(key); + (*options)->value = strdup(value); + (*options)->next = NULL; +} diff --git a/config/dbus-core.c b/config/dbus-core.c new file mode 100644 index 0000000..4c5e10f --- /dev/null +++ b/config/dbus-core.c @@ -0,0 +1,247 @@ +/* + * Copyright © 2006-2007 Daniel Stone + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Daniel Stone <daniel@fooishbar.org> + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <dbus/dbus.h> +#include <sys/select.h> + +#include "config-backends.h" +#include "dix.h" +#include "os.h" + +/* How often to attempt reconnecting when we get booted off the bus. */ +#define RECONNECT_DELAY (10 * 1000) /* in ms */ + +struct dbus_core_info { + int fd; + DBusConnection *connection; + OsTimerPtr timer; + struct config_dbus_core_hook *hooks; +}; +static struct dbus_core_info bus_info; + +static CARD32 reconnect_timer(OsTimerPtr timer, CARD32 time, pointer arg); + +static void +wakeup_handler(pointer data, int err, pointer read_mask) +{ + struct dbus_core_info *info = data; + + if (info->connection && FD_ISSET(info->fd, (fd_set *) read_mask)) { + do { + dbus_connection_read_write_dispatch(info->connection, 0); + } while (info->connection && + dbus_connection_get_is_connected(info->connection) && + dbus_connection_get_dispatch_status(info->connection) == DBUS_DISPATCH_DATA_REMAINS); + } +} + +static void +block_handler(pointer data, struct timeval **tv, pointer read_mask) +{ +} + +/** + * Disconnect (if we haven't already been forcefully disconnected), clean up + * after ourselves, and call all registered disconnect hooks. + */ +static void +teardown(void) +{ + struct config_dbus_core_hook *hook; + + if (bus_info.timer) { + TimerFree(bus_info.timer); + bus_info.timer = NULL; + } + + /* We should really have pre-disconnect hooks and run them here, for + * completeness. But then it gets awkward, given that you can't + * guarantee that they'll be called ... */ + if (bus_info.connection) + dbus_connection_unref(bus_info.connection); + + RemoveBlockAndWakeupHandlers(block_handler, wakeup_handler, &bus_info); + if (bus_info.fd != -1) + RemoveGeneralSocket(bus_info.fd); + bus_info.fd = -1; + bus_info.connection = NULL; + + for (hook = bus_info.hooks; hook; hook = hook->next) { + if (hook->disconnect) + hook->disconnect(hook->data); + } +} + +/** + * This is a filter, which only handles the disconnected signal, which + * doesn't go to the normal message handling function. This takes + * precedence over the message handling function, so have have to be + * careful to ignore anything we don't want to deal with here. + */ +static DBusHandlerResult +message_filter(DBusConnection *connection, DBusMessage *message, void *data) +{ + /* If we get disconnected, then take everything down, and attempt to + * reconnect immediately (assuming it's just a restart). The + * connection isn't valid at this point, so throw it out immediately. */ + if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, + "Disconnected")) { + DebugF("[config/dbus-core] disconnected from bus\n"); + bus_info.connection = NULL; + teardown(); + + if (bus_info.timer) + TimerFree(bus_info.timer); + bus_info.timer = TimerSet(NULL, 0, 1, reconnect_timer, NULL); + + return DBUS_HANDLER_RESULT_HANDLED; + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +/** + * Attempt to connect to the system bus, and set a filter to deal with + * disconnection (see message_filter above). + * + * @return 1 on success, 0 on failure. + */ +static int +connect_to_bus(void) +{ + DBusError error; + struct config_dbus_core_hook *hook; + + dbus_error_init(&error); + bus_info.connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); + if (!bus_info.connection || dbus_error_is_set(&error)) { + DebugF("[config/dbus-core] error connecting to system bus: %s (%s)\n", + error.name, error.message); + goto err_begin; + } + + /* Thankyou. Really, thankyou. */ + dbus_connection_set_exit_on_disconnect(bus_info.connection, FALSE); + + if (!dbus_connection_get_unix_fd(bus_info.connection, &bus_info.fd)) { + ErrorF("[config/dbus-core] couldn't get fd for system bus\n"); + goto err_unref; + } + + if (!dbus_connection_add_filter(bus_info.connection, message_filter, + &bus_info, NULL)) { + ErrorF("[config/dbus-core] couldn't add filter: %s (%s)\n", error.name, + error.message); + goto err_fd; + } + + dbus_error_free(&error); + AddGeneralSocket(bus_info.fd); + + RegisterBlockAndWakeupHandlers(block_handler, wakeup_handler, &bus_info); + + for (hook = bus_info.hooks; hook; hook = hook->next) { + if (hook->connect) + hook->connect(bus_info.connection, hook->data); + } + + return 1; + +err_fd: + bus_info.fd = -1; +err_unref: + dbus_connection_unref(bus_info.connection); + bus_info.connection = NULL; +err_begin: + dbus_error_free(&error); + + return 0; +} + +static CARD32 +reconnect_timer(OsTimerPtr timer, CARD32 time, pointer arg) +{ + if (connect_to_bus()) { + TimerFree(bus_info.timer); + bus_info.timer = NULL; + return 0; + } + else { + return RECONNECT_DELAY; + } +} + +int +config_dbus_core_add_hook(struct config_dbus_core_hook *hook) +{ + struct config_dbus_core_hook **prev; + + for (prev = &bus_info.hooks; *prev; prev = &(*prev)->next) + ; + + hook->next = NULL; + *prev = hook; + + /* If we're already connected, call the connect hook. */ + if (bus_info.connection) + hook->connect(bus_info.connection, hook->data); + + return 1; +} + +void +config_dbus_core_remove_hook(struct config_dbus_core_hook *hook) +{ + struct config_dbus_core_hook **prev; + + for (prev = &bus_info.hooks; *prev; prev = &(*prev)->next) { + if (*prev == hook) { + *prev = hook->next; + break; + } + } +} + +int +config_dbus_core_init(void) +{ + memset(&bus_info, 0, sizeof(bus_info)); + bus_info.fd = -1; + bus_info.hooks = NULL; + bus_info.connection = NULL; + bus_info.timer = TimerSet(NULL, 0, 1, reconnect_timer, NULL); + + return 1; +} + +void +config_dbus_core_fini(void) +{ + teardown(); +} diff --git a/config/dbus.c b/config/dbus.c new file mode 100644 index 0000000..34e3caa --- /dev/null +++ b/config/dbus.c @@ -0,0 +1,439 @@ +/* + * Copyright © 2006-2007 Daniel Stone + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Daniel Stone <daniel@fooishbar.org> + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <dbus/dbus.h> +#include <string.h> + +#include <X11/X.h> + +#include "config-backends.h" +#include "opaque.h" /* for 'display': there should be a better way. */ +#include "input.h" +#include "inputstr.h" + +#define API_VERSION 2 + +#define MATCH_RULE "type='method_call',interface='org.x.config.input'" + +#define MALFORMED_MSG "[config/dbus] malformed message, dropping" +#define MALFORMED_MESSAGE() { DebugF(MALFORMED_MSG "\n"); \ + ret = BadValue; \ + goto unwind; } +#define MALFORMED_MESSAGE_ERROR() { DebugF(MALFORMED_MSG ": %s, %s", \ + error->name, error->message); \ + ret = BadValue; \ + goto unwind; } + +struct connection_info { + char busobject[32]; + char busname[64]; + DBusConnection *connection; +}; + +static void +reset_info(struct connection_info *info) +{ + info->connection = NULL; + info->busname[0] = '\0'; + info->busobject[0] = '\0'; +} + +static int +add_device(DBusMessage *message, DBusMessage *reply, DBusError *error) +{ + DBusMessageIter iter, reply_iter, subiter; + InputOption *tmpo = NULL, *options = NULL; + char *tmp = NULL; + int ret, err; + DeviceIntPtr dev = NULL; + + dbus_message_iter_init_append(reply, &reply_iter); + + if (!dbus_message_iter_init(message, &iter)) { + ErrorF("[config/dbus] couldn't initialise iterator\n"); + MALFORMED_MESSAGE(); + } + + options = calloc(sizeof(*options), 1); + if (!options) { + ErrorF("[config/dbus] couldn't allocate option\n"); + return BadAlloc; + } + + options->key = strdup("_source"); + options->value = strdup("client/dbus"); + if (!options->key || !options->value) { + ErrorF("[config/dbus] couldn't allocate first key/value pair\n"); + ret = BadAlloc; + goto unwind; + } + + /* signature should be [ss][ss]... */ + while (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_ARRAY) { + tmpo = calloc(sizeof(*tmpo), 1); + if (!tmpo) { + ErrorF("[config/dbus] couldn't allocate option\n"); + ret = BadAlloc; + goto unwind; + } + tmpo->next = options; + options = tmpo; + + dbus_message_iter_recurse(&iter, &subiter); + + if (dbus_message_iter_get_arg_type(&subiter) != DBUS_TYPE_STRING) + MALFORMED_MESSAGE(); + + dbus_message_iter_get_basic(&subiter, &tmp); + if (!tmp) + MALFORMED_MESSAGE(); + /* The _ prefix refers to internal settings, and may not be given by + * the client. */ + if (tmp[0] == '_') { + ErrorF("[config/dbus] attempted subterfuge: option name %s given\n", + tmp); + MALFORMED_MESSAGE(); + } + options->key = strdup(tmp); + if (!options->key) { + ErrorF("[config/dbus] couldn't duplicate key!\n"); + ret = BadAlloc; + goto unwind; + } + + if (!dbus_message_iter_has_next(&subiter)) + MALFORMED_MESSAGE(); + dbus_message_iter_next(&subiter); + if (dbus_message_iter_get_arg_type(&subiter) != DBUS_TYPE_STRING) + MALFORMED_MESSAGE(); + + dbus_message_iter_get_basic(&subiter, &tmp); + if (!tmp) + MALFORMED_MESSAGE(); + options->value = strdup(tmp); + if (!options->value) { + ErrorF("[config/dbus] couldn't duplicate option!\n"); + ret = BadAlloc; + goto unwind; + } + + dbus_message_iter_next(&iter); + } + + ret = NewInputDeviceRequest(options, NULL, &dev); + if (ret != Success) { + DebugF("[config/dbus] NewInputDeviceRequest failed\n"); + goto unwind; + } + + if (!dev) { + DebugF("[config/dbus] NewInputDeviceRequest provided no device\n"); + ret = BadImplementation; + goto unwind; + } + + /* XXX: If we fail halfway through, we don't seem to have any way to + * empty the iterator, so you'll end up with some device IDs, + * plus an error. This seems to be a shortcoming in the D-Bus + * API. */ + for (; dev; dev = dev->next) { + if (!dbus_message_iter_append_basic(&reply_iter, DBUS_TYPE_INT32, + &dev->id)) { + ErrorF("[config/dbus] couldn't append to iterator\n"); + ret = BadAlloc; + goto unwind; + } + } + +unwind: + if (ret != Success) { + if (dev) + RemoveDevice(dev, TRUE); + + err = -ret; + dbus_message_iter_append_basic(&reply_iter, DBUS_TYPE_INT32, &err); + } + + while (options) { + tmpo = options; + options = options->next; + free(tmpo->key); + free(tmpo->value); + free(tmpo); + } + + return ret; +} + +static int +remove_device(DBusMessage *message, DBusMessage *reply, DBusError *error) +{ + int deviceid, ret, err; + DeviceIntPtr dev; + DBusMessageIter iter, reply_iter; + + dbus_message_iter_init_append(reply, &reply_iter); + + if (!dbus_message_iter_init(message, &iter)) { + ErrorF("[config/dbus] failed to init iterator\n"); + MALFORMED_MESSAGE(); + } + + if (!dbus_message_get_args(message, error, DBUS_TYPE_UINT32, + &deviceid, DBUS_TYPE_INVALID)) { + MALFORMED_MESSAGE_ERROR(); + } + + dixLookupDevice(&dev, deviceid, serverClient, DixDestroyAccess); + if (!dev) { + DebugF("[config/dbus] bogus device id %d given\n", deviceid); + ret = BadMatch; + goto unwind; + } + + DebugF("[config/dbus] removing device %s (id %d)\n", dev->name, deviceid); + + /* Call PIE here so we don't try to dereference a device that's + * already been removed. */ + OsBlockSignals(); + ProcessInputEvents(); + DeleteInputDeviceRequest(dev); + OsReleaseSignals(); + + ret = Success; + +unwind: + err = (ret == Success) ? ret : -ret; + dbus_message_iter_append_basic(&reply_iter, DBUS_TYPE_INT32, &err); + + return ret; +} + +static int +list_devices(DBusMessage *message, DBusMessage *reply, DBusError *error) +{ + DeviceIntPtr dev; + DBusMessageIter iter, subiter; + + dbus_message_iter_init_append(reply, &iter); + + for (dev = inputInfo.devices; dev; dev = dev->next) { + if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_STRUCT, NULL, + &subiter)) { + ErrorF("[config/dbus] couldn't init container\n"); + return BadAlloc; + } + if (!dbus_message_iter_append_basic(&subiter, DBUS_TYPE_UINT32, + &dev->id)) { + ErrorF("[config/dbus] couldn't append to iterator\n"); + return BadAlloc; + } + if (!dbus_message_iter_append_basic(&subiter, DBUS_TYPE_STRING, + &dev->name)) { + ErrorF("[config/dbus] couldn't append to iterator\n"); + return BadAlloc; + } + if (!dbus_message_iter_close_container(&iter, &subiter)) { + ErrorF("[config/dbus] couldn't close container\n"); + return BadAlloc; + } + } + + return Success; +} + +static int +get_version(DBusMessage *message, DBusMessage *reply, DBusError *error) +{ + DBusMessageIter iter; + unsigned int version = API_VERSION; + + dbus_message_iter_init_append(reply, &iter); + if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT32, &version)) { + ErrorF("[config/dbus] couldn't append version\n"); + return BadAlloc; + } + + return Success; +} + +static DBusHandlerResult +message_handler(DBusConnection *connection, DBusMessage *message, void *data) +{ + DBusError error; + DBusMessage *reply; + struct connection_info *info = data; + + /* ret is the overall D-Bus handler result, whereas err is the internal + * X error from our individual functions. */ + int ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + int err; + + DebugF("[config/dbus] received a message for %s\n", + dbus_message_get_interface(message)); + + dbus_error_init(&error); + + reply = dbus_message_new_method_return(message); + if (!reply) { + ErrorF("[config/dbus] failed to create reply\n"); + ret = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto err_start; + } + + if (strcmp(dbus_message_get_member(message), "add") == 0) + err = add_device(message, reply, &error); + else if (strcmp(dbus_message_get_member(message), "remove") == 0) + err = remove_device(message, reply, &error); + else if (strcmp(dbus_message_get_member(message), "listDevices") == 0) + err = list_devices(message, reply, &error); + else if (strcmp(dbus_message_get_member(message), "version") == 0) + err = get_version(message, reply, &error); + else + goto err_reply; + + /* Failure to allocate is a special case. */ + if (err == BadAlloc) { + ret = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto err_reply; + } + + /* While failure here is always an OOM, we don't return that, + * since that would result in devices being double-added/removed. */ + if (dbus_connection_send(info->connection, reply, NULL)) + dbus_connection_flush(info->connection); + else + ErrorF("[config/dbus] failed to send reply\n"); + + ret = DBUS_HANDLER_RESULT_HANDLED; + +err_reply: + dbus_message_unref(reply); +err_start: + dbus_error_free(&error); + + return ret; +} + +static void +connect_hook(DBusConnection *connection, void *data) +{ + DBusError error; + DBusObjectPathVTable vtable = { .message_function = message_handler, }; + struct connection_info *info = data; + + info->connection = connection; + + dbus_error_init(&error); + + dbus_bus_request_name(info->connection, info->busname, 0, &error); + if (dbus_error_is_set(&error)) { + ErrorF("[config/dbus] couldn't take over org.x.config: %s (%s)\n", + error.name, error.message); + goto err_start; + } + + /* blocks until we get a reply. */ + dbus_bus_add_match(info->connection, MATCH_RULE, &error); + if (dbus_error_is_set(&error)) { + ErrorF("[config/dbus] couldn't add match: %s (%s)\n", error.name, + error.message); + goto err_name; + } + + if (!dbus_connection_register_object_path(info->connection, + info->busobject, &vtable, + info)) { + ErrorF("[config/dbus] couldn't register object path\n"); + goto err_match; + } + + DebugF("[dbus] registered %s, %s\n", info->busname, info->busobject); + + dbus_error_free(&error); + + return; + +err_match: + dbus_bus_remove_match(info->connection, MATCH_RULE, &error); +err_name: + dbus_bus_release_name(info->connection, info->busname, &error); +err_start: + dbus_error_free(&error); + + reset_info(info); +} + +static void +disconnect_hook(void *data) +{ +} + +#if 0 +void +pre_disconnect_hook(void) +{ + DBusError error; + + dbus_error_init(&error); + dbus_connection_unregister_object_path(connection_data->connection, + connection_data->busobject); + dbus_bus_remove_match(connection_data->connection, MATCH_RULE, + &error); + dbus_bus_release_name(connection_data->connection, + connection_data->busname, &error); + dbus_error_free(&error); +} +#endif + +static struct connection_info connection_data; +static struct config_dbus_core_hook core_hook = { + .connect = connect_hook, + .disconnect = disconnect_hook, + .data = &connection_data, +}; + +int +config_dbus_init(void) +{ + snprintf(connection_data.busname, sizeof(connection_data.busname), + "org.x.config.display%d", atoi(display)); + snprintf(connection_data.busobject, sizeof(connection_data.busobject), + "/org/x/config/%d", atoi(display)); + + return config_dbus_core_add_hook(&core_hook); +} + +void +config_dbus_fini(void) +{ + config_dbus_core_remove_hook(&core_hook); + connection_data.busname[0] = '\0'; + connection_data.busobject[0] = '\0'; +} diff --git a/config/fdi2iclass.py b/config/fdi2iclass.py new file mode 100755 index 0000000..8974440 --- /dev/null +++ b/config/fdi2iclass.py @@ -0,0 +1,202 @@ +#!/usr/bin/python +# +# Convert xorg keys from hal FDIs files to xorg.conf InputClass sections. +# Modified from Martin Pitt's original fdi2mpi.py script: +# http://cgit.freedesktop.org/media-player-info/tree/tools/fdi2mpi.py +# +# (C) 2010 Dan Nicholson +# (C) 2009 Canonical Ltd. +# Author: Dan Nicholson <dbn.lists@gmail.com> +# Author: Martin Pitt <martin.pitt@ubuntu.com> +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# fur- nished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FIT- NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON- +# NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +import sys, xml.dom.minidom + +# dict converting <match> tags to Match* entries +match_table = { + 'info.product': 'MatchProduct', + 'input.product': 'MatchProduct', + 'info.vendor': 'MatchVendor', + 'input.vendor': 'MatchVendor', + 'info.device': 'MatchDevicePath', + 'linux.device_file': 'MatchDevicePath', + '/org/freedesktop/Hal/devices/computer:system.kernel.name': 'MatchOS', + '@info.parent:pnp.id': 'MatchPnPID', +} + +# dict converting info.capabilities list to Match* entries +cap_match_table = { + 'input.keys': 'MatchIsKeyboard', + 'input.keyboard': 'MatchIsKeyboard', + 'input.keypad': 'MatchIsKeyboard', + 'input.mouse': 'MatchIsPointer', + 'input.joystick': 'MatchIsJoystick', + 'input.tablet': 'MatchIsTablet', + 'input.touchpad': 'MatchIsTouchpad', + 'input.touchscreen': 'MatchIsTouchscreen', +} + +def device_glob(path): + '''Convert a contains device path to a glob entry''' + if path[0] != '/': + path = '*' + path + return path + '*' + +def parse_match(node): + '''Parse a <match> tag to a tuple with InputClass values''' + match = None + value = None + booltype = False + + # see what type of key we have + if node.attributes.has_key('key'): + key = node.attributes['key'].nodeValue + if key in match_table: + match = match_table[key] + elif key == 'info.capabilities': + booltype = True + + # bail out now if it's unrecognized + if not match and not booltype: + return (match, value) + + if node.attributes.has_key('string'): + value = node.attributes['string'].nodeValue + elif node.attributes.has_key('contains'): + value = node.attributes['contains'].nodeValue + if match == 'MatchDevicePath': + value = device_glob(value) + elif booltype and value in cap_match_table: + match = cap_match_table[value] + value = 'yes' + elif node.attributes.has_key('string_outof'): + value = node.attributes['string_outof'].nodeValue.replace(';','|') + elif node.attributes.has_key('contains_outof'): + all_values = node.attributes['contains_outof'].nodeValue.split(';') + for v in all_values: + if match == 'MatchDevicePath': + v = device_glob(v) + elif match == 'MatchPnPID' and len(v) < 7: + v += '*' + if value: + value += '|' + v + else: + value = v + + return (match, value) + +def parse_options(node): + '''Parse the x11_* options and return InputClass entries''' + driver = '' + ignore = False + options = [] + for n in node.childNodes: + if n.nodeType != xml.dom.minidom.Node.ELEMENT_NODE: + continue + + tag = n.tagName + key = n.attributes['key'].nodeValue + value = '' + + if n.hasChildNodes(): + content_node = n.childNodes[0] + assert content_node.nodeType == xml.dom.Node.TEXT_NODE + value = content_node.nodeValue + + if tag == 'match': + continue + assert tag in ('addset', 'merge', 'append', 'remove') + + if tag == 'remove' and key == 'input.x11_driver': + ignore = True + elif key == 'input.x11_driver': + driver = value + elif key.startswith('input.x11_options.'): + option = key.split('.', 2)[2] + options.append((option, value)) + + return (driver, ignore, options) + +def is_match_node(node): + '''Check if a node is a <match> element''' + return node.nodeType == xml.dom.minidom.Node.ELEMENT_NODE and \ + node.tagName == 'match' + +def parse_all_matches(node): + '''Parse a x11 match tag and any parents that don't supply their + own options''' + matches = [] + + while True: + (key, value) = parse_match(node) + if key and value: + matches.append((key, value)) + + # walk up to a parent match node + node = node.parentNode + if node == None or not is_match_node(node): + break + + # leave if there other options at this level + children = set([n.tagName for n in node.childNodes + if n.nodeType == xml.dom.minidom.Node.ELEMENT_NODE]) + if children & set(['addset', 'merge', 'append']): + break + + return matches + +# stupid counter to give "unique" rule names +num_sections = 1 +def print_section(matches, driver, ignore, options): + '''Print a valid InputClass section to stdout''' + global num_sections + print 'Section "InputClass"' + print '\tIdentifier "Converted Class %d"' % num_sections + num_sections += 1 + for m, v in matches: + print '\t%s "%s"' % (m, v) + if driver: + print '\tDriver "%s"' % driver + if ignore: + print '\tOption "Ignore" "yes"' + for o, v in options: + print '\tOption "%s" "%s"' % (o, v) + print 'EndSection' + +def parse_fdi(fdi): + '''Parse x11 matches from fdi''' + # find all <match> leaf nodes + num = 0 + for match_node in fdi.getElementsByTagName('match'): + children = set([n.tagName for n in match_node.childNodes + if n.nodeType == xml.dom.minidom.Node.ELEMENT_NODE]) + + # see if there are any options at this level + (driver, ignore, options) = parse_options(match_node) + if not driver and not ignore and not options: + continue + + matches = parse_all_matches(match_node) + if num > 0: + print + print_section(matches, driver, ignore, options) + num += 1 + +for f in sys.argv[1:]: + parse_fdi(xml.dom.minidom.parse(f)) diff --git a/config/hal.c b/config/hal.c new file mode 100644 index 0000000..297520a --- /dev/null +++ b/config/hal.c @@ -0,0 +1,654 @@ +/* + * Copyright © 2007 Daniel Stone + * Copyright © 2007 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Daniel Stone <daniel@fooishbar.org> + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <dbus/dbus.h> +#include <hal/libhal.h> +#include <string.h> +#include <sys/select.h> + +#include "input.h" +#include "inputstr.h" +#include "hotplug.h" +#include "config-backends.h" +#include "os.h" + + +#define LIBHAL_PROP_KEY "input.x11_options." +#define LIBHAL_XKB_PROP_KEY "input.xkb." + + +struct config_hal_info { + DBusConnection *system_bus; + LibHalContext *hal_ctx; +}; + +/* Used for special handling of xkb options. */ +struct xkb_options { + char* layout; + char* model; + char* rules; + char* variant; + char* options; +}; + +static void +device_removed(LibHalContext *ctx, const char *udi) +{ + char *value; + + if (asprintf (&value, "hal:%s", udi) == -1) + return; + + remove_devices("hal", value); + + free(value); +} + +static char * +get_prop_string(LibHalContext *hal_ctx, const char *udi, const char *name) +{ + char *prop, *ret; + + prop = libhal_device_get_property_string(hal_ctx, udi, name, NULL); + LogMessageVerb(X_INFO, 10, "config/hal: getting %s on %s returned %s\n", name, udi, prop ? prop : "(null)"); + if (prop) { + ret = strdup(prop); + libhal_free_string(prop); + } + else { + return NULL; + } + + return ret; +} + +static char * +get_prop_string_array(LibHalContext *hal_ctx, const char *udi, const char *prop) +{ + char **props, *ret, *str; + int i, len = 0; + + props = libhal_device_get_property_strlist(hal_ctx, udi, prop, NULL); + if (props) { + for (i = 0; props[i]; i++) + len += strlen(props[i]); + + ret = calloc(sizeof(char), len + i); /* i - 1 commas, 1 NULL */ + if (!ret) { + libhal_free_string_array(props); + return NULL; + } + + str = ret; + for (i = 0; props[i]; i++) { + strcpy(str, props[i]); + str += strlen(props[i]); + *str++ = ','; + } + *(str-1) = '\0'; + + libhal_free_string_array(props); + } + else { + return NULL; + } + + return ret; +} + +static void +device_added(LibHalContext *hal_ctx, const char *udi) +{ + char *path = NULL, *driver = NULL, *name = NULL, *config_info = NULL; + char *hal_tags, *parent; + InputOption *options = NULL, *tmpo = NULL; + InputAttributes attrs = {0}; + DeviceIntPtr dev = NULL; + DBusError error; + struct xkb_options xkb_opts = {0}; + int rc; + + LibHalPropertySet *set = NULL; + LibHalPropertySetIterator set_iter; + char *psi_key = NULL, *tmp_val; + + + dbus_error_init(&error); + + driver = get_prop_string(hal_ctx, udi, "input.x11_driver"); + if (!driver){ + /* verbose, don't tell the user unless they _want_ to see it */ + LogMessageVerb(X_INFO,7,"config/hal: no driver specified for device %s\n", udi); + goto unwind; + } + + path = get_prop_string(hal_ctx, udi, "input.device"); + if (!path) { + LogMessage(X_WARNING,"config/hal: no driver or path specified for %s\n", udi); + goto unwind; + } + attrs.device = strdup(path); + + name = get_prop_string(hal_ctx, udi, "info.product"); + if (!name) + name = strdup("(unnamed)"); + else + attrs.product = strdup(name); + + attrs.vendor = get_prop_string(hal_ctx, udi, "info.vendor"); + hal_tags = get_prop_string(hal_ctx, udi, "input.tags"); + attrs.tags = xstrtokenize(hal_tags, ","); + free(hal_tags); + + if (libhal_device_query_capability(hal_ctx, udi, "input.keys", NULL)) + attrs.flags |= ATTR_KEYBOARD; + if (libhal_device_query_capability(hal_ctx, udi, "input.mouse", NULL)) + attrs.flags |= ATTR_POINTER; + if (libhal_device_query_capability(hal_ctx, udi, "input.joystick", NULL)) + attrs.flags |= ATTR_JOYSTICK; + if (libhal_device_query_capability(hal_ctx, udi, "input.tablet", NULL)) + attrs.flags |= ATTR_TABLET; + if (libhal_device_query_capability(hal_ctx, udi, "input.touchpad", NULL)) + attrs.flags |= ATTR_TOUCHPAD; + if (libhal_device_query_capability(hal_ctx, udi, "input.touchscreen", NULL)) + attrs.flags |= ATTR_TOUCHSCREEN; + + parent = get_prop_string(hal_ctx, udi, "info.parent"); + if (parent) { + int usb_vendor, usb_product; + + attrs.pnp_id = get_prop_string(hal_ctx, parent, "pnp.id"); + + /* construct USB ID in lowercase - "0000:ffff" */ + usb_vendor = libhal_device_get_property_int(hal_ctx, parent, + "usb.vendor_id", NULL); + LogMessageVerb(X_INFO, 10, + "config/hal: getting usb.vendor_id on %s " + "returned %04x\n", parent, usb_vendor); + usb_product = libhal_device_get_property_int(hal_ctx, parent, + "usb.product_id", NULL); + LogMessageVerb(X_INFO, 10, + "config/hal: getting usb.product_id on %s " + "returned %04x\n", parent, usb_product); + if (usb_vendor && usb_product) + if (asprintf(&attrs.usb_id, "%04x:%04x", usb_vendor, usb_product) + == -1) + attrs.usb_id = NULL; + + free(parent); + } + + options = calloc(sizeof(*options), 1); + if (!options){ + LogMessage(X_ERROR, "config/hal: couldn't allocate space for input options!\n"); + goto unwind; + } + + options->key = strdup("_source"); + options->value = strdup("server/hal"); + if (!options->key || !options->value) { + LogMessage(X_ERROR, "config/hal: couldn't allocate first key/value pair\n"); + goto unwind; + } + + /* most drivers use device.. not path. evdev uses both however, but the + * path version isn't documented apparently. support both for now. */ + add_option(&options, "path", path); + add_option(&options, "device", path); + + add_option(&options, "driver", driver); + add_option(&options, "name", name); + + if (asprintf (&config_info, "hal:%s", udi) == -1) { + config_info = NULL; + LogMessage(X_ERROR, "config/hal: couldn't allocate name\n"); + goto unwind; + } + + /* Check for duplicate devices */ + if (device_is_duplicate(config_info)) + { + LogMessage(X_WARNING, "config/hal: device %s already added. Ignoring.\n", name); + goto unwind; + } + + /* ok, grab options from hal.. iterate through all properties + * and lets see if any of them are options that we can add */ + set = libhal_device_get_all_properties(hal_ctx, udi, &error); + + if (!set) { + LogMessage(X_ERROR, "config/hal: couldn't get property list for %s: %s (%s)\n", + udi, error.name, error.message); + goto unwind; + } + + libhal_psi_init(&set_iter,set); + while (libhal_psi_has_more(&set_iter)) { + /* we are looking for supported keys.. extract and add to options */ + psi_key = libhal_psi_get_key(&set_iter); + + if (psi_key){ + + /* normal options first (input.x11_options.<propname>) */ + if (!strncasecmp(psi_key, LIBHAL_PROP_KEY, sizeof(LIBHAL_PROP_KEY)-1)){ + char* tmp; + + /* only support strings for all values */ + tmp_val = get_prop_string(hal_ctx, udi, psi_key); + + if (tmp_val){ + + /* xkb needs special handling. HAL specs include + * input.xkb.xyz options, but the x11-input.fdi specifies + * input.x11_options.Xkbxyz options. By default, we use + * the former, unless the specific X11 ones are specified. + * Since we can't predict the order in which the keys + * arrive, we need to store them. + */ + if ((tmp = strcasestr(psi_key, "xkb")) && strlen(tmp) >= 4) + { + if (!strcasecmp(&tmp[3], "layout")) + { + free(xkb_opts.layout); + xkb_opts.layout = strdup(tmp_val); + } else if (!strcasecmp(&tmp[3], "model")) + { + free(xkb_opts.model); + xkb_opts.model = strdup(tmp_val); + } else if (!strcasecmp(&tmp[3], "rules")) + { + free(xkb_opts.rules); + xkb_opts.rules = strdup(tmp_val); + } else if (!strcasecmp(&tmp[3], "variant")) + { + free(xkb_opts.variant); + xkb_opts.variant = strdup(tmp_val); + } else if (!strcasecmp(&tmp[3], "options")) + { + free(xkb_opts.options); + xkb_opts.options = strdup(tmp_val); + } + } else + { + /* all others */ + add_option(&options, psi_key + sizeof(LIBHAL_PROP_KEY)-1, tmp_val); + free(tmp_val); + } + } else + { + /* server 1.4 had xkb_options as strlist. */ + if ((tmp = strcasestr(psi_key, "xkb")) && + (strlen(tmp) >= 4) && + (!strcasecmp(&tmp[3], "options")) && + (tmp_val = get_prop_string_array(hal_ctx, udi, psi_key))) + { + free(xkb_opts.options); + xkb_opts.options = strdup(tmp_val); + } + } + } else if (!strncasecmp(psi_key, LIBHAL_XKB_PROP_KEY, sizeof(LIBHAL_XKB_PROP_KEY)-1)){ + char* tmp; + + /* only support strings for all values */ + tmp_val = get_prop_string(hal_ctx, udi, psi_key); + + if (tmp_val && strlen(psi_key) >= sizeof(LIBHAL_XKB_PROP_KEY)) { + + tmp = &psi_key[sizeof(LIBHAL_XKB_PROP_KEY) - 1]; + + if (!strcasecmp(tmp, "layout")) + { + if (!xkb_opts.layout) + xkb_opts.layout = strdup(tmp_val); + } else if (!strcasecmp(tmp, "rules")) + { + if (!xkb_opts.rules) + xkb_opts.rules = strdup(tmp_val); + } else if (!strcasecmp(tmp, "variant")) + { + if (!xkb_opts.variant) + xkb_opts.variant = strdup(tmp_val); + } else if (!strcasecmp(tmp, "model")) + { + if (!xkb_opts.model) + xkb_opts.model = strdup(tmp_val); + } else if (!strcasecmp(tmp, "options")) + { + if (!xkb_opts.options) + xkb_opts.options = strdup(tmp_val); + } + free(tmp_val); + } else + { + /* server 1.4 had xkb options as strlist */ + tmp_val = get_prop_string_array(hal_ctx, udi, psi_key); + if (tmp_val && strlen(psi_key) >= sizeof(LIBHAL_XKB_PROP_KEY)) + { + tmp = &psi_key[sizeof(LIBHAL_XKB_PROP_KEY) - 1]; + if (!strcasecmp(tmp, ".options") && (!xkb_opts.options)) + xkb_opts.options = strdup(tmp_val); + } + } + } + } + + /* psi_key doesn't need to be freed */ + libhal_psi_next(&set_iter); + } + + + /* Now add xkb options */ + if (xkb_opts.layout) + add_option(&options, "xkb_layout", xkb_opts.layout); + if (xkb_opts.rules) + add_option(&options, "xkb_rules", xkb_opts.rules); + if (xkb_opts.variant) + add_option(&options, "xkb_variant", xkb_opts.variant); + if (xkb_opts.model) + add_option(&options, "xkb_model", xkb_opts.model); + if (xkb_opts.options) + add_option(&options, "xkb_options", xkb_opts.options); + add_option(&options, "config_info", config_info); + + /* this isn't an error, but how else do you output something that the user can see? */ + LogMessage(X_INFO, "config/hal: Adding input device %s\n", name); + if ((rc = NewInputDeviceRequest(options, &attrs, &dev)) != Success) { + LogMessage(X_ERROR, "config/hal: NewInputDeviceRequest failed (%d)\n", rc); + dev = NULL; + goto unwind; + } + +unwind: + if (set) + libhal_free_property_set(set); + free(path); + free(driver); + free(name); + free(config_info); + while ((tmpo = options)) { + options = tmpo->next; + free(tmpo->key); /* NULL if dev != NULL */ + free(tmpo->value); /* NULL if dev != NULL */ + free(tmpo); + } + + free(attrs.product); + free(attrs.vendor); + free(attrs.device); + free(attrs.pnp_id); + free(attrs.usb_id); + if (attrs.tags) { + char **tag = attrs.tags; + while (*tag) { + free(*tag); + tag++; + } + free(attrs.tags); + } + + free(xkb_opts.layout); + free(xkb_opts.rules); + free(xkb_opts.model); + free(xkb_opts.variant); + free(xkb_opts.options); + + dbus_error_free(&error); + + return; +} + +static void +disconnect_hook(void *data) +{ + DBusError error; + struct config_hal_info *info = data; + + if (info->hal_ctx) { + if (dbus_connection_get_is_connected(info->system_bus)) { + dbus_error_init(&error); + if (!libhal_ctx_shutdown(info->hal_ctx, &error)) + LogMessage(X_WARNING, "config/hal: disconnect_hook couldn't shut down context: %s (%s)\n", + error.name, error.message); + dbus_error_free(&error); + } + libhal_ctx_free(info->hal_ctx); + } + + info->hal_ctx = NULL; + info->system_bus = NULL; +} + +static BOOL +connect_and_register(DBusConnection *connection, struct config_hal_info *info) +{ + DBusError error; + char **devices; + int num_devices, i; + + if (info->hal_ctx) + return TRUE; /* already registered, pretend we did something */ + + info->system_bus = connection; + + dbus_error_init(&error); + + info->hal_ctx = libhal_ctx_new(); + if (!info->hal_ctx) { + LogMessage(X_ERROR, "config/hal: couldn't create HAL context\n"); + goto out_err; + } + + if (!libhal_ctx_set_dbus_connection(info->hal_ctx, info->system_bus)) { + LogMessage(X_ERROR, "config/hal: couldn't associate HAL context with bus\n"); + goto out_err; + } + if (!libhal_ctx_init(info->hal_ctx, &error)) { + LogMessage(X_ERROR, "config/hal: couldn't initialise context: %s (%s)\n", + error.name ? error.name : "unknown error", + error.message ? error.message : "null"); + goto out_err; + } + if (!libhal_device_property_watch_all(info->hal_ctx, &error)) { + LogMessage(X_ERROR, "config/hal: couldn't watch all properties: %s (%s)\n", + error.name ? error.name : "unknown error", + error.message ? error.message : "null"); + goto out_ctx; + } + libhal_ctx_set_device_added(info->hal_ctx, device_added); + libhal_ctx_set_device_removed(info->hal_ctx, device_removed); + + devices = libhal_find_device_by_capability(info->hal_ctx, "input", + &num_devices, &error); + /* FIXME: Get default devices if error is set. */ + if (dbus_error_is_set(&error)) { + LogMessage(X_ERROR, "config/hal: couldn't find input device: %s (%s)\n", + error.name ? error.name : "unknown error", + error.message ? error.message : "null"); + goto out_ctx; + } + for (i = 0; i < num_devices; i++) + device_added(info->hal_ctx, devices[i]); + libhal_free_string_array(devices); + + dbus_error_free(&error); + + return TRUE; + +out_ctx: + dbus_error_free(&error); + + if (!libhal_ctx_shutdown(info->hal_ctx, &error)) { + LogMessage(X_WARNING, "config/hal: couldn't shut down context: %s (%s)\n", + error.name ? error.name : "unknown error", + error.message ? error.message : "null"); + dbus_error_free(&error); + } + +out_err: + dbus_error_free(&error); + + if (info->hal_ctx) { + libhal_ctx_free(info->hal_ctx); + } + + info->hal_ctx = NULL; + info->system_bus = NULL; + + return FALSE; +} + + +/** + * Handle NewOwnerChanged signals to deal with HAL startup at X server runtime. + * + * NewOwnerChanged is send once when HAL shuts down, and once again when it + * comes back up. Message has three arguments, first is the name + * (org.freedesktop.Hal), the second one is the old owner, third one is new + * owner. + */ +static DBusHandlerResult +ownerchanged_handler(DBusConnection *connection, DBusMessage *message, void *data) +{ + int ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (dbus_message_is_signal(message, + "org.freedesktop.DBus", + "NameOwnerChanged")) { + DBusError error; + char *name, *old_owner, *new_owner; + + dbus_error_init(&error); + dbus_message_get_args(message, &error, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_STRING, &old_owner, + DBUS_TYPE_STRING, &new_owner, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&error)) { + ErrorF("[config/hal] failed to get NameOwnerChanged args: %s (%s)\n", + error.name, error.message); + } else if (name && strcmp(name, "org.freedesktop.Hal") == 0) { + + if (!old_owner || !strlen(old_owner)) { + DebugF("[config/hal] HAL startup detected.\n"); + if (connect_and_register(connection, (struct config_hal_info*)data)) + dbus_connection_unregister_object_path(connection, + "/org/freedesktop/DBus"); + else + ErrorF("[config/hal] Failed to connect to HAL bus.\n"); + } + + ret = DBUS_HANDLER_RESULT_HANDLED; + } + dbus_error_free(&error); + } + + return ret; +} + +/** + * Register a handler for the NameOwnerChanged signal. + */ +static BOOL +listen_for_startup(DBusConnection *connection, void *data) +{ + DBusObjectPathVTable vtable = { .message_function = ownerchanged_handler, }; + DBusError error; + const char MATCH_RULE[] = "sender='org.freedesktop.DBus'," + "interface='org.freedesktop.DBus'," + "type='signal'," + "path='/org/freedesktop/DBus'," + "member='NameOwnerChanged'"; + int rc = FALSE; + + dbus_error_init(&error); + dbus_bus_add_match(connection, MATCH_RULE, &error); + if (!dbus_error_is_set(&error)) { + if (dbus_connection_register_object_path(connection, + "/org/freedesktop/DBus", + &vtable, + data)) + rc = TRUE; + else + ErrorF("[config/hal] cannot register object path.\n"); + } else { + ErrorF("[config/hal] couldn't add match rule: %s (%s)\n", error.name, + error.message); + ErrorF("[config/hal] cannot detect a HAL startup.\n"); + } + + dbus_error_free(&error); + + return rc; +} + +static void +connect_hook(DBusConnection *connection, void *data) +{ + struct config_hal_info *info = data; + + if (listen_for_startup(connection, data) && + connect_and_register(connection, info)) + dbus_connection_unregister_object_path(connection, + "/org/freedesktop/DBus"); + + return; +} + +static struct config_hal_info hal_info; +static struct config_dbus_core_hook hook = { + .connect = connect_hook, + .disconnect = disconnect_hook, + .data = &hal_info, +}; + +int +config_hal_init(void) +{ + memset(&hal_info, 0, sizeof(hal_info)); + hal_info.system_bus = NULL; + hal_info.hal_ctx = NULL; + + if (!config_dbus_core_add_hook(&hook)) { + LogMessage(X_ERROR, "config/hal: failed to add D-Bus hook\n"); + return 0; + } + + /* verbose message */ + LogMessageVerb(X_INFO,7,"config/hal: initialized\n"); + + return 1; +} + +void +config_hal_fini(void) +{ + config_dbus_core_remove_hook(&hook); +} diff --git a/config/udev.c b/config/udev.c new file mode 100644 index 0000000..9ac34ee --- /dev/null +++ b/config/udev.c @@ -0,0 +1,325 @@ +/* + * Copyright © 2009 Julien Cristau + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Julien Cristau <jcristau@debian.org> + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <libudev.h> +#include <ctype.h> + +#include "input.h" +#include "inputstr.h" +#include "hotplug.h" +#include "config-backends.h" +#include "os.h" + +#define UDEV_XKB_PROP_KEY "xkb" + +#define LOG_PROPERTY(path, prop, val) \ + LogMessageVerb(X_INFO, 10, \ + "config/udev: getting property %s on %s " \ + "returned \"%s\"\n", \ + (prop), (path), (val) ? (val) : "(null)") +#define LOG_SYSATTR(path, attr, val) \ + LogMessageVerb(X_INFO, 10, \ + "config/udev: getting attribute %s on %s " \ + "returned \"%s\"\n", \ + (attr), (path), (val) ? (val) : "(null)") + +static struct udev_monitor *udev_monitor; + +static void +device_added(struct udev_device *udev_device) +{ + const char *path, *name = NULL; + char *config_info = NULL; + const char *syspath; + const char *tags_prop; + const char *key, *value, *tmp; + InputOption *options = NULL, *tmpo; + InputAttributes attrs = {}; + DeviceIntPtr dev = NULL; + struct udev_list_entry *set, *entry; + struct udev_device *parent; + int rc; + + path = udev_device_get_devnode(udev_device); + + syspath = udev_device_get_syspath(udev_device); + + if (!path || !syspath) + return; + + if (!udev_device_get_property_value(udev_device, "ID_INPUT")) { + LogMessageVerb(X_INFO, 10, + "config/udev: ignoring device %s without " + "property ID_INPUT set\n", + path); + return; + } + + options = calloc(sizeof(*options), 1); + if (!options) + return; + + options->key = strdup("_source"); + options->value = strdup("server/udev"); + if (!options->key || !options->value) + goto unwind; + + parent = udev_device_get_parent(udev_device); + if (parent) { + const char *ppath = udev_device_get_devnode(parent); + const char *product = udev_device_get_property_value(parent, "PRODUCT"); + const char *pnp_id = udev_device_get_sysattr_value(parent, "id"); + unsigned int usb_vendor, usb_model; + + name = udev_device_get_sysattr_value(parent, "name"); + LOG_SYSATTR(ppath, "name", name); + if (!name) { + name = udev_device_get_property_value(parent, "NAME"); + LOG_PROPERTY(ppath, "NAME", name); + } + + if (pnp_id) + attrs.pnp_id = strdup(pnp_id); + LOG_SYSATTR(ppath, "id", pnp_id); + + /* construct USB ID in lowercase hex - "0000:ffff" */ + if (product && sscanf(product, "%*x/%4x/%4x/%*x", &usb_vendor, &usb_model) == 2) { + if (asprintf(&attrs.usb_id, "%04x:%04x", usb_vendor, usb_model) + == -1) + attrs.usb_id = NULL; + else + LOG_PROPERTY(path, "PRODUCT", product); + } + } + if (!name) + name = "(unnamed)"; + else + attrs.product = strdup(name); + add_option(&options, "name", name); + + add_option(&options, "path", path); + add_option(&options, "device", path); + if (path) + attrs.device = strdup(path); + + tags_prop = udev_device_get_property_value(udev_device, "ID_INPUT.tags"); + LOG_PROPERTY(path, "ID_INPUT.tags", tags_prop); + attrs.tags = xstrtokenize(tags_prop, ","); + + if (asprintf(&config_info, "udev:%s", syspath) == -1) { + config_info = NULL; + goto unwind; + } + + if (device_is_duplicate(config_info)) { + LogMessage(X_WARNING, "config/udev: device %s already added. " + "Ignoring.\n", name); + goto unwind; + } + + set = udev_device_get_properties_list_entry(udev_device); + udev_list_entry_foreach(entry, set) { + key = udev_list_entry_get_name(entry); + if (!key) + continue; + value = udev_list_entry_get_value(entry); + if (!strncasecmp(key, UDEV_XKB_PROP_KEY, + sizeof(UDEV_XKB_PROP_KEY) - 1)) { + LOG_PROPERTY(path, key, value); + tmp = key + sizeof(UDEV_XKB_PROP_KEY) - 1; + if (!strcasecmp(tmp, "rules")) + add_option(&options, "xkb_rules", value); + else if (!strcasecmp(tmp, "layout")) + add_option(&options, "xkb_layout", value); + else if (!strcasecmp(tmp, "variant")) + add_option(&options, "xkb_variant", value); + else if (!strcasecmp(tmp, "model")) + add_option(&options, "xkb_model", value); + else if (!strcasecmp(tmp, "options")) + add_option(&options, "xkb_options", value); + } else if (!strcmp(key, "ID_VENDOR")) { + LOG_PROPERTY(path, key, value); + attrs.vendor = strdup(value); + } else if (!strcmp(key, "ID_INPUT_KEY")) { + LOG_PROPERTY(path, key, value); + attrs.flags |= ATTR_KEYBOARD; + } else if (!strcmp(key, "ID_INPUT_MOUSE")) { + LOG_PROPERTY(path, key, value); + attrs.flags |= ATTR_POINTER; + } else if (!strcmp(key, "ID_INPUT_JOYSTICK")) { + LOG_PROPERTY(path, key, value); + attrs.flags |= ATTR_JOYSTICK; + } else if (!strcmp(key, "ID_INPUT_TABLET")) { + LOG_PROPERTY(path, key, value); + attrs.flags |= ATTR_TABLET; + } else if (!strcmp(key, "ID_INPUT_TOUCHPAD")) { + LOG_PROPERTY(path, key, value); + attrs.flags |= ATTR_TOUCHPAD; + } else if (!strcmp(key, "ID_INPUT_TOUCHSCREEN")) { + LOG_PROPERTY(path, key, value); + attrs.flags |= ATTR_TOUCHSCREEN; + } + } + + add_option(&options, "config_info", config_info); + + LogMessage(X_INFO, "config/udev: Adding input device %s (%s)\n", + name, path); + rc = NewInputDeviceRequest(options, &attrs, &dev); + if (rc != Success) + goto unwind; + + unwind: + free(config_info); + while ((tmpo = options)) { + options = tmpo->next; + free(tmpo->key); /* NULL if dev != NULL */ + free(tmpo->value); /* NULL if dev != NULL */ + free(tmpo); + } + + free(attrs.usb_id); + free(attrs.pnp_id); + free(attrs.product); + free(attrs.device); + free(attrs.vendor); + if (attrs.tags) { + char **tag = attrs.tags; + while (*tag) { + free(*tag); + tag++; + } + free(attrs.tags); + } + + return; +} + +static void +device_removed(struct udev_device *device) +{ + char *value; + const char *syspath = udev_device_get_syspath(device); + + if (asprintf(&value, "udev:%s", syspath) == -1) + return; + + remove_devices("udev", value); + + free(value); +} + +static void +wakeup_handler(pointer data, int err, pointer read_mask) +{ + int udev_fd = udev_monitor_get_fd(udev_monitor); + struct udev_device *udev_device; + const char *action; + + if (err < 0) + return; + + if (FD_ISSET(udev_fd, (fd_set *)read_mask)) { + udev_device = udev_monitor_receive_device(udev_monitor); + if (!udev_device) + return; + action = udev_device_get_action(udev_device); + if (action) { + if (!strcmp(action, "add")) + device_added(udev_device); + else if (!strcmp(action, "remove")) + device_removed(udev_device); + else if (!strcmp(action, "change")) { + device_removed(udev_device); + device_added(udev_device); + } + } + udev_device_unref(udev_device); + } +} + +static void +block_handler(pointer data, struct timeval **tv, pointer read_mask) +{ +} + +int +config_udev_init(void) +{ + struct udev *udev; + struct udev_enumerate *enumerate; + struct udev_list_entry *devices, *device; + + udev = udev_new(); + if (!udev) + return 0; + udev_monitor = udev_monitor_new_from_netlink(udev, "udev"); + if (!udev_monitor) + return 0; + + if (udev_monitor_enable_receiving(udev_monitor)) { + ErrorF("config/udev: failed to bind the udev monitor\n"); + return 0; + } + + enumerate = udev_enumerate_new(udev); + if (!enumerate) + return 0; + udev_enumerate_scan_devices(enumerate); + devices = udev_enumerate_get_list_entry(enumerate); + udev_list_entry_foreach(device, devices) { + const char *syspath = udev_list_entry_get_name(device); + struct udev_device *udev_device = udev_device_new_from_syspath(udev, syspath); + device_added(udev_device); + udev_device_unref(udev_device); + } + udev_enumerate_unref(enumerate); + + RegisterBlockAndWakeupHandlers(block_handler, wakeup_handler, NULL); + AddGeneralSocket(udev_monitor_get_fd(udev_monitor)); + + return 1; +} + +void +config_udev_fini(void) +{ + struct udev *udev; + + if (!udev_monitor) + return; + + udev = udev_monitor_get_udev(udev_monitor); + + RemoveGeneralSocket(udev_monitor_get_fd(udev_monitor)); + RemoveBlockAndWakeupHandlers(block_handler, wakeup_handler, NULL); + udev_monitor_unref(udev_monitor); + udev_monitor = NULL; + udev_unref(udev); +} diff --git a/config/x11-input.fdi b/config/x11-input.fdi new file mode 100644 index 0000000..b263f36 --- /dev/null +++ b/config/x11-input.fdi @@ -0,0 +1,93 @@ +<?xml version="1.0" encoding="UTF-8"?> +<deviceinfo version="0.2"> + <device> + + <!-- The way this works: + + Match against some input device (see the HAL specification for more + information), and then merge in keys, which you can use to specify + the configuration similar to the way you would in xorg.conf. You will + need to restart HAL after making changes. If you are having issues, + starting X with the -logverbose 7 flag may yield useful information. + + Keys Supported: + + Key "input.x11_driver" (string) + This specifies the driver to use. You MUST specify this option, + or a driver will not be loaded and the rest will be ignored by + Xorg + + Key "input.x11_options.<option name>" (string) + This allows you to specify arbitrary options to pass to the driver. + Anything you would normally specify in xorg.conf goes here. So, for + option "Mode" in xorg.conf, you would specify the key name of + "input.x11_options.Mode". + + Do not specify "input.x11_options.Device" since "input.device" + will be used automatically. + + You MUST specify all options as strings, otherwise the server will + ignore them. + + Legacy Keys + "input.xkb.rules" + "input.xkb.model" + "input.xkb.layout" + "input.xkb.variant" + "input.xkb.options" + + These keys are deprecated. Use these instead: + "input.x11_options.XkbRules" + "input.x11_options.XkbModel" + "input.x11_options.XkbLayout" + "input.x11_options.XkbVariant" + "input.x11_options.XkbOptions" + + See the evdev documentation for more information. + + FIXME: Support tablets too. + TODO: I think its fixed, can't test + + --> + + <match key="info.capabilities" contains="input.mouse"> + <merge key="input.x11_driver" type="string">mouse</merge> + <match key="/org/freedesktop/Hal/devices/computer:system.kernel.name" + string="Linux"> + <merge key="input.x11_driver" type="string">evdev</merge> + </match> + <match key="/org/freedesktop/Hal/devices/computer:system.kernel.name" + string="SunOS"> + <match key="input.device" contains="usb"> + <merge key="input.x11_options.StreamsModule" type="string">usbms</merge> + <merge key="input.x11_options.Protocol" type="string">VUID</merge> + </match> + </match> + </match> + + <match key="info.capabilities" contains="input.keys"> + <merge key="input.x11_options.XkbRules" type="string">base</merge> + + <!-- If we're using Linux, we use evdev by default (falling back to + kbd otherwise). --> + <merge key="input.x11_driver" type="string">kbd</merge> + <merge key="input.x11_options.XkbModel" type="string">pc105</merge> + <match key="/org/freedesktop/Hal/devices/computer:system.kernel.name" + string="Linux"> + <merge key="input.x11_driver" type="string">evdev</merge> + <merge key="input.x11_options.XkbModel" type="string">evdev</merge> + </match> + <match key="/org/freedesktop/Hal/devices/computer:system.kernel.name" + string="SunOS"> + <match key="input.device" contains="usb"> + <merge key="input.x11_options.StreamsModule" type="string">usbkbm</merge> + <merge key="input.x11_options.Protocol" type="string">VUID</merge> + </match> + </match> + + <merge key="input.x11_options.XkbLayout" type="string">us</merge> + + <merge key="input.x11_options.XkbVariant" type="string" /> + </match> + </device> +</deviceinfo> diff --git a/config/xorg-server.conf b/config/xorg-server.conf new file mode 100644 index 0000000..47a9a78 --- /dev/null +++ b/config/xorg-server.conf @@ -0,0 +1,13 @@ +<!DOCTYPE busconfig PUBLIC + "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" + "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> +<busconfig> + <policy context="default"> + <allow own="org.x.config.display0"/> + <allow send_destination="org.x.config.display0"/> + <allow send_interface="org.x.config.display0"/> + <allow own="org.x.config.display1"/> + <allow send_destination="org.x.config.display1"/> + <allow send_interface="org.x.config.display1"/> + </policy> +</busconfig> |