[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