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 Signed-off-by: Laércio de Sousa <laercioso...@sme-mogidascruzes.sp.gov.br> --- hw/kdrive/src/Makefile.am | 8 ++ hw/kdrive/src/kdrive.c | 39 +++++++++ hw/kdrive/src/kinfo.c | 4 + hw/kdrive/src/kinput.c | 212 +++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 241 insertions(+), 22 deletions(-) diff --git a/hw/kdrive/src/Makefile.am b/hw/kdrive/src/Makefile.am index d69f0dd..b7f94b0 100644 --- a/hw/kdrive/src/Makefile.am +++ b/hw/kdrive/src/Makefile.am @@ -23,3 +23,11 @@ libkdrive_la_SOURCES = \ kshadow.c \ $(KDRIVE_XV_SOURCES) \ $(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 diff --git a/hw/kdrive/src/kdrive.c b/hw/kdrive/src/kdrive.c index dddbe6e..8930ace 100644 --- a/hw/kdrive/src/kdrive.c +++ b/hw/kdrive/src/kdrive.c @@ -45,6 +45,10 @@ #include <signal.h> +#if defined(CONFIG_UDEV) || defined(CONFIG_HAL) +#include <hotplug.h> +#endif + typedef struct _kdDepths { CARD8 depth; CARD8 bpp; @@ -1125,6 +1129,11 @@ KdInitOutput(ScreenInfo * pScreenInfo, int argc, char **argv) KdAddScreen(pScreenInfo, screen, argc, argv); OsRegisterSigWrapper(KdSignalWrapper); + +#if defined(CONFIG_UDEV) || defined(CONFIG_HAL) + if (SeatId) /* Enable input hot-plugging */ + config_pre_init(); +#endif } void @@ -1143,3 +1152,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..49c8bb6 100644 --- a/hw/kdrive/src/kinput.c +++ b/hw/kdrive/src/kinput.c @@ -51,6 +51,10 @@ #include "inpututils.h" #include "optionstr.h" +#if defined(CONFIG_UDEV) || defined(CONFIG_HAL) +#include <hotplug.h> +#endif + #ifdef KDRIVE_EVDEV #define DEV_INPUT_EVENT_PREFIX "/dev/input/event" #define DEV_INPUT_EVENT_PREFIX_LEN (sizeof(DEV_INPUT_EVENT_PREFIX) - 1) @@ -396,7 +400,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 +721,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 +896,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 +1081,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 +1227,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 +1365,21 @@ KdInitInput(void) } mieqInit(); + +#if defined(CONFIG_UDEV) || defined(CONFIG_HAL) + if (SeatId) /* Enable input hot-plugging */ + config_init(); +#endif } void KdCloseInput(void) { +#if defined(CONFIG_UDEV) || defined(CONFIG_HAL) + if (SeatId) /* Input hot-plugging is enabled */ + config_fini(); +#endif + mieqFini(); } @@ -2176,24 +2242,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 +2274,66 @@ 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 (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"); + 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 (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"); + 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 +2341,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 +2363,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 +2373,7 @@ NewInputDeviceRequest(InputOption *options, InputAttributes * attrs, } else { ErrorF("unrecognised device identifier!\n"); + input_option_free_list(&optionsdup); return BadValue; } @@ -2265,5 +2383,55 @@ NewInputDeviceRequest(InputOption *options, InputAttributes * attrs, void DeleteInputDeviceRequest(DeviceIntPtr pDev) { +#if defined(CONFIG_UDEV) || defined(CONFIG_HAL) + 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) { + KdKeyboardInfo *ki; + KdPointerInfo *pi; + int found = 0, 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(); +#else + RemoveDevice(pDev, TRUE); +#endif } -- 2.5.0 _______________________________________________ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel