xref: /openbmc/phosphor-fan-presence/presence/gpio.cpp (revision c65d91d63be09a1d8b90ccbee79440423e97f343)
15c589487SBrad Bishop /**
25c589487SBrad Bishop  * Copyright © 2017 IBM Corporation
35c589487SBrad Bishop  *
45c589487SBrad Bishop  * Licensed under the Apache License, Version 2.0 (the "License");
55c589487SBrad Bishop  * you may not use this file except in compliance with the License.
65c589487SBrad Bishop  * You may obtain a copy of the License at
75c589487SBrad Bishop  *
85c589487SBrad Bishop  *     http://www.apache.org/licenses/LICENSE-2.0
95c589487SBrad Bishop  *
105c589487SBrad Bishop  * Unless required by applicable law or agreed to in writing, software
115c589487SBrad Bishop  * distributed under the License is distributed on an "AS IS" BASIS,
125c589487SBrad Bishop  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135c589487SBrad Bishop  * See the License for the specific language governing permissions and
145c589487SBrad Bishop  * limitations under the License.
155c589487SBrad Bishop  */
162d2caa34SMatthew Barth #include "gpio.hpp"
172d2caa34SMatthew Barth 
18*c65d91d6SMatt Spinler #include "logging.hpp"
192d2caa34SMatthew Barth #include "rpolicy.hpp"
20*c65d91d6SMatt Spinler #include "sdbusplus.hpp"
212d2caa34SMatthew Barth 
225c589487SBrad Bishop #include <phosphor-logging/elog-errors.hpp>
235c589487SBrad Bishop #include <phosphor-logging/elog.hpp>
241cfc2f11SWilliam A. Kennington III #include <sdeventplus/event.hpp>
255c589487SBrad Bishop #include <xyz/openbmc_project/Common/Callout/error.hpp>
26*c65d91d6SMatt Spinler #include <xyz/openbmc_project/Logging/Entry/server.hpp>
272d2caa34SMatthew Barth 
282d2caa34SMatthew Barth #include <functional>
292d2caa34SMatthew Barth #include <tuple>
305c589487SBrad Bishop 
315c589487SBrad Bishop namespace phosphor
325c589487SBrad Bishop {
335c589487SBrad Bishop namespace fan
345c589487SBrad Bishop {
355c589487SBrad Bishop namespace presence
365c589487SBrad Bishop {
375c589487SBrad Bishop 
38*c65d91d6SMatt Spinler const auto loggingService = "xyz.openbmc_project.Logging";
39*c65d91d6SMatt Spinler const auto loggingPath = "/xyz/openbmc_project/logging";
40*c65d91d6SMatt Spinler const auto loggingCreateIface = "xyz.openbmc_project.Logging.Create";
41*c65d91d6SMatt Spinler 
422d2caa34SMatthew Barth Gpio::Gpio(const std::string& physDevice, const std::string& device,
435c589487SBrad Bishop            unsigned int physPin) :
445c589487SBrad Bishop     currentState(false),
452e9788d7SBrad Bishop     evdevfd(open(device.c_str(), O_RDONLY | O_NONBLOCK)),
462d2caa34SMatthew Barth     evdev(evdevpp::evdev::newFromFD(evdevfd())), phys(physDevice), pin(physPin)
472d2caa34SMatthew Barth {}
485c589487SBrad Bishop 
495c589487SBrad Bishop bool Gpio::start()
505c589487SBrad Bishop {
512d2caa34SMatthew Barth     source.emplace(sdeventplus::Event::get_default(), evdevfd(), EPOLLIN,
521cfc2f11SWilliam A. Kennington III                    std::bind(&Gpio::ioCallback, this));
535c589487SBrad Bishop     currentState = present();
545c589487SBrad Bishop     return currentState;
555c589487SBrad Bishop }
565c589487SBrad Bishop 
575c589487SBrad Bishop void Gpio::stop()
585c589487SBrad Bishop {
591cfc2f11SWilliam A. Kennington III     source.reset();
605c589487SBrad Bishop }
615c589487SBrad Bishop 
625c589487SBrad Bishop bool Gpio::present()
635c589487SBrad Bishop {
645c589487SBrad Bishop     return evdev.fetch(EV_KEY, pin) != 0;
655c589487SBrad Bishop }
665c589487SBrad Bishop 
675c589487SBrad Bishop void Gpio::fail()
685c589487SBrad Bishop {
695c589487SBrad Bishop     using namespace sdbusplus::xyz::openbmc_project::Common::Callout::Error;
705c589487SBrad Bishop     using namespace phosphor::logging;
715c589487SBrad Bishop     using namespace xyz::openbmc_project::Common::Callout;
725c589487SBrad Bishop 
735c589487SBrad Bishop     report<sdbusplus::xyz::openbmc_project::Common::Callout::Error::GPIO>(
742d2caa34SMatthew Barth         GPIO::CALLOUT_GPIO_NUM(pin), GPIO::CALLOUT_ERRNO(0),
755c589487SBrad Bishop         GPIO::CALLOUT_DEVICE_PATH(phys.c_str()));
765c589487SBrad Bishop }
775c589487SBrad Bishop 
781cfc2f11SWilliam A. Kennington III void Gpio::ioCallback()
795c589487SBrad Bishop {
805c589487SBrad Bishop     unsigned int type, code, value;
815c589487SBrad Bishop 
825c589487SBrad Bishop     std::tie(type, code, value) = evdev.next();
835c589487SBrad Bishop     if (type != EV_KEY || code != pin)
845c589487SBrad Bishop     {
855c589487SBrad Bishop         return;
865c589487SBrad Bishop     }
875c589487SBrad Bishop 
885c589487SBrad Bishop     bool newState = value != 0;
895c589487SBrad Bishop 
905c589487SBrad Bishop     if (currentState != newState)
915c589487SBrad Bishop     {
9211083ecaSBrad Bishop         getPolicy().stateChanged(newState, *this);
935c589487SBrad Bishop         currentState = newState;
945c589487SBrad Bishop     }
955c589487SBrad Bishop }
96*c65d91d6SMatt Spinler 
97*c65d91d6SMatt Spinler void Gpio::logConflict(const std::string& fanInventoryPath) const
98*c65d91d6SMatt Spinler {
99*c65d91d6SMatt Spinler     using namespace sdbusplus::xyz::openbmc_project::Logging::server;
100*c65d91d6SMatt Spinler     std::map<std::string, std::string> ad;
101*c65d91d6SMatt Spinler     Entry::Level severity = Entry::Level::Informational;
102*c65d91d6SMatt Spinler 
103*c65d91d6SMatt Spinler     static constexpr auto errorName =
104*c65d91d6SMatt Spinler         "xyz.openbmc_project.Fan.Presence.Error.Detection";
105*c65d91d6SMatt Spinler 
106*c65d91d6SMatt Spinler     ad.emplace("_PID", std::to_string(getpid()));
107*c65d91d6SMatt Spinler     ad.emplace("CALLOUT_INVENTORY_PATH", fanInventoryPath);
108*c65d91d6SMatt Spinler     ad.emplace("GPIO_NUM", std::to_string(pin));
109*c65d91d6SMatt Spinler     ad.emplace("GPIO_DEVICE_PATH", (phys.c_str()));
110*c65d91d6SMatt Spinler 
111*c65d91d6SMatt Spinler     getLogger().log(
112*c65d91d6SMatt Spinler         fmt::format("GPIO presence detect for fan {} said not present but "
113*c65d91d6SMatt Spinler                     "other methods indicated present",
114*c65d91d6SMatt Spinler                     fanInventoryPath));
115*c65d91d6SMatt Spinler     try
116*c65d91d6SMatt Spinler     {
117*c65d91d6SMatt Spinler         util::SDBusPlus::callMethod(loggingService, loggingPath,
118*c65d91d6SMatt Spinler                                     loggingCreateIface, "Create", errorName,
119*c65d91d6SMatt Spinler                                     severity, ad);
120*c65d91d6SMatt Spinler     }
121*c65d91d6SMatt Spinler     catch (const util::DBusError& e)
122*c65d91d6SMatt Spinler     {
123*c65d91d6SMatt Spinler         getLogger().log(
124*c65d91d6SMatt Spinler             fmt::format("Call to create a {} error for fan {} failed: {}",
125*c65d91d6SMatt Spinler                         errorName, fanInventoryPath, e.what()),
126*c65d91d6SMatt Spinler             Logger::error);
127*c65d91d6SMatt Spinler     }
128*c65d91d6SMatt Spinler }
129*c65d91d6SMatt Spinler 
1305c589487SBrad Bishop } // namespace presence
1315c589487SBrad Bishop } // namespace fan
1325c589487SBrad Bishop } // namespace phosphor
133