[PATCH 2/2] Add libudev input-hotplug backend

Peter Hutterer peter.hutterer at who-t.net
Thu Oct 15 21:30:40 PDT 2009


On Wed, Oct 14, 2009 at 10:21:12PM +0200, Julien Cristau wrote:
> If libudev is found, we use that for hotplug and disable the hal and
> dbus backends.
> We look for event devices with an "x11_driver" property.  XKB
> configuration happens using xkb.{rules,model,layout,variant,options}
> properties.  Arbitrary driver options can be set with a "x11_options."
> prefix.
> 
> udev rules would look something like:
> SUBSYSTEM=="input", KERNEL=="event*", ENV{x11_driver}="evdev"
> SUBSYSTEM=="input", KERNEL=="event*", ENV{ID_CLASS}=="kbd", ENV{xkb.layout}="fr", ENV{xkb.options}="terminate:ctrl_alt_bksp,compose:lwin"

I think we should provide an example .rules file in xserver/config/
seems the x11-input.fdi file from there was used as a template, at least
initially, it'd be good to have a template again for those building from
source.
(I know I'd have preferred just copying that file when testing the lot :)

> ---
>  config/Makefile.am              |   16 +++-
>  config/config-backends.h        |   21 +++-
>  config/config.c                 |   77 ++++++++++++-
>  config/hal.c                    |   63 +----------
>  config/udev.c                   |  247 +++++++++++++++++++++++++++++++++++++++
>  configure.ac                    |   23 ++++-
>  hw/kdrive/src/kinput.c          |    8 ++
>  hw/xfree86/common/xf86Config.c  |   15 ++-
>  hw/xfree86/common/xf86Globals.c |    2 +-
>  hw/xfree86/common/xf86Xinput.c  |    4 +-
>  include/dix-config.h.in         |    3 +
>  11 files changed, 400 insertions(+), 79 deletions(-)
>  create mode 100644 config/udev.c
> 
> diff --git a/config/Makefile.am b/config/Makefile.am
> index 7fa2df8..8c57948 100644
> --- a/config/Makefile.am
> +++ b/config/Makefile.am
> @@ -3,10 +3,18 @@ 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@
> +
> +else
> +
>  if CONFIG_NEED_DBUS
>  AM_CFLAGS += @DBUS_CFLAGS@
>  libconfig_la_SOURCES += dbus-core.c
> -endif
> +libconfig_la_LIBADD = @DBUS_LIBS@
>  
>  if CONFIG_DBUS_API
>  dbusconfigdir = $(sysconfdir)/dbus-1/system.d
> @@ -16,7 +24,13 @@ 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
> diff --git a/config/config-backends.h b/config/config-backends.h
> index 907e86b..0a2a22a 100644
> --- a/config/config-backends.h
> +++ b/config/config-backends.h
> @@ -26,8 +26,18 @@
>  #ifdef HAVE_DIX_CONFIG_H
>  #include <dix-config.h>
>  #endif
> +#include "input.h"
>  
> -#ifdef CONFIG_NEED_DBUS
> +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,
> @@ -46,14 +56,15 @@ 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
> +# endif
>  
> -#ifdef CONFIG_DBUS_API
> +# ifdef CONFIG_DBUS_API
>  int config_dbus_init(void);
>  void config_dbus_fini(void);
> -#endif
> +# endif
>  
> -#ifdef CONFIG_HAL
> +# 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
> index b013293..7bf5e41 100644
> --- a/config/config.c
> +++ b/config/config.c
> @@ -28,13 +28,17 @@
>  #endif
>  
>  #include "os.h"
> +#include "inputstr.h"
>  #include "hotplug.h"
>  #include "config-backends.h"
>  
>  void
>  config_init(void)
>  {
> -#if defined(CONFIG_DBUS_API) || defined(CONFIG_HAL)
> +#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())
> @@ -54,7 +58,9 @@ config_init(void)
>  void
>  config_fini(void)
>  {
> -#if defined(CONFIG_DBUS_API) || defined(CONFIG_HAL)
> +#if defined(CONFIG_UDEV)
> +    config_udev_fini();
> +#elif defined(CONFIG_NEED_DBUS)
>  # ifdef CONFIG_HAL
>      config_hal_fini();
>  # endif
> @@ -64,3 +70,70 @@ config_fini(void)
>      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 = xcalloc(sizeof(**options), 1);
> +    if (!*options) /* Yeesh. */
> +        return;
> +    (*options)->key = xstrdup(key);
> +    (*options)->value = xstrdup(value);
> +    (*options)->next = NULL;
> +}
> diff --git a/config/hal.c b/config/hal.c
> index 28f55a0..22af10f 100644
> --- a/config/hal.c
> +++ b/config/hal.c
> @@ -58,25 +58,9 @@ struct xkb_options {
>      char* options;
>  };
>  
> -
> -static void
> -remove_device(DeviceIntPtr dev)
> -{
> -    /* this only gets called for devices that have already been added */
> -    LogMessage(X_INFO, "config/hal: removing device %s\n", dev->name);
> -
> -    /* Call PIE here so we don't try to dereference a device that's
> -     * already been removed. */
> -    OsBlockSignals();
> -    ProcessInputEvents();
> -    DeleteInputDeviceRequest(dev);
> -    OsReleaseSignals();
> -}
> -
>  static void
>  device_removed(LibHalContext *ctx, const char *udi)
>  {
> -    DeviceIntPtr dev, next;
>      char *value;
>  
>      value = xalloc(strlen(udi) + 5); /* "hal:" + NULL */
> @@ -84,36 +68,11 @@ device_removed(LibHalContext *ctx, const char *udi)
>          return;
>      sprintf(value, "hal:%s", udi);
>  
> -    for (dev = inputInfo.devices; dev; dev = next) {
> -	next = dev->next;
> -        if (dev->config_info && strcmp(dev->config_info, value) == 0)
> -            remove_device(dev);
> -    }
> -    for (dev = inputInfo.off_devices; dev; dev = next) {
> -	next = dev->next;
> -        if (dev->config_info && strcmp(dev->config_info, value) == 0)
> -            remove_device(dev);
> -    }
> +    remove_devices("hal", value);
>  
>      xfree(value);
>  }
>  
> -static void
> -add_option(InputOption **options, const char *key, const char *value)
> -{
> -    if (!value || *value == '\0')
> -        return;
> -
> -    for (; *options; options = &(*options)->next)
> -        ;
> -    *options = xcalloc(sizeof(**options), 1);
> -    if (!*options) /* Yeesh. */
> -        return;
> -    (*options)->key = xstrdup(key);
> -    (*options)->value = xstrdup(value);
> -    (*options)->next = NULL;
> -}
> -
>  static char *
>  get_prop_string(LibHalContext *hal_ctx, const char *udi, const char *name)
>  {
> @@ -166,26 +125,6 @@ get_prop_string_array(LibHalContext *hal_ctx, const char *udi, const char *prop)
>      return ret;
>  }
>  
> -static BOOL
> -device_is_duplicate(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;
> -}
> -
>  static void
>  device_added(LibHalContext *hal_ctx, const char *udi)
>  {
> diff --git a/config/udev.c b/config/udev.c
> new file mode 100644
> index 0000000..62b9052
> --- /dev/null
> +++ b/config/udev.c
> @@ -0,0 +1,247 @@
> +/*
> + * 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 at debian.org>
> + */
> +
> +#ifdef HAVE_DIX_CONFIG_H
> +#include <dix-config.h>
> +#endif
> +
> +#include <libudev.h>
> +
> +#include "input.h"
> +#include "inputstr.h"
> +#include "hotplug.h"
> +#include "config-backends.h"
> +#include "os.h"
> +
> +#define UDEV_XKB_PROP_KEY "xkb."
> +#define UDEV_PROP_KEY "x11_options."
> +
> +static struct udev_monitor *udev_monitor;
> +
> +static void
> +device_added(struct udev_device *udev_device)
> +{
> +    const char *path = NULL, *driver = NULL, *name = NULL;
> +    char *config_info = NULL;
> +    const char *syspath;
> +    const char *key, *value, *tmp;
> +    InputOption *options = NULL, *tmpo;
> +    DeviceIntPtr dev = NULL;
> +    struct udev_list_entry *set, *entry;
> +    struct udev_device *parent;
> +    int rc;
> +
> +    driver = udev_device_get_property_value(udev_device, "x11_driver");
> +
> +    path = udev_device_get_devnode(udev_device);
> +
> +    syspath = udev_device_get_syspath(udev_device);
> +
> +    parent = udev_device_get_parent(udev_device);
> +    if (parent)
> +        name = udev_device_get_property_value(parent, "NAME");
> +    else
> +        name = "(unnamed)";
> +
> +    if (!driver || !path || !syspath)
> +        return;
> +    options = xcalloc(sizeof(*options), 1);
> +    if (!options)
> +        return;
> +
> +    options->key = xstrdup("_source");
> +    options->value = xstrdup("server/udev");
> +    if (!options->key || !options->value)
> +        goto unwind;
> +
> +    add_option(&options, "path", path);
> +    add_option(&options, "device", path);
> +    add_option(&options, "driver", driver);
> +
> +    config_info = Xprintf("udev:%s", syspath);
> +    if (!config_info)
> +        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;
> +        if (!strncasecmp(key, UDEV_PROP_KEY, sizeof(UDEV_PROP_KEY) - 1)) {
> +            value = udev_list_entry_get_value(entry);
> +            add_option(&options, key + sizeof(UDEV_PROP_KEY) - 1, value);
> +        } else if (!strncasecmp(key, UDEV_XKB_PROP_KEY,
> +                                sizeof(UDEV_XKB_PROP_KEY) - 1)) {
> +            tmp = key + sizeof(UDEV_XKB_PROP_KEY) - 1;
> +            value = udev_list_entry_get_value(entry);
> +            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);
> +        }
> +    }
> +    add_option(&options, "name", name);
> +    LogMessage(X_INFO, "config/udev: Adding input device %s (%s)\n",
> +               name, path);
> +    rc = NewInputDeviceRequest(options, &dev);
> +    if (rc != Success)
> +        goto unwind;
> +
> +    for (; dev; dev = dev->next) {
> +        xfree(dev->config_info);
> +        dev->config_info = xstrdup(config_info);
> +    }
> +
> + unwind:
> +    xfree(config_info);
> +    while (!dev && (tmpo = options)) {
> +        options = tmpo->next;
> +        xfree(tmpo->key);
> +        xfree(tmpo->value);
> +        xfree(tmpo);
> +    }
> +
> +    return;
> +}
> +
> +static void
> +device_removed(struct udev_device *device)
> +{
> +    char *value;
> +    const char *syspath = udev_device_get_syspath(device);
> +
> +    value = Xprintf("udev:%s", syspath);
> +    if (!value)
> +        return;
> +
> +    remove_devices("udev", value);
> +
> +    xfree(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)
> +            ;
> +        else if (!strcmp(action, "add"))
> +            device_added(udev_device);
> +        else if (!strcmp(action, "remove"))
> +            device_removed(udev_device);
> +        else
> +            DebugF("config/udev: unhandled action %s\n", action);
> +        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;
> +    int rc;
> +
> +    udev = udev_new();
> +    if (!udev)
> +        return 0;
> +    udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
> +    if (!udev_monitor)
> +        return 0;
> +    rc = udev_monitor_filter_add_match_subsystem_devtype(udev_monitor,
> +                                                         "input", NULL);
> +    if (rc < 0)
> +        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_add_match_subsystem(enumerate, "input");
> +    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, udev_monitor);
> +    udev_monitor_unref(udev_monitor);
> +    udev_monitor = NULL;
> +    udev_unref(udev);
> +}
> diff --git a/configure.ac b/configure.ac
> index fa454fa..86a1682 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -597,6 +597,7 @@ AC_ARG_ENABLE(multibuffer,    AS_HELP_STRING([--enable-multibuffer], [Build Mult
>  AC_ARG_ENABLE(dbe,            AS_HELP_STRING([--disable-dbe], [Build DBE extension (default: enabled)]), [DBE=$enableval], [DBE=yes])
>  AC_ARG_ENABLE(xf86bigfont,    AS_HELP_STRING([--disable-xf86bigfont], [Build XF86 Big Font extension (default: disabled)]), [XF86BIGFONT=$enableval], [XF86BIGFONT=no])
>  AC_ARG_ENABLE(dpms,           AS_HELP_STRING([--disable-dpms], [Build DPMS extension (default: enabled)]), [DPMSExtension=$enableval], [DPMSExtension=yes])
> +AC_ARG_ENABLE(config-udev,    AS_HELP_STRING([--enable-config-udev], [Build udev support (default: auto)]), [CONFIG_UDEV=$enableval], [CONFIG_UDEV=auto])
>  AC_ARG_ENABLE(config-dbus,    AS_HELP_STRING([--enable-config-dbus], [Build D-BUS API support (default: no)]), [CONFIG_DBUS_API=$enableval], [CONFIG_DBUS_API=no])
>  AC_ARG_ENABLE(config-hal,     AS_HELP_STRING([--disable-config-hal], [Build HAL support (default: auto)]), [CONFIG_HAL=$enableval], [CONFIG_HAL=auto])
>  AC_ARG_ENABLE(xfree86-utils,     AS_HELP_STRING([--enable-xfree86-utils], [Build xfree86 DDX utilities (default: enabled)]), [XF86UTILS=$enableval], [XF86UTILS=yes])
> @@ -755,6 +756,26 @@ LIBXI="xi >= 1.2.99.1"
>  LIBXTST="xtst >= 1.0.99.2"
>  LIBPCIACCESS="pciaccess >= 0.8.0"
>  LIBGLIB="glib-2.0 >= 2.16"
> +LIBUDEV="libudev >= 143"
> +
> +if test "x$CONFIG_UDEV" = xyes &&
> + { test "x$CONFIG_DBUS_API" = xyes || test "x$CONFIG_HAL" = xyes; }; then
> +	AC_MSG_ERROR([Hotplugging through both libudev and dbus/hal not allowed])
> +fi
> +
> +PKG_CHECK_MODULES(UDEV, $LIBUDEV, [HAVE_LIBUDEV=yes], [HAVE_LIBUDEV=no])
> +if test "x$CONFIG_UDEV" = xauto; then
> +	CONFIG_UDEV="$HAVE_LIBUDEV"
> +fi
> +AM_CONDITIONAL(CONFIG_UDEV, [test "x$CONFIG_UDEV" = xyes])
> +if test "x$CONFIG_UDEV" = xyes; then
> +	CONFIG_DBUS_API=no
> +	CONFIG_HAL=no
> +	if ! test "x$HAVE_LIBUDEV" = xyes; then
> +		AC_MSG_ERROR([udev configuration API requested, but libudev is not installed])
> +	fi
> +	AC_DEFINE(CONFIG_UDEV, 1, [Use libudev for input hotplug])
> +fi
>  
>  dnl HAVE_DBUS is true if we actually have the D-Bus library, whereas
>  dnl CONFIG_DBUS_API is true if we want to enable the D-Bus config
> @@ -788,13 +809,11 @@ if test "x$CONFIG_HAL" = xyes; then
>  	fi
>  
>  	AC_DEFINE(CONFIG_HAL, 1, [Use the HAL hotplug API])
> -        REQUIRED_LIBS="$REQUIRED_LIBS hal"
>  	CONFIG_NEED_DBUS="yes"
>  fi
>  AM_CONDITIONAL(CONFIG_HAL, [test "x$CONFIG_HAL" = xyes])
>  
>  if test "x$CONFIG_NEED_DBUS" = xyes; then
> -	REQUIRED_LIBS="$REQUIRED_LIBS dbus-1"
>          AC_DEFINE(CONFIG_NEED_DBUS, 1, [Use D-Bus for input hotplug])
>  fi
>  AM_CONDITIONAL(CONFIG_NEED_DBUS, [test "x$CONFIG_NEED_DBUS" = xyes])
> diff --git a/hw/kdrive/src/kinput.c b/hw/kdrive/src/kinput.c
> index fb8ebd0..8682763 100644
> --- a/hw/kdrive/src/kinput.c
> +++ b/hw/kdrive/src/kinput.c
> @@ -2280,6 +2280,14 @@ NewInputDeviceRequest(InputOption *options, DeviceIntPtr *pdev)
>              return BadValue;
>          }
>  #endif
> +#ifdef CONFIG_UDEV
> +        else if (strcmp(option->key, "_source") == 0 &&
> +                 strcmp(option->value, "server/udev") == 0)
> +        {
> +            ErrorF("Ignoring device from udev.\n");
> +            return BadValue;
> +        }
> +#endif
>      }
>  
>      if (!ki && !pi) {
> diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c
> index 40f65bd..12f9d49 100644
> --- a/hw/xfree86/common/xf86Config.c
> +++ b/hw/xfree86/common/xf86Config.c
> @@ -1453,12 +1453,19 @@ checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout)
>      }
>  
>      if (xf86Info.allowEmptyInput && !(foundPointer && foundKeyboard)) {
> -#ifdef CONFIG_HAL
> -	xf86Msg(X_INFO, "The server relies on HAL to provide the list of "
> +#if defined(CONFIG_HAL) || defined(CONFIG_UDEV)
> +	const char *config_backend;
> +#if defined(CONFIG_HAL)
> +	config_backend = "HAL";
> +#else
> +	config_backend = "udev";
> +#endif
> +	xf86Msg(X_INFO, "The server relies on %s to provide the list of "
>  	                "input devices.\n\tIf no devices become available, "
> -	                "reconfigure HAL or disable AllowEmptyInput.\n");
> +	                "reconfigure %s or disable AllowEmptyInput.\n",
> +			config_backend, config_backend);
>  #else
> -	xf86Msg(X_INFO, "HAL is disabled and no input devices were configured.\n"
> +	xf86Msg(X_INFO, "Hotplugging is disabled and no input devices were configured.\n"
>  			"\tTry disabling AllowEmptyInput.\n");
>  #endif
>      }
> diff --git a/hw/xfree86/common/xf86Globals.c b/hw/xfree86/common/xf86Globals.c
> index d8f7f7f..0b310e8 100644
> --- a/hw/xfree86/common/xf86Globals.c
> +++ b/hw/xfree86/common/xf86Globals.c
> @@ -132,7 +132,7 @@ xf86InfoRec xf86Info = {
>      .kbdCustomKeycodes          = FALSE,
>      .disableRandR               = FALSE,
>      .randRFrom                  = X_DEFAULT,
> -#ifdef CONFIG_HAL
> +#if defined(CONFIG_HAL) || defined(CONFIG_UDEV)
>      .allowEmptyInput            = TRUE,
>      .autoAddDevices             = TRUE,
>      .autoEnableDevices          = TRUE
> diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
> index fd07c2a..8ad1f95 100644
> --- a/hw/xfree86/common/xf86Xinput.c
> +++ b/hw/xfree86/common/xf86Xinput.c
> @@ -605,9 +605,9 @@ NewInputDeviceRequest (InputOption *options, DeviceIntPtr *pdev)
>              }
>          }
>  
> -        /* Right now, the only automatic config we know of is HAL. */
>          if (strcmp(option->key, "_source") == 0 &&
> -            strcmp(option->value, "server/hal") == 0) {
> +            (strcmp(option->value, "server/hal") == 0 ||
> +             strcmp(option->value, "server/udev") == 0)) {
>              is_auto = 1;
>              if (!xf86Info.autoAddDevices) {
>                  rval = BadMatch;
> diff --git a/include/dix-config.h.in b/include/dix-config.h.in
> index 798d9e7..423ba3a 100644
> --- a/include/dix-config.h.in
> +++ b/include/dix-config.h.in
> @@ -384,6 +384,9 @@
>  /* Support D-Bus */
>  #undef HAVE_DBUS
>  
> +/* Use libudev for input hotplug */
> +#undef CONFIG_UDEV
> +
>  /* Use D-Bus for input hotplug */
>  #undef CONFIG_NEED_DBUS
>  
> -- 
> 1.6.4.3

Tested-by: Peter Hutterer <peter.hutterer at who-t.net>

I haven't tested for the chroot issue you pointed out though. Patch looks
good though.

Cheers,
  Peter


More information about the xorg-devel mailing list