summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiklas Söderlund <niklas.soderlund@ragnatech.se>2020-08-03 18:35:09 +0200
committerNiklas Söderlund <niklas.soderlund@ragnatech.se>2020-08-05 20:07:13 +0200
commit39efe737746d6da8e4819f41b6e4069c4b09d359 (patch)
tree5dc4a23ce0061e509ffd0d54965500c7eefea0bf
parent6ad3258cd34295611e871edf5e8474d4aa79af59 (diff)
libcamera: sysfs: Add helper to lookup device firmware node path
A system's firmware description is recorded differently in sysfs depending if the system uses DT or ACPI. Add a helper to abstract this, allowing users not to care which of the two are used. 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. Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-rw-r--r--include/libcamera/internal/sysfs.h2
-rw-r--r--src/libcamera/sysfs.cpp58
2 files changed, 60 insertions, 0 deletions
diff --git a/include/libcamera/internal/sysfs.h b/include/libcamera/internal/sysfs.h
index 247a376a..bc6c1620 100644
--- a/include/libcamera/internal/sysfs.h
+++ b/include/libcamera/internal/sysfs.h
@@ -15,6 +15,8 @@ namespace sysfs {
std::string charDevPath(const std::string &deviceNode);
+std::string firmwareNodePath(const std::string &device);
+
} /* namespace sysfs */
} /* namespace libcamera */
diff --git a/src/libcamera/sysfs.cpp b/src/libcamera/sysfs.cpp
index 398df2c2..6c8e9554 100644
--- a/src/libcamera/sysfs.cpp
+++ b/src/libcamera/sysfs.cpp
@@ -7,10 +7,12 @@
#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"
/**
@@ -47,6 +49,62 @@ std::string charDevPath(const std::string &deviceNode)
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;
+
+ /* Lookup for DT-based systems */
+ node = device + "/of_node";
+ if (File::exists(node)) {
+ 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 */