xserver: Branch 'master' - 14 commits

Keith Packard keithp at kemper.freedesktop.org
Fri Mar 7 22:08:44 PST 2014


 config/config.c                              |   85 ++++
 config/udev.c                                |   43 +-
 configure.ac                                 |   21 +
 hw/xfree86/common/xf86Events.c               |   15 
 hw/xfree86/common/xf86Init.c                 |    3 
 hw/xfree86/common/xf86Module.h               |    4 
 hw/xfree86/common/xf86Xinput.c               |   65 +++
 hw/xfree86/common/xf86Xinput.h               |    8 
 hw/xfree86/common/xf86platformBus.c          |   60 ++-
 hw/xfree86/common/xf86platformBus.h          |   15 
 hw/xfree86/os-support/linux/Makefile.am      |    6 
 hw/xfree86/os-support/linux/lnx_init.c       |   25 -
 hw/xfree86/os-support/linux/lnx_platform.c   |   45 +-
 hw/xfree86/os-support/linux/systemd-logind.c |  532 +++++++++++++++++++++++++++
 hw/xfree86/os-support/shared/posix_tty.c     |    6 
 include/Makefile.am                          |    1 
 include/dix-config.h.in                      |    3 
 include/hotplug.h                            |   30 +
 include/systemd-logind.h                     |   45 ++
 19 files changed, 959 insertions(+), 53 deletions(-)

New commits:
commit 1c61d38528a573caadee2468ee59ea558c822e09
Merge: 5350ae1 bf35437
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Mar 7 22:07:19 2014 -0800

    Merge remote-tracking branch 'jwrdecoede/for-keith'

commit bf3543739db18c6cd52908f7c693cb64f43e3f23
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Sat Feb 1 13:21:15 2014 +0100

    xf86OpenSerial: Add support server managed fds
    
    Try to get a server managed fd from the Options before trying to open the
    device node ourselves.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/os-support/shared/posix_tty.c b/hw/xfree86/os-support/shared/posix_tty.c
index 4d08c1e..6e2af00 100644
--- a/hw/xfree86/os-support/shared/posix_tty.c
+++ b/hw/xfree86/os-support/shared/posix_tty.c
@@ -124,7 +124,11 @@ xf86OpenSerial(XF86OptionPtr options)
         return -1;
     }
 
-    SYSCALL(fd = open(dev, O_RDWR | O_NONBLOCK));
+    fd = xf86CheckIntOption(options, "fd", -1);
+
+    if (fd == -1)
+        SYSCALL(fd = open(dev, O_RDWR | O_NONBLOCK));
+
     if (fd == -1) {
         xf86Msg(X_ERROR,
                 "xf86OpenSerial: Cannot open device %s\n\t%s.\n",
commit d9a4059d400bf288aadd17c04885cb9b0fb93989
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Jan 14 15:47:48 2014 +0100

    config-udev: Don't try to add drm devices twice
    
    Before this commit we were trying to add most drm devices twice, once
    from xf86platformProbe() and once from config_udev_init().
    
    This results in somewhat confusing messages in Xorg.log, ie:
    
    (II) xfree86: Adding drm device (/dev/dri/card0)
    Later followed by:
    (II) config/udev: Adding drm device (/dev/dri/card0)
    
    By filtering out duplicate drm devices we avoid these confusing messages.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Acked-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/config/udev.c b/config/udev.c
index 2085185..d70eeb4 100644
--- a/config/udev.c
+++ b/config/udev.c
@@ -112,6 +112,10 @@ device_added(struct udev_device *udev_device)
         if (strncmp(sysname, "card", 4) != 0)
             return;
 
+        /* Check for devices already added through xf86platformProbe() */
+        if (xf86_find_platform_device_by_devnum(major(devnum), minor(devnum)))
+            return;
+
         LogMessage(X_INFO, "config/udev: Adding drm device (%s)\n", path);
 
         config_udev_odev_setup_attribs(path, syspath, major(devnum),
commit 687afa3f6475060e6c460aa9496ba1a6a7982102
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Jan 31 15:21:38 2014 +0100

    systemd-logind: Add delayed input device probing
    
    With systemd-logind we cannot probe input devices while switched away, so
    if we're switched away, put the pInfo on a list, and probe everything on
    that list on VT-Enter.
    
    This is using an array grown by re-alloc, rather than a xorg_list since
    creating a new data-type to store a pInfo + list-entry just for this seems
    overkill.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 9d6b3ca..7c3e479 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -105,6 +105,9 @@
 static int
  xf86InputDevicePostInit(DeviceIntPtr dev);
 
+static InputInfoPtr *new_input_devices;
+static int new_input_devices_count;
+
 /**
  * Eval config and modify DeviceVelocityRec accordingly
  */
@@ -839,10 +842,20 @@ xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable)
     }
 
     if (drv->capabilities & XI86_DRV_CAP_SERVER_FD) {
-        pInfo->fd = systemd_logind_take_fd(pInfo->major, pInfo->minor,
-                                           pInfo->attrs->device, &paused);
-        if (pInfo->fd != -1) {
-            /* FIXME handle paused */
+        int fd = systemd_logind_take_fd(pInfo->major, pInfo->minor,
+                                        pInfo->attrs->device, &paused);
+        if (fd != -1) {
+            if (paused) {
+                /* Put on new_input_devices list for delayed probe */
+                new_input_devices = xnfrealloc(new_input_devices,
+                            sizeof(pInfo) * (new_input_devices_count + 1));
+                new_input_devices[new_input_devices_count] = pInfo;
+                new_input_devices_count++;
+                systemd_logind_release_fd(pInfo->major, pInfo->minor);
+                close(fd);
+                return BadMatch;
+            }
+            pInfo->fd = fd;
             pInfo->flags |= XI86_SERVER_FD;
             pInfo->options = xf86ReplaceIntOption(pInfo->options, "fd", fd);
         }
@@ -1493,4 +1506,32 @@ xf86PostTouchEvent(DeviceIntPtr dev, uint32_t touchid, uint16_t type,
     QueueTouchEvents(dev, type, touchid, flags, mask);
 }
 
+void
+xf86InputEnableVTProbe(void)
+{
+    int i, is_auto = 0;
+    InputOption *option = NULL;
+    DeviceIntPtr pdev;
+
+    for (i = 0; i < new_input_devices_count; i++) {
+        InputInfoPtr pInfo = new_input_devices[i];
+
+        is_auto = 0;
+        nt_list_for_each_entry(option, pInfo->options, list.next) {
+            const char *key = input_option_get_key(option);
+            const char *value = input_option_get_value(option);
+
+            if (strcmp(key, "_source") == 0 &&
+                (strcmp(value, "server/hal") == 0 ||
+                 strcmp(value, "server/udev") == 0 ||
+                 strcmp(value, "server/wscons") == 0))
+                is_auto = 1;
+        }
+        xf86NewInputDevice(pInfo, &pdev,
+                                  (!is_auto ||
+                                   (is_auto && xf86Info.autoEnableDevices)));
+    }
+    new_input_devices_count = 0;
+}
+
 /* end of xf86Xinput.c */
diff --git a/hw/xfree86/common/xf86Xinput.h b/hw/xfree86/common/xf86Xinput.h
index 784e14e..9fe8c87 100644
--- a/hw/xfree86/common/xf86Xinput.h
+++ b/hw/xfree86/common/xf86Xinput.h
@@ -179,6 +179,7 @@ extern _X_EXPORT void xf86AddEnabledDevice(InputInfoPtr pInfo);
 extern _X_EXPORT void xf86RemoveEnabledDevice(InputInfoPtr pInfo);
 extern _X_EXPORT void xf86DisableDevice(DeviceIntPtr dev, Bool panic);
 extern _X_EXPORT void xf86EnableDevice(DeviceIntPtr dev);
+extern _X_EXPORT void xf86InputEnableVTProbe(void);
 
 /* not exported */
 int xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL is_auto);
diff --git a/hw/xfree86/os-support/linux/systemd-logind.c b/hw/xfree86/os-support/linux/systemd-logind.c
index 4732c08..abb8e44 100644
--- a/hw/xfree86/os-support/linux/systemd-logind.c
+++ b/hw/xfree86/os-support/linux/systemd-logind.c
@@ -198,6 +198,9 @@ systemd_logind_vtenter(void)
     for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next)
         if ((pInfo->flags & XI86_SERVER_FD) && pInfo->fd != -1)
             xf86EnableInputDeviceForVTSwitch(pInfo);
+
+    /* Do delayed input probing, this must be done after the above enabling */
+    xf86InputEnableVTProbe();
 }
 
 static InputInfoPtr
commit cac39219898f5e5a59ff8d8d6524f5fe0d111469
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Jan 14 15:37:33 2014 +0100

    systemd-logind: Hookup systemd-logind integration
    
    This commits makes the changes necessary outside of the systemd-logind core
    to make the server use systemd-logind managed fds for input devices and drm
    nodes.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/config/config.c b/config/config.c
index ea2f744..7971b87 100644
--- a/config/config.c
+++ b/config/config.c
@@ -27,10 +27,12 @@
 #include <dix-config.h>
 #endif
 
+#include <unistd.h>
 #include "os.h"
 #include "inputstr.h"
 #include "hotplug.h"
 #include "config-backends.h"
