mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2025-10-29 05:40:12 -04:00
backend/drm: populate wlr_output.port
This commit is contained in:
parent
85ab6b7eb2
commit
ade7fee5d2
5 changed files with 141 additions and 1 deletions
|
|
@ -13,6 +13,7 @@
|
|||
#include <xf86drm.h>
|
||||
#include "backend/drm/drm.h"
|
||||
#include "backend/drm/fb.h"
|
||||
#include "backend/drm/util.h"
|
||||
#include "render/drm_format_set.h"
|
||||
|
||||
struct wlr_drm_backend *get_drm_backend_from_backend(
|
||||
|
|
@ -227,6 +228,9 @@ struct wlr_backend *wlr_drm_backend_create(struct wlr_session *session,
|
|||
wlr_log(WLR_INFO, "Initializing DRM backend for %s (%s)", name, version->name);
|
||||
drmFreeVersion(version);
|
||||
|
||||
drmDevice *dev_info = NULL;
|
||||
drmGetDevice2(dev->fd, 0, &dev_info);
|
||||
|
||||
struct wlr_drm_backend *drm = calloc(1, sizeof(*drm));
|
||||
if (!drm) {
|
||||
wlr_log_errno(WLR_ERROR, "Allocation failed");
|
||||
|
|
@ -245,6 +249,9 @@ struct wlr_backend *wlr_drm_backend_create(struct wlr_session *session,
|
|||
drm->fd = dev->fd;
|
||||
drm->name = name;
|
||||
|
||||
drm->bus = get_drm_bus_str(dev_info);
|
||||
drmFreeDevice(&dev_info);
|
||||
|
||||
if (parent != NULL) {
|
||||
drm->parent = get_drm_backend_from_backend(parent);
|
||||
|
||||
|
|
|
|||
|
|
@ -1593,6 +1593,92 @@ static drmModeModeInfo *connector_get_current_mode(struct wlr_drm_connector *wlr
|
|||
}
|
||||
}
|
||||
|
||||
static struct wlr_drm_connector *find_drm_connector_by_id(struct wlr_drm_backend *drm, uint32_t id) {
|
||||
struct wlr_drm_connector *conn = NULL;
|
||||
wl_list_for_each(conn, &drm->connectors, link) {
|
||||
if (conn->id == id) {
|
||||
return conn;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool connector_write_root_port(struct wlr_drm_connector *wlr_conn, FILE *f) {
|
||||
struct wlr_drm_backend *drm = wlr_conn->backend;
|
||||
|
||||
size_t seq_num = 0;
|
||||
struct wlr_drm_connector *c;
|
||||
wl_list_for_each(c, &drm->connectors, link) {
|
||||
seq_num++;
|
||||
if (c == wlr_conn) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return fprintf(f, "%s/connector-%zu", drm->bus, seq_num) > 0;
|
||||
}
|
||||
|
||||
static bool connector_write_port(struct wlr_drm_connector *wlr_conn, FILE *f);
|
||||
|
||||
static bool connector_write_nested_port(struct wlr_drm_connector *wlr_conn, FILE *f) {
|
||||
struct wlr_drm_backend *drm = wlr_conn->backend;
|
||||
bool ok = false;
|
||||
|
||||
size_t size = 0;
|
||||
void *path_prop_data = get_drm_prop_blob(drm->fd, wlr_conn->id, wlr_conn->props.path, &size);
|
||||
if (path_prop_data == NULL) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
uint32_t parent_conn_id = 0;
|
||||
const char *child_path = NULL;
|
||||
if (!parse_dp_mst_path(path_prop_data, &parent_conn_id, &child_path)) {
|
||||
goto out;
|
||||
}
|
||||
struct wlr_drm_connector *parent = find_drm_connector_by_id(drm, parent_conn_id);
|
||||
if (parent == NULL) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!connector_write_port(parent, f)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
ok = fprintf(f, "/mst-%s", child_path) > 0;
|
||||
|
||||
out:
|
||||
free(path_prop_data);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static bool connector_write_port(struct wlr_drm_connector *wlr_conn, FILE *f) {
|
||||
if (wlr_conn->props.path != 0) {
|
||||
return connector_write_nested_port(wlr_conn, f);
|
||||
} else {
|
||||
return connector_write_root_port(wlr_conn, f);
|
||||
}
|
||||
}
|
||||
|
||||
static char *connector_get_port(struct wlr_drm_connector *wlr_conn) {
|
||||
if (wlr_conn->backend->bus == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *str = NULL;
|
||||
size_t str_size = 0;
|
||||
FILE *f = open_memstream(&str, &str_size);
|
||||
if (f == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool ok = connector_write_port(wlr_conn, f);
|
||||
if (fclose(f) != 0 || !ok) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
static bool connect_drm_connector(struct wlr_drm_connector *wlr_conn,
|
||||
const drmModeConnector *drm_conn) {
|
||||
struct wlr_drm_backend *drm = wlr_conn->backend;
|
||||
|
|
@ -1720,6 +1806,9 @@ static bool connect_drm_connector(struct wlr_drm_connector *wlr_conn,
|
|||
wlr_output_set_description(output, description);
|
||||
|
||||
free(subconnector);
|
||||
|
||||
output->port = connector_get_port(wlr_conn);
|
||||
|
||||
wlr_conn->status = DRM_MODE_CONNECTED;
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -270,3 +270,44 @@ void generate_cvt_mode(drmModeModeInfo *mode, int hdisplay, int vdisplay,
|
|||
};
|
||||
snprintf(mode->name, sizeof(mode->name), "%dx%d", hdisplay, vdisplay);
|
||||
}
|
||||
|
||||
char *get_drm_bus_str(const drmDevice *dev) {
|
||||
char buf[128];
|
||||
switch (dev->bustype) {
|
||||
case DRM_BUS_PCI:;
|
||||
const drmPciBusInfo *pci = dev->businfo.pci;
|
||||
snprintf(buf, sizeof(buf), "pci-%04" PRIx16 ":%02" PRIx8 ":%02" PRIx8 ".%" PRIu8,
|
||||
pci->domain, pci->bus, pci->dev, pci->func);
|
||||
return strdup(buf);
|
||||
case DRM_BUS_PLATFORM:;
|
||||
const drmPlatformBusInfo *platform = dev->businfo.platform;
|
||||
size_t str_size = strlen("platform-") + strlen(platform->fullname) + 1;
|
||||
char *str = malloc(str_size);
|
||||
if (str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
snprintf(str, str_size, "platform-%s", platform->fullname);
|
||||
return str;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool parse_dp_mst_path(const char *path, uint32_t *parent_conn_id, const char **child_path) {
|
||||
const char prefix[] = "mst:";
|
||||
if (strncmp(path, prefix, strlen(prefix)) != 0) {
|
||||
return false;
|
||||
}
|
||||
path = &path[strlen(prefix)];
|
||||
|
||||
char *id_end;
|
||||
errno = 0;
|
||||
unsigned long id = strtoul(path, &id_end, 10);
|
||||
if (errno != 0 || id_end[0] != '-' || id > UINT32_MAX) {
|
||||
wlr_log(WLR_ERROR, "Malformed PATH DP-MST property: invalid parent connector ID");
|
||||
return false;
|
||||
}
|
||||
|
||||
*parent_conn_id = (uint32_t)id;
|
||||
*child_path = &id_end[1];
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ struct wlr_drm_backend {
|
|||
bool addfb2_modifiers;
|
||||
|
||||
int fd;
|
||||
char *name;
|
||||
char *name, *bus;
|
||||
struct wlr_device *dev;
|
||||
struct liftoff_device *liftoff;
|
||||
|
||||
|
|
|
|||
|
|
@ -38,4 +38,7 @@ void match_connectors_with_crtcs(size_t num_conns,
|
|||
size_t num_crtcs, const uint32_t prev_crtcs[static restrict num_crtcs],
|
||||
uint32_t new_crtcs[static restrict num_crtcs]);
|
||||
|
||||
char *get_drm_bus_str(const drmDevice *dev);
|
||||
bool parse_dp_mst_path(const char *path, uint32_t *parent_conn_id, const char **child_path);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue