1
From 7dc78123e56b2d4c6855aa7f8f554f012433eed3 Mon Sep 17 00:00:00 2001
2
From: Julien Cristau <jcristau@debian.org>
3
Date: Sun, 27 Sep 2009 14:45:47 +0200
4
Subject: [PATCH 2/5] Add libudev input-hotplug backend
6
If libudev is found, we use that for hotplug and disable the hal and
8
We look for event devices with an "x11_driver" property. XKB
9
configuration happens using xkb.{rules,model,layout,variant,options}
10
properties. Arbitrary driver options can be set with a "x11_options."
13
udev rules would look something like:
14
SUBSYSTEM=="input", KERNEL=="event*", ENV{x11_driver}="evdev"
15
SUBSYSTEM=="input", KERNEL=="event*", ENV{ID_CLASS}=="kbd", ENV{xkb.layout}="fr", ENV{xkb.options}="terminate:ctrl_alt_bksp,compose:lwin"
17
Signed-off-by: Julien Cristau <jcristau@debian.org>
18
Tested-by: Peter Hutterer <peter.hutterer@who-t.net>
20
config/Makefile.am | 16 +++-
21
config/config-backends.h | 21 +++-
22
config/config.c | 77 ++++++++++++-
23
config/hal.c | 63 +----------
24
config/udev.c | 247 +++++++++++++++++++++++++++++++++++++++
25
configure.ac | 23 ++++-
26
hw/kdrive/src/kinput.c | 8 ++
27
hw/xfree86/common/xf86Config.c | 15 ++-
28
hw/xfree86/common/xf86Globals.c | 2 +-
29
hw/xfree86/common/xf86Xinput.c | 4 +-
30
include/dix-config.h.in | 3 +
31
11 files changed, 400 insertions(+), 79 deletions(-)
32
create mode 100644 config/udev.c
34
Index: xorg-server/config/Makefile.am
35
===================================================================
36
--- xorg-server.orig/config/Makefile.am
37
+++ xorg-server/config/Makefile.am
39
noinst_LTLIBRARIES = libconfig.la
40
libconfig_la_SOURCES = config.c config-backends.h
44
+AM_CFLAGS += @UDEV_CFLAGS@
45
+libconfig_la_SOURCES += udev.c
46
+libconfig_la_LIBADD = @UDEV_LIBS@
51
AM_CFLAGS += @DBUS_CFLAGS@
52
libconfig_la_SOURCES += dbus-core.c
54
+libconfig_la_LIBADD = @DBUS_LIBS@
57
dbusconfigdir = $(sysconfdir)/dbus-1/system.d
62
+AM_CFLAGS += @HAL_CFLAGS@
63
libconfig_la_SOURCES += hal.c
64
+libconfig_la_LIBADD += @HAL_LIBS@
67
+endif # CONFIG_NEED_DBUS
71
EXTRA_DIST = xorg-server.conf x11-input.fdi
72
Index: xorg-server/config/config-backends.h
73
===================================================================
74
--- xorg-server.orig/config/config-backends.h
75
+++ xorg-server/config/config-backends.h
77
#ifdef HAVE_DIX_CONFIG_H
78
#include <dix-config.h>
82
-#ifdef CONFIG_NEED_DBUS
83
+void remove_devices(const char *backend, const char *config_info);
84
+BOOL device_is_duplicate(const char *config_info);
85
+void add_option(InputOption **options, const char *key, const char *value);
88
+int config_udev_init(void);
89
+void config_udev_fini(void);
92
+# ifdef CONFIG_NEED_DBUS
93
#include <dbus/dbus.h>
95
typedef void (*config_dbus_core_connect_hook)(DBusConnection *connection,
97
void config_dbus_core_fini(void);
98
int config_dbus_core_add_hook(struct config_dbus_core_hook *hook);
99
void config_dbus_core_remove_hook(struct config_dbus_core_hook *hook);
103
-#ifdef CONFIG_DBUS_API
104
+# ifdef CONFIG_DBUS_API
105
int config_dbus_init(void);
106
void config_dbus_fini(void);
112
int config_hal_init(void);
113
void config_hal_fini(void);
116
Index: xorg-server/config/config.c
117
===================================================================
118
--- xorg-server.orig/config/config.c
119
+++ xorg-server/config/config.c
124
+#include "inputstr.h"
126
#include "config-backends.h"
131
-#if defined(CONFIG_DBUS_API) || defined(CONFIG_HAL)
133
+ if (!config_udev_init())
134
+ ErrorF("[config] failed to initialise udev\n");
135
+#elif defined(CONFIG_NEED_DBUS)
136
if (config_dbus_core_init()) {
137
# ifdef CONFIG_DBUS_API
138
if (!config_dbus_init())
143
-#if defined(CONFIG_DBUS_API) || defined(CONFIG_HAL)
144
+#if defined(CONFIG_UDEV)
145
+ config_udev_fini();
146
+#elif defined(CONFIG_NEED_DBUS)
151
config_dbus_core_fini();
156
+remove_device(const char *backend, DeviceIntPtr dev)
158
+ /* this only gets called for devices that have already been added */
159
+ LogMessage(X_INFO, "config/%s: removing device %s\n", backend, dev->name);
161
+ /* Call PIE here so we don't try to dereference a device that's
162
+ * already been removed. */
164
+ ProcessInputEvents();
165
+ DeleteInputDeviceRequest(dev);
166
+ OsReleaseSignals();
170
+remove_devices(const char *backend, const char *config_info)
172
+ DeviceIntPtr dev, next;
174
+ for (dev = inputInfo.devices; dev; dev = next) {
176
+ if (dev->config_info && strcmp(dev->config_info, config_info) == 0)
177
+ remove_device(backend, dev);
179
+ for (dev = inputInfo.off_devices; dev; dev = next) {
181
+ if (dev->config_info && strcmp(dev->config_info, config_info) == 0)
182
+ remove_device(backend, dev);
187
+device_is_duplicate(const char *config_info)
191
+ for (dev = inputInfo.devices; dev; dev = dev->next)
193
+ if (dev->config_info && (strcmp(dev->config_info, config_info) == 0))
197
+ for (dev = inputInfo.off_devices; dev; dev = dev->next)
199
+ if (dev->config_info && (strcmp(dev->config_info, config_info) == 0))
207
+add_option(InputOption **options, const char *key, const char *value)
209
+ if (!value || *value == '\0')
212
+ for (; *options; options = &(*options)->next)
214
+ *options = xcalloc(sizeof(**options), 1);
215
+ if (!*options) /* Yeesh. */
217
+ (*options)->key = xstrdup(key);
218
+ (*options)->value = xstrdup(value);
219
+ (*options)->next = NULL;
221
Index: xorg-server/config/hal.c
222
===================================================================
223
--- xorg-server.orig/config/hal.c
224
+++ xorg-server/config/hal.c
231
-remove_device(DeviceIntPtr dev)
233
- /* this only gets called for devices that have already been added */
234
- LogMessage(X_INFO, "config/hal: removing device %s\n", dev->name);
236
- /* Call PIE here so we don't try to dereference a device that's
237
- * already been removed. */
239
- ProcessInputEvents();
240
- DeleteInputDeviceRequest(dev);
241
- OsReleaseSignals();
245
device_removed(LibHalContext *ctx, const char *udi)
247
- DeviceIntPtr dev, next;
250
value = xalloc(strlen(udi) + 5); /* "hal:" + NULL */
253
sprintf(value, "hal:%s", udi);
255
- for (dev = inputInfo.devices; dev; dev = next) {
257
- if (dev->config_info && strcmp(dev->config_info, value) == 0)
258
- remove_device(dev);
260
- for (dev = inputInfo.off_devices; dev; dev = next) {
262
- if (dev->config_info && strcmp(dev->config_info, value) == 0)
263
- remove_device(dev);
265
+ remove_devices("hal", value);
271
-add_option(InputOption **options, const char *key, const char *value)
273
- if (!value || *value == '\0')
276
- for (; *options; options = &(*options)->next)
278
- *options = xcalloc(sizeof(**options), 1);
279
- if (!*options) /* Yeesh. */
281
- (*options)->key = xstrdup(key);
282
- (*options)->value = xstrdup(value);
283
- (*options)->next = NULL;
287
get_prop_string(LibHalContext *hal_ctx, const char *udi, const char *name)
294
-device_is_duplicate(char *config_info)
298
- for (dev = inputInfo.devices; dev; dev = dev->next)
300
- if (dev->config_info && (strcmp(dev->config_info, config_info) == 0))
304
- for (dev = inputInfo.off_devices; dev; dev = dev->next)
306
- if (dev->config_info && (strcmp(dev->config_info, config_info) == 0))
314
device_added(LibHalContext *hal_ctx, const char *udi)
316
Index: xorg-server/config/udev.c
317
===================================================================
319
+++ xorg-server/config/udev.c
322
+ * Copyright © 2009 Julien Cristau
324
+ * Permission is hereby granted, free of charge, to any person obtaining a
325
+ * copy of this software and associated documentation files (the "Software"),
326
+ * to deal in the Software without restriction, including without limitation
327
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
328
+ * and/or sell copies of the Software, and to permit persons to whom the
329
+ * Software is furnished to do so, subject to the following conditions:
331
+ * The above copyright notice and this permission notice (including the next
332
+ * paragraph) shall be included in all copies or substantial portions of the
335
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
336
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
337
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
338
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
339
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
340
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
341
+ * DEALINGS IN THE SOFTWARE.
343
+ * Author: Julien Cristau <jcristau@debian.org>
346
+#ifdef HAVE_DIX_CONFIG_H
347
+#include <dix-config.h>
350
+#include <libudev.h>
353
+#include "inputstr.h"
354
+#include "hotplug.h"
355
+#include "config-backends.h"
358
+#define UDEV_XKB_PROP_KEY "xkb."
359
+#define UDEV_PROP_KEY "x11_options."
361
+static struct udev_monitor *udev_monitor;
364
+device_added(struct udev_device *udev_device)
366
+ const char *path = NULL, *driver = NULL, *name = NULL;
367
+ char *config_info = NULL;
368
+ const char *syspath;
369
+ const char *key, *value, *tmp;
370
+ InputOption *options = NULL, *tmpo;
371
+ DeviceIntPtr dev = NULL;
372
+ struct udev_list_entry *set, *entry;
373
+ struct udev_device *parent;
376
+ driver = udev_device_get_property_value(udev_device, "x11_driver");
378
+ path = udev_device_get_devnode(udev_device);
380
+ syspath = udev_device_get_syspath(udev_device);
382
+ parent = udev_device_get_parent(udev_device);
384
+ name = udev_device_get_property_value(parent, "NAME");
386
+ name = "(unnamed)";
388
+ if (!driver || !path || !syspath)
390
+ options = xcalloc(sizeof(*options), 1);
394
+ options->key = xstrdup("_source");
395
+ options->value = xstrdup("server/udev");
396
+ if (!options->key || !options->value)
399
+ add_option(&options, "path", path);
400
+ add_option(&options, "device", path);
401
+ add_option(&options, "driver", driver);
403
+ config_info = Xprintf("udev:%s", syspath);
407
+ if (device_is_duplicate(config_info)) {
408
+ LogMessage(X_WARNING, "config/udev: device %s already added. "
409
+ "Ignoring.\n", name);
413
+ set = udev_device_get_properties_list_entry(udev_device);
414
+ udev_list_entry_foreach(entry, set) {
415
+ key = udev_list_entry_get_name(entry);
418
+ if (!strncasecmp(key, UDEV_PROP_KEY, sizeof(UDEV_PROP_KEY) - 1)) {
419
+ value = udev_list_entry_get_value(entry);
420
+ add_option(&options, key + sizeof(UDEV_PROP_KEY) - 1, value);
421
+ } else if (!strncasecmp(key, UDEV_XKB_PROP_KEY,
422
+ sizeof(UDEV_XKB_PROP_KEY) - 1)) {
423
+ tmp = key + sizeof(UDEV_XKB_PROP_KEY) - 1;
424
+ value = udev_list_entry_get_value(entry);
425
+ if (!strcasecmp(tmp, "rules"))
426
+ add_option(&options, "xkb_rules", value);
427
+ else if (!strcasecmp(tmp, "layout"))
428
+ add_option(&options, "xkb_layout", value);
429
+ else if (!strcasecmp(tmp, "variant"))
430
+ add_option(&options, "xkb_variant", value);
431
+ else if (!strcasecmp(tmp, "model"))
432
+ add_option(&options, "xkb_model", value);
433
+ else if (!strcasecmp(tmp, "options"))
434
+ add_option(&options, "xkb_options", value);
437
+ add_option(&options, "name", name);
438
+ LogMessage(X_INFO, "config/udev: Adding input device %s (%s)\n",
440
+ rc = NewInputDeviceRequest(options, &dev);
444
+ for (; dev; dev = dev->next) {
445
+ xfree(dev->config_info);
446
+ dev->config_info = xstrdup(config_info);
450
+ xfree(config_info);
451
+ while (!dev && (tmpo = options)) {
452
+ options = tmpo->next;
454
+ xfree(tmpo->value);
462
+device_removed(struct udev_device *device)
465
+ const char *syspath = udev_device_get_syspath(device);
467
+ value = Xprintf("udev:%s", syspath);
471
+ remove_devices("udev", value);
477
+wakeup_handler(pointer data, int err, pointer read_mask)
479
+ int udev_fd = udev_monitor_get_fd(udev_monitor);
480
+ struct udev_device *udev_device;
481
+ const char *action;
486
+ if (FD_ISSET(udev_fd, (fd_set *)read_mask)) {
487
+ udev_device = udev_monitor_receive_device(udev_monitor);
490
+ action = udev_device_get_action(udev_device);
493
+ else if (!strcmp(action, "add"))
494
+ device_added(udev_device);
495
+ else if (!strcmp(action, "remove"))
496
+ device_removed(udev_device);
498
+ DebugF("config/udev: unhandled action %s\n", action);
499
+ udev_device_unref(udev_device);
504
+block_handler(pointer data, struct timeval **tv, pointer read_mask)
509
+config_udev_init(void)
512
+ struct udev_enumerate *enumerate;
513
+ struct udev_list_entry *devices, *device;
519
+ udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
522
+ rc = udev_monitor_filter_add_match_subsystem_devtype(udev_monitor,
527
+ if (udev_monitor_enable_receiving(udev_monitor)) {
528
+ ErrorF("config/udev: failed to bind the udev monitor\n");
532
+ enumerate = udev_enumerate_new(udev);
535
+ udev_enumerate_add_match_subsystem(enumerate, "input");
536
+ udev_enumerate_scan_devices(enumerate);
537
+ devices = udev_enumerate_get_list_entry(enumerate);
538
+ udev_list_entry_foreach(device, devices) {
539
+ const char *syspath = udev_list_entry_get_name(device);
540
+ struct udev_device *udev_device = udev_device_new_from_syspath(udev, syspath);
541
+ device_added(udev_device);
542
+ udev_device_unref(udev_device);
544
+ udev_enumerate_unref(enumerate);
546
+ RegisterBlockAndWakeupHandlers(block_handler, wakeup_handler, NULL);
547
+ AddGeneralSocket(udev_monitor_get_fd(udev_monitor));
553
+config_udev_fini(void)
560
+ udev = udev_monitor_get_udev(udev_monitor);
562
+ RemoveGeneralSocket(udev_monitor_get_fd(udev_monitor));
563
+ RemoveBlockAndWakeupHandlers(block_handler, wakeup_handler, udev_monitor);
564
+ udev_monitor_unref(udev_monitor);
565
+ udev_monitor = NULL;
568
Index: xorg-server/configure.ac
569
===================================================================
570
--- xorg-server.orig/configure.ac
571
+++ xorg-server/configure.ac
573
AC_ARG_ENABLE(dbe, AS_HELP_STRING([--disable-dbe], [Build DBE extension (default: enabled)]), [DBE=$enableval], [DBE=yes])
574
AC_ARG_ENABLE(xf86bigfont, AS_HELP_STRING([--disable-xf86bigfont], [Build XF86 Big Font extension (default: disabled)]), [XF86BIGFONT=$enableval], [XF86BIGFONT=no])
575
AC_ARG_ENABLE(dpms, AS_HELP_STRING([--disable-dpms], [Build DPMS extension (default: enabled)]), [DPMSExtension=$enableval], [DPMSExtension=yes])
576
+AC_ARG_ENABLE(config-udev, AS_HELP_STRING([--enable-config-udev], [Build udev support (default: auto)]), [CONFIG_UDEV=$enableval], [CONFIG_UDEV=auto])
577
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])
578
AC_ARG_ENABLE(config-hal, AS_HELP_STRING([--disable-config-hal], [Build HAL support (default: auto)]), [CONFIG_HAL=$enableval], [CONFIG_HAL=auto])
579
AC_ARG_ENABLE(xfree86-utils, AS_HELP_STRING([--enable-xfree86-utils], [Build xfree86 DDX utilities (default: enabled)]), [XF86UTILS=$enableval], [XF86UTILS=yes])
581
LIBPCIACCESS="pciaccess >= 0.8.0"
582
LIBGLIB="glib-2.0 >= 2.16"
583
LIBSELINUX="libselinux >= 2.0.86"
584
+LIBUDEV="libudev >= 143"
586
+if test "x$CONFIG_UDEV" = xyes &&
587
+ { test "x$CONFIG_DBUS_API" = xyes || test "x$CONFIG_HAL" = xyes; }; then
588
+ AC_MSG_ERROR([Hotplugging through both libudev and dbus/hal not allowed])
591
+PKG_CHECK_MODULES(UDEV, $LIBUDEV, [HAVE_LIBUDEV=yes], [HAVE_LIBUDEV=no])
592
+if test "x$CONFIG_UDEV" = xauto; then
593
+ CONFIG_UDEV="$HAVE_LIBUDEV"
595
+AM_CONDITIONAL(CONFIG_UDEV, [test "x$CONFIG_UDEV" = xyes])
596
+if test "x$CONFIG_UDEV" = xyes; then
599
+ if ! test "x$HAVE_LIBUDEV" = xyes; then
600
+ AC_MSG_ERROR([udev configuration API requested, but libudev is not installed])
602
+ AC_DEFINE(CONFIG_UDEV, 1, [Use libudev for input hotplug])
605
dnl HAVE_DBUS is true if we actually have the D-Bus library, whereas
606
dnl CONFIG_DBUS_API is true if we want to enable the D-Bus config
607
@@ -793,13 +814,11 @@
610
AC_DEFINE(CONFIG_HAL, 1, [Use the HAL hotplug API])
611
- REQUIRED_LIBS="$REQUIRED_LIBS hal"
612
CONFIG_NEED_DBUS="yes"
614
AM_CONDITIONAL(CONFIG_HAL, [test "x$CONFIG_HAL" = xyes])
616
if test "x$CONFIG_NEED_DBUS" = xyes; then
617
- REQUIRED_LIBS="$REQUIRED_LIBS dbus-1"
618
AC_DEFINE(CONFIG_NEED_DBUS, 1, [Use D-Bus for input hotplug])
620
AM_CONDITIONAL(CONFIG_NEED_DBUS, [test "x$CONFIG_NEED_DBUS" = xyes])
621
Index: xorg-server/hw/kdrive/src/kinput.c
622
===================================================================
623
--- xorg-server.orig/hw/kdrive/src/kinput.c
624
+++ xorg-server/hw/kdrive/src/kinput.c
625
@@ -2280,6 +2280,14 @@
630
+ else if (strcmp(option->key, "_source") == 0 &&
631
+ strcmp(option->value, "server/udev") == 0)
633
+ ErrorF("Ignoring device from udev.\n");
640
Index: xorg-server/hw/xfree86/common/xf86Config.c
641
===================================================================
642
--- xorg-server.orig/hw/xfree86/common/xf86Config.c
643
+++ xorg-server/hw/xfree86/common/xf86Config.c
644
@@ -1444,12 +1444,19 @@
647
if (xf86Info.allowEmptyInput && !(foundPointer && foundKeyboard)) {
649
- xf86Msg(X_INFO, "The server relies on HAL to provide the list of "
650
+#if defined(CONFIG_HAL) || defined(CONFIG_UDEV)
651
+ const char *config_backend;
652
+#if defined(CONFIG_HAL)
653
+ config_backend = "HAL";
655
+ config_backend = "udev";
657
+ xf86Msg(X_INFO, "The server relies on %s to provide the list of "
658
"input devices.\n\tIf no devices become available, "
659
- "reconfigure HAL or disable AutoAddDevices.\n");
660
+ "reconfigure %s or disable AutoAddDevices.\n",
661
+ config_backend, config_backend);
663
- xf86Msg(X_INFO, "HAL is disabled and no input devices were configured.\n"
664
+ xf86Msg(X_INFO, "Hotplugging is disabled and no input devices were configured.\n"
665
"\tTry disabling AllowEmptyInput.\n");
668
Index: xorg-server/hw/xfree86/common/xf86Globals.c
669
===================================================================
670
--- xorg-server.orig/hw/xfree86/common/xf86Globals.c
671
+++ xorg-server/hw/xfree86/common/xf86Globals.c
673
.kbdCustomKeycodes = FALSE,
674
.disableRandR = FALSE,
675
.randRFrom = X_DEFAULT,
677
+#if defined(CONFIG_HAL) || defined(CONFIG_UDEV)
678
.allowEmptyInput = TRUE,
679
.autoAddDevices = TRUE,
680
.autoEnableDevices = TRUE
681
Index: xorg-server/hw/xfree86/common/xf86Xinput.c
682
===================================================================
683
--- xorg-server.orig/hw/xfree86/common/xf86Xinput.c
684
+++ xorg-server/hw/xfree86/common/xf86Xinput.c
689
- /* Right now, the only automatic config we know of is HAL. */
690
if (strcmp(option->key, "_source") == 0 &&
691
- strcmp(option->value, "server/hal") == 0) {
692
+ (strcmp(option->value, "server/hal") == 0 ||
693
+ strcmp(option->value, "server/udev") == 0)) {
695
if (!xf86Info.autoAddDevices) {
697
Index: xorg-server/include/dix-config.h.in
698
===================================================================
699
--- xorg-server.orig/include/dix-config.h.in
700
+++ xorg-server/include/dix-config.h.in
705
+/* Use libudev for input hotplug */
708
/* Use D-Bus for input hotplug */
709
#undef CONFIG_NEED_DBUS