DeviceMgmt: add I2CDeviceParams::deviceStatic() method

This will be used to determine whether a given i2c device is statically
instantiated via a device tree or if it's a dynamically-created device
managed by userspace.  As dbus-sensors daemons assume responsibility for
device lifecycle management this can be used to distinguish between
static and dynamic device nodes even if a previous process crashed after
instantiating one (whereas a simple presence check might mistake a
device that was instantiated but not cleaned up for a static device and
thus never remove it).

Signed-off-by: Zev Weiss <zev@bewilderbeest.net>
Change-Id: I3911b0cace60689766993a8be3b8f160f71de2d1
diff --git a/include/DeviceMgmt.hpp b/include/DeviceMgmt.hpp
index 3eaf897..4a5b7a1 100644
--- a/include/DeviceMgmt.hpp
+++ b/include/DeviceMgmt.hpp
@@ -25,6 +25,7 @@
     uint64_t address;
 
     bool devicePresent(void) const;
+    bool deviceStatic(void) const;
 };
 
 std::optional<I2CDeviceParams>
diff --git a/src/DeviceMgmt.cpp b/src/DeviceMgmt.cpp
index fdf7577..f137908 100644
--- a/src/DeviceMgmt.cpp
+++ b/src/DeviceMgmt.cpp
@@ -63,6 +63,21 @@
     return fs::exists(path, ec);
 }
 
+bool I2CDeviceParams::deviceStatic(void) const
+{
+    if (!devicePresent())
+    {
+        return false;
+    }
+
+    fs::path ofNode = i2cBusPath(bus) / deviceDirName(bus, address) / "of_node";
+
+    // Ignore errors -- if of_node is present the device is a static DT node;
+    // otherwise we can assume we created it from userspace.
+    std::error_code ec;
+    return fs::exists(ofNode, ec);
+}
+
 I2CDevice::I2CDevice(I2CDeviceParams params) : params(params)
 {
     if (create() != 0)