The scope of File::exists() was changed to only validate that a file
exists and is therefore not usable to check if a directory exists. This
breaks the persistent name generation for DT based systems as it uses
File::exists() to check for directories, fix this by using stat()
directly.
On Scarlet the persistent names of the cameras are impacted by this and
where incorrectly reported as:
$ cam -l
Available cameras:
1: Internal front camera (platform/ff160000.i2c/i2c-7/7-003c ov2685)
2: Internal front camera (platform/ff160000.i2c/i2c-7/7-0036 ov5695
While the expected ones are restored with this fix:
$ cam -l
Available cameras:
1: Internal front camera (/base/i2c@ff160000/camera@3c)
2: Internal front camera (/base/i2c@ff160000/camera@36)
Fixes: 8f4e16f014 ("test: file: Check that directories are not treated as files")
Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
112 lines
2.7 KiB
C++
112 lines
2.7 KiB
C++
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
/*
|
|
* Copyright (C) 2020, Google Inc.
|
|
*
|
|
* sysfs.cpp - Miscellaneous utility functions to access sysfs
|
|
*/
|
|
|
|
#include "libcamera/internal/sysfs.h"
|
|
|
|
#include <fstream>
|
|
#include <sstream>
|
|
#include <sys/stat.h>
|
|
#include <sys/sysmacros.h>
|
|
|
|
#include "libcamera/internal/file.h"
|
|
#include "libcamera/internal/log.h"
|
|
|
|
/**
|
|
* \file sysfs.h
|
|
* \brief Miscellaneous utility functions to access sysfs
|
|
*/
|
|
|
|
namespace libcamera {
|
|
|
|
LOG_DEFINE_CATEGORY(SysFs)
|
|
|
|
namespace sysfs {
|
|
|
|
/**
|
|
* \brief Retrieve the sysfs path for a character device
|
|
* \param[in] deviceNode Path to character device node
|
|
* \return The sysfs path on success or an empty string on failure
|
|
*/
|
|
std::string charDevPath(const std::string &deviceNode)
|
|
{
|
|
struct stat st;
|
|
int ret = stat(deviceNode.c_str(), &st);
|
|
if (ret < 0) {
|
|
ret = -errno;
|
|
LOG(SysFs, Error)
|
|
<< "Unable to stat '" << deviceNode << "': "
|
|
<< strerror(-ret);
|
|
return {};
|
|
}
|
|
|
|
std::ostringstream dev("/sys/dev/char/", std::ios_base::ate);
|
|
dev << major(st.st_rdev) << ":" << minor(st.st_rdev);
|
|
|
|
return dev.str();
|
|
}
|
|
|
|
/**
|
|
* \brief Retrieve the path of the firmware node for a device
|
|
* \param[in] device Path in sysfs to search
|
|
*
|
|
* Physical devices in a system are described by the system firmware. Depending
|
|
* on the type of platform, devices are identified using different naming
|
|
* schemes. The Linux kernel abstract those differences with "firmware nodes".
|
|
* This function retrieves the firmware node path corresponding to the
|
|
* \a device.
|
|
*
|
|
* For DT-based systems, the path is the full name of the DT node that
|
|
* represents the device. For ACPI-based systems, the path is the absolute
|
|
* namespace path to the ACPI object that represents the device. In both cases,
|
|
* the path is guaranteed to be unique and persistent as long as the system
|
|
* firmware is not modified.
|
|
*
|
|
* \return The firmware node path on success or an empty string on failure
|
|
*/
|
|
std::string firmwareNodePath(const std::string &device)
|
|
{
|
|
std::string fwPath, node;
|
|
struct stat st;
|
|
|
|
/* Lookup for DT-based systems */
|
|
node = device + "/of_node";
|
|
if (!stat(node.c_str(), &st)) {
|
|
char *ofPath = realpath(node.c_str(), nullptr);
|
|
if (!ofPath)
|
|
return {};
|
|
|
|
static const char prefix[] = "/sys/firmware/devicetree";
|
|
if (strncmp(ofPath, prefix, strlen(prefix)) == 0)
|
|
fwPath = ofPath + strlen(prefix);
|
|
else
|
|
fwPath = ofPath;
|
|
|
|
free(ofPath);
|
|
|
|
return fwPath;
|
|
}
|
|
|
|
/* Lookup for ACPI-based systems */
|
|
node = device + "/firmware_node/path";
|
|
if (File::exists(node)) {
|
|
std::ifstream file(node);
|
|
if (!file.is_open())
|
|
return {};
|
|
|
|
std::getline(file, fwPath);
|
|
file.close();
|
|
|
|
return fwPath;
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
} /* namespace sysfs */
|
|
|
|
} /* namespace libcamera */
|