[igt-dev] [PATCH i-g-t v7 6/8] kms_content_protection: uevent for HDCP status change

Shankar, Uma uma.shankar at intel.com
Tue Jul 2 13:16:51 UTC 2019



>-----Original Message-----
>From: C, Ramalingam
>Sent: Thursday, May 30, 2019 8:31 PM
>To: Shankar, Uma <uma.shankar at intel.com>; Vetter, Daniel
><daniel.vetter at intel.com>; igt-dev at lists.freedesktop.org
>Cc: Mun, Gwan-gyeong <gwan-gyeong.mun at intel.com>; C, Ramalingam
><ramalingam.c at intel.com>
>Subject: [PATCH i-g-t v7 6/8] kms_content_protection: uevent for HDCP status
>change
>
>To detect the HDCP status change we are reading the uevent sent with the
>corresponding connector id and property id.
>
>This avoids the polling of the property every mSec.
>
>v2:
>  Made it as subtest. Remaining tests will use polling. [Daniel]
>
>Signed-off-by: Ramalingam C <ramalingam.c at intel.com>
>Acked-by: Daniel Vetter <daniel.vetter at ffwll.ch>
>---
> tests/kms_content_protection.c | 158 ++++++++++++++++++++++++++++++++-
> 1 file changed, 156 insertions(+), 2 deletions(-)
>
>diff --git a/tests/kms_content_protection.c b/tests/kms_content_protection.c index
>215b7a7c0fc7..ab6a2da55c23 100644
>--- a/tests/kms_content_protection.c
>+++ b/tests/kms_content_protection.c
>@@ -24,6 +24,9 @@
>
> #include <poll.h>
> #include <fcntl.h>
>+#include <sys/epoll.h>
>+#include <sys/stat.h>
>+#include <libudev.h>
> #include "igt.h"
> #include "igt_sysfs.h"
> #include "igt_kms.h"
>@@ -43,6 +46,7 @@ struct data {
> #define CP_LIC					(1 << 1)
> #define CP_MEI_RELOAD				(1 << 2)
> #define CP_TYPE_CHANGE				(1 << 3)
>+#define CP_UEVENT				(1 << 4)
>
> #define CP_UNDESIRED				0
> #define CP_DESIRED				1
>@@ -102,6 +106,137 @@ static int wait_flip_event(void)
> 	return rc;
> }
>
>+static bool hdcp_event(struct udev_monitor *uevent_monitor,
>+		       struct udev *udev, uint32_t conn_id, uint32_t prop_id) {
>+	struct udev_device *dev;
>+	dev_t udev_devnum;
>+	struct stat s;
>+	const char *hotplug, *connector, *property;
>+	bool ret = false;
>+
>+	dev = udev_monitor_receive_device(uevent_monitor);
>+	if (!dev)
>+		goto out;
>+
>+	udev_devnum = udev_device_get_devnum(dev);
>+	fstat(data.display.drm_fd, &s);
>+
>+	hotplug = udev_device_get_property_value(dev, "HOTPLUG");
>+	if (!(memcmp(&s.st_rdev, &udev_devnum, sizeof(dev_t)) == 0 &&
>+	    hotplug && atoi(hotplug) == 1)) {
>+		igt_debug("Not a Hotplug event\n");
>+		goto out_dev;
>+	}
>+
>+	connector = udev_device_get_property_value(dev, "CONNECTOR");
>+	if (!(memcmp(&s.st_rdev, &udev_devnum, sizeof(dev_t)) == 0 &&
>+	    connector && atoi(connector) == conn_id)) {
>+		igt_debug("Not for connector id: %u\n", conn_id);
>+		goto out_dev;
>+	}
>+
>+	property = udev_device_get_property_value(dev, "PROPERTY");
>+	if (!(memcmp(&s.st_rdev, &udev_devnum, sizeof(dev_t)) == 0 &&
>+	    property && atoi(property) == prop_id)) {
>+		igt_debug("Not for property id: %u\n", prop_id);
>+		goto out_dev;
>+	}
>+	ret = true;
>+
>+out_dev:
>+	udev_device_unref(dev);
>+out:
>+	return ret;
>+}
>+
>+static void hdcp_udev_fini(struct udev_monitor *uevent_monitor,
>+			   struct udev *udev)
>+{
>+	if (uevent_monitor)
>+		udev_monitor_unref(uevent_monitor);
>+	if (udev)
>+		udev_unref(udev);
>+}
>+
>+static int hdcp_udev_init(struct udev_monitor *uevent_monitor,
>+			  struct udev *udev)
>+{
>+	int ret = -EINVAL;
>+
>+	udev = udev_new();
>+	if (!udev) {
>+		igt_info("failed to create udev object\n");
>+		goto out;
>+	}
>+
>+	uevent_monitor = udev_monitor_new_from_netlink(udev, "udev");
>+	if (!uevent_monitor) {
>+		igt_info("failed to create udev event monitor\n");
>+		goto out;
>+	}
>+
>+	ret = udev_monitor_filter_add_match_subsystem_devtype(uevent_monitor,
>+							      "drm",
>+							      "drm_minor");
>+	if (ret < 0) {
>+		igt_info("failed to filter for drm events\n");
>+		goto out;
>+	}
>+
>+	ret = udev_monitor_enable_receiving(uevent_monitor);
>+	if (ret < 0) {
>+		igt_info("failed to enable udev event reception\n");
>+		goto out;
>+	}
>+
>+	return udev_monitor_get_fd(uevent_monitor);
>+
>+out:
>+	hdcp_udev_fini(uevent_monitor, udev);
>+	return ret;
>+}
>+
>+#define MAX_EVENTS	10
>+static bool wait_for_hdcp_event(uint32_t conn_id, uint32_t prop_id,
>+				uint32_t timeout_mSec)
>+{
>+
>+	struct udev_monitor *uevent_monitor = NULL;
>+	struct udev *udev = NULL;
>+	int udev_fd, epoll_fd;
>+	struct epoll_event event, events[MAX_EVENTS];
>+	bool ret = false;
>+
>+	udev_fd = hdcp_udev_init(uevent_monitor, udev);
>+	if (udev_fd < 0)
>+		return false;
>+
>+	epoll_fd = epoll_create1(0);
>+	if (epoll_fd == -1) {
>+		igt_info("Failed to create epoll fd. %d\n", epoll_fd);
>+		goto out_ep_create;
>+	}
>+
>+	event.events = EPOLLIN | EPOLLERR;
>+	event.data.fd = 0;
>+
>+	if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, udev_fd, &event)) {
>+		igt_info("failed to fd into epoll\n");
>+		goto out_ep_ctl;
>+	}
>+
>+	if (epoll_wait(epoll_fd, events, MAX_EVENTS, timeout_mSec))
>+		ret = hdcp_event(uevent_monitor, udev, conn_id, prop_id);
>+
>+out_ep_ctl:
>+	if (close(epoll_fd))
>+		igt_info("failed to close the epoll fd\n");
>+out_ep_create:
>+	hdcp_udev_fini(uevent_monitor, udev);
>+	return ret;
>+}
>+
> static bool
> wait_for_prop_value(igt_output_t *output, uint64_t expected,
> 		    uint32_t timeout_mSec)
>@@ -109,13 +244,26 @@ wait_for_prop_value(igt_output_t *output, uint64_t
>expected,
> 	uint64_t val;
> 	int i;
>
>-	for (i = 0; i < timeout_mSec; i++) {
>+	if (data.cp_tests & CP_UEVENT) {
>+		if (wait_for_hdcp_event(output->id,
>+				output-
>>props[IGT_CONNECTOR_CONTENT_PROTECTION],
>+				timeout_mSec))

Here, this call can fail and it seems we will immediately come out and attempt a get
and will not go for usleep either. Handle this gracefully, else all look good to me.

With the above fixed.
Reviewed-by: Uma Shankar <uma.shankar at intel.com>

>+			igt_debug("hdcp event received\n");
>+
> 		val = igt_output_get_prop(output,
>
>IGT_CONNECTOR_CONTENT_PROTECTION);
> 		if (val == expected)
> 			return true;
>-		usleep(1000);
>+	} else {
>+		for (i = 0; i < timeout_mSec; i++) {
>+			val = igt_output_get_prop(output,
>+
>IGT_CONNECTOR_CONTENT_PROTECTION);
>+			if (val == expected)
>+				return true;
>+			usleep(1000);
>+		}
> 	}
>+
> 	igt_info("prop_value mismatch %" PRId64 " != %" PRId64 "\n",
> 		 val, expected);
>
>@@ -493,6 +641,12 @@ igt_main
> 		test_content_protection(COMMIT_ATOMIC,
>HDCP_CONTENT_TYPE_1);
> 	}
>
>+	igt_subtest("uevent") {
>+		igt_require(data.display.is_atomic);
>+		data.cp_tests = CP_UEVENT;
>+		test_content_protection(COMMIT_ATOMIC,
>HDCP_CONTENT_TYPE_0);
>+	}
>+
> 	igt_fixture
> 		igt_display_fini(&data.display);
> }
>--
>2.19.1



More information about the igt-dev mailing list