Delay opening OCC device until bind

Fixes openbmc/openbmc#2118

Change-Id: If9e2610fe7443daa2196b0e5989f81bc544266b2
Signed-off-by: Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com>
diff --git a/occ_pass_through.cpp b/occ_pass_through.cpp
index 2846dda..4a7057b 100644
--- a/occ_pass_through.cpp
+++ b/occ_pass_through.cpp
@@ -2,11 +2,14 @@
 #include <algorithm>
 #include <fcntl.h>
 #include <errno.h>
+#include <string>
+#include <unistd.h>
 #include <phosphor-logging/log.hpp>
 #include <phosphor-logging/elog.hpp>
 #include <org/open_power/OCC/Device/error.hpp>
 #include "occ_pass_through.hpp"
 #include "elog-errors.hpp"
+#include "config.h"
 namespace open_power
 {
 namespace occ
@@ -17,20 +20,22 @@
     const char* path) :
     Iface(bus, path),
     path(path),
-    fd(openDevice())
+    devicePath(OCC_DEV_PATH + std::to_string((this->path.back() - '0') + 1)),
+    activeStatusSignal(
+            bus,
+            sdbusRule::propertiesChanged(path, "org.open_power.OCC.Status"),
+            std::bind(std::mem_fn(&PassThrough::activeStatusEvent),
+                this, std::placeholders::_1))
 {
     // Nothing to do.
 }
 
-int PassThrough::openDevice()
+void PassThrough::openDevice()
 {
     using namespace phosphor::logging;
     using namespace sdbusplus::org::open_power::OCC::Device::Error;
 
-    // Device instance number starts from 1.
-    devicePath.append(std::to_string((this->path.back() - '0') + 1));
-
-    int fd = open(devicePath.c_str(), O_RDWR | O_NONBLOCK);
+    fd = open(devicePath.c_str(), O_RDWR | O_NONBLOCK);
     if (fd < 0)
     {
         // This would log and terminate since its not handled.
@@ -40,7 +45,15 @@
             phosphor::logging::org::open_power::OCC::Device::
                 OpenFailure::CALLOUT_DEVICE_PATH(devicePath.c_str()));
     }
-    return fd;
+    return;
+}
+
+void PassThrough::closeDevice()
+{
+    if (fd >= 0)
+    {
+        close(fd);
+    }
 }
 
 std::vector<int32_t> PassThrough::send(std::vector<int32_t> command)
@@ -60,7 +73,7 @@
             [](decltype(cmdInBytes)::value_type x){return x;});
 
     ssize_t size = cmdInBytes.size() * sizeof(decltype(cmdInBytes)::value_type);
-    auto rc = write((fd)(), cmdInBytes.data(), size);
+    auto rc = write(fd, cmdInBytes.data(), size);
     if (rc < 0 || (rc != size))
     {
         // This would log and terminate since its not handled.
@@ -75,7 +88,7 @@
     while(1)
     {
         uint8_t data {};
-        auto len = read((fd)(), &data, sizeof(data));
+        auto len = read(fd, &data, sizeof(data));
         if (len > 0)
         {
             response.emplace_back(data);
@@ -105,5 +118,28 @@
     return response;
 }
 
+// Called at OCC Status change signal
+void PassThrough::activeStatusEvent(sdbusplus::message::message& msg)
+{
+    std::string statusInterface;
+    std::map<std::string, sdbusplus::message::variant<bool>> msgData;
+    msg.read(statusInterface, msgData);
+
+    auto propertyMap = msgData.find("OccActive");
+    if (propertyMap != msgData.end())
+    {
+        // Extract the OccActive property
+        if (sdbusplus::message::variant_ns::get<bool>(propertyMap->second))
+        {
+            this->openDevice();
+        }
+        else
+        {
+            this->closeDevice();
+        }
+    }
+    return;
+}
+
 } // namespace occ
 } // namespace open_power