kdrive: introduce input hot-plugging support for udev and hal backends (#33140)

This patch introduces input hot-plugging support for kdrive-based
applications in multi-seat context. This feature is enabled by passing
-seat option with desired seat name. All keyboard/mouse devices assigned
to that seat will be automatically grabbed by kdrive.

It supports udev and hal backends for input hot-plugging support.
Another patches may be required for wscons backend.

Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=33140

Reviewed-by: Adam Jackson <ajax@redhat.com>
Signed-off-by: Laércio de Sousa <laerciosousa@sme-mogidascruzes.sp.gov.br>
This commit is contained in:
Laércio de Sousa 2016-02-12 14:17:59 -02:00 committed by Adam Jackson
parent 2116f03be0
commit 0cf3d72be6
4 changed files with 198 additions and 22 deletions

View File

@ -23,3 +23,11 @@ libkdrive_la_SOURCES = \
kshadow.c \ kshadow.c \
$(KDRIVE_XV_SOURCES) \ $(KDRIVE_XV_SOURCES) \
$(top_srcdir)/mi/miinitext.c $(top_srcdir)/mi/miinitext.c
if CONFIG_UDEV
libkdrive_la_LIBADD = $(top_builddir)/config/libconfig.la
else
if CONFIG_HAL
libkdrive_la_LIBADD = $(top_builddir)/config/libconfig.la
endif
endif

View File

@ -45,6 +45,14 @@
#include <signal.h> #include <signal.h>
#if defined(CONFIG_UDEV) || defined(CONFIG_HAL)
#include <hotplug.h>
#endif
/* This stub can be safely removed once we can
* split input and GPU parts in hotplug.h et al. */
#include <systemd-logind.h>
typedef struct _kdDepths { typedef struct _kdDepths {
CARD8 depth; CARD8 depth;
CARD8 bpp; CARD8 bpp;
@ -1125,6 +1133,11 @@ KdInitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
KdAddScreen(pScreenInfo, screen, argc, argv); KdAddScreen(pScreenInfo, screen, argc, argv);
OsRegisterSigWrapper(KdSignalWrapper); OsRegisterSigWrapper(KdSignalWrapper);
#if defined(CONFIG_UDEV) || defined(CONFIG_HAL)
if (SeatId) /* Enable input hot-plugging */
config_pre_init();
#endif
} }
void void
@ -1143,3 +1156,36 @@ DPMSSupported(void)
{ {
return FALSE; 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;
}
#ifdef SYSTEMD_LOGIND
void
systemd_logind_vtenter(void)
{
}
void
systemd_logind_release_fd(int major, int minor, int fd)
{
close(fd);
}
#endif

View File

@ -134,6 +134,7 @@ KdFreePointer(KdPointerInfo * pi)
free(pi->name); free(pi->name);
free(pi->path); free(pi->path);
input_option_free_list(&pi->options); input_option_free_list(&pi->options);
pi->next = NULL;
free(pi); free(pi);
} }
@ -145,6 +146,9 @@ KdFreeKeyboard(KdKeyboardInfo * ki)
free(ki->xkbRules); free(ki->xkbRules);
free(ki->xkbModel); free(ki->xkbModel);
free(ki->xkbLayout); free(ki->xkbLayout);
free(ki->xkbVariant);
free(ki->xkbOptions);
input_option_free_list(&ki->options);
ki->next = NULL; ki->next = NULL;
free(ki); free(ki);
} }

View File

@ -51,6 +51,10 @@
#include "inpututils.h" #include "inpututils.h"
#include "optionstr.h" #include "optionstr.h"
#if defined(CONFIG_UDEV) || defined(CONFIG_HAL)
#include <hotplug.h>
#endif
#ifdef KDRIVE_EVDEV #ifdef KDRIVE_EVDEV
#define DEV_INPUT_EVENT_PREFIX "/dev/input/event" #define DEV_INPUT_EVENT_PREFIX "/dev/input/event"
#define DEV_INPUT_EVENT_PREFIX_LEN (sizeof(DEV_INPUT_EVENT_PREFIX) - 1) #define DEV_INPUT_EVENT_PREFIX_LEN (sizeof(DEV_INPUT_EVENT_PREFIX) - 1)
@ -407,7 +411,8 @@ KdPointerProc(DeviceIntPtr pDevice, int onoff)
#endif #endif
if (!pi->driver) { if (!pi->driver) {
if (!pi->driverPrivate) { 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; return BadImplementation;
} }
@ -727,7 +732,8 @@ KdKeyboardProc(DeviceIntPtr pDevice, int onoff)
#endif #endif
if (!ki->driver) { if (!ki->driver) {
if (!ki->driverPrivate) { 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; return BadImplementation;
} }
@ -901,6 +907,8 @@ KdNewKeyboard(void)
ki->bellDuration = 200; ki->bellDuration = 200;
ki->next = NULL; ki->next = NULL;
ki->options = NULL; ki->options = NULL;
ki->name = strdup("Generic Keyboard");
ki->path = NULL;
ki->xkbRules = strdup(XKB_DFLT_RULES); ki->xkbRules = strdup(XKB_DFLT_RULES);
ki->xkbModel = strdup(XKB_DFLT_MODEL); ki->xkbModel = strdup(XKB_DFLT_MODEL);
ki->xkbLayout = strdup(XKB_DFLT_LAYOUT); ki->xkbLayout = strdup(XKB_DFLT_LAYOUT);
@ -1084,18 +1092,52 @@ KdParseKbdOptions(KdKeyboardInfo * ki)
const char *key = input_option_get_key(option); const char *key = input_option_get_key(option);
const char *value = input_option_get_value(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); 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); 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); 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); 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); 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); 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")) else if (!strcasecmp(key, "driver"))
ki->driver = KdFindKeyboardDriver(value); ki->driver = KdFindKeyboardDriver(value);
else else
@ -1196,8 +1238,22 @@ KdParsePointerOptions(KdPointerInfo * pi)
pi->transformCoordinates = TRUE; pi->transformCoordinates = TRUE;
else if (!strcasecmp(key, "rawcoord")) else if (!strcasecmp(key, "rawcoord"))
pi->transformCoordinates = FALSE; pi->transformCoordinates = FALSE;
else if (!strcasecmp(key, "device")) else if (!strcasecmp(key, "device")) {
if (pi->path != NULL)
free(pi->path);
pi->path = strdup(value); 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")) else if (!strcasecmp(key, "protocol"))
pi->protocol = strdup(value); pi->protocol = strdup(value);
else if (!strcasecmp(key, "driver")) else if (!strcasecmp(key, "driver"))
@ -1320,11 +1376,21 @@ KdInitInput(void)
} }
mieqInit(); mieqInit();
#if defined(CONFIG_UDEV) || defined(CONFIG_HAL)
if (SeatId) /* Enable input hot-plugging */
config_init();
#endif
} }
void void
KdCloseInput(void) KdCloseInput(void)
{ {
#if defined(CONFIG_UDEV) || defined(CONFIG_HAL)
if (SeatId) /* Input hot-plugging is enabled */
config_fini();
#endif
mieqFini(); mieqFini();
} }
@ -2141,25 +2207,30 @@ int
NewInputDeviceRequest(InputOption *options, InputAttributes * attrs, NewInputDeviceRequest(InputOption *options, InputAttributes * attrs,
DeviceIntPtr *pdev) DeviceIntPtr *pdev)
{ {
InputOption *option = NULL; InputOption *option = NULL, *optionsdup = NULL;
KdPointerInfo *pi = NULL; KdPointerInfo *pi = NULL;
KdKeyboardInfo *ki = NULL; KdKeyboardInfo *ki = NULL;
nt_list_for_each_entry(option, options, list.next) { nt_list_for_each_entry(option, options, list.next) {
const char *key = input_option_get_key(option); const char *key = input_option_get_key(option);
const char *value = input_option_get_value(option); const char *value = input_option_get_value(option);
optionsdup = input_option_new(optionsdup, key, value);
if (strcmp(key, "type") == 0) { if (strcmp(key, "type") == 0) {
if (strcmp(value, "pointer") == 0) { if (strcmp(value, "pointer") == 0) {
pi = KdNewPointer(); pi = KdNewPointer();
if (!pi) if (!pi) {
input_option_free_list(&optionsdup);
return BadAlloc; return BadAlloc;
} }
}
else if (strcmp(value, "keyboard") == 0) { else if (strcmp(value, "keyboard") == 0) {
ki = KdNewKeyboard(); ki = KdNewKeyboard();
if (!ki) if (!ki) {
input_option_free_list(&optionsdup);
return BadAlloc; return BadAlloc;
} }
}
else { else {
ErrorF("unrecognised device type!\n"); ErrorF("unrecognised device type!\n");
return BadValue; return BadValue;
@ -2168,25 +2239,66 @@ NewInputDeviceRequest(InputOption *options, InputAttributes * attrs,
#ifdef CONFIG_HAL #ifdef CONFIG_HAL
else if (strcmp(key, "_source") == 0 && else if (strcmp(key, "_source") == 0 &&
strcmp(value, "server/hal") == 0) { strcmp(value, "server/hal") == 0) {
if (SeatId) {
/* Input hot-plugging is enabled */
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"); ErrorF("Ignoring device from HAL.\n");
input_option_free_list(&optionsdup);
return BadValue; return BadValue;
} }
}
#endif #endif
#ifdef CONFIG_UDEV #ifdef CONFIG_UDEV
else if (strcmp(key, "_source") == 0 && else if (strcmp(key, "_source") == 0 &&
strcmp(value, "server/udev") == 0) { strcmp(value, "server/udev") == 0) {
if (SeatId) {
/* Input hot-plugging is enabled */
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"); ErrorF("Ignoring device from udev.\n");
input_option_free_list(&optionsdup);
return BadValue; return BadValue;
} }
}
#endif #endif
} }
if (pi) { if (pi) {
pi->options = options; pi->options = optionsdup;
KdParsePointerOptions(pi); KdParsePointerOptions(pi);
if (!pi->driver) { 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); KdFreePointer(pi);
return BadValue; return BadValue;
} }
@ -2194,18 +2306,21 @@ NewInputDeviceRequest(InputOption *options, InputAttributes * attrs,
if (KdAddPointer(pi) != Success || if (KdAddPointer(pi) != Success ||
ActivateDevice(pi->dixdev, TRUE) != Success || ActivateDevice(pi->dixdev, TRUE) != Success ||
EnableDevice(pi->dixdev, TRUE) != TRUE) { 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; return BadImplementation;
} }
*pdev = pi->dixdev; *pdev = pi->dixdev;
} }
else if (ki) { else if (ki) {
ki->options = options; ki->options = optionsdup;
KdParseKbdOptions(ki); KdParseKbdOptions(ki);
if (!ki->driver) { 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); KdFreeKeyboard(ki);
return BadValue; return BadValue;
} }
@ -2213,7 +2328,9 @@ NewInputDeviceRequest(InputOption *options, InputAttributes * attrs,
if (KdAddKeyboard(ki) != Success || if (KdAddKeyboard(ki) != Success ||
ActivateDevice(ki->dixdev, TRUE) != Success || ActivateDevice(ki->dixdev, TRUE) != Success ||
EnableDevice(ki->dixdev, TRUE) != TRUE) { 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; return BadImplementation;
} }
@ -2221,6 +2338,7 @@ NewInputDeviceRequest(InputOption *options, InputAttributes * attrs,
} }
else { else {
ErrorF("unrecognised device identifier!\n"); ErrorF("unrecognised device identifier!\n");
input_option_free_list(&optionsdup);
return BadValue; return BadValue;
} }