Read the PCIe Cable card's presence GPIO

Take pre and post action based on it's presence on PASS2 planar.
Smae action on PASS1 planar will be independent of presence.
If presence GPIO says it is Present then enable the output line.

Test-
DBG: Processing - /sys/bus/i2c/drivers/at24/20-0050/eeprom, for presence Node
DBG:presPinName-SLOT0_EXPANDER_PRSNT_N
DBG:presenceLine INPUT request done

DBG:Device not attached, but forcing to take action

DBG:preAction executing...
Setting GPIO: SLOT0_PRSNT_EN_RSVD to 1
DBG: Output pin Updated

Binding device 20-0050
echo "20-0050" > /sys/bus/i2c/drivers/at24/bind
sh: line 1: echo: write error: No such device
EEPROM /sys/bus/i2c/drivers/at24/20-0050/eeprom does not exist. Take failure action
Setting GPIO: SLOT0_PRSNT_EN_RSVD to 0

Tested on rain104bmc-
pin - SLOT0_EXPANDER_PRSNT_N
value - 0
presence pin state is- 0,i.e. it is present.
Setting output GPIO: SLOT0_PRSNT_EN_RSVD to 1

Change-Id: I055cb3598358fb36ad4fd986b5d96ff7aaccda73
Signed-off-by: Alpana Kumari <alpankum@in.ibm.com>
diff --git a/ibm_vpd_app.cpp b/ibm_vpd_app.cpp
index 14d405f..cf37259 100644
--- a/ibm_vpd_app.cpp
+++ b/ibm_vpd_app.cpp
@@ -434,58 +434,94 @@
     }
 }
 
-/** Performs any pre-action needed to get the FRU setup for collection.
+/**
+ * @brief This sets the appropriate value to presence GPIO based on device
+ * attached or not on expander GPIO, which enables that FRU's VPD collection.
  *
  * @param[in] json - json object
  * @param[in] file - eeprom file path
  */
 static void preAction(const nlohmann::json& json, const string& file)
 {
-    if ((json["frus"][file].at(0)).find("preAction") ==
+    if ((json["frus"][file].at(0)).find("presence") !=
         json["frus"][file].at(0).end())
     {
-        return;
+        if (((json["frus"][file].at(0)["presence"]).find("pin") !=
+             json["frus"][file].at(0)["presence"].end()) &&
+            ((json["frus"][file].at(0)["presence"]).find("value") !=
+             json["frus"][file].at(0)["presence"].end()))
+        {
+            Byte presPinName = json["frus"][file].at(0)["presence"]["pin"];
+            string presPinValue = json["frus"][file].at(0)["presence"]["value"];
+
+            try
+            {
+                gpiod::line presenceLine = gpiod::find_line(presPinName);
+
+                if (!presenceLine)
+                {
+                    cerr << "couldn't find presence line:" << presPinName
+                         << "\n";
+                    return;
+                }
+
+                presenceLine.request({"Read the presence line",
+                                      gpiod::line_request::DIRECTION_INPUT, 0});
+
+                Byte gpioData = presenceLine.get_value();
+
+                if (gpioData != presPinValue)
+                {
+                    return;
+                }
+            }
+            catch (system_error&)
+            {
+                cerr << "Failed to get the presence GPIO for - " << presPinName
+                     << endl;
+                return;
+            }
+        }
     }
 
-    uint8_t pinValue = 0;
-    string pinName;
-
-    for (const auto& postAction :
-         (json["frus"][file].at(0))["preAction"].items())
+    if ((json["frus"][file].at(0)).find("preAction") !=
+        json["frus"][file].at(0).end())
     {
-        if (postAction.key() == "pin")
+        if (((json["frus"][file].at(0)["preAction"]).find("pin") !=
+             json["frus"][file].at(0)["preAction"].end()) &&
+            ((json["frus"][file].at(0)["preAction"]).find("value") !=
+             json["frus"][file].at(0)["preAction"].end()))
         {
-            pinName = postAction.value();
-        }
-        else if (postAction.key() == "value")
-        {
+            string pinName = json["frus"][file].at(0)["preAction"]["pin"];
             // Get the value to set
-            pinValue = postAction.value();
+            Byte pinValue = json["frus"][file].at(0)["preAction"]["value"];
+
+            cout << "Setting GPIO: " << pinName << " to " << (int)pinValue
+                 << endl;
+            try
+            {
+                gpiod::line outputLine = gpiod::find_line(pinName);
+
+                if (!outputLine)
+                {
+                    cout << "Couldn't find output line:" << pinName
+                         << " on GPIO. Skipping...\n";
+
+                    return;
+                }
+                outputLine.request({"FRU pre-action",
+                                    ::gpiod::line_request::DIRECTION_OUTPUT, 0},
+                                   pinValue);
+            }
+            catch (system_error&)
+            {
+                cerr << "Failed to set pre-action for GPIO - " << pinName
+                     << endl;
+                return;
+            }
         }
     }
 
-    cout << "Setting GPIO: " << pinName << " to " << (int)pinValue << endl;
-    try
-    {
-        gpiod::line outputLine = gpiod::find_line(pinName);
-
-        if (!outputLine)
-        {
-            cout << "Couldn't find output line:" << pinName
-                 << " on GPIO. Skipping...\n";
-
-            return;
-        }
-        outputLine.request(
-            {"FRU pre-action", ::gpiod::line_request::DIRECTION_OUTPUT, 0},
-            pinValue);
-    }
-    catch (const system_error&)
-    {
-        cerr << "Failed to set pre-action GPIO" << endl;
-        return;
-    }
-
     // Now bind the device
     string bind = json["frus"][file].at(0).value("devAddress", "");
     cout << "Binding device " << bind << endl;
@@ -577,10 +613,14 @@
 
     for (auto& itemFRUS : jsObject["frus"].items())
     {
-        // Take pre actions
-        preAction(jsObject, itemFRUS.key());
         for (auto& itemEEPROM : itemFRUS.value())
         {
+            // Take pre actions if needed
+            if (itemEEPROM.find("preAction") != itemEEPROM.end())
+            {
+                preAction(jsObject, itemFRUS.key());
+            }
+
             inventory::InterfaceMap interfaces;
             inventory::Object object(itemEEPROM.at("inventoryPath"));