ipmi: add zone controller interface

Implementations of this interface can make the library mode testable and
work in environments other than dbus.

The main entry point to the IPMI handler now expects to receive a
handler pointer.  The handler itself is implemented to process IPMI
requests and responses in the expected way.  The default object receives
a dbus implementation for the zone controls.

Signed-off-by: Patrick Venture <venture@google.com>
Change-Id: I6d7be871bdc5cce3c3cc53c16d80b501aaaafc7d
diff --git a/ipmi/manualcmds.cpp b/ipmi/manualcmds.cpp
index 5dcac09..0ff0c0a 100644
--- a/ipmi/manualcmds.cpp
+++ b/ipmi/manualcmds.cpp
@@ -16,6 +16,7 @@
 
 #include "manualcmds.hpp"
 
+#include "control.hpp"
 #include "dbus_mode.hpp"
 #include "manual_messages.hpp"
 
@@ -25,6 +26,7 @@
 #include <sdbusplus/message.hpp>
 
 #include <map>
+#include <memory>
 #include <string>
 #include <tuple>
 #include <variant>
@@ -34,25 +36,12 @@
 namespace ipmi
 {
 
-static constexpr auto objectPath = "/xyz/openbmc_project/settings/fanctrl/zone";
-static constexpr auto busName = "xyz.openbmc_project.State.FanCtrl";
-static constexpr auto intf = "xyz.openbmc_project.Control.Mode";
 static constexpr auto manualProperty = "Manual";
 static constexpr auto failsafeProperty = "FailSafe";
-static constexpr auto propertiesintf = "org.freedesktop.DBus.Properties";
 
-using Property = std::string;
-using Value = std::variant<bool>;
-using PropertyMap = std::map<Property, Value>;
-
-/* The following was copied directly from my manual thread handler. */
-static std::string getControlPath(int8_t zone)
-{
-    return std::string(objectPath) + std::to_string(zone);
-}
-
-static ipmi_ret_t getFailsafeModeState(const uint8_t* reqBuf, uint8_t* replyBuf,
-                                       size_t* dataLen)
+ipmi_ret_t ZoneControlIpmiHandler::getFailsafeModeState(const uint8_t* reqBuf,
+                                                        uint8_t* replyBuf,
+                                                        size_t* dataLen)
 {
     bool current;
 
@@ -65,7 +54,7 @@
         reinterpret_cast<const struct FanCtrlRequest*>(&reqBuf[0]);
 
     ipmi_ret_t rc =
-        getFanCtrlProperty(request->zone, &current, failsafeProperty);
+        _control->getFanCtrlProperty(request->zone, &current, failsafeProperty);
     if (rc)
     {
         return rc;
@@ -82,8 +71,9 @@
  *   <arg name="properties" direction="out" type="a{sv}"/>
  * </method>
  */
-static ipmi_ret_t getManualModeState(const uint8_t* reqBuf, uint8_t* replyBuf,
-                                     size_t* dataLen)
+ipmi_ret_t ZoneControlIpmiHandler::getManualModeState(const uint8_t* reqBuf,
+                                                      uint8_t* replyBuf,
+                                                      size_t* dataLen)
 {
     bool current;
 
@@ -95,7 +85,8 @@
     const auto request =
         reinterpret_cast<const struct FanCtrlRequest*>(&reqBuf[0]);
 
-    ipmi_ret_t rc = getFanCtrlProperty(request->zone, &current, manualProperty);
+    ipmi_ret_t rc =
+        _control->getFanCtrlProperty(request->zone, &current, manualProperty);
     if (rc)
     {
         return rc;
@@ -113,51 +104,28 @@
  *   <arg name="value" direction="in" type="v"/>
  * </method>
  */
-static ipmi_ret_t setManualModeState(const uint8_t* reqBuf, uint8_t* replyBuf,
-                                     size_t* dataLen)
+ipmi_ret_t ZoneControlIpmiHandler::setManualModeState(const uint8_t* reqBuf,
+                                                      uint8_t* replyBuf,
+                                                      size_t* dataLen)
 {
     if (*dataLen < sizeof(struct FanCtrlRequestSet))
     {
         return IPMI_CC_INVALID;
     }
 
-    using Value = std::variant<bool>;
-
     const auto request =
         reinterpret_cast<const struct FanCtrlRequestSet*>(&reqBuf[0]);
 
     /* 0 is false, 1 is true */
-    bool setValue = static_cast<bool>(request->value);
-    Value v{setValue};
-
-    auto PropertyWriteBus = sdbusplus::bus::new_system();
-
-    std::string path = getControlPath(request->zone);
-
-    auto pimMsg = PropertyWriteBus.new_method_call(busName, path.c_str(),
-                                                   propertiesintf, "Set");
-    pimMsg.append(intf);
-    pimMsg.append(manualProperty);
-    pimMsg.append(v);
-
-    ipmi_ret_t rc = IPMI_CC_OK;
-
-    try
-    {
-        PropertyWriteBus.call_noreply(pimMsg);
-    }
-    catch (const sdbusplus::exception::SdBusError& ex)
-    {
-        rc = IPMI_CC_INVALID;
-    }
-    /* TODO(venture): Should sanity check the result. */
-
+    ipmi_ret_t rc = _control->setFanCtrlProperty(
+        request->zone, static_cast<bool>(request->value), manualProperty);
     return rc;
 }
 
 /* Three command packages: get, set true, set false */
-ipmi_ret_t manualModeControl(ipmi_cmd_t cmd, const uint8_t* reqBuf,
-                             uint8_t* replyCmdBuf, size_t* dataLen)
+ipmi_ret_t manualModeControl(ZoneControlIpmiHandler* handler, ipmi_cmd_t cmd,
+                             const uint8_t* reqBuf, uint8_t* replyCmdBuf,
+                             size_t* dataLen)
 {
     // FanCtrlRequest is the smaller of the requests, so it's at a minimum.
     if (*dataLen < sizeof(struct FanCtrlRequest))
@@ -173,11 +141,11 @@
     switch (request->command)
     {
         case getControlState:
-            return getManualModeState(reqBuf, replyCmdBuf, dataLen);
+            return handler->getManualModeState(reqBuf, replyCmdBuf, dataLen);
         case setControlState:
-            return setManualModeState(reqBuf, replyCmdBuf, dataLen);
+            return handler->setManualModeState(reqBuf, replyCmdBuf, dataLen);
         case getFailsafeState:
-            return getFailsafeModeState(reqBuf, replyCmdBuf, dataLen);
+            return handler->getFailsafeModeState(reqBuf, replyCmdBuf, dataLen);
         default:
             rc = IPMI_CC_INVALID;
     }