| #include "gpioMonitor.hpp" | 
 |  | 
 | #include "common_utility.hpp" | 
 | #include "ibm_vpd_utils.hpp" | 
 |  | 
 | #include <systemd/sd-event.h> | 
 |  | 
 | #include <chrono> | 
 | #include <gpiod.hpp> | 
 | #include <sdeventplus/clock.hpp> | 
 | #include <sdeventplus/utility/timer.hpp> | 
 |  | 
 | using namespace std; | 
 | using namespace openpower::vpd::constants; | 
 | using sdeventplus::ClockId; | 
 | using sdeventplus::Event; | 
 | using Timer = sdeventplus::utility::Timer<ClockId::Monotonic>; | 
 | using namespace std::chrono_literals; | 
 |  | 
 | namespace openpower | 
 | { | 
 | namespace vpd | 
 | { | 
 | namespace manager | 
 | { | 
 |  | 
 | bool GpioEventHandler::getPresencePinValue() | 
 | { | 
 |     Byte gpioData = 1; | 
 |     gpiod::line presenceLine = gpiod::find_line(presencePin); | 
 |     if (!presenceLine) | 
 |     { | 
 |         cerr << "Error getPresencePinValue: couldn't find presence line:" | 
 |              << presencePin << " on GPIO \n"; | 
 |         // return previous state as we couldn't read current state | 
 |         return prevPresPinValue; | 
 |     } | 
 |  | 
 |     presenceLine.request( | 
 |         {"Op-panel presence line", gpiod::line_request::DIRECTION_INPUT, 0}); | 
 |  | 
 |     gpioData = presenceLine.get_value(); | 
 |  | 
 |     return gpioData; | 
 | } | 
 |  | 
 | void GpioMonitor::initGpioInfos(Event& event) | 
 | { | 
 |     Byte outputValue = 0; | 
 |     Byte presenceValue = 0; | 
 |     string presencePinName{}, outputPinName{}; | 
 |     string devNameAddr{}, driverType{}, busType{}, objectPath{}; | 
 |  | 
 |     for (const auto& eachFRU : jsonFile["frus"].items()) | 
 |     { | 
 |         for (const auto& eachInventory : eachFRU.value()) | 
 |         { | 
 |             objectPath = eachInventory["inventoryPath"]; | 
 |  | 
 |             if ((eachInventory.find("presence") != eachInventory.end()) && | 
 |                 (eachInventory.find("preAction") != eachInventory.end())) | 
 |             { | 
 |                 for (const auto& presStatus : eachInventory["presence"].items()) | 
 |                 { | 
 |                     if (presStatus.key() == "pin") | 
 |                     { | 
 |                         presencePinName = presStatus.value(); | 
 |                     } | 
 |                     else if (presStatus.key() == "value") | 
 |                     { | 
 |                         presenceValue = presStatus.value(); | 
 |                     } | 
 |                 } | 
 |  | 
 |                 // Based on presence pin value, preAction pin will be set/reset | 
 |                 // This action will be taken before vpd collection. | 
 |                 for (const auto& preAction : eachInventory["preAction"].items()) | 
 |                 { | 
 |                     if (preAction.key() == "pin") | 
 |                     { | 
 |                         outputPinName = preAction.value(); | 
 |                     } | 
 |                     else if (preAction.key() == "value") | 
 |                     { | 
 |                         outputValue = preAction.value(); | 
 |                     } | 
 |                 } | 
 |  | 
 |                 devNameAddr = eachInventory["devAddress"]; | 
 |                 driverType = eachInventory["driverType"]; | 
 |                 busType = eachInventory["busType"]; | 
 |  | 
 |                 // Init all Gpio info variables | 
 |                 std::shared_ptr<GpioEventHandler> gpioObj = | 
 |                     make_shared<GpioEventHandler>( | 
 |                         presencePinName, presenceValue, outputPinName, | 
 |                         outputValue, devNameAddr, driverType, busType, | 
 |                         objectPath, event); | 
 |  | 
 |                 gpioObjects.push_back(gpioObj); | 
 |             } | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | void GpioEventHandler::toggleGpio() | 
 | { | 
 |     bool presPinVal = getPresencePinValue(); | 
 |     bool isPresent = false; | 
 |  | 
 |     // preserve the new value | 
 |     prevPresPinValue = presPinVal; | 
 |  | 
 |     if (presPinVal == presenceValue) | 
 |     { | 
 |         isPresent = true; | 
 |     } | 
 |  | 
 |     // if FRU went away set the present property to false | 
 |     if (!isPresent) | 
 |     { | 
 |         inventory::ObjectMap objects; | 
 |         inventory::InterfaceMap interfaces; | 
 |         inventory::PropertyMap presProp; | 
 |  | 
 |         presProp.emplace("Present", false); | 
 |         interfaces.emplace("xyz.openbmc_project.Inventory.Item", presProp); | 
 |         objects.emplace(objectPath, move(interfaces)); | 
 |  | 
 |         common::utility::callPIM(move(objects)); | 
 |     } | 
 |  | 
 |     gpiod::line outputLine = gpiod::find_line(outputPin); | 
 |     if (!outputLine) | 
 |     { | 
 |         cerr << "Error: toggleGpio: couldn't find output line:" << outputPin | 
 |              << ". Skipping update\n"; | 
 |  | 
 |         return; | 
 |     } | 
 |  | 
 |     outputLine.request({"FRU presence: update the output GPIO pin", | 
 |                         gpiod::line_request::DIRECTION_OUTPUT, 0}, | 
 |                        isPresent ? outputValue : (!outputValue)); | 
 |  | 
 |     string cmnd = createBindUnbindDriverCmnd(devNameAddr, busType, driverType, | 
 |                                              isPresent ? "bind" : "unbind"); | 
 |  | 
 |     cout << cmnd << endl; | 
 |     executeCmd(cmnd); | 
 | } | 
 |  | 
 | void GpioEventHandler::doEventAndTimerSetup(sdeventplus::Event& event) | 
 | { | 
 |     prevPresPinValue = getPresencePinValue(); | 
 |  | 
 |     static vector<shared_ptr<Timer>> timers; | 
 |     shared_ptr<Timer> timer = make_shared<Timer>( | 
 |         event, | 
 |         [this](Timer&) { | 
 |             if (hasEventOccurred()) | 
 |             { | 
 |                 toggleGpio(); | 
 |             } | 
 |         }, | 
 |         std::chrono::seconds{5s}); | 
 |  | 
 |     timers.push_back(timer); | 
 | } | 
 |  | 
 | } // namespace manager | 
 | } // namespace vpd | 
 | } // namespace openpower |