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 {
handleChangeInGpioPin(const bool & i_isFruPresent)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 commonUtility::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
handleTimerExpiry(const boost::system::error_code & i_errorCode,const std::shared_ptr<boost::asio::steady_timer> & i_timerObj)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 commonUtility::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
setEventHandlerForGpioPresence(const std::shared_ptr<boost::asio::io_context> & i_ioContext)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 commonUtility::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
initHandlerForGpio(const std::shared_ptr<boost::asio::io_context> & i_ioContext,const std::shared_ptr<Worker> & i_worker)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 commonUtility::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