[PATCH libdrm 2/3] tests/util: Make util_open() use drmDevice

Thierry Reding thierry.reding at gmail.com
Mon Jan 30 10:29:22 UTC 2017


From: Thierry Reding <treding at nvidia.com>

The util_open() helper is used in a couple of test programs to open an
appropriate device. It takes a device path and a module name, both are
optional, as parameters. If a device path is specified, it will try to
open the given device. Otherwise it will try all available devices. If
only a specific subset is desired, the module parameter can be used as
a filter. The function will use it to open only devices whose kernel
driver matches the given module name.

Instead of relying on the legacy drmOpen() function to do this, convert
util_open() to use the new drmDevice helpers. This gets it functionally
much closer to what other DRM/KMS users, such as the X.Org Server or a
Wayland server, do.

Signed-off-by: Thierry Reding <treding at nvidia.com>
---
 tests/util/kms.c | 167 +++++++++++++++++++++++++++++++++++++++++--------------
 tests/util/kms.h |  43 ++++++++++++++
 2 files changed, 168 insertions(+), 42 deletions(-)

diff --git a/tests/util/kms.c b/tests/util/kms.c
index d866398237bb..c5d35ab616d1 100644
--- a/tests/util/kms.c
+++ b/tests/util/kms.c
@@ -42,15 +42,18 @@
 #endif
 
 #include <errno.h>
+#include <fcntl.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
 #include "xf86drm.h"
 #include "xf86drmMode.h"
 
 #include "common.h"
+#include "kms.h"
 
 struct type_name {
     unsigned int type;
@@ -125,58 +128,138 @@ const char *util_lookup_connector_type_name(unsigned int type)
                                  ARRAY_SIZE(connector_type_names));
 }
 
