[libcamera-devel] [PATCH] cam: drm: Support /dev/dri cards other than 0

Jacopo Mondi jacopo at jmondi.org
Wed Jun 1 19:26:31 CEST 2022


Hi Eric

On Wed, Jun 01, 2022 at 04:23:45PM +0100, Eric Curtin via libcamera-devel wrote:
> 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 at redhat.com>
> Signed-off-by: Eric Curtin <ecurtin at redhat.com>
> ---
>  src/cam/drm.cpp | 37 +++++++++++++++++++++++++++----------
>  1 file changed, 27 insertions(+), 10 deletions(-)
>
> diff --git a/src/cam/drm.cpp b/src/cam/drm.cpp
> index 42c5a3b1..5a322819 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,8 +394,10 @@ Device::~Device()
>
>  int Device::init()
>  {
> -	constexpr size_t NODE_NAME_MAX = sizeof("/dev/dri/card255");
> -	char name[NODE_NAME_MAX];
> +	constexpr size_t DIR_NAME_MAX = sizeof("/dev/dri/");
> +	constexpr size_t BASE_NAME_MAX = sizeof("card255");
> +	constexpr size_t NODE_NAME_MAX = DIR_NAME_MAX + BASE_NAME_MAX - 1;
> +	char name[NODE_NAME_MAX] = "/dev/dri/";
>  	int ret;
>
>  	/*
> @@ -404,14 +407,28 @@ int Device::init()
>  	 * 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;
> -		return ret;
> +	DIR *folder = opendir(name);
> +	if (folder) {
> +		for (struct dirent *res; (res = readdir(folder));) {
> +			if (strlen(res->d_name) > 4 &&

I feel this might be a bit simplified, maybe using std::filesystem

	const std::filesystem::path dri("/dev/dri");
	for (const auto &dir : std::filesystem::directory_iterator(dri)) {
		const std::string &direntry = dir.path().filename().string();

		if (direntry.find("card") == std::string::npos)
			continue;

		fd_ = open(dir.path().string().c_str(), O_RDWR | O_CLOEXEC);

                ...
        }

> +			    !strncmp(res->d_name, "card", 4)) {
> +				memcpy(name + DIR_NAME_MAX - 1, res->d_name,
> +				       BASE_NAME_MAX);
> +				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;
> +					continue;
> +				}
> +
> +				break;
> +			}
> +		}
> +
> +		closedir(folder);

What if no card is found ?
Should fd_ be initialized and here checked ?

Thanks
   j

>  	}
>
>  	/*
> --
> 2.35.3
>


More information about the libcamera-devel mailing list