blob: 69d5e609fa4b6fb95e8c4e6c24f6a0b0569f1189 [file] [log] [blame]
Alpana Kumarib17dd3b2020-10-01 00:18:10 -05001#include "gpioMonitor.hpp"
2
3#include "common_utility.hpp"
4#include "ibm_vpd_utils.hpp"
5
6#include <systemd/sd-event.h>
7
8#include <chrono>
9#include <gpiod.hpp>
10#include <sdeventplus/clock.hpp>
11#include <sdeventplus/utility/timer.hpp>
12
13using namespace std;
14using namespace openpower::vpd::constants;
15using sdeventplus::ClockId;
16using sdeventplus::Event;
17using Timer = sdeventplus::utility::Timer<ClockId::Monotonic>;
18using namespace std::chrono_literals;
19
20namespace openpower
21{
22namespace vpd
23{
24namespace manager
25{
26
27bool GpioEventHandler::getPresencePinValue()
28{
29 Byte gpioData = 1;
30 gpiod::line presenceLine = gpiod::find_line(presencePin);
31 if (!presenceLine)
32 {
33 cerr << "Error getPresencePinValue: couldn't find presence line:"
34 << presencePin << " on GPIO \n";
35 // return previous state as we couldn't read current state
36 return prevPresPinValue;
37 }
38
39 presenceLine.request(
40 {"Op-panel presence line", gpiod::line_request::DIRECTION_INPUT, 0});
41
42 gpioData = presenceLine.get_value();
43
44 return gpioData;
45}
46
47void GpioMonitor::initGpioInfos(Event& event)
48{
49 Byte outputValue = 0;
50 Byte presenceValue = 0;
51 string presencePinName{}, outputPinName{};
52 string devNameAddr{}, driverType{}, busType{}, objectPath{};
53
54 for (const auto& eachFRU : jsonFile["frus"].items())
55 {
56 for (const auto& eachInventory : eachFRU.value())
57 {
58 objectPath = eachInventory["inventoryPath"];
59
60 if ((eachInventory.find("presence") != eachInventory.end()) &&
61 (eachInventory.find("preAction") != eachInventory.end()))
62 {
Alpana Kumari187bc272022-02-10 23:18:09 -060063 if (!eachInventory["presence"].value("pollingRequired", false))
64 {
65 // Polling not required for this FRU , skip.
66 continue;
67 }
68
Alpana Kumarib17dd3b2020-10-01 00:18:10 -050069 for (const auto& presStatus : eachInventory["presence"].items())
70 {
71 if (presStatus.key() == "pin")
72 {
73 presencePinName = presStatus.value();
74 }
75 else if (presStatus.key() == "value")
76 {
77 presenceValue = presStatus.value();
78 }
79 }
80
81 // Based on presence pin value, preAction pin will be set/reset
82 // This action will be taken before vpd collection.
83 for (const auto& preAction : eachInventory["preAction"].items())
84 {
85 if (preAction.key() == "pin")
86 {
87 outputPinName = preAction.value();
88 }
89 else if (preAction.key() == "value")
90 {
91 outputValue = preAction.value();
92 }
93 }
94
Alpana Kumari64b9f5f2022-02-19 13:25:58 -060095 if ((eachInventory.find("devAddress") != eachInventory.end()) &&
96 (eachInventory.find("driverType") != eachInventory.end()) &&
97 (eachInventory.find("busType") != eachInventory.end()))
98 {
99 devNameAddr = eachInventory["devAddress"];
100 driverType = eachInventory["driverType"];
101 busType = eachInventory["busType"];
Alpana Kumarib17dd3b2020-10-01 00:18:10 -0500102
Alpana Kumari64b9f5f2022-02-19 13:25:58 -0600103 // Init all Gpio info variables
104 std::shared_ptr<GpioEventHandler> gpioObj =
105 make_shared<GpioEventHandler>(
106 presencePinName, presenceValue, outputPinName,
107 outputValue, devNameAddr, driverType, busType,
108 objectPath, event);
Alpana Kumarib17dd3b2020-10-01 00:18:10 -0500109
Alpana Kumari64b9f5f2022-02-19 13:25:58 -0600110 gpioObjects.push_back(gpioObj);
111 }
Alpana Kumarib17dd3b2020-10-01 00:18:10 -0500112 }
113 }
114 }
115}
116
117void GpioEventHandler::toggleGpio()
118{
119 bool presPinVal = getPresencePinValue();
120 bool isPresent = false;
121
122 // preserve the new value
123 prevPresPinValue = presPinVal;
124
125 if (presPinVal == presenceValue)
126 {
127 isPresent = true;
128 }
129
130 // if FRU went away set the present property to false
131 if (!isPresent)
132 {
133 inventory::ObjectMap objects;
134 inventory::InterfaceMap interfaces;
135 inventory::PropertyMap presProp;
136
137 presProp.emplace("Present", false);
138 interfaces.emplace("xyz.openbmc_project.Inventory.Item", presProp);
139 objects.emplace(objectPath, move(interfaces));
140
141 common::utility::callPIM(move(objects));
142 }
143
144 gpiod::line outputLine = gpiod::find_line(outputPin);
145 if (!outputLine)
146 {
147 cerr << "Error: toggleGpio: couldn't find output line:" << outputPin
148 << ". Skipping update\n";
149
150 return;
151 }
152
153 outputLine.request({"FRU presence: update the output GPIO pin",
154 gpiod::line_request::DIRECTION_OUTPUT, 0},
155 isPresent ? outputValue : (!outputValue));
156
157 string cmnd = createBindUnbindDriverCmnd(devNameAddr, busType, driverType,
158 isPresent ? "bind" : "unbind");
159
160 cout << cmnd << endl;
161 executeCmd(cmnd);
162}
163
164void GpioEventHandler::doEventAndTimerSetup(sdeventplus::Event& event)
165{
166 prevPresPinValue = getPresencePinValue();
167
168 static vector<shared_ptr<Timer>> timers;
169 shared_ptr<Timer> timer = make_shared<Timer>(
170 event,
171 [this](Timer&) {
172 if (hasEventOccurred())
173 {
174 toggleGpio();
175 }
176 },
177 std::chrono::seconds{5s});
178
179 timers.push_back(timer);
180}
181
182} // namespace manager
183} // namespace vpd
184} // namespace openpower