-static const char * const modules[] = {
-    "i915",
-    "amdgpu",
-    "radeon",
-    "nouveau",
-    "vmwgfx",
-    "omapdrm",
-    "exynos",
-    "tilcdc",
-    "msm",
-    "sti",
-    "tegra",
-    "imx-drm",
-    "rockchip",
-    "atmel-hlcdc",
-    "fsl-dcu-drm",
-    "vc4",
-    "virtio_gpu",
-    "mediatek",
-    "meson",
-};
+char *util_get_driver(int fd)
+{
+    drmVersionPtr version;
+    char *driver;
 
-int util_open(const char *device, const char *module)
+    version = drmGetVersion(fd);
+    if (!version)
+        return NULL;
+
+    driver = strdup(version->name);
+
+    drmFreeVersion(version);
+
+    return driver;
+}
+
+int util_get_devices(drmDevicePtr **devicesp, uint32_t flags)
+{
+    drmDevicePtr *devices;
+    unsigned int count;
+    int err;
+
+    err = drmGetDevices2(flags, NULL, 0);
+    if (err < 0)
+        return err;
+
+    /*
+     * If the caller hasn't specified a return pointer for the new devices
+     * array, all of the below is pointless, so simply return the number of
+     * devices available.
+     */
+    if (!devicesp)
+        return err;
+
+    count = err;
+
+    devices = calloc(count, sizeof(*devices));
+    if (!devices)
+        return -ENOMEM;
+
+    err = drmGetDevices2(flags, devices, count);
+    if (err < 0) {
+        free(devices);
+        return err;
+    }
+
+    if (devicesp)
+        *devicesp = devices;
+    else
+        free(devices);
+
+    return count;
+}
+
+void util_free_devices(drmDevicePtr *devices, unsigned int count)
+{
+    drmFreeDevices(devices, count);
+    free(devices);
+}
+
+int util_open_with_module(const char *device, const char *module)
 {
-    int fd;
+    int fd, err = 0;
+
+    if (module)
+        printf("trying to open `%s' with `%s'...", device, module);
+    else
+        printf("trying to open `%s'...", device);
+
+    fd = open(device, O_RDWR);
+    if (fd < 0) {
+        err = -errno;
+        goto out;
+    }
 
     if (module) {
-        fd = drmOpen(module, device);
-        if (fd < 0) {
-            fprintf(stderr, "failed to open device '%s': %s\n",
-                module, strerror(errno));
-            return -errno;
+        char *driver = util_get_driver(fd);
+        if (!driver) {
+            err = -EINVAL;
+            goto close;
         }
-    } else {
-        unsigned int i;
 
-        for (i = 0; i < ARRAY_SIZE(modules); i++) {
-            printf("trying to open device '%s'...", modules[i]);
+        if (strcmp(module, driver) != 0)
+            err = -EINVAL;
+
+        free(driver);
+
+        if (err < 0)
+            goto close;
+    }
+
+    printf("done\n");
+    return fd;
+
+close:
+    close(fd);
+out:
+    printf("failed\n");
+    return err;
+}
 
-            fd = drmOpen(modules[i], device);
-            if (fd < 0) {
-                printf("failed\n");
-            } else {
-                printf("done\n");
+int util_open(const char *device, const char *module)
+{
+    int fd, err;
+
+    if (!device) {
+        drmDevicePtr *devices, dev;
+        unsigned int count, i, j;
+        const char *node;
+
+        err = util_get_devices(&devices, 0);
+        if (err < 0)
+            return err;
+
+        count = err;
+
+        util_for_each_device(dev, i, devices, count) {
+            node = util_device_get_node(dev, DRM_NODE_PRIMARY);
+            if (!node)
+                continue;
+
+            fd = util_open_with_module(node, module);
+            if (fd >= 0)
                 break;
-            }
         }
 
-        if (fd < 0) {
-            fprintf(stderr, "no device found\n");
-            return -ENODEV;
-        }
+        util_free_devices(devices, count);
+
+        if (i == count)
+            fd = -ENOENT;
+    } else {
+        fd = util_open_with_module(device, module);
     }
 
     return fd;
diff --git a/tests/util/kms.h b/tests/util/kms.h
index dde2ed2c5636..b7b5b4747950 100644
--- a/tests/util/kms.h
+++ b/tests/util/kms.h
@@ -30,6 +30,49 @@ const char *util_lookup_encoder_type_name(unsigned int type);
 const char *util_lookup_connector_status_name(unsigned int type);
 const char *util_lookup_connector_type_name(unsigned int type);
 
+char *util_get_driver(int fd);
+
+int util_get_devices(drmDevicePtr **devicesp, uint32_t flags);
+void util_free_devices(drmDevicePtr *devices, unsigned int count);
+
+static inline drmDevicePtr util_get_device(drmDevicePtr *devices,
+                                           unsigned int count,
+                                           unsigned int index)
+{
+    if (index >= count)
+        return NULL;
+
+    return devices[index];
+}
+
+#define util_for_each_device(device, index, devices, count)     \
+    for (device = util_get_device(devices, count, (index) = 0); \
+         (index) < (count);                                     \
+         device = util_get_device(devices, count, ++(index)))
+
+static inline char *util_device_get_node(drmDevicePtr device,
+                                         unsigned int type)
+{
+    if (type >= DRM_NODE_MAX)
+        return NULL;
+
+    return device->nodes[type];
+}
+
+#define for_each_if(condition) \
+    if (!(condition)) {        \
+    } else
+
+#define util_device_for_each_node(node, type, device)     \
+    for (node = util_device_get_node(device, (type) = 0); \
+         (type) < DRM_NODE_MAX;                           \
+         node = util_device_get_node(device, ++(type)))
+
+#define util_device_for_each_available_node(node, type, device)     \
+        util_device_for_each_node(node, type, device)               \
+            for_each_if ((device)->available_nodes & (1 << (type)))
+
+int util_open_with_module(const char *device, const char *module);
 int util_open(const char *device, const char *module);
 
 #endif /* UTIL_KMS_H */
-- 
2.11.0



More information about the dri-devel mailing list