pseq: Retrieve compatible systems from EM

Retrieve compatible systems value from entity manager using appropriate
D-Bus methods.  Will be used to load correct configuration file
containing system rail and pin information.

Signed-off-by: Jim Wright <jlwright@us.ibm.com>
Change-Id: I040b4fcb182f752e5ac1a3c930b53464eebef2da
diff --git a/phosphor-power-sequencer/src/ucd90320_monitor.cpp b/phosphor-power-sequencer/src/ucd90320_monitor.cpp
index 36301b4..cd798d5 100644
--- a/phosphor-power-sequencer/src/ucd90320_monitor.cpp
+++ b/phosphor-power-sequencer/src/ucd90320_monitor.cpp
@@ -16,20 +16,132 @@
 
 #include "ucd90320_monitor.hpp"
 
-#include <fmt/format.h>
+#include "utility.hpp"
 
+#include <fmt/format.h>
+#include <fmt/ranges.h>
+
+#include <phosphor-logging/log.hpp>
+#include <sdbusplus/bus.hpp>
+
+#include <map>
 #include <string>
 
 namespace phosphor::power::sequencer
 {
 
+using namespace phosphor::logging;
+using namespace phosphor::power;
+
+const std::string compatibleInterface =
+    "xyz.openbmc_project.Configuration.IBMCompatibleSystem";
+const std::string compatibleNamesProperty = "Names";
+
 UCD90320Monitor::UCD90320Monitor(sdbusplus::bus::bus& bus, std::uint8_t i2cBus,
                                  std::uint16_t i2cAddress) :
     PowerSequencerMonitor(),
-    bus{bus}, interface {
-    fmt::format("/sys/bus/i2c/devices/{}-{:04x}", i2cBus, i2cAddress).c_str(),
-        "ucd9000", 0
+    bus{bus}, match{bus,
+                    sdbusplus::bus::match::rules::interfacesAdded() +
+                        sdbusplus::bus::match::rules::sender(
+                            "xyz.openbmc_project.EntityManager"),
+                    std::bind(&UCD90320Monitor::interfacesAddedHandler, this,
+                              std::placeholders::_1)},
+    pmbusInterface{
+        fmt::format("/sys/bus/i2c/devices/{}-{:04x}", i2cBus, i2cAddress)
+            .c_str(),
+        "ucd9000", 0}
+
+{
+    // Use the compatible system types information, if already available, to
+    // load the configuration file
+    findCompatibleSystemTypes();
 }
-{}
+
+void UCD90320Monitor::findCompatibleSystemTypes()
+{
+    try
+    {
+        auto subTree = util::getSubTree(bus, "/xyz/openbmc_project/inventory",
+                                        compatibleInterface, 0);
+
+        auto objectIt = subTree.cbegin();
+        if (objectIt != subTree.cend())
+        {
+            const auto& objPath = objectIt->first;
+
+            // Get the first service name
+            auto serviceIt = objectIt->second.cbegin();
+            if (serviceIt != objectIt->second.cend())
+            {
+                std::string service = serviceIt->first;
+                if (!service.empty())
+                {
+                    std::vector<std::string> compatibleSystemTypes;
+
+                    // Get compatible system types property value
+                    util::getProperty(compatibleInterface,
+                                      compatibleNamesProperty, objPath, service,
+                                      bus, compatibleSystemTypes);
+
+                    log<level::DEBUG>(
+                        fmt::format("Found compatible systems: {}",
+                                    compatibleSystemTypes)
+                            .c_str());
+                    // Use compatible systems information to find config file
+                }
+            }
+        }
+    }
+    catch (const std::exception&)
+    {
+        // Compatible system types information is not available.
+    }
+}
+
+void UCD90320Monitor::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, std::variant<std::vector<std::string>>>>
+            interfaces;
+        msg.read(objPath, interfaces);
+
+        // Find the compatible interface, if present
+        auto itIntf = interfaces.find(compatibleInterface);
+        if (itIntf != interfaces.cend())
+        {
+            // Find the Names property of the compatible interface, if present
+            auto itProp = itIntf->second.find(compatibleNamesProperty);
+            if (itProp != itIntf->second.cend())
+            {
+                // Get value of Names property
+                const auto& propValue = std::get<0>(itProp->second);
+                if (!propValue.empty())
+                {
+                    log<level::INFO>(
+                        fmt::format(
+                            "InterfacesAdded for compatible systems: {}",
+                            propValue)
+                            .c_str());
+
+                    // Use compatible systems information to find config file
+                }
+            }
+        }
+    }
+    catch (const std::exception&)
+    {
+        // Error trying to read interfacesAdded message.
+    }
+}
 
 } // namespace phosphor::power::sequencer
diff --git a/phosphor-power-sequencer/src/ucd90320_monitor.hpp b/phosphor-power-sequencer/src/ucd90320_monitor.hpp
index 9512190..ce6af97 100644
--- a/phosphor-power-sequencer/src/ucd90320_monitor.hpp
+++ b/phosphor-power-sequencer/src/ucd90320_monitor.hpp
@@ -4,6 +4,7 @@
 #include "power_sequencer_monitor.hpp"
 
 #include <sdbusplus/bus.hpp>
+#include <sdbusplus/bus/match.hpp>
 
 namespace phosphor::power::sequencer
 {
@@ -32,6 +33,12 @@
     UCD90320Monitor(sdbusplus::bus::bus& bus, std::uint8_t i2cBus,
                     const std::uint16_t i2cAddress);
 
+    /**
+     * Callback function to handle interfacesAdded D-Bus signals
+     * @param msg Expanded sdbusplus message data
+     */
+    void interfacesAddedHandler(sdbusplus::message::message& msg);
+
   private:
     /**
      * The D-Bus bus object
@@ -39,9 +46,21 @@
     sdbusplus::bus::bus& bus;
 
     /**
+     * The match to Entity Manager interfaces added.
+     */
+    sdbusplus::bus::match_t match;
+
+    /**
      * The read/write interface to this hardware
      */
-    pmbus::PMBus interface;
+    pmbus::PMBus pmbusInterface;
+
+    /**
+     * Finds the list of compatible system types using D-Bus methods.
+     * This list is used to find the correct JSON configuration file for the
+     * current system.
+     */
+    void findCompatibleSystemTypes();
 };
 
 } // namespace phosphor::power::sequencer