This adds some basic helpers for connecting to udev and watching for sysfs hotplug events. Cc: Tomeu Vizoso <tomeu@xxxxxxxxxxxxxxx> Signed-off-by: Lyude <lyude@xxxxxxxxxx> Changes since v1: - Remove unused arg from documentation Changes since v2: - Make udev_monitor explicit so that we can use this for detecting FSMs from the Chamelium in rpc calls --- lib/igt_kms.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/igt_kms.h | 7 ++++ 2 files changed, 118 insertions(+) diff --git a/lib/igt_kms.c b/lib/igt_kms.c index 2c5a6e8..df50451 100644 --- a/lib/igt_kms.c +++ b/lib/igt_kms.c @@ -38,6 +38,10 @@ #elif HAVE_SYS_KD_H #include <sys/kd.h> #endif +#ifdef HAVE_UDEV +#include <libudev.h> +#include <poll.h> +#endif #include <errno.h> #include <time.h> @@ -2917,6 +2921,113 @@ void igt_reset_connectors(void) "detect"); } +#ifdef HAVE_UDEV + +/** + * igt_watch_hotplug: + * + * Begin monitoring udev for sysfs hotplug events. + * + * Returns: a udev monitor for detecting hotplugs on + */ +struct udev_monitor *igt_watch_hotplug(void) +{ + struct udev *udev; + struct udev_monitor *mon; + int ret, flags, fd; + + udev = udev_new(); + igt_assert(udev != NULL); + + mon = udev_monitor_new_from_netlink(udev, "udev"); + igt_assert(mon != NULL); + + ret = udev_monitor_filter_add_match_subsystem_devtype(mon, + "drm", + "drm_minor"); + igt_assert_eq(ret, 0); + ret = udev_monitor_filter_update(mon); + igt_assert_eq(ret, 0); + ret = udev_monitor_enable_receiving(mon); + igt_assert_eq(ret, 0); + + /* Set the fd for udev as non blocking */ + fd = udev_monitor_get_fd(mon); + flags = fcntl(fd, F_GETFL, 0); + igt_assert(flags); + + flags |= O_NONBLOCK; + igt_assert_neq(fcntl(fd, F_SETFL, flags), -1); + + return mon; +} + +/** + * igt_hotplug_detected: + * @mon: A udev monitor initialized with #igt_watch_hotplug + * @timeout_secs: How long to wait for a hotplug event to occur. + * + * Assert that a hotplug event was received since we last checked the monitor. + * + * Returns: true if a sysfs hotplug event was received, false if we timed out + */ +bool igt_hotplug_detected(struct udev_monitor *mon, int timeout_secs) +{ + struct udev_device *dev; + const char *hotplug_val; + struct pollfd fd = { + .fd = udev_monitor_get_fd(mon), + .events = POLLIN + }; + bool hotplug_received = false; + + /* Go through all of the events pending on the udev monitor. Once we + * receive a hotplug, we continue going through the rest of the events + * so that redundant hotplug events don't change the results of future + * checks + */ + while (!hotplug_received && poll(&fd, 1, timeout_secs * 1000)) { + dev = udev_monitor_receive_device(mon); + + hotplug_val = udev_device_get_property_value(dev, "HOTPLUG"); + if (hotplug_val && atoi(hotplug_val) == 1) + hotplug_received = true; + + udev_device_unref(dev); + } + + return hotplug_received; +} + +/** + * igt_flush_hotplugs: + * @mon: A udev monitor initialized with #igt_watch_hotplug + * + * Get rid of any pending hotplug events + */ +void igt_flush_hotplugs(struct udev_monitor *mon) +{ + struct udev_device *dev; + + while ((dev = udev_monitor_receive_device(mon))) + udev_device_unref(dev); +} + +/** + * igt_cleanup_hotplug: + * + * Cleanup the resources allocated by #igt_watch_hotplug + */ +void igt_cleanup_hotplug(struct udev_monitor *mon) +{ + struct udev *udev = udev_monitor_get_udev(mon); + + udev_monitor_unref(mon); + mon = NULL; + udev_unref(udev); +} +#endif + /** * kmstest_get_vbl_flag: * @pipe_id: Pipe to convert to flag representation. diff --git a/lib/igt_kms.h b/lib/igt_kms.h index 81be77f..72ed6a3 100644 --- a/lib/igt_kms.h +++ b/lib/igt_kms.h @@ -502,5 +502,12 @@ uint32_t kmstest_get_vbl_flag(uint32_t pipe_id); const unsigned char* igt_kms_get_base_edid(void); const unsigned char* igt_kms_get_alt_edid(void); +#ifdef HAVE_UDEV +struct udev_monitor *igt_watch_hotplug(void); +bool igt_hotplug_detected(struct udev_monitor *mon, + int timeout_secs); +void igt_flush_hotplugs(struct udev_monitor *mon); +void igt_cleanup_hotplug(struct udev_monitor *mon); +#endif #endif /* __IGT_KMS_H__ */ -- 2.9.3 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx