pseq: Retrieve device info from entity manager

Retrieve power sequencer device information from entity manager using
appropriate DBUS methods.

Signed-off-by: Jim Wright <jlwright@us.ibm.com>
Change-Id: I4b0f821345fa9be9146e1a480d2b4e8aabd2c267
diff --git a/phosphor-power-sequencer/src/meson.build b/phosphor-power-sequencer/src/meson.build
index adb8a3f..8f74c7e 100644
--- a/phosphor-power-sequencer/src/meson.build
+++ b/phosphor-power-sequencer/src/meson.build
@@ -15,6 +15,9 @@
         sdeventplus,
         stdplus
     ],
+    link_with: [
+        libpower
+    ],
     implicit_include_directories: false,
     include_directories: phosphor_power_sequencer_include_directories,
     install: true
diff --git a/phosphor-power-sequencer/src/power_control.cpp b/phosphor-power-sequencer/src/power_control.cpp
index 981a957..6e9fa58 100644
--- a/phosphor-power-sequencer/src/power_control.cpp
+++ b/phosphor-power-sequencer/src/power_control.cpp
@@ -17,7 +17,6 @@
 #include "power_control.hpp"
 
 #include "types.hpp"
-#include "utility.hpp"
 
 #include <fmt/format.h>
 #include <sys/types.h>
@@ -36,8 +35,10 @@
 namespace phosphor::power::sequencer
 {
 
-const std::string powerControlLineName = "power-chassis-control";
-const std::string pgoodLineName = "power-chassis-good";
+const std::string interfaceName = "xyz.openbmc_project.Configuration.UCD90320";
+const std::string addressPropertyName = "Address";
+const std::string busPropertyName = "Bus";
+const std::string namePropertyName = "Name";
 
 PowerControl::PowerControl(sdbusplus::bus::bus& bus,
                            const sdeventplus::Event& event) :
@@ -47,9 +48,59 @@
 {
     // Obtain dbus service name
     bus.request_name(POWER_IFACE);
+
+    // Subscribe to D-Bus interfacesAdded signal from Entity Manager.  This
+    // notifies us if the interface becomes available later.
+    match = std::make_unique<sdbusplus::bus::match_t>(
+        bus,
+        sdbusplus::bus::match::rules::interfacesAdded() +
+            sdbusplus::bus::match::rules::sender(
+                "xyz.openbmc_project.EntityManager"),
+        std::bind(&PowerControl::interfacesAddedHandler, this,
+                  std::placeholders::_1));
+    setUpDevice();
     setUpGpio();
 }
 
+void PowerControl::getDeviceProperties(util::DbusPropertyMap& properties)
+{
+    uint64_t* i2cBus = nullptr;
+    uint64_t* i2cAddress = nullptr;
+    std::string* name = nullptr;
+
+    for (const auto& property : properties)
+    {
+        try
+        {
+            if (property.first == busPropertyName)
+            {
+                i2cBus = std::get_if<uint64_t>(&properties[busPropertyName]);
+            }
+            else if (property.first == addressPropertyName)
+            {
+                i2cAddress =
+                    std::get_if<uint64_t>(&properties[addressPropertyName]);
+            }
+            else if (property.first == namePropertyName)
+            {
+                name = std::get_if<std::string>(&properties[namePropertyName]);
+            }
+        }
+        catch (std::exception& e)
+        {}
+    }
+
+    if (i2cBus && i2cAddress && name && !name->empty())
+    {
+        log<level::INFO>(
+            fmt::format(
+                "Found power sequencer device properties, name: {}, bus: {} addr: {:#02x} ",
+                *name, *i2cBus, *i2cAddress)
+                .c_str());
+        // Create device object
+    }
+}
+
 int PowerControl::getPgood() const
 {
     return pgood;
@@ -65,6 +116,37 @@
     return state;
 }
 
+void PowerControl::interfacesAddedHandler(sdbusplus::message::message& msg)
+{
+    // Verify message is valid
+    if (!msg)
+    {
+        return;
+    }
+
+    try
+    {
+        // Read the dbus message
+        sdbusplus::message::object_path objPath;
+        std::map<std::string, std::map<std::string, util::DbusVariant>>
+            interfaces;
+        msg.read(objPath, interfaces);
+
+        // Find the device interface, if present
+        auto itIntf = interfaces.find(interfaceName);
+        if (itIntf != interfaces.cend())
+        {
+            log<level::INFO>(
+                fmt::format("InterfacesAdded for: {}", interfaceName).c_str());
+            getDeviceProperties(itIntf->second);
+        }
+    }
+    catch (const std::exception&)
+    {
+        // Error trying to read interfacesAdded message.
+    }
+}
+
 void PowerControl::pollPgood()
 {
     if (inStateTransition)
@@ -179,8 +261,41 @@
     emitPropertyChangedSignal("state");
 }
 
+void PowerControl::setUpDevice()
+{
+    try
+    {
+        auto objects = util::getSubTree(bus, "/", interfaceName, 0);
+
+        // Search for matching interface in returned objects
+        for (const auto& [path, services] : objects)
+        {
+            auto service = services.begin()->first;
+
+            if (path.empty() || service.empty())
+            {
+                continue;
+            }
+
+            // Get the properties for the device interface
+            auto properties =
+                util::getAllProperties(bus, path, interfaceName, service);
+
+            getDeviceProperties(properties);
+        }
+    }
+    catch (const std::exception& e)
+    {
+        // Interface or property not found. Let the Interfaces Added callback
+        // process the information once the interfaces are added to D-Bus.
+    }
+}
+
 void PowerControl::setUpGpio()
 {
+    const std::string powerControlLineName = "power-chassis-control";
+    const std::string pgoodLineName = "power-chassis-good";
+
     pgoodLine = gpiod::find_line(pgoodLineName);
     if (!pgoodLine)
     {
diff --git a/phosphor-power-sequencer/src/power_control.hpp b/phosphor-power-sequencer/src/power_control.hpp
index 4359074..1699dcc 100644
--- a/phosphor-power-sequencer/src/power_control.hpp
+++ b/phosphor-power-sequencer/src/power_control.hpp
@@ -1,9 +1,11 @@
 #pragma once
 
 #include "power_interface.hpp"
+#include "utility.hpp"
 
 #include <gpiod.hpp>
 #include <sdbusplus/bus.hpp>
+#include <sdbusplus/bus/match.hpp>
 #include <sdbusplus/message.hpp>
 #include <sdbusplus/server/object.hpp>
 #include <sdeventplus/clock.hpp>
@@ -48,6 +50,12 @@
     /** @copydoc PowerInterface::getState() */
     int getState() const override;
 
+    /**
+     * Callback function to handle interfacesAdded D-Bus signals
+     * @param msg Expanded sdbusplus message data
+     */
+    void interfacesAddedHandler(sdbusplus::message::message& msg);
+
     /** @copydoc PowerInterface::setPgoodTimeout() */
     void setPgoodTimeout(int timeout) override;
 
@@ -66,6 +74,11 @@
     bool inStateTransition{false};
 
     /**
+     * The match to Entity Manager interfaces added.
+     */
+    std::unique_ptr<sdbusplus::bus::match_t> match;
+
+    /**
      * Power good
      */
     int pgood{0};
@@ -113,11 +126,22 @@
     sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> timer;
 
     /**
+     * Get the device properties
+     * @param[in] properties A map of property names and values
+     */
+    void getDeviceProperties(util::DbusPropertyMap& properties);
+
+    /**
      * Polling method for monitoring the system power good
      */
     void pollPgood();
 
     /**
+     * Set up power sequencer device
+     */
+    void setUpDevice();
+
+    /**
      * Set up GPIOs
      */
     void setUpGpio();