mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-11-03 09:01:40 -05:00 
			
		
		
		
	Merge branch 'conn-port' into 'master'
Draft: output: add wlr_output.port See merge request wlroots/wlroots!3979
This commit is contained in:
		
						commit
						7dc492bde9
					
				
					 7 changed files with 143 additions and 1 deletions
				
			
		| 
						 | 
					@ -11,6 +11,7 @@
 | 
				
			||||||
#include <xf86drm.h>
 | 
					#include <xf86drm.h>
 | 
				
			||||||
#include "backend/drm/drm.h"
 | 
					#include "backend/drm/drm.h"
 | 
				
			||||||
#include "backend/drm/fb.h"
 | 
					#include "backend/drm/fb.h"
 | 
				
			||||||
 | 
					#include "backend/drm/util.h"
 | 
				
			||||||
#include "render/drm_format_set.h"
 | 
					#include "render/drm_format_set.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlr_drm_backend *get_drm_backend_from_backend(
 | 
					struct wlr_drm_backend *get_drm_backend_from_backend(
 | 
				
			||||||
| 
						 | 
					@ -225,6 +226,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);
 | 
						wlr_log(WLR_INFO, "Initializing DRM backend for %s (%s)", name, version->name);
 | 
				
			||||||
	drmFreeVersion(version);
 | 
						drmFreeVersion(version);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						drmDevice *dev_info = NULL;
 | 
				
			||||||
 | 
						drmGetDevice2(dev->fd, 0, &dev_info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct wlr_drm_backend *drm = calloc(1, sizeof(*drm));
 | 
						struct wlr_drm_backend *drm = calloc(1, sizeof(*drm));
 | 
				
			||||||
	if (!drm) {
 | 
						if (!drm) {
 | 
				
			||||||
		wlr_log_errno(WLR_ERROR, "Allocation failed");
 | 
							wlr_log_errno(WLR_ERROR, "Allocation failed");
 | 
				
			||||||
| 
						 | 
					@ -243,6 +247,9 @@ struct wlr_backend *wlr_drm_backend_create(struct wlr_session *session,
 | 
				
			||||||
	drm->fd = dev->fd;
 | 
						drm->fd = dev->fd;
 | 
				
			||||||
	drm->name = name;
 | 
						drm->name = name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						drm->bus = get_drm_bus_str(dev_info);
 | 
				
			||||||
 | 
						drmFreeDevice(&dev_info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (parent != NULL) {
 | 
						if (parent != NULL) {
 | 
				
			||||||
		drm->parent = get_drm_backend_from_backend(parent);
 | 
							drm->parent = get_drm_backend_from_backend(parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1603,6 +1603,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,
 | 
					static bool connect_drm_connector(struct wlr_drm_connector *wlr_conn,
 | 
				
			||||||
		const drmModeConnector *drm_conn) {
 | 
							const drmModeConnector *drm_conn) {
 | 
				
			||||||
	struct wlr_drm_backend *drm = wlr_conn->backend;
 | 
						struct wlr_drm_backend *drm = wlr_conn->backend;
 | 
				
			||||||
| 
						 | 
					@ -1745,6 +1831,9 @@ static bool connect_drm_connector(struct wlr_drm_connector *wlr_conn,
 | 
				
			||||||
	wlr_output_set_description(output, description);
 | 
						wlr_output_set_description(output, description);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	free(subconnector);
 | 
						free(subconnector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						output->port = connector_get_port(wlr_conn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wlr_conn->status = DRM_MODE_CONNECTED;
 | 
						wlr_conn->status = DRM_MODE_CONNECTED;
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -281,3 +281,44 @@ void generate_cvt_mode(drmModeModeInfo *mode, int hdisplay, int vdisplay,
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	snprintf(mode->name, sizeof(mode->name), "%dx%d", hdisplay, 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;
 | 
						bool addfb2_modifiers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int fd;
 | 
						int fd;
 | 
				
			||||||
	char *name;
 | 
						char *name, *bus;
 | 
				
			||||||
	struct wlr_device *dev;
 | 
						struct wlr_device *dev;
 | 
				
			||||||
	struct liftoff_device *liftoff;
 | 
						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],
 | 
						size_t num_crtcs, const uint32_t prev_crtcs[static restrict num_crtcs],
 | 
				
			||||||
	uint32_t new_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
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -186,6 +186,7 @@ struct wlr_output {
 | 
				
			||||||
	char *name;
 | 
						char *name;
 | 
				
			||||||
	char *description; // may be NULL
 | 
						char *description; // may be NULL
 | 
				
			||||||
	char *make, *model, *serial; // may be NULL
 | 
						char *make, *model, *serial; // may be NULL
 | 
				
			||||||
 | 
						char *port; // may be NULL
 | 
				
			||||||
	int32_t phys_width, phys_height; // mm
 | 
						int32_t phys_width, phys_height; // mm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Note: some backends may have zero modes
 | 
						// Note: some backends may have zero modes
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -433,6 +433,7 @@ void wlr_output_finish(struct wlr_output *output) {
 | 
				
			||||||
	free(output->make);
 | 
						free(output->make);
 | 
				
			||||||
	free(output->model);
 | 
						free(output->model);
 | 
				
			||||||
	free(output->serial);
 | 
						free(output->serial);
 | 
				
			||||||
 | 
						free(output->port);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void wlr_output_destroy(struct wlr_output *output) {
 | 
					void wlr_output_destroy(struct wlr_output *output) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue