From: "Murthy, Arun R" <arun.r.murthy@intel.com>
To: Kunal Joshi <kunal1.joshi@intel.com>, <igt-dev@lists.freedesktop.org>
Subject: Re: [i-g-t,2/6] lib/igt_connector_helper: Add generic connector helpers
Date: Mon, 9 Mar 2026 15:08:39 +0530 [thread overview]
Message-ID: <d256aedf-2e67-41be-a440-a6e39ad5d18b@intel.com> (raw)
In-Reply-To: <20260225212859.876713-3-kunal1.joshi@intel.com>
On 26-02-2026 02:58, Kunal Joshi wrote:
> Add a lightweight helper library for DRM connector operations used
> by USB4 switch and other dock/undock tests:
>
> - igt_connector_get_connected(): enumerate connected connectors
> - igt_connector_get_info(): query name, EDID serial, and MST path
> - igt_connector_find_by_path(): PATH-based connector lookup (MST)
> - igt_connector_find_by_name(): name-based connector lookup
> - igt_connector_reprobe_all(): force reprobe all connectors by
> iterating each connector to trigger DRM core re-detection
>
> These helpers abstract common DRM connector patterns that are needed
> by multiple test suites for display enumeration and verification.
The contents of these are already present in lib/igt__kms.c
Instead of a new file, can these be exported from lib/igt_kms.c ?
Thanks and Regards,
Arun R Murthy
-------------------
>
> Signed-off-by: Kunal Joshi <kunal1.joshi@intel.com>
> ---
> lib/igt_connector_helper.c | 299 +++++++++++++++++++++++++++++++++++++
> lib/igt_connector_helper.h | 27 ++++
> lib/meson.build | 1 +
> 3 files changed, 327 insertions(+)
> create mode 100644 lib/igt_connector_helper.c
> create mode 100644 lib/igt_connector_helper.h
>
> diff --git a/lib/igt_connector_helper.c b/lib/igt_connector_helper.c
> new file mode 100644
> index 000000000..6be849b7a
> --- /dev/null
> +++ b/lib/igt_connector_helper.c
> @@ -0,0 +1,299 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2026 Intel Corporation
> + */
> +
> +/**
> + * SECTION:igt_connector_helper
> + * @short_description: Generic connector helper functions for DRM/KMS
> + * @title: Connector Helper
> + * @include: igt_connector_helper.h
> + *
> + * Helper functions for DRM connector operations including enumeration,
> + * lookup by name/path, and EDID serial extraction.
> + */
> +
> +#include <string.h>
> +#include <xf86drm.h>
> +#include <xf86drmMode.h>
> +
> +#include "igt_core.h"
> +#include "igt_edid.h"
> +#include "igt_kms.h"
> +#include "igt_connector_helper.h"
> +
> +/**
> + * igt_connector_get_connected:
> + * @drm_fd: DRM file descriptor
> + * @connectors: array to store connector IDs; must be valid if @max_connectors > 0
> + * @max_connectors: maximum number of connectors to store
> + *
> + * Walks all DRM connectors and stores the IDs of those currently connected.
> + * Scanning stops once @max_connectors IDs have been collected; later
> + * connectors are not examined.
> + *
> + * Returns: number of connector IDs written to @connectors, capped by
> + * @max_connectors.
> + */
> +int igt_connector_get_connected(int drm_fd, uint32_t *connectors,
> + int max_connectors)
> +{
> + drmModeRes *res;
> + drmModeConnector *conn;
> + int count = 0;
> + int i;
> +
> + igt_assert(max_connectors >= 0);
> + if (max_connectors > 0)
> + igt_assert(connectors);
> +
> + res = drmModeGetResources(drm_fd);
> + if (!res)
> + return 0;
> +
> + for (i = 0; i < res->count_connectors && count < max_connectors; i++) {
> + conn = drmModeGetConnector(drm_fd, res->connectors[i]);
> + if (!conn)
> + continue;
> +
> + if (conn->connection == DRM_MODE_CONNECTED)
> + connectors[count++] = conn->connector_id;
> +
> + drmModeFreeConnector(conn);
> + }
> +
> + drmModeFreeResources(res);
> + return count;
> +}
> +
> +/**
> + * igt_connector_get_info:
> + * @drm_fd: DRM file descriptor
> + * @connector_id: connector ID
> + * @name: buffer for connector name (mandatory)
> + * @name_size: size of @name; must be > 0
> + * @serial: buffer for EDID-derived serial (mandatory)
> + * @serial_size: size of @serial; must be > 1
> + * @path: buffer for MST PATH property (optional, may be NULL)
> + * @path_size: size of @path buffer
> + *
> + * Fills connector name, MST PATH, and EDID-derived serial for a connector.
> + * @name is always filled when the connector is found. @serial is filled from
> + * the ASCII serial string descriptor (0xFF) if present, else from the 32-bit
> + * header serial number; left empty if no EDID is available. @path is filled
> + * only if requested and the PATH property exists.
> + *
> + * Success means the connector object was found and @name was filled.
> + * @serial and @path are best-effort and may still be empty on success.
> + *
> + * Returns: true if the connector was found, false otherwise.
> + */
> +bool igt_connector_get_info(int drm_fd, uint32_t connector_id,
> + char *name, size_t name_size,
> + char *serial, size_t serial_size,
> + char *path, size_t path_size)
> +{
> + drmModeConnector *conn;
> + drmModePropertyBlobPtr edid_blob = NULL;
> + uint64_t blob_id = 0;
> + drmModePropertyPtr prop;
> + const struct edid *edid;
> + int i;
> +
> + igt_assert(name && name_size > 0);
> + igt_assert(serial && serial_size > 1);
> + igt_assert(!path || path_size > 0);
> +
> + name[0] = '\0';
> + serial[0] = '\0';
> + if (path)
> + path[0] = '\0';
> +
> + conn = drmModeGetConnector(drm_fd, connector_id);
> + if (!conn)
> + return false;
> +
> + snprintf(name, name_size, "%s-%d",
> + kmstest_connector_type_str(conn->connector_type),
> + conn->connector_type_id);
> +
> + for (i = 0; i < conn->count_props; i++) {
> + prop = drmModeGetProperty(drm_fd, conn->props[i]);
> + if (!prop)
> + continue;
> +
> + if (strcmp(prop->name, "EDID") == 0)
> + blob_id = conn->prop_values[i];
> +
> + drmModeFreeProperty(prop);
> + if (blob_id)
> + break;
> + }
> +
> + /* Extract MST PATH if requested */
> + if (path) {
> + drmModePropertyBlobPtr path_blob;
> +
> + /* PATH blob payload is a NUL-terminated string */
> + path_blob = kmstest_get_path_blob(drm_fd, connector_id);
> + if (path_blob) {
> + snprintf(path, path_size, "%s",
> + (const char *)path_blob->data);
> + drmModeFreePropertyBlob(path_blob);
> + }
> + }
> +
> + drmModeFreeConnector(conn);
> +
> + if (blob_id) {
> + edid_blob = drmModeGetPropertyBlob(drm_fd, blob_id);
> + if (edid_blob) {
> + if (edid_blob->length >= sizeof(struct edid)) {
> + edid = edid_blob->data;
> + edid_get_any_serial(edid, serial, serial_size);
> + }
> + drmModeFreePropertyBlob(edid_blob);
> + }
> + }
> +
> + return true;
> +}
> +
> +/**
> + * igt_connector_find_by_path:
> + * @drm_fd: DRM file descriptor
> + * @path: MST PATH property value to match
> + * @connector_id: output for connector ID (filled on success)
> + *
> + * Finds the currently connected connector whose PATH property matches @path
> + * (exact string comparison). PATH is the preferred stable identity for MST
> + * connectors; connector IDs may change across hotplug events.
> + *
> + * Returns: true if a matching connected connector was found.
> + */
> +bool igt_connector_find_by_path(int drm_fd, const char *path,
> + uint32_t *connector_id)
> +{
> + drmModeRes *res;
> + drmModeConnector *conn;
> + drmModePropertyBlobPtr path_blob;
> + bool found = false;
> + int i;
> +
> + if (!path || !connector_id)
> + return false;
> +
> + res = drmModeGetResources(drm_fd);
> + if (!res)
> + return false;
> +
> + for (i = 0; i < res->count_connectors && !found; i++) {
> + conn = drmModeGetConnector(drm_fd, res->connectors[i]);
> + if (!conn)
> + continue;
> +
> + if (conn->connection == DRM_MODE_CONNECTED) {
> + path_blob = kmstest_get_path_blob(drm_fd,
> + conn->connector_id);
> + if (path_blob) {
> + if (strcmp(path_blob->data, path) == 0) {
> + *connector_id = conn->connector_id;
> + found = true;
> + }
> + drmModeFreePropertyBlob(path_blob);
> + }
> + }
> +
> + drmModeFreeConnector(conn);
> + }
> +
> + drmModeFreeResources(res);
> +
> + if (found)
> + igt_debug("igt_connector: Found connector %u for path '%s'\n",
> + *connector_id, path);
> +
> + return found;
> +}
> +
> +/**
> + * igt_connector_find_by_name:
> + * @drm_fd: DRM file descriptor
> + * @name: connector name to match (e.g., "DP-6")
> + * @connector_id: output for connector ID (filled on success)
> + *
> + * Name-based lookup helper. Prefer igt_connector_find_by_path() for MST
> + * connectors, since connector names and IDs may change across hotplug events.
> + *
> + * Returns: true if a matching connected connector was found.
> + */
> +bool igt_connector_find_by_name(int drm_fd, const char *name,
> + uint32_t *connector_id)
> +{
> + drmModeRes *res;
> + drmModeConnector *conn;
> + char conn_name[IGT_CONNECTOR_NAME_MAX];
> + bool found = false;
> + int i;
> +
> + if (!name || !connector_id)
> + return false;
> +
> + res = drmModeGetResources(drm_fd);
> + if (!res)
> + return false;
> +
> + for (i = 0; i < res->count_connectors && !found; i++) {
> + conn = drmModeGetConnector(drm_fd, res->connectors[i]);
> + if (!conn)
> + continue;
> +
> + snprintf(conn_name, sizeof(conn_name), "%s-%d",
> + kmstest_connector_type_str(conn->connector_type),
> + conn->connector_type_id);
> +
> + if (strcmp(conn_name, name) == 0 &&
> + conn->connection == DRM_MODE_CONNECTED) {
> + *connector_id = conn->connector_id;
> + found = true;
> + }
> +
> + drmModeFreeConnector(conn);
> + }
> +
> + drmModeFreeResources(res);
> +
> + if (found)
> + igt_debug("igt_connector: Found connector %u for name '%s'\n",
> + *connector_id, name);
> +
> + return found;
> +}
> +
> +/**
> + * igt_connector_reprobe_all:
> + * @drm_fd: DRM file descriptor
> + *
> + * Issues a GETCONNECTOR ioctl for every connector, requesting fresh state
> + * from the kernel. This is often sufficient to refresh connector status and
> + * MST topology visibility after hotplug events, but does not guarantee a
> + * full hardware reprobe in all driver paths.
> + */
> +void igt_connector_reprobe_all(int drm_fd)
> +{
> + drmModeRes *res;
> + drmModeConnector *conn;
> + int i;
> +
> + res = drmModeGetResources(drm_fd);
> + if (!res)
> + return;
> +
> + for (i = 0; i < res->count_connectors; i++) {
> + conn = drmModeGetConnector(drm_fd, res->connectors[i]);
> + if (conn)
> + drmModeFreeConnector(conn);
> + }
> +
> + drmModeFreeResources(res);
> +}
> diff --git a/lib/igt_connector_helper.h b/lib/igt_connector_helper.h
> new file mode 100644
> index 000000000..fffb2661b
> --- /dev/null
> +++ b/lib/igt_connector_helper.h
> @@ -0,0 +1,27 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2026 Intel Corporation
> + */
> +
> +#ifndef IGT_CONNECTOR_HELPER_H
> +#define IGT_CONNECTOR_HELPER_H
> +
> +#include <stdbool.h>
> +#include <stddef.h>
> +#include <stdint.h>
> +
> +#define IGT_CONNECTOR_NAME_MAX 32
> +
> +int igt_connector_get_connected(int drm_fd, uint32_t *connectors,
> + int max_connectors);
> +bool igt_connector_get_info(int drm_fd, uint32_t connector_id,
> + char *name, size_t name_size,
> + char *serial, size_t serial_size,
> + char *path, size_t path_size);
> +bool igt_connector_find_by_path(int drm_fd, const char *path,
> + uint32_t *connector_id);
> +bool igt_connector_find_by_name(int drm_fd, const char *name,
> + uint32_t *connector_id);
> +void igt_connector_reprobe_all(int drm_fd);
> +
> +#endif /* IGT_CONNECTOR_HELPER_H */
> diff --git a/lib/meson.build b/lib/meson.build
> index ea721ecf7..074b21fdf 100644
> --- a/lib/meson.build
> +++ b/lib/meson.build
> @@ -113,6 +113,7 @@ lib_sources = [
> 'igt_vmwgfx.c',
> 'igt_psr.c',
> 'igt_amd.c',
> + 'igt_connector_helper.c',
> 'igt_edid.c',
> 'igt_eld.c',
> 'igt_infoframe.c',
next prev parent reply other threads:[~2026-03-09 9:38 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-25 21:28 [PATCH i-g-t 0/6] add test to validate dock/undock and switch Kunal Joshi
2026-02-25 21:28 ` [PATCH i-g-t 1/6] lib/igt_edid: add EDID serial extraction helpers Kunal Joshi
2026-03-09 9:30 ` [i-g-t,1/6] " Murthy, Arun R
2026-03-09 11:02 ` Joshi, Kunal1
2026-03-16 3:03 ` Murthy, Arun R
2026-02-25 21:28 ` [PATCH i-g-t 2/6] lib/igt_connector_helper: Add generic connector helpers Kunal Joshi
2026-03-09 9:38 ` Murthy, Arun R [this message]
2026-03-09 11:06 ` [i-g-t,2/6] " Joshi, Kunal1
2026-03-16 3:17 ` Murthy, Arun R
2026-02-25 21:28 ` [PATCH i-g-t 3/6] lib/igt_serial: add generic serial communication helper Kunal Joshi
2026-03-16 5:40 ` [i-g-t,3/6] " Murthy, Arun R
2026-02-25 21:28 ` [PATCH i-g-t 4/6] lib/igt_usb4_switch: add helper library for USB4 Switch 3141 Kunal Joshi
2026-03-16 8:45 ` [i-g-t,4/6] " Murthy, Arun R
2026-02-25 21:28 ` [PATCH i-g-t 5/6] tests/kms_feature_discovery: add basic usb4 switch discovery Kunal Joshi
2026-03-09 10:05 ` [i-g-t,5/6] " Murthy, Arun R
2026-02-25 21:28 ` [PATCH i-g-t 6/6] tests/intel/kms_usb4_switch: Add USB4 switch test suite Kunal Joshi
2026-03-09 10:03 ` [i-g-t,6/6] " Murthy, Arun R
2026-03-09 11:14 ` Joshi, Kunal1
2026-03-16 3:38 ` Murthy, Arun R
2026-02-26 2:20 ` ✗ Xe.CI.BAT: failure for add test to validate dock/undock and switch (rev3) Patchwork
2026-02-26 3:04 ` ✓ i915.CI.BAT: success " Patchwork
2026-02-26 6:52 ` ✗ Xe.CI.FULL: failure " Patchwork
2026-02-26 7:45 ` ✗ i915.CI.Full: " Patchwork
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=d256aedf-2e67-41be-a440-a6e39ad5d18b@intel.com \
--to=arun.r.murthy@intel.com \
--cc=igt-dev@lists.freedesktop.org \
--cc=kunal1.joshi@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox