1 #include "gpio_monitor.hpp" 2 3 #include "constants.hpp" 4 #include "error_codes.hpp" 5 #include "logger.hpp" 6 #include "types.hpp" 7 #include "utility/dbus_utility.hpp" 8 #include "utility/json_utility.hpp" 9 #include "utility/vpd_specific_utility.hpp" 10 11 #include <boost/asio.hpp> 12 #include <boost/bind/bind.hpp> 13 #include <gpiod.hpp> 14 15 namespace vpd 16 { 17 void GpioEventHandler::handleChangeInGpioPin(const bool& i_isFruPresent) 18 { 19 try 20 { 21 if (i_isFruPresent) 22 { 23 types::VPDMapVariant l_parsedVpd = 24 m_worker->parseVpdFile(m_fruPath); 25 26 if (std::holds_alternative<std::monostate>(l_parsedVpd)) 27 { 28 throw std::runtime_error( 29 "VPD parsing failed for " + std::string(m_fruPath)); 30 } 31 32 types::ObjectMap l_dbusObjectMap; 33 m_worker->populateDbus(l_parsedVpd, l_dbusObjectMap, m_fruPath); 34 35 if (l_dbusObjectMap.empty()) 36 { 37 throw std::runtime_error("Failed to create D-bus object map."); 38 } 39 40 if (!dbusUtility::callPIM(move(l_dbusObjectMap))) 41 { 42 throw std::runtime_error("call PIM failed"); 43 } 44 } 45 else 46 { 47 uint16_t l_errCode = 0; 48 std::string l_invPath = jsonUtility::getInventoryObjPathFromJson( 49 m_worker->getSysCfgJsonObj(), m_fruPath, l_errCode); 50 51 if (l_errCode) 52 { 53 throw std::runtime_error( 54 "Failed to get inventory path from JSON, error : " + 55 vpdSpecificUtility::getErrCodeMsg(l_errCode)); 56 } 57 58 m_worker->deleteFruVpd(l_invPath); 59 } 60 } 61 catch (std::exception& l_ex) 62 { 63 logging::logMessage(std::string(l_ex.what())); 64 } 65 } 66 67 void GpioEventHandler::handleTimerExpiry( 68 const boost::system::error_code& i_errorCode, 69 const std::shared_ptr<boost::asio::steady_timer>& i_timerObj) 70 { 71 if (i_errorCode == boost::asio::error::operation_aborted) 72 { 73 logging::logMessage("Timer aborted for GPIO pin"); 74 return; 75 } 76 77 if (i_errorCode) 78 { 79 logging::logMessage("Timer wait failed for gpio pin" + 80 std::string(i_errorCode.message())); 81 return; 82 } 83 84 uint16_t l_errCode = 0; 85 bool l_currentPresencePinValue = jsonUtility::processGpioPresenceTag( 86 m_worker->getSysCfgJsonObj(), m_fruPath, "pollingRequired", 87 "hotPlugging", l_errCode); 88 89 if (l_errCode && l_errCode != error_code::DEVICE_NOT_PRESENT) 90 { 91 logging::logMessage("processGpioPresenceTag returned false for FRU [" + 92 m_fruPath + "] Due to error. Reason: " + 93 vpdSpecificUtility::getErrCodeMsg(l_errCode)); 94 } 95 96 if (m_prevPresencePinValue != l_currentPresencePinValue) 97 { 98 m_prevPresencePinValue = l_currentPresencePinValue; 99 handleChangeInGpioPin(l_currentPresencePinValue); 100 } 101 102 i_timerObj->expires_at(std::chrono::steady_clock::now() + 103 std::chrono::seconds(constants::VALUE_5)); 104 i_timerObj->async_wait( 105 boost::bind(&GpioEventHandler::handleTimerExpiry, this, 106 boost::asio::placeholders::error, i_timerObj)); 107 } 108 109 void GpioEventHandler::setEventHandlerForGpioPresence( 110 const std::shared_ptr<boost::asio::io_context>& i_ioContext) 111 { 112 uint16_t l_errCode = 0; 113 m_prevPresencePinValue = jsonUtility::processGpioPresenceTag( 114 m_worker->getSysCfgJsonObj(), m_fruPath, "pollingRequired", 115 "hotPlugging", l_errCode); 116 117 if (l_errCode && l_errCode != error_code::DEVICE_NOT_PRESENT) 118 { 119 logging::logMessage("processGpioPresenceTag returned false for FRU [" + 120 m_fruPath + "] Due to error. Reason: " + 121 vpdSpecificUtility::getErrCodeMsg(l_errCode)); 122 } 123 124 static std::vector<std::shared_ptr<boost::asio::steady_timer>> l_timers; 125 126 auto l_timerObj = make_shared<boost::asio::steady_timer>( 127 *i_ioContext, std::chrono::seconds(constants::VALUE_5)); 128 129 l_timerObj->async_wait( 130 boost::bind(&GpioEventHandler::handleTimerExpiry, this, 131 boost::asio::placeholders::error, l_timerObj)); 132 133 l_timers.push_back(l_timerObj); 134 } 135 136 void GpioMonitor::initHandlerForGpio( 137 const std::shared_ptr<boost::asio::io_context>& i_ioContext, 138 const std::shared_ptr<Worker>& i_worker) 139 { 140 uint16_t l_errCode = 0; 141 std::vector<std::string> l_gpioPollingRequiredFrusList = 142 jsonUtility::getListOfGpioPollingFrus(m_sysCfgJsonObj, l_errCode); 143 144 if (l_errCode) 145 { 146 logging::logMessage( 147 "Failed to get list of frus required for gpio polling. Error : " + 148 vpdSpecificUtility::getErrCodeMsg(l_errCode)); 149 return; 150 } 151 152 for (const auto& l_fruPath : l_gpioPollingRequiredFrusList) 153 { 154 std::shared_ptr<GpioEventHandler> l_gpioEventHandlerObj = 155 std::make_shared<GpioEventHandler>(l_fruPath, i_worker, 156 i_ioContext); 157 158 m_gpioEventHandlerObjects.push_back(l_gpioEventHandlerObj); 159 } 160 } 161 } // namespace vpd 162