Add getSubtree and getAllProperties functions

These will be used to get callout information from
the inventory.

Also added a helper function getService to find a service
name in the GetSubtree data based on an object
path and interface name.

Tested:  The functions work when called in future commit.

Change-Id: Ib9af94263506041c353fa813167051559c30bcac
Signed-off-by: Matt Spinler <spinler@us.ibm.com>
diff --git a/dbus.cpp b/dbus.cpp
index 17ad210..06b0078 100644
--- a/dbus.cpp
+++ b/dbus.cpp
@@ -21,6 +21,13 @@
 namespace logging
 {
 
+constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
+constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";
+constexpr auto MAPPER_IFACE = "xyz.openbmc_project.ObjectMapper";
+constexpr auto PROPERTY_IFACE = "org.freedesktop.DBus.Properties";
+
+using namespace phosphor::logging;
+
 ObjectValueTree getManagedObjects(sdbusplus::bus::bus& bus,
                                   const std::string& service,
                                   const std::string& objPath)
@@ -35,8 +42,8 @@
 
     if (reply.is_method_error())
     {
-        using namespace phosphor::logging;
         log<level::ERR>("Failed to get managed objects",
+                        entry("SERVICE=%s", service.c_str()),
                         entry("PATH=%s", objPath.c_str()));
     }
     else
@@ -46,5 +53,81 @@
 
     return interfaces;
 }
+
+DbusPropertyMap getAllProperties(sdbusplus::bus::bus& bus,
+                                 const std::string& service,
+                                 const std::string& objPath,
+                                 const std::string& interface)
+{
+    DbusPropertyMap properties;
+
+    auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
+                                      PROPERTY_IFACE, "GetAll");
+    method.append(interface);
+    auto reply = bus.call(method);
+
+    if (reply.is_method_error())
+    {
+        log<level::ERR>("Failed to get all properties",
+                        entry("SERVICE=%s", service.c_str()),
+                        entry("PATH=%s", objPath.c_str()),
+                        entry("INTERFACE=%s", interface.c_str()));
+    }
+    else
+    {
+        reply.read(properties);
+    }
+
+    return properties;
+}
+
+DbusSubtree getSubtree(sdbusplus::bus::bus& bus, const std::string& root,
+                       size_t depth, const std::string& interface)
+{
+    DbusSubtree tree;
+
+    auto method = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH, MAPPER_IFACE,
+                                      "GetSubTree");
+    method.append(root);
+    method.append(depth);
+    method.append(std::vector<std::string>({interface}));
+    auto reply = bus.call(method);
+
+    if (reply.is_method_error())
+    {
+        log<level::ERR>("Failed to get subtree", entry("ROOT=%s", root.c_str()),
+                        entry("INTERFACE=%s", interface.c_str()));
+    }
+    else
+    {
+        reply.read(tree);
+    }
+
+    return tree;
+}
+
+DbusService getService(const std::string& objPath, const std::string& interface,
+                       const DbusSubtree& tree)
+{
+    DbusService service;
+
+    auto services = tree.find(objPath);
+    if (services != tree.end())
+    {
+        auto s = std::find_if(services->second.begin(), services->second.end(),
+                              [&interface](const auto& entry) {
+                                  auto i =
+                                      std::find(entry.second.begin(),
+                                                entry.second.end(), interface);
+                                  return i != entry.second.end();
+                              });
+        if (s != services->second.end())
+        {
+            service = s->first;
+        }
+    }
+
+    return service;
+}
 }
 }