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
18c65d91d6SMatt Spinler #include "logging.hpp"
192d2caa34SMatthew Barth #include "rpolicy.hpp"
20c65d91d6SMatt 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>
26c65d91d6SMatt 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
38c65d91d6SMatt Spinler const auto loggingService = "xyz.openbmc_project.Logging";
39c65d91d6SMatt Spinler const auto loggingPath = "/xyz/openbmc_project/logging";
40c65d91d6SMatt Spinler const auto loggingCreateIface = "xyz.openbmc_project.Logging.Create";
41c65d91d6SMatt Spinler
Gpio(const std::string & physDevice,const std::string & device,unsigned int physPin)422d2caa34SMatthew Barth Gpio::Gpio(const std::string& physDevice, const std::string& device,
435c589487SBrad Bishop unsigned int physPin) :
44*dfddd648SPatrick Williams currentState(false), evdevfd(open(device.c_str(), O_RDONLY | O_NONBLOCK)),
452d2caa34SMatthew Barth evdev(evdevpp::evdev::newFromFD(evdevfd())), phys(physDevice), pin(physPin)
462d2caa34SMatthew Barth {}
475c589487SBrad Bishop
start()485c589487SBrad Bishop bool Gpio::start()
495c589487SBrad Bishop {
502d2caa34SMatthew Barth source.emplace(sdeventplus::Event::get_default(), evdevfd(), EPOLLIN,
511cfc2f11SWilliam A. Kennington III std::bind(&Gpio::ioCallback, this));
525c589487SBrad Bishop currentState = present();
535c589487SBrad Bishop return currentState;
545c589487SBrad Bishop }
555c589487SBrad Bishop
stop()565c589487SBrad Bishop void Gpio::stop()
575c589487SBrad Bishop {
581cfc2f11SWilliam A. Kennington III source.reset();
595c589487SBrad Bishop }
605c589487SBrad Bishop
present()615c589487SBrad Bishop bool Gpio::present()
625c589487SBrad Bishop {
635c589487SBrad Bishop return evdev.fetch(EV_KEY, pin) != 0;
645c589487SBrad Bishop }
655c589487SBrad Bishop
fail()665c589487SBrad Bishop void Gpio::fail()
675c589487SBrad Bishop {
685c589487SBrad Bishop using namespace sdbusplus::xyz::openbmc_project::Common::Callout::Error;
695c589487SBrad Bishop using namespace phosphor::logging;
705c589487SBrad Bishop using namespace xyz::openbmc_project::Common::Callout;
715c589487SBrad Bishop
725c589487SBrad Bishop report<sdbusplus::xyz::openbmc_project::Common::Callout::Error::GPIO>(
732d2caa34SMatthew Barth GPIO::CALLOUT_GPIO_NUM(pin), GPIO::CALLOUT_ERRNO(0),
745c589487SBrad Bishop GPIO::CALLOUT_DEVICE_PATH(phys.c_str()));
755c589487SBrad Bishop }
765c589487SBrad Bishop
ioCallback()771cfc2f11SWilliam A. Kennington III void Gpio::ioCallback()
785c589487SBrad Bishop {
795c589487SBrad Bishop unsigned int type, code, value;
805c589487SBrad Bishop
815c589487SBrad Bishop std::tie(type, code, value) = evdev.next();
825c589487SBrad Bishop if (type != EV_KEY || code != pin)
835c589487SBrad Bishop {
845c589487SBrad Bishop return;
855c589487SBrad Bishop }
865c589487SBrad Bishop
875c589487SBrad Bishop bool newState = value != 0;
885c589487SBrad Bishop
895c589487SBrad Bishop if (currentState != newState)
905c589487SBrad Bishop {
9111083ecaSBrad Bishop getPolicy().stateChanged(newState, *this);
925c589487SBrad Bishop currentState = newState;
935c589487SBrad Bishop }
945c589487SBrad Bishop }
95c65d91d6SMatt Spinler
logConflict(const std::string & fanInventoryPath) const96c65d91d6SMatt Spinler void Gpio::logConflict(const std::string& fanInventoryPath) const
97c65d91d6SMatt Spinler {
98c65d91d6SMatt Spinler using namespace sdbusplus::xyz::openbmc_project::Logging::server;
99c65d91d6SMatt Spinler std::map<std::string, std::string> ad;
100c65d91d6SMatt Spinler Entry::Level severity = Entry::Level::Informational;
101c65d91d6SMatt Spinler
102c65d91d6SMatt Spinler static constexpr auto errorName =
103c65d91d6SMatt Spinler "xyz.openbmc_project.Fan.Presence.Error.Detection";
104c65d91d6SMatt Spinler
105c65d91d6SMatt Spinler ad.emplace("_PID", std::to_string(getpid()));
106c65d91d6SMatt Spinler ad.emplace("CALLOUT_INVENTORY_PATH", fanInventoryPath);
107c65d91d6SMatt Spinler ad.emplace("GPIO_NUM", std::to_string(pin));
108c65d91d6SMatt Spinler ad.emplace("GPIO_DEVICE_PATH", (phys.c_str()));
109c65d91d6SMatt Spinler
110c65d91d6SMatt Spinler getLogger().log(
111fbf4703fSPatrick Williams std::format("GPIO presence detect for fan {} said not present but "
112c65d91d6SMatt Spinler "other methods indicated present",
113c65d91d6SMatt Spinler fanInventoryPath));
114c65d91d6SMatt Spinler try
115c65d91d6SMatt Spinler {
116c65d91d6SMatt Spinler util::SDBusPlus::callMethod(loggingService, loggingPath,
117c65d91d6SMatt Spinler loggingCreateIface, "Create", errorName,
118c65d91d6SMatt Spinler severity, ad);
119c65d91d6SMatt Spinler }
120c65d91d6SMatt Spinler catch (const util::DBusError& e)
121c65d91d6SMatt Spinler {
122c65d91d6SMatt Spinler getLogger().log(
123fbf4703fSPatrick Williams std::format("Call to create a {} error for fan {} failed: {}",
124c65d91d6SMatt Spinler errorName, fanInventoryPath, e.what()),
125c65d91d6SMatt Spinler Logger::error);
126c65d91d6SMatt Spinler }
127c65d91d6SMatt Spinler }
128c65d91d6SMatt Spinler
1295c589487SBrad Bishop } // namespace presence
1305c589487SBrad Bishop } // namespace fan
1315c589487SBrad Bishop } // namespace phosphor
132