xref: /openbmc/openpower-vpd-parser/vpd-manager/src/gpio_monitor.cpp (revision 480807cf8a3ef27eef4063bac422d69343b123d1)
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     bool l_currentPresencePinValue = jsonUtility::processGpioPresenceTag(
85         m_worker->getSysCfgJsonObj(), m_fruPath, "pollingRequired",
86         "hotPlugging");
87 
88     if (m_prevPresencePinValue != l_currentPresencePinValue)
89     {
90         m_prevPresencePinValue = l_currentPresencePinValue;
91         handleChangeInGpioPin(l_currentPresencePinValue);
92     }
93 
94     i_timerObj->expires_at(std::chrono::steady_clock::now() +
95                            std::chrono::seconds(constants::VALUE_5));
96     i_timerObj->async_wait(
97         boost::bind(&GpioEventHandler::handleTimerExpiry, this,
98                     boost::asio::placeholders::error, i_timerObj));
99 }
100 
101 void GpioEventHandler::setEventHandlerForGpioPresence(
102     const std::shared_ptr<boost::asio::io_context>& i_ioContext)
103 {
104     m_prevPresencePinValue = jsonUtility::processGpioPresenceTag(
105         m_worker->getSysCfgJsonObj(), m_fruPath, "pollingRequired",
106         "hotPlugging");
107 
108     static std::vector<std::shared_ptr<boost::asio::steady_timer>> l_timers;
109 
110     auto l_timerObj = make_shared<boost::asio::steady_timer>(
111         *i_ioContext, std::chrono::seconds(constants::VALUE_5));
112 
113     l_timerObj->async_wait(
114         boost::bind(&GpioEventHandler::handleTimerExpiry, this,
115                     boost::asio::placeholders::error, l_timerObj));
116 
117     l_timers.push_back(l_timerObj);
118 }
119 
120 void GpioMonitor::initHandlerForGpio(
121     const std::shared_ptr<boost::asio::io_context>& i_ioContext,
122     const std::shared_ptr<Worker>& i_worker)
123 {
124     std::vector<std::string> l_gpioPollingRequiredFrusList =
125         jsonUtility::getListOfGpioPollingFrus(m_sysCfgJsonObj);
126 
127     for (const auto& l_fruPath : l_gpioPollingRequiredFrusList)
128     {
129         std::shared_ptr<GpioEventHandler> l_gpioEventHandlerObj =
130             std::make_shared<GpioEventHandler>(l_fruPath, i_worker,
131                                                i_ioContext);
132 
133         m_gpioEventHandlerObjects.push_back(l_gpioEventHandlerObj);
134     }
135 }
136 } // namespace vpd
137