+#include "systemd-logind.h"
 
 void
 config_pre_init(void)
@@ -235,10 +237,21 @@ void
 config_odev_free_attributes(struct OdevAttributes *attribs)
 {
     struct OdevAttribute *iter, *safe;
+    int major = 0, minor = 0, fd = -1;
 
     xorg_list_for_each_entry_safe(iter, safe, &attribs->list, member) {
+        switch (iter->attrib_id) {
+        case ODEV_ATTRIB_MAJOR: major = iter->attrib_value; break;
+        case ODEV_ATTRIB_MINOR: minor = iter->attrib_value; break;
+        case ODEV_ATTRIB_FD: fd = iter->attrib_value; break;
+        }
         xorg_list_del(&iter->member);
         free(iter->attrib_name);
         free(iter);
     }
+
+    if (fd != -1) {
+        systemd_logind_release_fd(major, minor);
+        close(fd);
+    }
 }
diff --git a/config/udev.c b/config/udev.c
index 68ed348..2085185 100644
--- a/config/udev.c
+++ b/config/udev.c
@@ -29,6 +29,7 @@
 
 #include <libudev.h>
 #include <ctype.h>
+#include <unistd.h>
 
 #include "input.h"
 #include "inputstr.h"
@@ -36,6 +37,7 @@
 #include "config-backends.h"
 #include "os.h"
 #include "globals.h"
+#include "systemd-logind.h"
 
 #define UDEV_XKB_PROP_KEY "xkb"
 
@@ -55,9 +57,18 @@ static struct udev_monitor *udev_monitor;
 #ifdef CONFIG_UDEV_KMS
 static Bool
 config_udev_odev_setup_attribs(const char *path, const char *syspath,
+                               int major, int minor,
                                config_odev_probe_proc_ptr probe_callback);
 #endif
 
+static char itoa_buf[16];
+
+static const char *itoa(int i)
+{
+    snprintf(itoa_buf, sizeof(itoa_buf), "%d", i);
+    return itoa_buf;
+}
+
 static void
 device_added(struct udev_device *udev_device)
 {
@@ -73,6 +84,7 @@ device_added(struct udev_device *udev_device)
     struct udev_device *parent;
     int rc;
     const char *dev_seat;
+    dev_t devnum;
 
     path = udev_device_get_devnode(udev_device);
 
@@ -91,6 +103,8 @@ device_added(struct udev_device *udev_device)
     if (!SeatId && strcmp(dev_seat, "seat0"))
         return;
 
+    devnum = udev_device_get_devnum(udev_device);
+
 #ifdef CONFIG_UDEV_KMS
     if (!strcmp(udev_device_get_subsystem(udev_device), "drm")) {
         const char *sysname = udev_device_get_sysname(udev_device);
@@ -100,7 +114,8 @@ device_added(struct udev_device *udev_device)
 
         LogMessage(X_INFO, "config/udev: Adding drm device (%s)\n", path);
 
-        config_udev_odev_setup_attribs(path, syspath, NewGPUDeviceRequest);
+        config_udev_odev_setup_attribs(path, syspath, major(devnum),
+                                       minor(devnum), NewGPUDeviceRequest);
         return;
     }
 #endif
@@ -153,6 +168,8 @@ device_added(struct udev_device *udev_device)
     input_options = input_option_new(input_options, "name", name);
     input_options = input_option_new(input_options, "path", path);
     input_options = input_option_new(input_options, "device", path);
+    input_options = input_option_new(input_options, "major", itoa(major(devnum)));
+    input_options = input_option_new(input_options, "minor", itoa(minor(devnum)));
     if (path)
         attrs.device = strdup(path);
 
@@ -270,6 +287,7 @@ device_removed(struct udev_device *device)
     if (!strcmp(udev_device_get_subsystem(device), "drm")) {
         const char *sysname = udev_device_get_sysname(device);
         const char *path = udev_device_get_devnode(device);
+        dev_t devnum = udev_device_get_devnum(device);
 
         if (strncmp(sysname,"card", 4) != 0)
             return;
@@ -277,7 +295,10 @@ device_removed(struct udev_device *device)
         if (!path)
             return;
 
-        config_udev_odev_setup_attribs(path, syspath, DeleteGPUDeviceRequest);
+        config_udev_odev_setup_attribs(path, syspath, major(devnum),
+                                       minor(devnum), DeleteGPUDeviceRequest);
+        /* Retry vtenter after a drm node removal */
+        systemd_logind_vtenter();
         return;
     }
 #endif
@@ -427,6 +448,7 @@ config_udev_fini(void)
 
 static Bool
 config_udev_odev_setup_attribs(const char *path, const char *syspath,
+                               int major, int minor,
                                config_odev_probe_proc_ptr probe_callback)
 {
     struct OdevAttributes *attribs = config_odev_allocate_attribute_list();
@@ -443,6 +465,14 @@ config_udev_odev_setup_attribs(const char *path, const char *syspath,
     if (ret == FALSE)
         goto fail;
 
+    ret = config_odev_add_int_attribute(attribs, ODEV_ATTRIB_MAJOR, major);
+    if (ret == FALSE)
+        goto fail;
+
+    ret = config_odev_add_int_attribute(attribs, ODEV_ATTRIB_MINOR, minor);
+    if (ret == FALSE)
+        goto fail;
+
     /* ownership of attribs is passed to probe layer */
     probe_callback(attribs);
     return TRUE;
@@ -477,6 +507,7 @@ config_udev_odev_probe(config_odev_probe_proc_ptr probe_callback)
         struct udev_device *udev_device = udev_device_new_from_syspath(udev, syspath);
         const char *path = udev_device_get_devnode(udev_device);
         const char *sysname = udev_device_get_sysname(udev_device);
+        dev_t devnum = udev_device_get_devnum(udev_device);
 
         if (!path || !syspath)
             goto no_probe;
@@ -485,8 +516,8 @@ config_udev_odev_probe(config_odev_probe_proc_ptr probe_callback)
         else if (strncmp(sysname, "card", 4) != 0)
             goto no_probe;
 
-        config_udev_odev_setup_attribs(path, syspath, probe_callback);
-
+        config_udev_odev_setup_attribs(path, syspath, major(devnum),
+                                       minor(devnum), probe_callback);
     no_probe:
         udev_device_unref(udev_device);
     }
diff --git a/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c
index 7b53949..06af739 100644
--- a/hw/xfree86/common/xf86Events.c
+++ b/hw/xfree86/common/xf86Events.c
@@ -85,6 +85,8 @@
 #endif
 
 #include "xf86platformBus.h"
+#include "systemd-logind.h"
+
 /*
  * This is a toggling variable:
  *  FALSE = No VT switching keys have been pressed last time around
@@ -556,8 +558,11 @@ xf86VTEnter(void)
     /* Turn screen saver off when switching back */
     dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset);
 
-    for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next)
-        xf86EnableInputDeviceForVTSwitch(pInfo);
+    /* If we use systemd-logind it will enable input devices for us */
+    if (!systemd_logind_controls_session())
+        for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next)
+            xf86EnableInputDeviceForVTSwitch(pInfo);
+
     for (ih = InputHandlers; ih; ih = ih->next) {
         if (ih->is_input)
             xf86EnableInputHandler(ih);
@@ -589,10 +594,14 @@ xf86VTSwitch(void)
     /*
      * Since all screens are currently all in the same state it is sufficient
      * check the first.  This might change in future.
+     *
+     * VTLeave is always handled here (VT_PROCESS guarantees this is safe),
+     * if we use systemd_logind xf86VTEnter() gets called by systemd-logind.c
+     * once it has resumed all drm nodes.
      */
     if (xf86VTOwner())
         xf86VTLeave();
-    else
+    else if (!systemd_logind_controls_session())
         xf86VTEnter();
 }
 
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 7d13f75..9d6b3ca 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -63,6 +63,7 @@
 #include "mipointer.h"
 #include "extinit.h"
 #include "loaderProcs.h"
+#include "systemd-logind.h"
 
 #include "exevents.h"           /* AddInputDevice */
 #include "exglobals.h"
@@ -80,6 +81,7 @@
 
 #include <stdarg.h>
 #include <stdint.h>             /* for int64_t */
+#include <unistd.h>
 
 #include "mi.h"
 
@@ -773,6 +775,11 @@ xf86DeleteInput(InputInfoPtr pInp, int flags)
         /* Else the entry wasn't in the xf86InputDevs list (ignore this). */
     }
 
+    if (pInp->flags & XI86_SERVER_FD) {
+        systemd_logind_release_fd(pInp->major, pInp->minor);
+        close(pInp->fd);
+    }
+
     free((void *) pInp->driver);
     free((void *) pInp->name);
     xf86optionListFree(pInp->options);
@@ -816,6 +823,7 @@ xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable)
 {
     InputDriverPtr drv = NULL;
     DeviceIntPtr dev = NULL;
+    Bool paused;
     int rval;
 
     /* Memory leak for every attached device if we don't
@@ -830,6 +838,16 @@ xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable)
         goto unwind;
     }
 
+    if (drv->capabilities & XI86_DRV_CAP_SERVER_FD) {
+        pInfo->fd = systemd_logind_take_fd(pInfo->major, pInfo->minor,
+                                           pInfo->attrs->device, &paused);
+        if (pInfo->fd != -1) {
+            /* FIXME handle paused */
+            pInfo->flags |= XI86_SERVER_FD;
+            pInfo->options = xf86ReplaceIntOption(pInfo->options, "fd", fd);
+        }
+    }
+
     xf86Msg(X_INFO, "Using input driver '%s' for '%s'\n", drv->driverName,
             pInfo->name);
 
diff --git a/hw/xfree86/os-support/linux/lnx_platform.c b/hw/xfree86/os-support/linux/lnx_platform.c
index f4c4d12..109a9a7 100644
--- a/hw/xfree86/os-support/linux/lnx_platform.c
+++ b/hw/xfree86/os-support/linux/lnx_platform.c
@@ -18,16 +18,38 @@
 #include "xf86Bus.h"
 
 #include "hotplug.h"
+#include "systemd-logind.h"
 
 static Bool
 get_drm_info(struct OdevAttributes *attribs, char *path, int delayed_index)
 {
     drmSetVersion sv;
     char *buf;
-    int fd;
+    int major, minor, fd;
     int err = 0;
+    Bool paused, server_fd = FALSE;
+
+    major = config_odev_get_int_attribute(attribs, ODEV_ATTRIB_MAJOR, 0);
+    minor = config_odev_get_int_attribute(attribs, ODEV_ATTRIB_MINOR, 0);
+
+    fd = systemd_logind_take_fd(major, minor, path, &paused);
+    if (fd != -1) {
+        if (paused) {
+            LogMessage(X_ERROR,
+                    "Error systemd-logind returned paused fd for drm node\n");
+            systemd_logind_release_fd(major, minor);
+            return FALSE;
+        }
+        if (!config_odev_add_int_attribute(attribs, ODEV_ATTRIB_FD, fd)) {
+            systemd_logind_release_fd(major, minor);
+            return FALSE;
+        }
+        server_fd = TRUE;
+    }
+
+    if (fd == -1)
+        fd = open(path, O_RDWR, O_CLOEXEC);
 
-    fd = open(path, O_RDWR, O_CLOEXEC);
     if (fd == -1)
         return FALSE;
 
@@ -48,12 +70,16 @@ get_drm_info(struct OdevAttributes *attribs, char *path, int delayed_index)
             delayed_index = xf86_num_platform_devices - 1;
     }
 
+    if (server_fd)
+        xf86_platform_devices[delayed_index].flags |= XF86_PDEV_SERVER_FD;
+
     buf = drmGetBusid(fd);
     xf86_add_platform_device_attrib(delayed_index,
                                     ODEV_ATTRIB_BUSID, buf);
     drmFreeBusid(buf);
 out:
-    close(fd);
+    if (!server_fd)
+        close(fd);
     return (err == 0);
 }
 
commit 82863656ec449644cd34a86388ba40f36cea11e9
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Jan 7 12:15:12 2014 +0100

    systemd-logind: Add systemd-logind "core"
    
    This commits add the bulk of the systemd-logind integration code, but does
    not hook it up yet other then calling its init and fini functions, which
    don't do that much.
    
    Note the configure bits check for udev since systemd-logind use will only be
    supported in combination with udev. Besides that it only checks for dbus
    since all communication with systemd-logind is happening over dbus, so
    no further libs are needed.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/configure.ac b/configure.ac
index 0fb2fc3..588ae59 100644
--- a/configure.ac
+++ b/configure.ac
@@ -626,6 +626,7 @@ AC_ARG_ENABLE(clientids,      AS_HELP_STRING([--disable-clientids], [Build Xorg
 AC_ARG_ENABLE(pciaccess, AS_HELP_STRING([--enable-pciaccess], [Build Xorg with pciaccess library (default: enabled)]), [PCI=$enableval], [PCI=yes])
 AC_ARG_ENABLE(linux_acpi, AS_HELP_STRING([--disable-linux-acpi], [Disable building ACPI support on Linux (if available).]), [enable_linux_acpi=$enableval], [enable_linux_acpi=yes])
 AC_ARG_ENABLE(linux_apm, AS_HELP_STRING([--disable-linux-apm], [Disable building APM support on Linux (if available).]), [enable_linux_apm=$enableval], [enable_linux_apm=yes])
+AC_ARG_ENABLE(systemd-logind, AC_HELP_STRING([--enable-systemd-logind], [Build systemd-logind support (default: auto)]), [SYSTEMD_LOGIND=$enableval], [SYSTEMD_LOGIND=auto])
 
 dnl DDXes.
 AC_ARG_ENABLE(xorg,    	      AS_HELP_STRING([--enable-xorg], [Build Xorg server (default: auto)]), [XORG=$enableval], [XORG=auto])
@@ -901,6 +902,26 @@ if test "x$CONFIG_HAL" = xyes; then
 fi
 AM_CONDITIONAL(CONFIG_HAL, [test "x$CONFIG_HAL" = xyes])
 
+if test "x$SYSTEMD_LOGIND" = xauto; then
+        if test "x$HAVE_DBUS" = xyes -a "x$CONFIG_UDEV" = xyes ; then
+                SYSTEMD_LOGIND=yes
+        else
+                SYSTEMD_LOGIND=no
+        fi
+fi
+if test "x$SYSTEMD_LOGIND" = xyes; then
+        if ! test "x$HAVE_DBUS" = xyes; then
+                AC_MSG_ERROR([systemd-logind requested, but D-Bus is not installed.])
+        fi
+        if ! test "x$CONFIG_UDEV" = xyes ; then
+                AC_MSG_ERROR([systemd-logind is only supported in combination with udev configuration.])
+        fi
+
+        AC_DEFINE(SYSTEMD_LOGIND, 1, [Enable systemd-logind integration])
+        NEED_DBUS="yes"
+fi
+AM_CONDITIONAL(SYSTEMD_LOGIND, [test "x$SYSTEMD_LOGIND" = xyes])
+
 if test "x$NEED_DBUS" = xyes; then
         AC_DEFINE(NEED_DBUS, 1, [Enable D-Bus core])
 fi
diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c
index ff4d38f..4579ff5 100644
--- a/hw/xfree86/common/xf86Init.c
+++ b/hw/xfree86/common/xf86Init.c
@@ -54,6 +54,7 @@
 #include "site.h"
 #include "mi.h"
 #include "dbus-core.h"
+#include "systemd-logind.h"
 
 #include "compiler.h"
 
@@ -458,6 +459,7 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
             DoShowOptions();
 
         dbus_core_init();
+        systemd_logind_init();
 
         /* Do a general bus probe.  This will be a PCI probe for x86 platforms */
         xf86BusProbe();
@@ -1062,6 +1064,7 @@ ddxGiveUp(enum ExitCode error)
     if (xorgHWOpenConsole)
         xf86CloseConsole();
 
+    systemd_logind_fini();
     dbus_core_fini();
 
     xf86CloseLog(error);
diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c
index e1d7bd0..4447e19 100644
--- a/hw/xfree86/common/xf86platformBus.c
+++ b/hw/xfree86/common/xf86platformBus.c
@@ -52,7 +52,7 @@ int platformSlotClaimed;
 
 int xf86_num_platform_devices;
 
-static struct xf86_platform_device *xf86_platform_devices;
+struct xf86_platform_device *xf86_platform_devices;
 
 int
 xf86_add_platform_device(struct OdevAttributes *attribs, Bool unowned)
diff --git a/hw/xfree86/common/xf86platformBus.h b/hw/xfree86/common/xf86platformBus.h
index 3e27d34..78b5a5b 100644
--- a/hw/xfree86/common/xf86platformBus.h
+++ b/hw/xfree86/common/xf86platformBus.h
@@ -36,12 +36,14 @@ struct xf86_platform_device {
 /* xf86_platform_device flags */
 #define XF86_PDEV_UNOWNED       0x01
 #define XF86_PDEV_SERVER_FD     0x02
+#define XF86_PDEV_PAUSED        0x04
 
 #ifdef XSERVER_PLATFORM_BUS
 int xf86platformProbe(void);
 int xf86platformProbeDev(DriverPtr drvp);
 
 extern int xf86_num_platform_devices;
+extern struct xf86_platform_device *xf86_platform_devices;
 
 extern char *
 xf86_get_platform_attrib(int index, int attrib_id);
diff --git a/hw/xfree86/os-support/linux/Makefile.am b/hw/xfree86/os-support/linux/Makefile.am
index 83e7e00..1686dc2 100644
--- a/hw/xfree86/os-support/linux/Makefile.am
+++ b/hw/xfree86/os-support/linux/Makefile.am
@@ -21,6 +21,11 @@ APM_SRCS = lnx_apm.c
 XORG_CFLAGS += -DHAVE_APM
 endif
 
+if SYSTEMD_LOGIND
+LOGIND_SRCS = systemd-logind.c
+XORG_CFLAGS += $(DBUS_CFLAGS)
+endif
+
 liblinux_la_SOURCES = lnx_init.c lnx_video.c \
                      lnx_agp.c lnx_kmod.c lnx_bell.c lnx_platform.c \
                      $(srcdir)/../shared/bios_mmap.c \
@@ -30,6 +35,7 @@ liblinux_la_SOURCES = lnx_init.c lnx_video.c \
 		     $(srcdir)/../shared/sigio.c \
                      $(ACPI_SRCS) \
                      $(APM_SRCS) \
+                     $(LOGIND_SRCS) \
                      $(PLATFORM_PCI_SUPPORT)
 
 AM_CFLAGS = -DUSESTDRES -DHAVE_SYSV_IPC $(DIX_CFLAGS) $(XORG_CFLAGS) $(PLATFORM_DEFINES)
diff --git a/hw/xfree86/os-support/linux/systemd-logind.c b/hw/xfree86/os-support/linux/systemd-logind.c
new file mode 100644
index 0000000..4732c08
--- /dev/null
+++ b/hw/xfree86/os-support/linux/systemd-logind.c
@@ -0,0 +1,529 @@
+/*
+ * Copyright © 2013 Red Hat Inc.
+ *
+ * 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: Hans de Goede <hdegoede at redhat.com>
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include <dbus/dbus.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "os.h"
+#include "dbus-core.h"
+#include "xf86.h"
+#include "xf86platformBus.h"
+#include "xf86Xinput.h"
+
+#include "systemd-logind.h"
+
+#define DBUS_TIMEOUT 500 /* Wait max 0.5 seconds */
+
+struct systemd_logind_info {
+    DBusConnection *conn;
+    char *session;
+    Bool active;
+    Bool vt_active;
+};
+
+static struct systemd_logind_info logind_info;
+
+int
+systemd_logind_take_fd(int _major, int _minor, const char *path,
+                       Bool *paused_ret)
+{
+    struct systemd_logind_info *info = &logind_info;
+    DBusError error;
+    DBusMessage *msg = NULL;
+    DBusMessage *reply = NULL;
+    dbus_int32_t major = _major;
+    dbus_int32_t minor = _minor;
+    dbus_bool_t paused;
+    int fd = -1;
+
+    if (!info->session || major == 0)
+        return -1;
+
+    /* logind does not support mouse devs (with evdev we don't need them) */
+    if (strstr(path, "mouse"))
+        return -1;
+
+    dbus_error_init(&error);
+
+    msg = dbus_message_new_method_call("org.freedesktop.login1", info->session,
+            "org.freedesktop.login1.Session", "TakeDevice");
+    if (!msg) {
+        LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+        goto cleanup;
+    }
+
+    if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, &major,
+                                       DBUS_TYPE_UINT32, &minor,
+                                       DBUS_TYPE_INVALID)) {
+        LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+        goto cleanup;
+    }
+
+    reply = dbus_connection_send_with_reply_and_block(info->conn, msg,
+                                                      DBUS_TIMEOUT, &error);
+    if (!reply) {
+        LogMessage(X_ERROR, "systemd-logind: failed to take device %s: %s\n",
+                   path, error.message);
+        goto cleanup;
+    }
+
+    if (!dbus_message_get_args(reply, &error,
+                               DBUS_TYPE_UNIX_FD, &fd,
+                               DBUS_TYPE_BOOLEAN, &paused,
+                               DBUS_TYPE_INVALID)) {
+        LogMessage(X_ERROR, "systemd-logind: TakeDevice %s: %s\n",
+                   path, error.message);
+        goto cleanup;
+    }
+
+    *paused_ret = paused;
+
+    LogMessage(X_INFO, "systemd-logind: got fd for %s %u:%u fd %d paused %d\n",
+               path, major, minor, fd, paused);
+
+cleanup:
+    if (msg)
+        dbus_message_unref(msg);
+    if (reply)
+        dbus_message_unref(reply);
+    dbus_error_free(&error);
+
+    return fd;
+}
+
+void
+systemd_logind_release_fd(int _major, int _minor)
+{
+    struct systemd_logind_info *info = &logind_info;
+    DBusError error;
+    DBusMessage *msg = NULL;
+    DBusMessage *reply = NULL;
+    dbus_int32_t major = _major;
+    dbus_int32_t minor = _minor;
+
+    if (!info->session || major == 0)
+        return;
+
+    dbus_error_init(&error);
+
+    msg = dbus_message_new_method_call("org.freedesktop.login1", info->session,
+            "org.freedesktop.login1.Session", "ReleaseDevice");
+    if (!msg) {
+        LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+        goto cleanup;
+    }
+
+    if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, &major,
+                                       DBUS_TYPE_UINT32, &minor,
+                                       DBUS_TYPE_INVALID)) {
+        LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+        goto cleanup;
+    }
+
+    reply = dbus_connection_send_with_reply_and_block(info->conn, msg,
+                                                      DBUS_TIMEOUT, &error);
+    if (!reply)
+        LogMessage(X_ERROR, "systemd-logind: failed to release device: %s\n",
+                   error.message);
+
+cleanup:
+    if (msg)
+        dbus_message_unref(msg);
+    if (reply)
+        dbus_message_unref(reply);
+    dbus_error_free(&error);
+}
+
+int
+systemd_logind_controls_session(void)
+{
+    return logind_info.session ? 1 : 0;
+}
+
+void
+systemd_logind_vtenter(void)
+{
+    struct systemd_logind_info *info = &logind_info;
+    InputInfoPtr pInfo;
+    int i;
+
+    if (!info->session)
+        return; /* Not using systemd-logind */
+
+    if (!info->active)
+        return; /* Session not active */
+
+    if (info->vt_active)
+        return; /* Already did vtenter */
+
+    for (i = 0; i < xf86_num_platform_devices; i++) {
+        if (xf86_platform_devices[i].flags & XF86_PDEV_PAUSED)
+            break;
+    }
+    if (i != xf86_num_platform_devices)
+        return; /* Some drm nodes are still paused wait for resume */
+
+    xf86VTEnter();
+    info->vt_active = TRUE;
+
+    /* Activate any input devices which were resumed before the drm nodes */
+    for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next)
+        if ((pInfo->flags & XI86_SERVER_FD) && pInfo->fd != -1)
+            xf86EnableInputDeviceForVTSwitch(pInfo);
+}
+
+static InputInfoPtr
+systemd_logind_find_info_ptr_by_devnum(int major, int minor)
+{
+    InputInfoPtr pInfo;
+
+    for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next)
+        if (pInfo->major == major && pInfo->minor == minor &&
+                (pInfo->flags & XI86_SERVER_FD))
+            return pInfo;
+
+    return NULL;
+}
+
+static void
+systemd_logind_ack_pause(struct systemd_logind_info *info,
+                         dbus_int32_t minor, dbus_int32_t major)
+{
+    DBusError error;
+    DBusMessage *msg = NULL;
+    DBusMessage *reply = NULL;
+
+    dbus_error_init(&error);
+
+    msg = dbus_message_new_method_call("org.freedesktop.login1", info->session,
+            "org.freedesktop.login1.Session", "PauseDeviceComplete");
+    if (!msg) {
+        LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+        goto cleanup;
+    }
+
+    if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, &major,
+                                       DBUS_TYPE_UINT32, &minor,
+                                       DBUS_TYPE_INVALID)) {
+        LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+        goto cleanup;
+    }
+
+    reply = dbus_connection_send_with_reply_and_block(info->conn, msg,
+                                                      DBUS_TIMEOUT, &error);
+    if (!reply)
+        LogMessage(X_ERROR, "systemd-logind: failed to ack pause: %s\n",
+                   error.message);
+
+cleanup:
+    if (msg)
+        dbus_message_unref(msg);
+    if (reply)
+        dbus_message_unref(reply);
+    dbus_error_free(&error);
+}
+
+static DBusHandlerResult
+message_filter(DBusConnection * connection, DBusMessage * message, void *data)
+{
+    struct systemd_logind_info *info = data;
+    struct xf86_platform_device *pdev = NULL;
+    InputInfoPtr pInfo = NULL;
+    int ack = 0, pause = 0, fd = -1;
+    DBusError error;
+    dbus_int32_t major, minor;
+    char *pause_str;
+
+    if (strcmp(dbus_message_get_path(message), info->session) != 0)
+        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+    dbus_error_init(&error);
+
+    if (dbus_message_is_signal(message, "org.freedesktop.login1.Session",
+                               "PauseDevice")) {
+        if (!dbus_message_get_args(message, &error,
+                               DBUS_TYPE_UINT32, &major,
+                               DBUS_TYPE_UINT32, &minor,
+                               DBUS_TYPE_STRING, &pause_str,
+                               DBUS_TYPE_INVALID)) {
+            LogMessage(X_ERROR, "systemd-logind: PauseDevice: %s\n",
+                       error.message);
+            dbus_error_free(&error);
+            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+        }
+
+        if (strcmp(pause_str, "pause") == 0) {
+            pause = 1;
+            ack = 1;
+        }
+        else if (strcmp(pause_str, "force") == 0) {
+            pause = 1;
+        }
+        else if (strcmp(pause_str, "gone") == 0) {
+            /* Device removal is handled through udev */
+            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+        }
+        else {
+            LogMessage(X_WARNING, "systemd-logind: unknown pause type: %s\n",
+                       pause_str);
+            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+        }
+    }
+    else if (dbus_message_is_signal(message, "org.freedesktop.login1.Session",
+                                    "ResumeDevice")) {
+        if (!dbus_message_get_args(message, &error,
+                                   DBUS_TYPE_UINT32, &major,
+                                   DBUS_TYPE_UINT32, &minor,
+                                   DBUS_TYPE_UNIX_FD, &fd,
+                                   DBUS_TYPE_INVALID)) {
+            LogMessage(X_ERROR, "systemd-logind: ResumeDevice: %s\n",
+                       error.message);
+            dbus_error_free(&error);
+            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+        }
+    } else
+        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+    LogMessage(X_INFO, "systemd-logind: got %s for %u:%u\n",
+               pause ? "pause" : "resume", major, minor);
+
+    pdev = xf86_find_platform_device_by_devnum(major, minor);        
+    if (!pdev)
+        pInfo = systemd_logind_find_info_ptr_by_devnum(major, minor);
+    if (!pdev && !pInfo) {
+        LogMessage(X_WARNING, "systemd-logind: could not find dev %u:%u\n",
+                   major, minor);
+        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+    }
+
+    if (pause) {
+        /* Our VT_PROCESS usage guarantees we've already given up the vt */
+        info->active = info->vt_active = FALSE;
+        /* Note the actual vtleave has already been handled by xf86Events.c */
+        if (pdev)
+            pdev->flags |= XF86_PDEV_PAUSED;
+        else {
+            close(pInfo->fd);
+            pInfo->fd = -1;
+            pInfo->options = xf86ReplaceIntOption(pInfo->options, "fd", -1);
+        }
+        if (ack)
+            systemd_logind_ack_pause(info, major, minor);
+    }
+    else {
+        /* info->vt_active gets set by systemd_logind_vtenter() */
+        info->active = TRUE;
+
+        if (pdev) {
+            pdev->flags &= ~XF86_PDEV_PAUSED;
+            systemd_logind_vtenter();
+        }
+        else {
+            pInfo->fd = fd;
+            pInfo->options = xf86ReplaceIntOption(pInfo->options, "fd", fd);
+            if (info->vt_active)
+                xf86EnableInputDeviceForVTSwitch(pInfo);
+        }
+    }
+    return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static void
+connect_hook(DBusConnection *connection, void *data)
+{
+    struct systemd_logind_info *info = data;
+    DBusError error;
+    DBusMessage *msg = NULL;
+    DBusMessage *reply = NULL;
+    dbus_int32_t arg;
+    char *session = NULL;
+
+    dbus_error_init(&error);
+
+    msg = dbus_message_new_method_call("org.freedesktop.login1",
+            "/org/freedesktop/login1", "org.freedesktop.login1.Manager",
+            "GetSessionByPID");
+    if (!msg) {
+        LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+        goto cleanup;
+    }
+
+    arg = getpid();
+    if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, &arg,
+                                  DBUS_TYPE_INVALID)) {
+        LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+        goto cleanup;
+    }
+
+    reply = dbus_connection_send_with_reply_and_block(connection, msg,
+                                                      DBUS_TIMEOUT, &error);
+    if (!reply) {
+        LogMessage(X_ERROR, "systemd-logind: failed to get session: %s\n",
+                   error.message);
+        goto cleanup;
+    }
+    dbus_message_unref(msg);
+
+    if (!dbus_message_get_args(reply, &error, DBUS_TYPE_OBJECT_PATH, &session,
+                               DBUS_TYPE_INVALID)) {
+        LogMessage(X_ERROR, "systemd-logind: GetSessionByPID: %s\n",
+                   error.message);
+        goto cleanup;
+    }
+    session = XNFstrdup(session);
+
+    dbus_message_unref(reply);
+    reply = NULL;
+
+
+    msg = dbus_message_new_method_call("org.freedesktop.login1",
+            session, "org.freedesktop.login1.Session", "TakeControl");
+    if (!msg) {
+        LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+        goto cleanup;
+    }
+
+    arg = FALSE; /* Don't forcibly take over over the session */
+    if (!dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &arg,
+                                  DBUS_TYPE_INVALID)) {
+        LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+        goto cleanup;
+    }
+
+    reply = dbus_connection_send_with_reply_and_block(connection, msg,
+                                                      DBUS_TIMEOUT, &error);
+    if (!reply) {
+        LogMessage(X_ERROR, "systemd-logind: TakeControl failed: %s\n",
+                   error.message);
+        goto cleanup;
+    }
+
+    /*
+     * HdG: This is not useful with systemd <= 208 since the signal only
+     * contains invalidated property names there, rather than property, val
+     * pairs as it should.  Instead we just use the first resume / pause now.
+     */
+#if 0
+    snprintf(match, sizeof(match),
+        "type='signal',sender='org.freedesktop.login1',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged',path='%s'",
+        session);
+    dbus_bus_add_match(connection, match, &error);
+    if (dbus_error_is_set(&error)) {
+        LogMessage(X_ERROR, "systemd-logind: could not add match: %s\n",
+                   error.message);
+        goto cleanup;
+    }
+#endif
+
+    if (!dbus_connection_add_filter(connection, message_filter, info, NULL)) {
+        LogMessage(X_ERROR, "systemd-logind: could not add filter: %s\n",
+                   error.message);
+        goto cleanup;
+    }
+
+    LogMessage(X_INFO, "systemd-logind: took control of session %s\n",
+               session);
+    info->conn = connection;
+    info->session = session;
+    info->vt_active = info->active = TRUE; /* The server owns the vt during init */
+    session = NULL;
+
+cleanup:
+    free(session);
+    if (msg)
+        dbus_message_unref(msg);
+    if (reply)
+        dbus_message_unref(reply);
+    dbus_error_free(&error);
+}
+
+static void
+systemd_logind_release_control(struct systemd_logind_info *info)
+{
+    DBusError error;
+    DBusMessage *msg = NULL;
+    DBusMessage *reply = NULL;
+
+    dbus_error_init(&error);
+
+    msg = dbus_message_new_method_call("org.freedesktop.login1",
+            info->session, "org.freedesktop.login1.Session", "ReleaseControl");
+    if (!msg) {
+        LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+        goto cleanup;
+    }
+
+    reply = dbus_connection_send_with_reply_and_block(info->conn, msg,
+                                                      DBUS_TIMEOUT, &error);
+    if (!reply) {
+        LogMessage(X_ERROR, "systemd-logind: ReleaseControl failed: %s\n",
+                   error.message);
+        goto cleanup;
+    }
+
+cleanup:
+    if (msg)
+        dbus_message_unref(msg);
+    if (reply)
+        dbus_message_unref(reply);
+    dbus_error_free(&error);
+}
+
+static void
+disconnect_hook(void *data)
+{
+    struct systemd_logind_info *info = data;
+
+    free(info->session);
+    info->session = NULL;
+    info->conn = NULL;
+}
+
+static struct dbus_core_hook core_hook = {
+    .connect = connect_hook,
+    .disconnect = disconnect_hook,
+    .data = &logind_info,
+};
+
+int
+systemd_logind_init(void)
+{
+    return dbus_core_add_hook(&core_hook);
+}
+
+void
+systemd_logind_fini(void)
+{
+    if (logind_info.session)
+        systemd_logind_release_control(&logind_info);
+
+    dbus_core_remove_hook(&core_hook);
+}
diff --git a/include/Makefile.am b/include/Makefile.am
index fa6da00..6578038 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -72,4 +72,5 @@ EXTRA_DIST = 	\
 	dix-config-apple-verbatim.h \
 	dixfontstubs.h eventconvert.h eventstr.h inpututils.h \
 	protocol-versions.h \
+	systemd-logind.h \
 	xsha1.h
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index 7c77956..3865d5e 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -420,6 +420,9 @@
 /* Support HAL for hotplug */
 #undef CONFIG_HAL
 
+/* Enable systemd-logind integration */
+#undef SYSTEMD_LOGIND 1
+
 /* Have a monotonic clock from clock_gettime() */
 #undef MONOTONIC_CLOCK
 
diff --git a/include/systemd-logind.h b/include/systemd-logind.h
new file mode 100644
index 0000000..8b09081
--- /dev/null
+++ b/include/systemd-logind.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright © 2013 Red Hat, Inc.
+ *
+ * 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: Hans de Goede <hdegoede at redhat.com>
+ */
+
+#ifndef SYSTEMD_LOGIND_H
+#define SYSTEMD_LOGIND_H
+
+#ifdef SYSTEMD_LOGIND
+int systemd_logind_init(void);
+void systemd_logind_fini(void);
+int systemd_logind_take_fd(int major, int minor, const char *path, Bool *paus);
+void systemd_logind_release_fd(int major, int minor);
+int systemd_logind_controls_session(void);
+void systemd_logind_vtenter(void);
+#else
+#define systemd_logind_init()
+#define systemd_logind_fini()
+#define systemd_logind_take_fd(major, minor, path) -1
+#define systemd_logind_release_fd(dev)
+#define systemd_logind_controls_session() 0
+#define systemd_logind_vtenter()
+#endif
+
+#endif
commit 5fb641a29bfb4a33da964e1e9af523f3472015c6
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Mon Jan 13 12:03:46 2014 +0100

    hotplug: Extend OdevAttributes for server-managed fd support
    
    With systemd-logind support, the xserver, rather than the drivers will be
    responsible for opening/closing the fd for drm nodes.
    
    This commit adds a fd member to OdevAttributes to store the fd to pass it
    along to the driver.
    
    systemd-logind tracks devices by their chardev major + minor numbers, so
    also add OdevAttributes to store the major and minor.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Dave Airlie <airlied at redhat.com>

diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c
index 97d606a..e1d7bd0 100644
--- a/hw/xfree86/common/xf86platformBus.c
+++ b/hw/xfree86/common/xf86platformBus.c
@@ -128,6 +128,20 @@ xf86_get_platform_device_unowned(int index)
         TRUE : FALSE;
 }
 
+struct xf86_platform_device *
+xf86_find_platform_device_by_devnum(int major, int minor)
+{
+    int i, attr_major, attr_minor;
+
+    for (i = 0; i < xf86_num_platform_devices; i++) {
+        attr_major = xf86_get_platform_int_attrib(i, ODEV_ATTRIB_MAJOR, 0);
+        attr_minor = xf86_get_platform_int_attrib(i, ODEV_ATTRIB_MINOR, 0);
+        if (attr_major == major && attr_minor == minor)
+            return &xf86_platform_devices[i];
+    }
+    return NULL;
+}
+
 /*
  * xf86IsPrimaryPlatform() -- return TRUE if primary device
  * is a platform device and it matches this one.
diff --git a/hw/xfree86/common/xf86platformBus.h b/hw/xfree86/common/xf86platformBus.h
index 9a49260..3e27d34 100644
--- a/hw/xfree86/common/xf86platformBus.h
+++ b/hw/xfree86/common/xf86platformBus.h
@@ -35,6 +35,7 @@ struct xf86_platform_device {
 
 /* xf86_platform_device flags */
 #define XF86_PDEV_UNOWNED       0x01
+#define XF86_PDEV_SERVER_FD     0x02
 
 #ifdef XSERVER_PLATFORM_BUS
 int xf86platformProbe(void);
diff --git a/include/hotplug.h b/include/hotplug.h
index 0e78721..1d9364e 100644
--- a/include/hotplug.h
+++ b/include/hotplug.h
@@ -78,6 +78,12 @@ config_odev_free_attributes(struct OdevAttributes *attribs);
 #define ODEV_ATTRIB_SYSPATH 2
 /* DRI-style bus id */
 #define ODEV_ATTRIB_BUSID 3
+/* Server managed FD */
+#define ODEV_ATTRIB_FD 4
+/* Major number of the device node pointed to by ODEV_ATTRIB_PATH */
+#define ODEV_ATTRIB_MAJOR 5
+/* Minor number of the device node pointed to by ODEV_ATTRIB_PATH */
+#define ODEV_ATTRIB_MINOR 6
 
 typedef void (*config_odev_probe_proc_ptr)(struct OdevAttributes *attribs);
 void config_odev_probe(config_odev_probe_proc_ptr probe_callback);
@@ -88,4 +94,8 @@ void DeleteGPUDeviceRequest(struct OdevAttributes *attribs);
 #endif
 
 #define ServerIsNotSeat0() (SeatId && strcmp(SeatId, "seat0"))
+
+struct xf86_platform_device *
+xf86_find_platform_device_by_devnum(int major, int minor);
+
 #endif                          /* HOTPLUG_H */
commit a8d802cb019da0549da57576ba0cc2cef1c8a98c
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Sun Feb 2 13:54:33 2014 +0100

    OdevAttribute: Remove unowned flag from OdevAttributes head
    
    The OdevAttributes struct should just be a head of the attributes list, and
    not contain various unrelated flags. Instead add a flags field to
    struct xf86_platform_device and use that.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Dave Airlie <airlied at redhat.com>

diff --git a/hw/xfree86/common/xf86Module.h b/hw/xfree86/common/xf86Module.h
index 96ac3b0..e8c24f2 100644
--- a/hw/xfree86/common/xf86Module.h
+++ b/hw/xfree86/common/xf86Module.h
@@ -80,7 +80,7 @@ typedef enum {
  * mask is 0xFFFF0000.
  */
 #define ABI_ANSIC_VERSION	SET_ABI_VERSION(0, 4)
-#define ABI_VIDEODRV_VERSION	SET_ABI_VERSION(15, 0)
+#define ABI_VIDEODRV_VERSION	SET_ABI_VERSION(16, 0)
 #define ABI_XINPUT_VERSION	SET_ABI_VERSION(21, 0)
 #define ABI_EXTENSION_VERSION	SET_ABI_VERSION(8, 0)
 #define ABI_FONT_VERSION	SET_ABI_VERSION(0, 6)
diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c
index 7a9600a..97d606a 100644
--- a/hw/xfree86/common/xf86platformBus.c
+++ b/hw/xfree86/common/xf86platformBus.c
@@ -55,7 +55,7 @@ int xf86_num_platform_devices;
 static struct xf86_platform_device *xf86_platform_devices;
 
 int
-xf86_add_platform_device(struct OdevAttributes *attribs)
+xf86_add_platform_device(struct OdevAttributes *attribs, Bool unowned)
 {
     xf86_platform_devices = xnfrealloc(xf86_platform_devices,
                                    (sizeof(struct xf86_platform_device)
@@ -63,6 +63,8 @@ xf86_add_platform_device(struct OdevAttributes *attribs)
 
     xf86_platform_devices[xf86_num_platform_devices].attribs = attribs;
     xf86_platform_devices[xf86_num_platform_devices].pdev = NULL;
+    xf86_platform_devices[xf86_num_platform_devices].flags =
+        unowned ? XF86_PDEV_UNOWNED : 0;
 
     xf86_num_platform_devices++;
     return 0;
@@ -122,7 +124,8 @@ xf86_get_platform_device_int_attrib(struct xf86_platform_device *device, int att
 Bool
 xf86_get_platform_device_unowned(int index)
 {
-    return xf86_platform_devices[index].attribs->unowned;
+    return (xf86_platform_devices[index].flags & XF86_PDEV_UNOWNED) ?
+        TRUE : FALSE;
 }
 
 /*
@@ -529,10 +532,10 @@ void xf86platformVTProbe(void)
     int i;
 
     for (i = 0; i < xf86_num_platform_devices; i++) {
-        if (xf86_platform_devices[i].attribs->unowned == FALSE)
+        if (!(xf86_platform_devices[i].flags & XF86_PDEV_UNOWNED))
             continue;
 
-        xf86_platform_devices[i].attribs->unowned = FALSE;
+        xf86_platform_devices[i].flags &= ~XF86_PDEV_UNOWNED;
         xf86PlatformReprobeDevice(i, xf86_platform_devices[i].attribs);
     }
 }
diff --git a/hw/xfree86/common/xf86platformBus.h b/hw/xfree86/common/xf86platformBus.h
index d764026..9a49260 100644
--- a/hw/xfree86/common/xf86platformBus.h
+++ b/hw/xfree86/common/xf86platformBus.h
@@ -30,8 +30,12 @@ struct xf86_platform_device {
     struct OdevAttributes *attribs;
     /* for PCI devices */
     struct pci_device *pdev;
+    int flags;
 };
 
+/* xf86_platform_device flags */
+#define XF86_PDEV_UNOWNED       0x01
+
 #ifdef XSERVER_PLATFORM_BUS
 int xf86platformProbe(void);
 int xf86platformProbeDev(DriverPtr drvp);
@@ -43,7 +47,7 @@ xf86_get_platform_attrib(int index, int attrib_id);
 extern int
 xf86_get_platform_int_attrib(int index, int attrib_id, int def);
 extern int
-xf86_add_platform_device(struct OdevAttributes *attribs);
+xf86_add_platform_device(struct OdevAttributes *attribs, Bool unowned);
 extern int
 xf86_remove_platform_device(int dev_index);
 extern Bool
diff --git a/hw/xfree86/os-support/linux/lnx_platform.c b/hw/xfree86/os-support/linux/lnx_platform.c
index 4317209..f4c4d12 100644
--- a/hw/xfree86/os-support/linux/lnx_platform.c
+++ b/hw/xfree86/os-support/linux/lnx_platform.c
@@ -44,7 +44,7 @@ get_drm_info(struct OdevAttributes *attribs, char *path, int delayed_index)
 
     /* for a delayed probe we've already added the device */
     if (delayed_index == -1) {
-            xf86_add_platform_device(attribs);
+            xf86_add_platform_device(attribs, FALSE);
             delayed_index = xf86_num_platform_devices - 1;
     }
 
@@ -142,8 +142,7 @@ xf86PlatformDeviceProbe(struct OdevAttributes *attribs)
     if (!xf86VTOwner()) {
             /* if we don't currently own the VT then don't probe the device,
                just mark it as unowned for later use */
-            attribs->unowned = TRUE;
-            xf86_add_platform_device(attribs);
+            xf86_add_platform_device(attribs, TRUE);
             return;
     }
 
diff --git a/include/hotplug.h b/include/hotplug.h
index 4657669..0e78721 100644
--- a/include/hotplug.h
+++ b/include/hotplug.h
@@ -46,7 +46,6 @@ struct OdevAttribute {
 
 struct OdevAttributes {
     struct xorg_list list;
-    Bool unowned;
 };
 
 struct OdevAttributes *
commit bc9d17fb566d57eabe4a3372773654fcf6ae5b44
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Sun Feb 2 15:28:31 2014 +0100

    OdevAttribute: Add support for integer attributes
    
    Add a couple of new functions for dealing with storing integer values into
    OdevAttributes.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Dave Airlie <airlied at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/config/config.c b/config/config.c
index 776f1d8..ea2f744 100644
--- a/config/config.c
+++ b/config/config.c
@@ -172,6 +172,26 @@ config_odev_add_attribute(struct OdevAttributes *attribs, int attrib,
     oa->attrib_id = attrib;
     free(oa->attrib_name);
     oa->attrib_name = strdup(attrib_name);
+    oa->attrib_type = ODEV_ATTRIB_STRING;
+    xorg_list_append(&oa->member, &attribs->list);
+    return TRUE;
+}
+
+Bool
+config_odev_add_int_attribute(struct OdevAttributes *attribs, int attrib,
+                              int attrib_value)
+{
+    struct OdevAttribute *oa;
+
+    oa = config_odev_find_attribute(attribs, attrib);
+    if (!oa)
+        oa = calloc(1, sizeof(struct OdevAttribute));
+    if (!oa)
+        return FALSE;
+
+    oa->attrib_id = attrib;
+    oa->attrib_value = attrib_value;
+    oa->attrib_type = ODEV_ATTRIB_INT;
     xorg_list_append(&oa->member, &attribs->list);
     return TRUE;
 }
@@ -185,9 +205,32 @@ config_odev_get_attribute(struct OdevAttributes *attribs, int attrib_id)
     if (!oa)
         return NULL;
 
+    if (oa->attrib_type != ODEV_ATTRIB_STRING) {
+        LogMessage(X_ERROR, "Error %s called for non string attrib %d\n",
+                   __func__, attrib_id);
+        return NULL;
+    }
     return oa->attrib_name;
 }
 
+int
+config_odev_get_int_attribute(struct OdevAttributes *attribs, int attrib_id, int def)
+{
+    struct OdevAttribute *oa;
+
+    oa = config_odev_find_attribute(attribs, attrib_id);
+    if (!oa)
+        return def;
+
+    if (oa->attrib_type != ODEV_ATTRIB_INT) {
+        LogMessage(X_ERROR, "Error %s called for non integer attrib %d\n",
+                   __func__, attrib_id);
+        return def;
+    }
+
+    return oa->attrib_value;
+}
+
 void
 config_odev_free_attributes(struct OdevAttributes *attribs)
 {
diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c
index 6d3816d..7a9600a 100644
--- a/hw/xfree86/common/xf86platformBus.c
+++ b/hw/xfree86/common/xf86platformBus.c
@@ -89,6 +89,12 @@ xf86_add_platform_device_attrib(int index, int attrib_id, char *attrib_name)
     return config_odev_add_attribute(device->attribs, attrib_id, attrib_name);
 }
 
+Bool
+xf86_add_platform_device_int_attrib(int index, int attrib_id, int attrib_value)
+{
+    return config_odev_add_int_attribute(xf86_platform_devices[index].attribs, attrib_id, attrib_value);
+}
+
 char *
 xf86_get_platform_attrib(int index, int attrib_id)
 {
@@ -101,6 +107,18 @@ xf86_get_platform_device_attrib(struct xf86_platform_device *device, int attrib_
     return config_odev_get_attribute(device->attribs, attrib_id);
 }
 
+int
+xf86_get_platform_int_attrib(int index, int attrib_id, int def)
+{
+    return config_odev_get_int_attribute(xf86_platform_devices[index].attribs, attrib_id, def);
+}
+
+int
+xf86_get_platform_device_int_attrib(struct xf86_platform_device *device, int attrib_id, int def)
+{
+    return config_odev_get_int_attribute(device->attribs, attrib_id, def);
+}
+
 Bool
 xf86_get_platform_device_unowned(int index)
 {
diff --git a/hw/xfree86/common/xf86platformBus.h b/hw/xfree86/common/xf86platformBus.h
index 4e17578..d764026 100644
--- a/hw/xfree86/common/xf86platformBus.h
+++ b/hw/xfree86/common/xf86platformBus.h
@@ -41,12 +41,16 @@ extern int xf86_num_platform_devices;
 extern char *
 xf86_get_platform_attrib(int index, int attrib_id);
 extern int
+xf86_get_platform_int_attrib(int index, int attrib_id, int def);
+extern int
 xf86_add_platform_device(struct OdevAttributes *attribs);
 extern int
 xf86_remove_platform_device(int dev_index);
 extern Bool
 xf86_add_platform_device_attrib(int index, int attrib_id, char *attrib_str);
 extern Bool
+xf86_add_platform_device_int_attrib(int index, int attrib_id, int attrib_value);
+extern Bool
 xf86_get_platform_device_unowned(int index);
 
 extern int
@@ -56,6 +60,8 @@ xf86platformRemoveDevice(int index);
 
 extern _X_EXPORT char *
 xf86_get_platform_device_attrib(struct xf86_platform_device *device, int attrib_id);
+extern _X_EXPORT int
+xf86_get_platform_device_int_attrib(struct xf86_platform_device *device, int attrib_id, int def);
 extern _X_EXPORT Bool
 xf86PlatformDeviceCheckBusID(struct xf86_platform_device *device, const char *busid);
 
diff --git a/include/hotplug.h b/include/hotplug.h
index ee7b7d7..4657669 100644
--- a/include/hotplug.h
+++ b/include/hotplug.h
@@ -32,10 +32,16 @@ extern _X_EXPORT void config_pre_init(void);
 extern _X_EXPORT void config_init(void);
 extern _X_EXPORT void config_fini(void);
 
+enum { ODEV_ATTRIB_STRING, ODEV_ATTRIB_INT };
+
 struct OdevAttribute {
     struct xorg_list member;
     int attrib_id;
-    char *attrib_name;
+    union {
+        char *attrib_name;
+        int attrib_value;
+    };
+    int attrib_type;
 };
 
 struct OdevAttributes {
@@ -56,6 +62,14 @@ config_odev_add_attribute(struct OdevAttributes *attribs, int attrib,
 char *
 config_odev_get_attribute(struct OdevAttributes *attribs, int attrib_id);
 
+Bool
+config_odev_add_int_attribute(struct OdevAttributes *attribs, int attrib,
+                              int attrib_value);
+
+int
+config_odev_get_int_attribute(struct OdevAttributes *attribs, int attrib,
+                              int def);
+
 void
 config_odev_free_attributes(struct OdevAttributes *attribs);
 
commit 350559dcdcd8b0de57801302e385e25debcb91f1
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Mon Feb 3 15:47:35 2014 +0100

    OdevAttribute: config_odev_add_attribute: replace existing values
    
    If an attribute already exists replace its value rather than adding a
    duplicate attribute with the new value to the list.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Dave Airlie <airlied at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/config/config.c b/config/config.c
index 088bd5a..776f1d8 100644
--- a/config/config.c
+++ b/config/config.c
@@ -163,11 +163,14 @@ config_odev_add_attribute(struct OdevAttributes *attribs, int attrib,
 {
     struct OdevAttribute *oa;
 
-    oa = malloc(sizeof(struct OdevAttribute));
+    oa = config_odev_find_attribute(attribs, attrib);
+    if (!oa)
+        oa = calloc(1, sizeof(struct OdevAttribute));
     if (!oa)
         return FALSE;
 
     oa->attrib_id = attrib;
+    free(oa->attrib_name);
     oa->attrib_name = strdup(attrib_name);
     xorg_list_append(&oa->member, &attribs->list);
     return TRUE;
commit 10c64e80569bbd35e97916a067f553cab27454b5
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Sun Feb 2 11:25:34 2014 +0100

    OdevAttribute: Add config_odev_get_attribute helper
    
    Add a config_odev_get_attribute helper, and replace the diy looping over all
    the attributes done in various places with calls to this helper.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Dave Airlie <airlied at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/config/config.c b/config/config.c
index 760cf19..088bd5a 100644
--- a/config/config.c
+++ b/config/config.c
@@ -145,6 +145,18 @@ config_odev_free_attribute_list(struct OdevAttributes *attribs)
     free(attribs);
 }
 
+static struct OdevAttribute *
+config_odev_find_attribute(struct OdevAttributes *attribs, int attrib_id)
+{
+    struct OdevAttribute *oa;
+
+    xorg_list_for_each_entry(oa, &attribs->list, member) {
+        if (oa->attrib_id == attrib_id)
+          return oa;
+    }
+    return NULL;
+}
+
 Bool
 config_odev_add_attribute(struct OdevAttributes *attribs, int attrib,
                           const char *attrib_name)
@@ -161,6 +173,18 @@ config_odev_add_attribute(struct OdevAttributes *attribs, int attrib,
     return TRUE;
 }
 
+char *
+config_odev_get_attribute(struct OdevAttributes *attribs, int attrib_id)
+{
+    struct OdevAttribute *oa;
+
+    oa = config_odev_find_attribute(attribs, attrib_id);
+    if (!oa)
+        return NULL;
+
+    return oa->attrib_name;
+}
+
 void
 config_odev_free_attributes(struct OdevAttributes *attribs)
 {
diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c
index 5875a91..6d3816d 100644
--- a/hw/xfree86/common/xf86platformBus.c
+++ b/hw/xfree86/common/xf86platformBus.c
@@ -92,26 +92,13 @@ xf86_add_platform_device_attrib(int index, int attrib_id, char *attrib_name)
 char *
 xf86_get_platform_attrib(int index, int attrib_id)
 {
-    struct xf86_platform_device *device = &xf86_platform_devices[index];
-    struct OdevAttribute *oa;
-
-    xorg_list_for_each_entry(oa, &device->attribs->list, member) {
-        if (oa->attrib_id == attrib_id)
-            return oa->attrib_name;
-    }
-    return NULL;
+    return config_odev_get_attribute(xf86_platform_devices[index].attribs, attrib_id);
 }
 
 char *
 xf86_get_platform_device_attrib(struct xf86_platform_device *device, int attrib_id)
 {
-    struct OdevAttribute *oa;
-
-    xorg_list_for_each_entry(oa, &device->attribs->list, member) {
-        if (oa->attrib_id == attrib_id)
-            return oa->attrib_name;
-    }
-    return NULL;
+    return config_odev_get_attribute(device->attribs, attrib_id);
 }
 
 Bool
diff --git a/hw/xfree86/os-support/linux/lnx_platform.c b/hw/xfree86/os-support/linux/lnx_platform.c
index 1865b31..4317209 100644
--- a/hw/xfree86/os-support/linux/lnx_platform.c
+++ b/hw/xfree86/os-support/linux/lnx_platform.c
@@ -118,17 +118,11 @@ xf86PlatformReprobeDevice(int index, struct OdevAttributes *attribs)
 void
 xf86PlatformDeviceProbe(struct OdevAttributes *attribs)
 {
-    struct OdevAttribute *attrib;
     int i;
     char *path = NULL;
     Bool ret;
 
-    xorg_list_for_each_entry(attrib, &attribs->list, member) {
-        if (attrib->attrib_id == ODEV_ATTRIB_PATH) {
-            path = attrib->attrib_name;
-            break;
-        }
-    }
+    path = config_odev_get_attribute(attribs, ODEV_ATTRIB_PATH);
     if (!path)
         goto out_free;
 
diff --git a/include/hotplug.h b/include/hotplug.h
index 29a22c4..ee7b7d7 100644
--- a/include/hotplug.h
+++ b/include/hotplug.h
@@ -53,6 +53,9 @@ Bool
 config_odev_add_attribute(struct OdevAttributes *attribs, int attrib,
                           const char *attrib_name);
 
+char *
+config_odev_get_attribute(struct OdevAttributes *attribs, int attrib_id);
+
 void
 config_odev_free_attributes(struct OdevAttributes *attribs);
 
commit 3346166a6596115421702c1f7e2732215674ab8e
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Mon Jan 13 11:57:38 2014 +0100

    xf86Xinput: Modify API for server-managed fd support
    
    With systemd-logind support, the xserver, rather than the drivers will be
    responsible for opening/closing the fd for input devices.
    
    This commit adds a new capabilities field to the InputDriverRec and a
    XI86_DRV_CAP_SERVER_FD flag for drivers to indicate that they support server
    managed fds.
    
    This commit adds a new XI86_SERVER_FD flag to indicate to drivers when the
    server is managing the fd and they should not open/close it. Note that even
    if drivers declare they support server managed fds there is no guarantee they
    will actually get them.
    
    Since this changes the input driver ABI, this commit bumps it.
    
    systemd-logind tracks devices by their chardev major + minor numbers, since
    we are breaking ABI anyways also add major and minor fields for easy storage /
    retrieval of these.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/common/xf86Module.h b/hw/xfree86/common/xf86Module.h
index b6ec19d..96ac3b0 100644
--- a/hw/xfree86/common/xf86Module.h
+++ b/hw/xfree86/common/xf86Module.h
@@ -81,7 +81,7 @@ typedef enum {
  */
 #define ABI_ANSIC_VERSION	SET_ABI_VERSION(0, 4)
 #define ABI_VIDEODRV_VERSION	SET_ABI_VERSION(15, 0)
-#define ABI_XINPUT_VERSION	SET_ABI_VERSION(20, 0)
+#define ABI_XINPUT_VERSION	SET_ABI_VERSION(21, 0)
 #define ABI_EXTENSION_VERSION	SET_ABI_VERSION(8, 0)
 #define ABI_FONT_VERSION	SET_ABI_VERSION(0, 6)
 
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index f6f2b90..7d13f75 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -949,6 +949,12 @@ NewInputDeviceRequest(InputOption *options, InputAttributes * attrs,
                 goto unwind;
             }
         }
+
+        if (strcmp(key, "major") == 0)
+            pInfo->major = atoi(value);
+
+        if (strcmp(key, "minor") == 0)
+            pInfo->minor = atoi(value);
     }
 
     nt_list_for_each_entry(option, options, list.next) {
diff --git a/hw/xfree86/common/xf86Xinput.h b/hw/xfree86/common/xf86Xinput.h
index b6d1251..784e14e 100644
--- a/hw/xfree86/common/xf86Xinput.h
+++ b/hw/xfree86/common/xf86Xinput.h
@@ -64,6 +64,10 @@
 /* 0x08 is reserved for legacy XI86_SEND_DRAG_EVENTS, do not use for now */
 /* server-internal only */
 #define XI86_DEVICE_DISABLED    0x10    /* device was disabled before vt switch */
+#define XI86_SERVER_FD		0x20	/* fd is managed by xserver */
+
+/* Input device driver capabilities */
+#define XI86_DRV_CAP_SERVER_FD	0x01
 
 /* This holds the input driver entry and module information. */
 typedef struct _InputDriverRec {
@@ -76,6 +80,7 @@ typedef struct _InputDriverRec {
                     struct _InputInfoRec * pInfo, int flags);
     void *module;
     const char **default_options;
+    int capabilities;
 } InputDriverRec, *InputDriverPtr;
 
 /* This is to input devices what the ScrnInfoRec is to screens. */
@@ -96,6 +101,8 @@ typedef struct _InputInfoRec {
       int *valuators, int first_valuator, int num_valuators);
 
     int fd;
+    int major;
+    int minor;
     DeviceIntPtr dev;
     void *private;
     const char *type_name;
commit 6b79f28f5cb259f2168ecc3034fe2161e969bf7d
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Wed Jan 22 11:32:56 2014 +0100

    linux: xf86OpenConsole: Don't detach from controlling tty when it is our vt
    
    Detaching from our controlling tty makes little sense when it is the same
    as the vt we're asked to run on. So automatically assume -keeptty in this case.
    
    This is useful to do because when not running as root the server can only make
    various VT related ioctls when it does not detach from the tty.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/os-support/linux/lnx_init.c b/hw/xfree86/os-support/linux/lnx_init.c
index 9ccf261..85709c6 100644
--- a/hw/xfree86/os-support/linux/lnx_init.c
+++ b/hw/xfree86/os-support/linux/lnx_init.c
@@ -79,9 +79,10 @@ switch_to(int vt, const char *from)
 void
 xf86OpenConsole(void)
 {
-    int i, fd = -1, ret;
+    int i, fd = -1, ret, current_vt = -1;
     struct vt_mode VT;
     struct vt_stat vts;
+    struct stat st;
     MessageType from = X_PROBED;
     const char *tty0[] = { "/dev/tty0", "/dev/vc/0", NULL };
     const char *vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL };
@@ -126,6 +127,22 @@ xf86OpenConsole(void)
 
         xf86Msg(from, "using VT number %d\n\n", xf86Info.vtno);
 
+        /* Some of stdin / stdout / stderr maybe redirected to a file */
+        for (i = STDIN_FILENO; i <= STDERR_FILENO; i++) {
+            ret = fstat(i, &st);
+            if (ret == 0 && S_ISCHR(st.st_mode) && major(st.st_rdev) == 4) {
+                current_vt = minor(st.st_rdev);
+                break;
+            }
+        }
+
+        if (!KeepTty && current_vt == xf86Info.vtno) {
+            xf86Msg(X_PROBED,
+                    "controlling tty is VT number %d, auto-enabling KeepTty\n",
+                    current_vt);
+            KeepTty = TRUE;
+        }
+
         if (!KeepTty) {
             pid_t ppid = getppid();
             pid_t ppgid;
commit 701b7ab34984b0f9f0c357b0ff8b53c5132c6324
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Thu Jan 16 10:37:28 2014 +0100

    linux: xf86OpenConsole remove root-rights check for keeptty option
    
    There is no reason why keeptty cannot be used without root-rights.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/os-support/linux/lnx_init.c b/hw/xfree86/os-support/linux/lnx_init.c
index 46438e6..9ccf261 100644
--- a/hw/xfree86/os-support/linux/lnx_init.c
+++ b/hw/xfree86/os-support/linux/lnx_init.c
@@ -87,12 +87,6 @@ xf86OpenConsole(void)
     const char *vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL };
 
     if (serverGeneration == 1) {
-
-        /* when KeepTty check if we're run with euid==0 */
-        if (KeepTty && geteuid() != 0)
-            FatalError("xf86OpenConsole:"
-                       " Server must be suid root for option \"KeepTTY\"\n");
-
         /*
          * setup the virtual terminal manager
          */


More information about the xorg-commit mailing list