[RFC,1/1] xf86drm: Add drmHandleMatch func
diff mbox

Message ID 20180412035554.30874-2-robert.foss@collabora.com
State New
Headers show

Commit Message

Robert Foss April 12, 2018, 3:55 a.m. UTC
drmHandleMatch is intended to allow for userspace to filter out
devices that it does not want to open.

Opening specific devices using paths alone is not a reliable due to
probing order. This function intends to provide a mechanism
for filtering out devices that don't fit what you need using the
already existing drmVersion and drmDevice structs.

Most fields of drmVersion and drmDevice can be used for comparing
between the target device and the actual FD that has been provided.

Signed-off-by: Robert Foss <robert.foss@collabora.com>
---
 xf86drm.h     |  2 ++
 xf86drmMode.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 71 insertions(+)

Patch
diff mbox

diff --git a/xf86drm.h b/xf86drm.h
index 7773d71a8030..7ef1e2818301 100644
--- a/xf86drm.h
+++ b/xf86drm.h
@@ -863,6 +863,8 @@  extern int drmGetDevices2(uint32_t flags, drmDevicePtr devices[], int max_device
 
 extern int drmDevicesEqual(drmDevicePtr a, drmDevicePtr b);
 
+extern int drmHandleMatch(int fd, drmVersionPtr ver, drmDevicePtr dev);
+
 extern int drmSyncobjCreate(int fd, uint32_t flags, uint32_t *handle);
 extern int drmSyncobjDestroy(int fd, uint32_t handle);
 extern int drmSyncobjHandleToFD(int fd, uint32_t handle, int *obj_fd);
diff --git a/xf86drmMode.c b/xf86drmMode.c
index 9a15b5e78dda..e403515a94b7 100644
--- a/xf86drmMode.c
+++ b/xf86drmMode.c
@@ -946,6 +946,75 @@  int drmHandleEvent(int fd, drmEventContextPtr evctx)
 	return 0;
 }
 
+#define matchCmpInt(ver, ver_fd, element) \
+	if (ver->element > 0 && ver->element != ver_fd->element) \
+		goto fail;
+
+#define matchCmpStr(ver, ver_fd, element) \
+	if (ver->element != NULL && !strcmp(ver->element, ver_fd->element)) \
+		goto fail;
+
+static int drmMatchVersion(int fd, drmVersionPtr ver)
+{
+	drmVersionPtr ver_fd = NULL;
+
+	if (!ver)
+		goto success;
+
+	ver_fd = drmGetVersion(fd);
+	if (!ver_fd)
+		goto fail;
+
+	matchCmpInt(ver, ver_fd, version_major);
+	matchCmpInt(ver, ver_fd, version_minor);
+	matchCmpInt(ver, ver_fd, version_patchlevel);
+
+	matchCmpStr(ver, ver_fd, name);
+	matchCmpStr(ver, ver_fd, date);
+	matchCmpStr(ver, ver_fd, desc);
+
+success:
+	drmFreeVersion(ver_fd);
+	return 1;
+fail:
+    drmFreeVersion(ver_fd);
+	return 0;
+}
+
+static int drmMatchDevice(int fd, drmDevicePtr dev)
+{
+	drmDevicePtr dev_fd = NULL;
+
+	if (!dev)
+		goto success;
+
+    if (drmGetDevice2(fd, 0, &dev_fd) != 0) {
+		goto fail;
+    }
+
+	matchCmpInt(dev, dev_fd, available_nodes)
+	matchCmpInt(dev, dev_fd, bustype)
+
+	drmDevicesEqual(dev, dev_fd);
+
+success:
+	drmFreeDevice(&dev_fd);
+	return 1;
+fail:
+	drmFreeDevice(&dev_fd);
+	return 0;
+}
+
+int drmHandleMatch(int fd, drmVersionPtr ver, drmDevicePtr dev)
+{
+	int ret = 1;
+
+	ret &= drmMatchVersion(fd, ver);
+	ret &= drmMatchDevice(fd, dev);
+
+	return ret;
+}
+
 int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id,
 		    uint32_t flags, void *user_data)
 {