| Alpana Kumari | b17dd3b | 2020-10-01 00:18:10 -0500 | [diff] [blame] | 1 | #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 |  | 
|  | 13 | using namespace std; | 
|  | 14 | using namespace openpower::vpd::constants; | 
|  | 15 | using sdeventplus::ClockId; | 
|  | 16 | using sdeventplus::Event; | 
|  | 17 | using Timer = sdeventplus::utility::Timer<ClockId::Monotonic>; | 
|  | 18 | using namespace std::chrono_literals; | 
|  | 19 |  | 
|  | 20 | namespace openpower | 
|  | 21 | { | 
|  | 22 | namespace vpd | 
|  | 23 | { | 
|  | 24 | namespace manager | 
|  | 25 | { | 
|  | 26 |  | 
|  | 27 | bool 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 |  | 
|  | 47 | void 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 Kumari | 187bc27 | 2022-02-10 23:18:09 -0600 | [diff] [blame] | 63 | if (!eachInventory["presence"].value("pollingRequired", false)) | 
|  | 64 | { | 
|  | 65 | // Polling not required for this FRU , skip. | 
|  | 66 | continue; | 
|  | 67 | } | 
|  | 68 |  | 
| Alpana Kumari | b17dd3b | 2020-10-01 00:18:10 -0500 | [diff] [blame] | 69 | 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 Kumari | 64b9f5f | 2022-02-19 13:25:58 -0600 | [diff] [blame] | 95 | 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 Kumari | b17dd3b | 2020-10-01 00:18:10 -0500 | [diff] [blame] | 102 |  | 
| Alpana Kumari | 64b9f5f | 2022-02-19 13:25:58 -0600 | [diff] [blame] | 103 | // 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 Kumari | b17dd3b | 2020-10-01 00:18:10 -0500 | [diff] [blame] | 109 |  | 
| Alpana Kumari | 64b9f5f | 2022-02-19 13:25:58 -0600 | [diff] [blame] | 110 | gpioObjects.push_back(gpioObj); | 
|  | 111 | } | 
| Alpana Kumari | b17dd3b | 2020-10-01 00:18:10 -0500 | [diff] [blame] | 112 | } | 
|  | 113 | } | 
|  | 114 | } | 
|  | 115 | } | 
|  | 116 |  | 
|  | 117 | void 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 |  | 
|  | 164 | void 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 |