summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Chalupa <mchqwerty@gmail.com>2015-08-31 18:03:53 +0200
committerRay Strode <rstrode@redhat.com>2015-09-07 08:42:21 -0400
commit79f755bf0fa03eac3687184670c1f8142d3160a6 (patch)
tree911d5fe76ac1c8318a030ceb04a60970561a86da
parent1845bfe1b6235ed80e2737078843ffc5feb7c7b8 (diff)
downloadmutter-79f755bf0fa03eac3687184670c1f8142d3160a6.tar.gz
launcher: find the right drm device
Instead of hard-coding /dev/dri/card0, find the device that has boot_vga flag set or has been explicitly assigned a seat id other than seat0 https://bugzilla.gnome.org/show_bug.cgi?id=753434
-rw-r--r--src/backends/native/meta-launcher.c108
1 files changed, 104 insertions, 4 deletions
diff --git a/src/backends/native/meta-launcher.c b/src/backends/native/meta-launcher.c
index 616c09238..5ceeda7da 100644
--- a/src/backends/native/meta-launcher.c
+++ b/src/backends/native/meta-launcher.c
@@ -37,6 +37,7 @@
#include <unistd.h>
#include <systemd/sd-login.h>
+#include <gudev/gudev.h>
#include "dbus-utils.h"
#include "meta-dbus-login1.h"
@@ -276,17 +277,95 @@ on_active_changed (Login1Session *session,
sync_active (self);
}
+static gchar *
+get_primary_gpu_path (const gchar *seat_name)
+{
+ const gchar *subsystems[] = {"drm", NULL};
+ gchar *path = NULL;
+ GList *devices, *tmp;
+
+ GUdevClient *gudev_client = g_udev_client_new (subsystems);
+ GUdevEnumerator *enumerator = g_udev_enumerator_new (gudev_client);
+
+ g_udev_enumerator_add_match_name (enumerator, "card*");
+ g_udev_enumerator_add_match_tag (enumerator, "seat");
+
+ devices = g_udev_enumerator_execute (enumerator);
+ if (!devices)
+ goto out;
+
+ for (tmp = devices; tmp != NULL; tmp = tmp->next)
+ {
+ GUdevDevice *pci_device;
+ GUdevDevice *dev = tmp->data;
+ gint boot_vga;
+ const gchar *device_seat;
+
+ /* filter out devices that are not character device, like card0-VGA-1 */
+ if (g_udev_device_get_device_type (dev) != G_UDEV_DEVICE_TYPE_CHAR)
+ continue;
+
+ device_seat = g_udev_device_get_property (dev, "ID_SEAT");
+ if (!device_seat)
+ {
+ /* when ID_SEAT is not set, it means seat0 */
+ device_seat = "seat0";
+ }
+ else if (g_strcmp0 (device_seat, "seat0") != 0)
+ {
+ /* if the device has been explicitly assigned other seat
+ * than seat0, it is probably the right device to use */
+ path = g_strdup (g_udev_device_get_device_file (dev));
+ break;
+ }
+
+ /* skip devices that do not belong to our seat */
+ if (g_strcmp0 (seat_name, device_seat))
+ continue;
+
+ pci_device = g_udev_device_get_parent_with_subsystem (dev, "pci", NULL);
+ if (!pci_device)
+ continue;
+
+ /* get value of boot_vga attribute or 0 if the device has no boot_vga */
+ boot_vga = g_udev_device_get_sysfs_attr_as_int (pci_device, "boot_vga");
+ g_object_unref (pci_device);
+
+ if (boot_vga == 1)
+ {
+ /* found the boot_vga device */
+ path = g_strdup (g_udev_device_get_device_file (dev));
+ break;
+ }
+ }
+
+ g_list_free_full (devices, g_object_unref);
+
+out:
+ g_object_unref (enumerator);
+ g_object_unref (gudev_client);
+
+ return path;
+}
+
static void
get_kms_fd (Login1Session *session_proxy,
+ const gchar *seat_id,
int *fd_out)
{
int major, minor;
int fd;
+ gchar *path;
GError *error = NULL;
- /* XXX -- use udev to find the DRM master device */
- if (!get_device_info_from_path ("/dev/dri/card0", &major, &minor))
- g_error ("Could not stat /dev/dri/card0: %m");
+ path = get_primary_gpu_path (seat_id);
+ if (!path)
+ g_error ("could not find drm kms device");
+
+ if (!get_device_info_from_path (path, &major, &minor))
+ g_error ("Could not stat %s: %m", path);
+
+ g_free (path);
if (!take_device (session_proxy, major, minor, &fd, NULL, &error))
report_error_and_die ("Could not open DRM device", error);
@@ -294,11 +373,27 @@ get_kms_fd (Login1Session *session_proxy,
*fd_out = fd;
}
+static gchar *
+get_seat_id (void)
+{
+ char *session_id, *seat_id = NULL;
+
+ if (sd_pid_get_session (0, &session_id) < 0)
+ return NULL;
+
+ /* on error the seat_id will remain NULL */
+ sd_session_get_seat (session_id, &seat_id);
+ free (session_id);
+
+ return seat_id;
+}
+
MetaLauncher *
meta_launcher_new (void)
{
MetaLauncher *self = NULL;
Login1Session *session_proxy;
+ char *seat_id;
GError *error = NULL;
int kms_fd;
@@ -306,7 +401,12 @@ meta_launcher_new (void)
if (!login1_session_call_take_control_sync (session_proxy, FALSE, NULL, &error))
report_error_and_die ("Could not take control", error);
- get_kms_fd (session_proxy, &kms_fd);
+ seat_id = get_seat_id ();
+ if (!seat_id)
+ g_error ("Failed getting seat id");
+
+ get_kms_fd (session_proxy, seat_id, &kms_fd);
+ free (seat_id);
self = g_slice_new0 (MetaLauncher);
self->session_proxy = session_proxy;