xref: /openbmc/openpower-vpd-parser/vpd-manager/src/gpio_monitor.cpp (revision c6159a29119d5e08476ed85eaf1cf47ebf9bebdb)
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