|  | /** | 
|  | * Copyright © 2017 IBM Corporation | 
|  | * | 
|  | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | * you may not use this file except in compliance with the License. | 
|  | * You may obtain a copy of the License at | 
|  | * | 
|  | *     http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, software | 
|  | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | * See the License for the specific language governing permissions and | 
|  | * limitations under the License. | 
|  | */ | 
|  | #include <memory> | 
|  | #include <phosphor-logging/elog-errors.hpp> | 
|  | #include <phosphor-logging/elog.hpp> | 
|  | #include <tuple> | 
|  | #include <xyz/openbmc_project/Common/Callout/error.hpp> | 
|  | #include "gpio.hpp" | 
|  | #include "rpolicy.hpp" | 
|  | #include "sdevent.hpp" | 
|  |  | 
|  | namespace phosphor | 
|  | { | 
|  | namespace fan | 
|  | { | 
|  | namespace presence | 
|  | { | 
|  |  | 
|  | Gpio::Gpio( | 
|  | const std::string& physDevice, | 
|  | const std::string& device, | 
|  | unsigned int physPin) : | 
|  | currentState(false), | 
|  | evdevfd(open(device.c_str(), O_RDONLY | O_NONBLOCK)), | 
|  | evdev(evdevpp::evdev::newFromFD(evdevfd())), | 
|  | phys(physDevice), | 
|  | pin(physPin), | 
|  | callback(nullptr) | 
|  | { | 
|  |  | 
|  | } | 
|  |  | 
|  | bool Gpio::start() | 
|  | { | 
|  | callback = std::make_unique<sdevent::event::io::IO>( | 
|  | util::SDEvent::getEvent(), | 
|  | evdevfd(), | 
|  | [this](auto& s){this->ioCallback(s);}); | 
|  | currentState = present(); | 
|  | return currentState; | 
|  | } | 
|  |  | 
|  | void Gpio::stop() | 
|  | { | 
|  | callback = nullptr; | 
|  | } | 
|  |  | 
|  | bool Gpio::present() | 
|  | { | 
|  | return evdev.fetch(EV_KEY, pin) != 0; | 
|  | } | 
|  |  | 
|  | void Gpio::fail() | 
|  | { | 
|  | using namespace sdbusplus::xyz::openbmc_project::Common::Callout::Error; | 
|  | using namespace phosphor::logging; | 
|  | using namespace xyz::openbmc_project::Common::Callout; | 
|  |  | 
|  | report<sdbusplus::xyz::openbmc_project::Common::Callout::Error::GPIO>( | 
|  | GPIO::CALLOUT_GPIO_NUM(pin), | 
|  | GPIO::CALLOUT_ERRNO(0), | 
|  | GPIO::CALLOUT_DEVICE_PATH(phys.c_str())); | 
|  | } | 
|  |  | 
|  | void Gpio::ioCallback(sdevent::source::Source& source) | 
|  | { | 
|  | unsigned int type, code, value; | 
|  |  | 
|  | std::tie(type, code, value) = evdev.next(); | 
|  | if (type != EV_KEY || code != pin) | 
|  | { | 
|  | return; | 
|  | } | 
|  |  | 
|  | bool newState = value != 0; | 
|  |  | 
|  | if (currentState != newState) | 
|  | { | 
|  | getPolicy().stateChanged(newState, *this); | 
|  | currentState = newState; | 
|  | } | 
|  | } | 
|  | } // namespace presence | 
|  | } // namespace fan | 
|  | } // namespace phosphor |