@@ -15,6 +15,9 @@ namespace sysfs {
std::string charDevPath(const std::string &deviceNode);
+std::string devicePath(const std::string &deviceNode);
+std::string devicePath(unsigned int deviceMajor, unsigned int deviceMinor);
+
std::string firmwareNodePath(const std::string &device);
} /* namespace sysfs */
@@ -9,6 +9,7 @@
#include <fstream>
#include <sstream>
+#include <stdlib.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
@@ -26,6 +27,26 @@ LOG_DEFINE_CATEGORY(SysFs)
namespace sysfs {
+namespace {
+
+/*
+ * Resolve the "device" symbolic link of a sysfs character device directory to
+ * the sysfs path of the physical device associated with it.
+ */
+std::string resolveDevicePath(const std::string &charDevDir)
+{
+ char *realPath = realpath((charDevDir + "/device").c_str(), nullptr);
+ if (!realPath)
+ return {};
+
+ std::string path{ realPath };
+ free(realPath);
+
+ return path;
+}
+
+} /* namespace */
+
/**
* \brief Retrieve the sysfs path for a character device
* \param[in] deviceNode Path to character device node
@@ -49,6 +70,46 @@ std::string charDevPath(const std::string &deviceNode)
return dev.str();
}
+/**
+ * \brief Retrieve the sysfs path of the physical device for a character device
+ * \param[in] deviceNode Path to character device node
+ *
+ * Retrieve the sysfs path of the physical device associated with the character
+ * device \a deviceNode. The path is absolute and contains no symbolic link.
+ *
+ * \return The device path on success or an empty string on failure
+ */
+std::string devicePath(const std::string &deviceNode)
+{
+ std::string path = charDevPath(deviceNode);
+ if (path.empty())
+ return {};
+
+ return resolveDevicePath(path);
+}
+
+/**
+ * \brief Retrieve the sysfs path of the physical device for a character device
+ * \param[in] deviceMajor The character device major number
+ * \param[in] deviceMinor The character device minor number
+ *
+ * Retrieve the sysfs path of the physical device associated with the character
+ * device identified by \a deviceMajor and \a deviceMinor. The path is absolute
+ * and contains no symbolic link.
+ *
+ * Unlike the device node variant of this function, resolving the device from
+ * its device numbers requires no access to the device node itself.
+ *
+ * \return The device path on success or an empty string on failure
+ */
+std::string devicePath(unsigned int deviceMajor, unsigned int deviceMinor)
+{
+ std::ostringstream dev("/sys/dev/char/", std::ios_base::ate);
+ dev << deviceMajor << ":" << deviceMinor;
+
+ return resolveDevicePath(dev.str());
+}
+
/**
* \brief Retrieve the path of the firmware node for a device
* \param[in] device Path in sysfs to search
@@ -454,17 +454,10 @@ const struct v4l2_query_ext_ctrl *V4L2Device::controlInfo(uint32_t id) const
*/
std::string V4L2Device::devicePath() const
{
- std::string devicePath = sysfs::charDevPath(deviceNode_) + "/device";
-
- char *realPath = realpath(devicePath.c_str(), nullptr);
- if (!realPath) {
+ std::string path = sysfs::devicePath(deviceNode_);
+ if (path.empty())
LOG(V4L2, Fatal)
- << "Can not resolve device path for " << devicePath;
- return {};
- }
-
- std::string path{ realPath };
- free(realPath);
+ << "Can not resolve device path for " << deviceNode_;
return path;
}
Add sysfs::devicePath() helpers to resolve the sysfs path of the device via a character device from either the device node or the device major and minor numbers. The helper is used in V4L2Device::devicePath(), replacing the baked in logic there. Signed-off-by: Naushir Patuck <naush@raspberrypi.com> --- include/libcamera/internal/sysfs.h | 3 ++ src/libcamera/sysfs.cpp | 61 ++++++++++++++++++++++++++++++ src/libcamera/v4l2_device.cpp | 13 ++----- 3 files changed, 67 insertions(+), 10 deletions(-)