[PATCH v3 04/10] kdrive: introduce input hotplugging support for udev and hal backends (#33140)
Laércio de Sousa
laerciosousa at sme-mogidascruzes.sp.gov.br
Thu Apr 2 13:02:26 PDT 2015
This patch introduces a command-line option -input-hotplug for kdrive-based
applications, which can be used to enable input hotplugging support, instead
of passing explicit -keybd and/or -mouse options.
It supports udev and hal backends for input hotplugging support.
Another patches may be required for wscons backend.
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=33140
Signed-off-by: Laércio de Sousa <laerciosousa at sme-mogidascruzes.sp.gov.br>
---
hw/kdrive/src/Makefile.am | 2 +
hw/kdrive/src/kdrive.c | 41 ++++++++++
hw/kdrive/src/kinfo.c | 4 +
hw/kdrive/src/kinput.c | 200 +++++++++++++++++++++++++++++++++++++++++-----
4 files changed, 225 insertions(+), 22 deletions(-)
diff --git a/hw/kdrive/src/Makefile.am b/hw/kdrive/src/Makefile.am
index d69f0dd..f446f1a 100644
--- a/hw/kdrive/src/Makefile.am
+++ b/hw/kdrive/src/Makefile.am
@@ -23,3 +23,5 @@ libkdrive_la_SOURCES = \
kshadow.c \
$(KDRIVE_XV_SOURCES) \
$(top_srcdir)/mi/miinitext.c
+
+libkdrive_la_LIBADD = $(top_builddir)/config/libconfig.la
diff --git a/hw/kdrive/src/kdrive.c b/hw/kdrive/src/kdrive.c
index dddbe6e..40aea9a 100644
--- a/hw/kdrive/src/kdrive.c
+++ b/hw/kdrive/src/kdrive.c
@@ -44,6 +44,7 @@
#endif
#include <signal.h>
+#include <hotplug.h>
typedef struct _kdDepths {
CARD8 depth;
@@ -81,6 +82,7 @@ char *kdSwitchCmd;
DDXPointRec kdOrigin;
Bool kdHasPointer = FALSE;
Bool kdHasKbd = FALSE;
+Bool kdEnableInputHotplugging = FALSE;
static Bool kdCaughtSignal = FALSE;
@@ -444,6 +446,8 @@ KdUseMsg(void)
ErrorF
("-rgba rgb/bgr/vrgb/vbgr/none Specify subpixel ordering for LCD panels\n");
ErrorF
+ ("-input-hotplug Enable input device hotplugging support\n");
+ ErrorF
("-mouse driver [,n,,options] Specify the pointer driver and its options (n is the number of buttons)\n");
ErrorF
("-keybd driver [,,options] Specify the keyboard driver and its options\n");
@@ -555,6 +559,10 @@ KdProcessArgument(int argc, char **argv, int i)
sscanf(argv[i], "vt%2d", &kdVirtualTerminal) == 1) {
return 1;
}
+ if (!strcmp(argv[i], "-input-hotplug")) {
+ kdEnableInputHotplugging = TRUE;
+ return 1;
+ }
if (!strcmp(argv[i], "-mouse") || !strcmp(argv[i], "-pointer")) {
if (i + 1 >= argc)
UseMsg();
@@ -1125,6 +1133,9 @@ KdInitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
KdAddScreen(pScreenInfo, screen, argc, argv);
OsRegisterSigWrapper(KdSignalWrapper);
+
+ if (kdEnableInputHotplugging)
+ config_pre_init();
}
void
@@ -1143,3 +1154,33 @@ DPMSSupported(void)
{
return FALSE;
}
+
+/* These stubs can be safely removed once we can
+ * split input and GPU parts in hotplug.h et al. */
+#ifdef CONFIG_UDEV_KMS
+void
+NewGPUDeviceRequest(struct OdevAttributes *attribs)
+{
+}
+
+void
+DeleteGPUDeviceRequest(struct OdevAttributes *attribs)
+{
+}
+#endif
+
+struct xf86_platform_device *
+xf86_find_platform_device_by_devnum(int major, int minor)
+{
+ return NULL;
+}
+
+void
+systemd_logind_release_fd(int _major, int _minor, int fd)
+{
+}
+
+void
+systemd_logind_vtenter(void)
+{
+}
diff --git a/hw/kdrive/src/kinfo.c b/hw/kdrive/src/kinfo.c
index 01ae1e4..f91d575 100644
--- a/hw/kdrive/src/kinfo.c
+++ b/hw/kdrive/src/kinfo.c
@@ -134,6 +134,7 @@ KdFreePointer(KdPointerInfo * pi)
free(pi->name);
free(pi->path);
input_option_free_list(&pi->options);
+ pi->next = NULL;
free(pi);
}
@@ -145,6 +146,9 @@ KdFreeKeyboard(KdKeyboardInfo * ki)
free(ki->xkbRules);
free(ki->xkbModel);
free(ki->xkbLayout);
+ free(ki->xkbVariant);
+ free(ki->xkbOptions);
+ input_option_free_list(&ki->options);
ki->next = NULL;
free(ki);
}
diff --git a/hw/kdrive/src/kinput.c b/hw/kdrive/src/kinput.c
index a0c1565..260ecf6 100644
--- a/hw/kdrive/src/kinput.c
+++ b/hw/kdrive/src/kinput.c
@@ -50,6 +50,7 @@
#include "xserver-properties.h"
#include "inpututils.h"
#include "optionstr.h"
+#include <hotplug.h>
#ifdef KDRIVE_EVDEV
#define DEV_INPUT_EVENT_PREFIX "/dev/input/event"
@@ -97,6 +98,7 @@ static KdInputFd kdInputFds[KD_MAX_INPUT_FDS];
static int kdNumInputFds;
extern Bool kdRawPointerCoordinates;
+extern Bool kdEnableInputHotplugging;
static void
KdSigio(int sig)
@@ -396,7 +398,8 @@ KdPointerProc(DeviceIntPtr pDevice, int onoff)
#endif
if (!pi->driver) {
if (!pi->driverPrivate) {
- ErrorF("no driver specified for %s\n", pi->name);
+ ErrorF("no driver specified for pointer device \"%s\" (%s)\n",
+ pi->name ? pi->name : "(unnamed)", pi->path);
return BadImplementation;
}
@@ -716,7 +719,8 @@ KdKeyboardProc(DeviceIntPtr pDevice, int onoff)
#endif
if (!ki->driver) {
if (!ki->driverPrivate) {
- ErrorF("no driver specified!\n");
+ ErrorF("no driver specified for keyboard device \"%s\" (%s)\n",
+ ki->name ? ki->name : "(unnamed)", ki->path);
return BadImplementation;
}
@@ -890,6 +894,8 @@ KdNewKeyboard(void)
ki->bellDuration = 200;
ki->next = NULL;
ki->options = NULL;
+ ki->name = strdup("Generic Keyboard");
+ ki->path = NULL;
ki->xkbRules = strdup(XKB_DFLT_RULES);
ki->xkbModel = strdup(XKB_DFLT_MODEL);
ki->xkbLayout = strdup(XKB_DFLT_LAYOUT);
@@ -1073,18 +1079,52 @@ KdParseKbdOptions(KdKeyboardInfo * ki)
const char *key = input_option_get_key(option);
const char *value = input_option_get_value(option);
- if (strcasecmp(key, "XkbRules") == 0)
+ if (
+#if defined(CONFIG_UDEV) || defined(CONFIG_HAL)
+ strcasecmp(key, "xkb_rules") == 0 ||
+#endif
+ strcasecmp(key, "XkbRules") == 0)
ki->xkbRules = strdup(value);
- else if (strcasecmp(key, "XkbModel") == 0)
+ else if (
+#if defined(CONFIG_UDEV) || defined(CONFIG_HAL)
+ strcasecmp(key, "xkb_model") == 0 ||
+#endif
+ strcasecmp(key, "XkbModel") == 0)
ki->xkbModel = strdup(value);
- else if (strcasecmp(key, "XkbLayout") == 0)
+ else if (
+#if defined(CONFIG_UDEV) || defined(CONFIG_HAL)
+ strcasecmp(key, "xkb_layout") == 0 ||
+#endif
+ strcasecmp(key, "XkbLayout") == 0)
ki->xkbLayout = strdup(value);
- else if (strcasecmp(key, "XkbVariant") == 0)
+ else if (
+#if defined(CONFIG_UDEV) || defined(CONFIG_HAL)
+ strcasecmp(key, "xkb_variant") == 0 ||
+#endif
+ strcasecmp(key, "XkbVariant") == 0)
ki->xkbVariant = strdup(value);
- else if (strcasecmp(key, "XkbOptions") == 0)
+ else if (
+#if defined(CONFIG_UDEV) || defined(CONFIG_HAL)
+ strcasecmp(key, "xkb_options") == 0 ||
+#endif
+ strcasecmp(key, "XkbOptions") == 0)
ki->xkbOptions = strdup(value);
- else if (!strcasecmp(key, "device"))
+ else if (!strcasecmp(key, "device")) {
+ if (ki->path != NULL)
+ free(ki->path);
+ ki->path = strdup(value);
+ }
+#if defined(CONFIG_UDEV) || defined(CONFIG_HAL)
+ else if (!strcasecmp(key, "path")) {
+ if (ki->path != NULL)
+ free(ki->path);
ki->path = strdup(value);
+ }
+ else if (!strcasecmp(key, "name")) {
+ free(ki->name);
+ ki->name = strdup(value);
+ }
+#endif
else if (!strcasecmp(key, "driver"))
ki->driver = KdFindKeyboardDriver(value);
else
@@ -1185,8 +1225,22 @@ KdParsePointerOptions(KdPointerInfo * pi)
pi->transformCoordinates = TRUE;
else if (!strcasecmp(key, "rawcoord"))
pi->transformCoordinates = FALSE;
- else if (!strcasecmp(key, "device"))
+ else if (!strcasecmp(key, "device")) {
+ if (pi->path != NULL)
+ free(pi->path);
+ pi->path = strdup(value);
+ }
+#if defined(CONFIG_UDEV) || defined(CONFIG_HAL)
+ else if (!strcasecmp(key, "path")) {
+ if (pi->path != NULL)
+ free(pi->path);
pi->path = strdup(value);
+ }
+ else if (!strcasecmp(key, "name")) {
+ free(pi->name);
+ pi->name = strdup(value);
+ }
+#endif
else if (!strcasecmp(key, "protocol"))
pi->protocol = strdup(value);
else if (!strcasecmp(key, "driver"))
@@ -1309,11 +1363,17 @@ KdInitInput(void)
}
mieqInit();
+
+ if (kdEnableInputHotplugging)
+ config_init();
}
void
KdCloseInput(void)
{
+ if (kdEnableInputHotplugging)
+ config_fini();
+
mieqFini();
}
@@ -2176,24 +2236,29 @@ int
NewInputDeviceRequest(InputOption *options, InputAttributes * attrs,
DeviceIntPtr *pdev)
{
- InputOption *option = NULL;
+ InputOption *option = NULL, *optionsdup = NULL;
KdPointerInfo *pi = NULL;
KdKeyboardInfo *ki = NULL;
nt_list_for_each_entry(option, options, list.next) {
const char *key = input_option_get_key(option);
const char *value = input_option_get_value(option);
+ optionsdup = input_option_new(optionsdup, key, value);
if (strcmp(key, "type") == 0) {
if (strcmp(value, "pointer") == 0) {
pi = KdNewPointer();
- if (!pi)
+ if (!pi) {
+ input_option_free_list(&optionsdup);
return BadAlloc;
+ }
}
else if (strcmp(value, "keyboard") == 0) {
ki = KdNewKeyboard();
- if (!ki)
+ if (!ki) {
+ input_option_free_list(&optionsdup);
return BadAlloc;
+ }
}
else {
ErrorF("unrecognised device type!\n");
@@ -2203,25 +2268,64 @@ NewInputDeviceRequest(InputOption *options, InputAttributes * attrs,
#ifdef CONFIG_HAL
else if (strcmp(key, "_source") == 0 &&
strcmp(value, "server/hal") == 0) {
- ErrorF("Ignoring device from HAL.\n");
- return BadValue;
+ if (kdEnableInputHotplugging) {
+ if (attrs->flags & ATTR_POINTER) {
+ pi = KdNewPointer();
+ if (!pi) {
+ input_option_free_list(&optionsdup);
+ return BadAlloc;
+ }
+ }
+ else if (attrs->flags & ATTR_KEYBOARD) {
+ ki = KdNewKeyboard();
+ if (!ki) {
+ input_option_free_list(&optionsdup);
+ return BadAlloc;
+ }
+ }
+ }
+ else {
+ ErrorF("Ignoring device from HAL.\n");
+ input_option_free_list(&optionsdup);
+ return BadValue;
+ }
}
#endif
#ifdef CONFIG_UDEV
else if (strcmp(key, "_source") == 0 &&
strcmp(value, "server/udev") == 0) {
- ErrorF("Ignoring device from udev.\n");
- return BadValue;
+ if (kdEnableInputHotplugging) {
+ if (attrs->flags & ATTR_POINTER) {
+ pi = KdNewPointer();
+ if (!pi) {
+ input_option_free_list(&optionsdup);
+ return BadAlloc;
+ }
+ }
+ else if (attrs->flags & ATTR_KEYBOARD) {
+ ki = KdNewKeyboard();
+ if (!ki) {
+ input_option_free_list(&optionsdup);
+ return BadAlloc;
+ }
+ }
+ }
+ else {
+ ErrorF("Ignoring device from udev.\n");
+ input_option_free_list(&optionsdup);
+ return BadValue;
+ }
}
#endif
}
if (pi) {
- pi->options = options;
+ pi->options = optionsdup;
KdParsePointerOptions(pi);
if (!pi->driver) {
- ErrorF("couldn't find driver!\n");
+ ErrorF("couldn't find driver for pointer device \"%s\" (%s)\n",
+ pi->name ? pi->name : "(unnamed)", pi->path);
KdFreePointer(pi);
return BadValue;
}
@@ -2229,18 +2333,21 @@ NewInputDeviceRequest(InputOption *options, InputAttributes * attrs,
if (KdAddPointer(pi) != Success ||
ActivateDevice(pi->dixdev, TRUE) != Success ||
EnableDevice(pi->dixdev, TRUE) != TRUE) {
- ErrorF("couldn't add or enable pointer\n");
+ ErrorF("couldn't add or enable pointer \"%s\" (%s)\n",
+ pi->name ? pi->name : "(unnamed)", pi->path);
+ KdFreePointer(pi);
return BadImplementation;
}
*pdev = pi->dixdev;
}
else if (ki) {
- ki->options = options;
+ ki->options = optionsdup;
KdParseKbdOptions(ki);
if (!ki->driver) {
- ErrorF("couldn't find driver!\n");
+ ErrorF("couldn't find driver for keyboard device \"%s\" (%s)\n",
+ ki->name ? ki->name : "(unnamed)", ki->path);
KdFreeKeyboard(ki);
return BadValue;
}
@@ -2248,7 +2355,9 @@ NewInputDeviceRequest(InputOption *options, InputAttributes * attrs,
if (KdAddKeyboard(ki) != Success ||
ActivateDevice(ki->dixdev, TRUE) != Success ||
EnableDevice(ki->dixdev, TRUE) != TRUE) {
- ErrorF("couldn't add or enable keyboard\n");
+ ErrorF("couldn't add or enable keyboard \"%s\" (%s)\n",
+ ki->name ? ki->name : "(unnamed)", ki->path);
+ KdFreeKeyboard(ki);
return BadImplementation;
}
@@ -2256,6 +2365,7 @@ NewInputDeviceRequest(InputOption *options, InputAttributes * attrs,
}
else {
ErrorF("unrecognised device identifier!\n");
+ input_option_free_list(&optionsdup);
return BadValue;
}
@@ -2265,5 +2375,51 @@ NewInputDeviceRequest(InputOption *options, InputAttributes * attrs,
void
DeleteInputDeviceRequest(DeviceIntPtr pDev)
{
+ KdKeyboardInfo *ki;
+ KdPointerInfo *pi;
+ int found = 0, i = 0;
+
+ OsBlockSIGIO();
RemoveDevice(pDev, TRUE);
+
+ /*
+ * Search for fds that were not unregistered correctly
+ * by RemoveDevice() call and unregister them.
+ * Code taken from KdInputDisable() implementation.
+ */
+ if (kdNumInputFds) {
+ i = 0;
+ while (i < kdNumInputFds) {
+ found = 0;
+ for (ki = kdKeyboards; ki; ki = ki->next) {
+ if (ki == kdInputFds[i].closure) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (found) {
+ i++;
+ continue;
+ }
+
+ for (pi = kdPointers; pi; pi = pi->next) {
+ if (pi == kdInputFds[i].closure) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (found) {
+ i++;
+ continue;
+ }
+
+ ErrorF("Unregistering fd not claimed by any active device: %d\n",
+ kdInputFds[i].fd);
+ KdUnregisterFd(kdInputFds[i].closure, kdInputFds[i].fd, TRUE);
+ }
+ }
+
+ OsReleaseSIGIO();
}
--
2.2.0
More information about the xorg-devel
mailing list