config: add libudev input-hotplug backend
Add a backend using libudev for input hotplug, and disable the hal and dbus backends if this one is enabled. XKB configuration happens using xkb{rules,model,layout,variant,options} properties (case-insensitive) on the device. We fill in InputAttributes to allow configuration through InputClass in Xorg. Requires udev 148 for the input_id helper and ID_INPUT* properties. Signed-off-by: Julien Cristau <jcristau@debian.org> Acked-by: Dan Nicholson <dbn.lists@gmail.com> Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
b8b12e41c4
commit
435f27667f
|
@ -1,12 +1,20 @@
|
||||||
AM_CFLAGS = @DIX_CFLAGS@
|
AM_CFLAGS = $(DIX_CFLAGS)
|
||||||
|
|
||||||
noinst_LTLIBRARIES = libconfig.la
|
noinst_LTLIBRARIES = libconfig.la
|
||||||
libconfig_la_SOURCES = config.c config-backends.h
|
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
|
if CONFIG_NEED_DBUS
|
||||||
AM_CFLAGS += @DBUS_CFLAGS@
|
AM_CFLAGS += $(DBUS_CFLAGS)
|
||||||
libconfig_la_SOURCES += dbus-core.c
|
libconfig_la_SOURCES += dbus-core.c
|
||||||
endif
|
libconfig_la_LIBADD = $(DBUS_LIBS)
|
||||||
|
|
||||||
if CONFIG_DBUS_API
|
if CONFIG_DBUS_API
|
||||||
dbusconfigdir = $(sysconfdir)/dbus-1/system.d
|
dbusconfigdir = $(sysconfdir)/dbus-1/system.d
|
||||||
|
@ -16,7 +24,13 @@ libconfig_la_SOURCES += dbus.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if CONFIG_HAL
|
if CONFIG_HAL
|
||||||
|
AM_CFLAGS += $(HAL_CFLAGS)
|
||||||
libconfig_la_SOURCES += hal.c
|
libconfig_la_SOURCES += hal.c
|
||||||
|
libconfig_la_LIBADD += $(HAL_LIBS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
endif # CONFIG_NEED_DBUS
|
||||||
|
|
||||||
|
endif # !CONFIG_UDEV
|
||||||
|
|
||||||
EXTRA_DIST = xorg-server.conf x11-input.fdi
|
EXTRA_DIST = xorg-server.conf x11-input.fdi
|
||||||
|
|
|
@ -26,8 +26,18 @@
|
||||||
#ifdef HAVE_DIX_CONFIG_H
|
#ifdef HAVE_DIX_CONFIG_H
|
||||||
#include <dix-config.h>
|
#include <dix-config.h>
|
||||||
#endif
|
#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>
|
#include <dbus/dbus.h>
|
||||||
|
|
||||||
typedef void (*config_dbus_core_connect_hook)(DBusConnection *connection,
|
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);
|
void config_dbus_core_fini(void);
|
||||||
int config_dbus_core_add_hook(struct config_dbus_core_hook *hook);
|
int config_dbus_core_add_hook(struct config_dbus_core_hook *hook);
|
||||||
void config_dbus_core_remove_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);
|
int config_dbus_init(void);
|
||||||
void config_dbus_fini(void);
|
void config_dbus_fini(void);
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
#ifdef CONFIG_HAL
|
# ifdef CONFIG_HAL
|
||||||
int config_hal_init(void);
|
int config_hal_init(void);
|
||||||
void config_hal_fini(void);
|
void config_hal_fini(void);
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -28,13 +28,17 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
|
#include "inputstr.h"
|
||||||
#include "hotplug.h"
|
#include "hotplug.h"
|
||||||
#include "config-backends.h"
|
#include "config-backends.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
config_init(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()) {
|
if (config_dbus_core_init()) {
|
||||||
# ifdef CONFIG_DBUS_API
|
# ifdef CONFIG_DBUS_API
|
||||||
if (!config_dbus_init())
|
if (!config_dbus_init())
|
||||||
|
@ -54,7 +58,9 @@ config_init(void)
|
||||||
void
|
void
|
||||||
config_fini(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
|
# ifdef CONFIG_HAL
|
||||||
config_hal_fini();
|
config_hal_fini();
|
||||||
# endif
|
# endif
|
||||||
|
@ -64,3 +70,70 @@ config_fini(void)
|
||||||
config_dbus_core_fini();
|
config_dbus_core_fini();
|
||||||
#endif
|
#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;
|
||||||
|
}
|
||||||
|
|
63
config/hal.c
63
config/hal.c
|
@ -58,25 +58,9 @@ struct xkb_options {
|
||||||
char* 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
|
static void
|
||||||
device_removed(LibHalContext *ctx, const char *udi)
|
device_removed(LibHalContext *ctx, const char *udi)
|
||||||
{
|
{
|
||||||
DeviceIntPtr dev, next;
|
|
||||||
char *value;
|
char *value;
|
||||||
|
|
||||||
value = xalloc(strlen(udi) + 5); /* "hal:" + NULL */
|
value = xalloc(strlen(udi) + 5); /* "hal:" + NULL */
|
||||||
|
@ -84,36 +68,11 @@ device_removed(LibHalContext *ctx, const char *udi)
|
||||||
return;
|
return;
|
||||||
sprintf(value, "hal:%s", udi);
|
sprintf(value, "hal:%s", udi);
|
||||||
|
|
||||||
for (dev = inputInfo.devices; dev; dev = next) {
|
remove_devices("hal", value);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
xfree(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 *
|
static char *
|
||||||
get_prop_string(LibHalContext *hal_ctx, const char *udi, const char *name)
|
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;
|
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
|
static void
|
||||||
device_added(LibHalContext *hal_ctx, const char *udi)
|
device_added(LibHalContext *hal_ctx, const char *udi)
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,260 @@
|
||||||
|
/*
|
||||||
|
* 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 "input.h"
|
||||||
|
#include "inputstr.h"
|
||||||
|
#include "hotplug.h"
|
||||||
|
#include "config-backends.h"
|
||||||
|
#include "os.h"
|
||||||
|
|
||||||
|
#define UDEV_XKB_PROP_KEY "xkb"
|
||||||
|
|
||||||
|
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 *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"))
|
||||||
|
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;
|
||||||
|
|
||||||
|
parent = udev_device_get_parent(udev_device);
|
||||||
|
if (parent)
|
||||||
|
name = udev_device_get_property_value(parent, "NAME");
|
||||||
|
if (!name)
|
||||||
|
name = "(unnamed)";
|
||||||
|
else
|
||||||
|
attrs.product = name;
|
||||||
|
add_option(&options, "name", name);
|
||||||
|
|
||||||
|
add_option(&options, "path", path);
|
||||||
|
add_option(&options, "device", path);
|
||||||
|
attrs.device = path;
|
||||||
|
|
||||||
|
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;
|
||||||
|
value = udev_list_entry_get_value(entry);
|
||||||
|
if (!strncasecmp(key, UDEV_XKB_PROP_KEY,
|
||||||
|
sizeof(UDEV_XKB_PROP_KEY) - 1)) {
|
||||||
|
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")) {
|
||||||
|
attrs.vendor = value;
|
||||||
|
} else if (!strcmp(key, "ID_INPUT_KEY")) {
|
||||||
|
attrs.flags |= ATTR_KEYBOARD;
|
||||||
|
} else if (!strcmp(key, "ID_INPUT_MOUSE")) {
|
||||||
|
attrs.flags |= ATTR_POINTER;
|
||||||
|
} else if (!strcmp(key, "ID_INPUT_JOYSTICK")) {
|
||||||
|
attrs.flags |= ATTR_JOYSTICK;
|
||||||
|
} else if (!strcmp(key, "ID_INPUT_TABLET")) {
|
||||||
|
attrs.flags |= ATTR_TABLET;
|
||||||
|
} else if (!strcmp(key, "ID_INPUT_TOUCHPAD")) {
|
||||||
|
attrs.flags |= ATTR_TOUCHPAD;
|
||||||
|
} else if (!strcmp(key, "ID_INPUT_TOUCHSCREEN")) {
|
||||||
|
attrs.flags |= ATTR_TOUCHSCREEN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LogMessage(X_INFO, "config/udev: Adding input device %s (%s)\n",
|
||||||
|
name, path);
|
||||||
|
rc = NewInputDeviceRequest(options, &attrs, &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) {
|
||||||
|
if (!strcmp(action, "add"))
|
||||||
|
device_added(udev_device);
|
||||||
|
else if (!strcmp(action, "remove"))
|
||||||
|
device_removed(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;
|
||||||
|
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);
|
||||||
|
}
|
23
configure.ac
23
configure.ac
|
@ -618,6 +618,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(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(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(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: no)]), [CONFIG_UDEV=$enableval], [CONFIG_UDEV=no])
|
||||||
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-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(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])
|
AC_ARG_ENABLE(xfree86-utils, AS_HELP_STRING([--enable-xfree86-utils], [Build xfree86 DDX utilities (default: enabled)]), [XF86UTILS=$enableval], [XF86UTILS=yes])
|
||||||
|
@ -775,6 +776,26 @@ LIBXI="xi >= 1.2.99.1"
|
||||||
LIBXTST="xtst >= 1.0.99.2"
|
LIBXTST="xtst >= 1.0.99.2"
|
||||||
LIBPCIACCESS="pciaccess >= 0.8.0"
|
LIBPCIACCESS="pciaccess >= 0.8.0"
|
||||||
LIBGLIB="glib-2.0 >= 2.16"
|
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 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
|
dnl CONFIG_DBUS_API is true if we want to enable the D-Bus config
|
||||||
|
@ -808,13 +829,11 @@ if test "x$CONFIG_HAL" = xyes; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_DEFINE(CONFIG_HAL, 1, [Use the HAL hotplug API])
|
AC_DEFINE(CONFIG_HAL, 1, [Use the HAL hotplug API])
|
||||||
REQUIRED_LIBS="$REQUIRED_LIBS hal"
|
|
||||||
CONFIG_NEED_DBUS="yes"
|
CONFIG_NEED_DBUS="yes"
|
||||||
fi
|
fi
|
||||||
AM_CONDITIONAL(CONFIG_HAL, [test "x$CONFIG_HAL" = xyes])
|
AM_CONDITIONAL(CONFIG_HAL, [test "x$CONFIG_HAL" = xyes])
|
||||||
|
|
||||||
if test "x$CONFIG_NEED_DBUS" = xyes; then
|
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])
|
AC_DEFINE(CONFIG_NEED_DBUS, 1, [Use D-Bus for input hotplug])
|
||||||
fi
|
fi
|
||||||
AM_CONDITIONAL(CONFIG_NEED_DBUS, [test "x$CONFIG_NEED_DBUS" = xyes])
|
AM_CONDITIONAL(CONFIG_NEED_DBUS, [test "x$CONFIG_NEED_DBUS" = xyes])
|
||||||
|
|
|
@ -2280,6 +2280,14 @@ NewInputDeviceRequest(InputOption *options, InputAttributes *attrs,
|
||||||
ErrorF("Ignoring device from HAL.\n");
|
ErrorF("Ignoring device from HAL.\n");
|
||||||
return BadValue;
|
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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1461,12 +1461,19 @@ checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xf86Info.allowEmptyInput && !(foundPointer && foundKeyboard)) {
|
if (xf86Info.allowEmptyInput && !(foundPointer && foundKeyboard)) {
|
||||||
#ifdef CONFIG_HAL
|
#if defined(CONFIG_HAL) || defined(CONFIG_UDEV)
|
||||||
xf86Msg(X_INFO, "The server relies on HAL to provide the list of "
|
const char *config_backend;
|
||||||
"input devices.\n\tIf no devices become available, "
|
#if defined(CONFIG_HAL)
|
||||||
"reconfigure HAL or disable AutoAddDevices.\n");
|
config_backend = "HAL";
|
||||||
#else
|
#else
|
||||||
xf86Msg(X_INFO, "HAL is disabled and no input devices were configured.\n"
|
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 %s or disable AutoAddDevices.\n",
|
||||||
|
config_backend, config_backend);
|
||||||
|
#else
|
||||||
|
xf86Msg(X_INFO, "Hotplugging is disabled and no input devices were configured.\n"
|
||||||
"\tTry disabling AllowEmptyInput.\n");
|
"\tTry disabling AllowEmptyInput.\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,7 +132,7 @@ xf86InfoRec xf86Info = {
|
||||||
.kbdCustomKeycodes = FALSE,
|
.kbdCustomKeycodes = FALSE,
|
||||||
.disableRandR = FALSE,
|
.disableRandR = FALSE,
|
||||||
.randRFrom = X_DEFAULT,
|
.randRFrom = X_DEFAULT,
|
||||||
#ifdef CONFIG_HAL
|
#if defined(CONFIG_HAL) || defined(CONFIG_UDEV)
|
||||||
.allowEmptyInput = TRUE,
|
.allowEmptyInput = TRUE,
|
||||||
.autoAddDevices = TRUE,
|
.autoAddDevices = TRUE,
|
||||||
.autoEnableDevices = TRUE
|
.autoEnableDevices = TRUE
|
||||||
|
|
|
@ -692,9 +692,9 @@ NewInputDeviceRequest (InputOption *options, InputAttributes *attrs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Right now, the only automatic config we know of is HAL. */
|
|
||||||
if (strcmp(option->key, "_source") == 0 &&
|
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;
|
is_auto = 1;
|
||||||
if (!xf86Info.autoAddDevices) {
|
if (!xf86Info.autoAddDevices) {
|
||||||
rval = BadMatch;
|
rval = BadMatch;
|
||||||
|
|
|
@ -399,6 +399,9 @@
|
||||||
/* Support D-Bus */
|
/* Support D-Bus */
|
||||||
#undef HAVE_DBUS
|
#undef HAVE_DBUS
|
||||||
|
|
||||||
|
/* Use libudev for input hotplug */
|
||||||
|
#undef CONFIG_UDEV
|
||||||
|
|
||||||
/* Use D-Bus for input hotplug */
|
/* Use D-Bus for input hotplug */
|
||||||
#undef CONFIG_NEED_DBUS
|
#undef CONFIG_NEED_DBUS
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue