aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/config
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/config')
-rw-r--r--xorg-server/config/config.c85
-rw-r--r--xorg-server/config/udev.c43
2 files changed, 123 insertions, 5 deletions
diff --git a/xorg-server/config/config.c b/xorg-server/config/config.c
index 760cf193a..732670038 100644
--- a/xorg-server/config/config.c
+++ b/xorg-server/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)
@@ -145,30 +147,111 @@ 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)
{
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);
+ 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;
+}
+
+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;
+
+ if (oa->attrib_type != ODEV_ATTRIB_STRING) {
+ LogMessage(X_ERROR, "Error %s called for non string attrib %d\n",
+ __FUNCTION__, 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",
+ __FUNCTION__, attrib_id);
+ return def;
+ }
+
+ return oa->attrib_value;
+}
+
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/xorg-server/config/udev.c b/xorg-server/config/udev.c
index 68ed34843..d70eeb48c 100644
--- a/xorg-server/config/udev.c
+++ b/xorg-server/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);
@@ -98,9 +112,14 @@ 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, NewGPUDeviceRequest);
+ config_udev_odev_setup_attribs(path, syspath, major(devnum),
+ minor(devnum), NewGPUDeviceRequest);
return;
}
#endif
@@ -153,6 +172,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 +291,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 +299,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 +452,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 +469,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 +511,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 +520,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);
}