diff options
author | Eric Curtin <ecurtin@redhat.com> | 2022-06-17 11:00:44 +0100 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2022-06-19 00:02:47 +0300 |
commit | 7f500a6c366a16fedfaba8bf67b147ccc8239eb7 (patch) | |
tree | f687c4e11f2fcd5ce5fbea95081f7297c3a64d17 | |
parent | 4bb284e0fa5669bbf6adda93e2f770014834c8cb (diff) |
cam: drm: Support /dev/dri cards other than 0
Existing code is hardcoded to card0. Since recent fedora upgrades, we
have noticed on more than one machine that card1 is present as the
lowest numbered device, could theoretically be higher. This technique
tries every file starting with card and continue only when we have
successfully opened one. These devices with card1 as the lowest device
were simply failing when they do not see a /dev/dri/card0 file present.
Reported-by: Ian Mullins <imullins@redhat.com>
Tested-by: Ian Mullins <imullins@redhat.com>
Signed-off-by: Eric Curtin <ecurtin@redhat.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-rw-r--r-- | src/cam/drm.cpp | 65 | ||||
-rw-r--r-- | src/cam/drm.h | 1 |
2 files changed, 48 insertions, 18 deletions
diff --git a/src/cam/drm.cpp b/src/cam/drm.cpp index 42c5a3b1..fbfc0a59 100644 --- a/src/cam/drm.cpp +++ b/src/cam/drm.cpp @@ -8,6 +8,7 @@ #include "drm.h" #include <algorithm> +#include <dirent.h> #include <errno.h> #include <fcntl.h> #include <iostream> @@ -393,24 +394,10 @@ Device::~Device() int Device::init() { - constexpr size_t NODE_NAME_MAX = sizeof("/dev/dri/card255"); - char name[NODE_NAME_MAX]; - int ret; - - /* - * Open the first DRM/KMS device. The libdrm drmOpen*() functions - * require either a module name or a bus ID, which we don't have, so - * bypass them. The automatic module loading and device node creation - * from drmOpen() is of no practical use as any modern system will - * handle that through udev or an equivalent component. - */ - snprintf(name, sizeof(name), "/dev/dri/card%u", 0); - fd_ = open(name, O_RDWR | O_CLOEXEC); - if (fd_ < 0) { - ret = -errno; - std::cerr - << "Failed to open DRM/KMS device " << name << ": " - << strerror(-ret) << std::endl; + int ret = openCard(); + if (ret < 0) { + std::cerr << "Failed to open any DRM/KMS device: " + << strerror(-ret) << std::endl; return ret; } @@ -438,6 +425,48 @@ int Device::init() return 0; } +int Device::openCard() +{ + const std::string dirName = "/dev/dri/"; + int ret = -ENOENT; + + /* + * Open the first DRM/KMS device beginning with /dev/dri/card. The + * libdrm drmOpen*() functions require either a module name or a bus ID, + * which we don't have, so bypass them. The automatic module loading and + * device node creation from drmOpen() is of no practical use as any + * modern system will handle that through udev or an equivalent + * component. + */ + DIR *folder = opendir(dirName.c_str()); + if (!folder) { + ret = -errno; + std::cerr << "Failed to open " << dirName + << " directory: " << strerror(-ret) << std::endl; + return ret; + } + + for (struct dirent *res; (res = readdir(folder));) { + if (strncmp(res->d_name, "card", 4)) + continue; + + const std::string devName = dirName + res->d_name; + fd_ = open(devName.c_str(), O_RDWR | O_CLOEXEC); + if (fd_ >= 0) { + ret = 0; + break; + } + + ret = -errno; + std::cerr << "Failed to open DRM/KMS device " << devName << ": " + << strerror(-ret) << std::endl; + } + + closedir(folder); + + return ret; +} + int Device::getResources() { int ret; diff --git a/src/cam/drm.h b/src/cam/drm.h index de57e445..655a7509 100644 --- a/src/cam/drm.h +++ b/src/cam/drm.h @@ -311,6 +311,7 @@ private: Device &operator=(const Device &) = delete; Device &operator=(const Device &&) = delete; + int openCard(); int getResources(); void drmEvent(); |