#include "gpioMonitor.hpp" #include "common_utility.hpp" #include "ibm_vpd_utils.hpp" #include #include #include using namespace std; using namespace openpower::vpd::constants; 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( std::shared_ptr& ioContext) { 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 gpioObj = make_shared( presencePinName, presenceValue, outputPinName, outputValue, devNameAddr, driverType, busType, objectPath, ioContext); 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::handleTimerExpiry( const boost::system::error_code& ec, std::shared_ptr& timer) { if (ec == boost::asio::error::operation_aborted) { return; } if (ec) { std::cerr << "Timer wait failed for gpio pin" << ec.message(); return; } if (hasEventOccurred()) { toggleGpio(); } timer->expires_at( std::chrono::steady_clock::now() + std::chrono::seconds(5)); timer->async_wait(boost::bind(&GpioEventHandler::handleTimerExpiry, this, boost::asio::placeholders::error, timer)); } void GpioEventHandler::doEventAndTimerSetup( std::shared_ptr& ioContext) { prevPresPinValue = getPresencePinValue(); static vector> timers; auto timer = make_shared( *ioContext, std::chrono::seconds(5)); timer->async_wait(boost::bind(&GpioEventHandler::handleTimerExpiry, this, boost::asio::placeholders::error, timer)); timers.push_back(timer); } } // namespace manager } // namespace vpd } // namespace openpower