diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c index 0fee8a8382b2eac08563ac532aa1bf09cb3ee540..26244bd5fc9725ceda6f4641356b4feb17921549 100644 --- a/lib/igt_chamelium.c +++ b/lib/igt_chamelium.c @@ -182,6 +182,20 @@ unsigned int chamelium_port_get_type(const struct chamelium_port *port) { return port->type; } +/** + * chamelium_port_get_name: + * @port: The chamelium port to retrieve the name of + * + * Gets the name of the DRM connector corresponding to the given Chamelium + * port. + * + * Returns: the name of the DRM connector + */ +const char *chamelium_port_get_name(struct chamelium_port *port) +{ + return port->name; +} + /** * chamelium_port_get_connector: * @chamelium: The Chamelium instance to use @@ -197,30 +211,79 @@ drmModeConnector *chamelium_port_get_connector(struct chamelium *chamelium, struct chamelium_port *port, bool reprobe) { - drmModeConnector *connector; + typedef drmModeConnectorPtr (*getConnectorPtr)(int fd, + uint32_t connector_id); - if (reprobe) - connector = drmModeGetConnector(chamelium->drm_fd, - port->connector_id); - else - connector = drmModeGetConnectorCurrent( - chamelium->drm_fd, port->connector_id); + drmModeRes *res = NULL; + int i; - return connector; -} + bool is_mst_port = !!port->connector_path; + getConnectorPtr getConnector = reprobe ? &drmModeGetConnector : + &drmModeGetConnectorCurrent; + int drm_fd = chamelium->drm_fd; + drmModeConnector *connector = getConnector(drm_fd, port->connector_id); -/** - * chamelium_port_get_name: - * @port: The chamelium port to retrieve the name of - * - * Gets the name of the DRM connector corresponding to the given Chamelium - * port. - * - * Returns: the name of the DRM connector - */ -const char *chamelium_port_get_name(struct chamelium_port *port) -{ - return port->name; + /* If the port isn't MST, then the connector ID should be consistent to grab the connector. */ + if (!is_mst_port) { + return connector; + } + + /* If the port is MST, then we need to find the connector ID from the path. */ + + /* In case the connector ID is still valid, do a quick check if we're have the connector we expect. + * Otherwise, read the new resources and find the new connector we're looking for. */ + if (connector) { + drmModePropertyBlobPtr path_blob = + kmstest_get_path_blob(drm_fd, connector->connector_id); + if (path_blob) { + bool is_correct_connector = + strcmp(port->connector_path, path_blob->data) == + 0; + drmModeFreePropertyBlob(path_blob); + if (is_correct_connector) + return connector; + } + + drmModeFreeConnector(connector); + connector = NULL; + } + + res = drmModeGetResources(drm_fd); + for (i = 0; i < res->count_connectors; i++) { + drmModePropertyBlobPtr path_blob = NULL; + + connector = getConnector(drm_fd, res->connectors[i]); + /* Check if the connector is not disconnected and in zombie mode. */ + if (!connector) + continue; + /* Check if the connector is MST. */ + path_blob = + kmstest_get_path_blob(drm_fd, connector->connector_id); + if (!path_blob) + continue; + + if (strcmp(path_blob->data, port->connector_path) == 0) { + char connector_name[50]; + /* At finding the connector, update its metadata. */ + port->connector_id = connector->connector_id; + + snprintf(connector_name, 50, "%s-%u", + kmstest_connector_type_str( + connector->connector_type), + connector->connector_type_id); + port->name = strdup(connector_name); + + goto out; + } + + drmModeFreePropertyBlob(path_blob); + drmModeFreeConnector(connector); + connector = NULL; + } + +out: + drmModeFreeResources(res); + return connector; } /** @@ -2862,7 +2925,7 @@ struct chamelium *chamelium_init(int drm_fd) bool type_mismatch = false; struct chamelium_port * port = &chamelium->ports[i]; drmModeConnectorPtr connector = - drmModeGetConnectorCurrent(drm_fd, port->connector_id); + chamelium_port_get_connector(chamelium, port, false); igt_assert(connector != NULL); diff --git a/lib/igt_kms.c b/lib/igt_kms.c index 665594aa39b2bd2b23a2d7787a1764575b6092ae..55fcd8111bd0501cfe3649879a8954268a89a5c8 100644 --- a/lib/igt_kms.c +++ b/lib/igt_kms.c @@ -1786,6 +1786,22 @@ bool kmstest_get_connector_config(int drm_fd, uint32_t connector_id, config, 0); } +drmModePropertyBlobPtr kmstest_get_path_blob(int drm_fd, uint32_t connector_id) +{ + uint64_t path_blob_id = 0; + drmModePropertyBlobPtr path_blob = NULL; + + if (!kmstest_get_property(drm_fd, connector_id, + DRM_MODE_OBJECT_CONNECTOR, "PATH", NULL, + &path_blob_id, NULL)) { + return NULL; + } + + path_blob = drmModeGetPropertyBlob(drm_fd, path_blob_id); + igt_assert(path_blob); + return path_blob; +} + /** * kmstest_probe_connector_config: * @drm_fd: DRM fd diff --git a/lib/igt_kms.h b/lib/igt_kms.h index ca2765e9431d3a192ec2a9692e8d925e79709dff..fe98944f2b3dbe2bf3cf750c25853c2e6e3b35c6 100644 --- a/lib/igt_kms.h +++ b/lib/igt_kms.h @@ -234,6 +234,7 @@ bool kmstest_get_connector_default_mode(int drm_fd, drmModeConnector *connector, bool kmstest_get_connector_config(int drm_fd, uint32_t connector_id, unsigned long crtc_idx_mask, struct kmstest_connector_config *config); +drmModePropertyBlobPtr kmstest_get_path_blob(int drm_fd, uint32_t connector_id); bool kmstest_probe_connector_config(int drm_fd, uint32_t connector_id, unsigned long crtc_idx_mask, struct kmstest_connector_config *config);