blob: 69d5e609fa4b6fb95e8c4e6c24f6a0b0569f1189 [file] [log] [blame]
#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()))
{
if (!eachInventory["presence"].value("pollingRequired", false))
{
// Polling not required for this FRU , skip.
continue;
}
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();
}
}
if ((eachInventory.find("devAddress") != eachInventory.end()) &&
(eachInventory.find("driverType") != eachInventory.end()) &&
(eachInventory.find("busType") != eachInventory.end()))
{
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