From 5c5894878b09fdef8fcbee000f83283b73b8da64 Mon Sep 17 00:00:00 2001 From: Brad Bishop Date: Wed, 14 Jun 2017 22:32:20 -0400 Subject: presence: Add gpio presence sensor Add a gpio presence implementation of the PresenceSensor interface. The gpio sensor simply maps the on off state of a gpio directly to the xyz.openbmc_project.Inventory.Item Present property. Change-Id: I071dd475bebb15372edb59506352746c20542eff Signed-off-by: Brad Bishop --- presence/Makefile.am | 1 + presence/gpio.cpp | 98 ++++++++++++++++++++++++++++++++++++++++++++++ presence/gpio.hpp | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 206 insertions(+) create mode 100644 presence/gpio.cpp create mode 100644 presence/gpio.hpp diff --git a/presence/Makefile.am b/presence/Makefile.am index 2ea4929..2a5976c 100644 --- a/presence/Makefile.am +++ b/presence/Makefile.am @@ -6,6 +6,7 @@ sbin_PROGRAMS = \ phosphor_fan_presence_tach_SOURCES = \ fan.cpp \ + gpio.cpp \ tach.cpp \ fan_enclosure.cpp \ tach_sensor.cpp \ diff --git a/presence/gpio.cpp b/presence/gpio.cpp new file mode 100644 index 0000000..dfd72db --- /dev/null +++ b/presence/gpio.cpp @@ -0,0 +1,98 @@ +/** + * 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 +#include +#include +#include +#include +#include "gpio.hpp" +#include "rpolicy.hpp" +#include "sdevent.hpp" + +namespace phosphor +{ +namespace fan +{ +namespace presence +{ + +Gpio::Gpio( + const std::string& physDevice, + unsigned int physPin) : + currentState(false), + evdevfd(open("/dev/input/by-path/platform-gpio-keys-event", + O_RDONLY | O_NONBLOCK)), + evdev(evdevpp::evdev::newFromFD(evdevfd())), + phys(physDevice), + pin(physPin), + callback(nullptr) +{ + +} + +bool Gpio::start() +{ + callback = std::make_unique( + 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( + 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); + currentState = newState; + } +} +} // namespace presence +} // namespace fan +} // namespace phosphor diff --git a/presence/gpio.hpp b/presence/gpio.hpp new file mode 100644 index 0000000..e516e0f --- /dev/null +++ b/presence/gpio.hpp @@ -0,0 +1,107 @@ +#pragma once + +#include +#include "evdevpp/evdev.hpp" +#include "sdevent/io.hpp" +#include "sdevent/source.hpp" +#include "psensor.hpp" +#include "utility.hpp" + +namespace phosphor +{ +namespace fan +{ +namespace presence +{ +class RedundancyPolicy; + +/** + * @class Gpio + * @brief Gpio presence sensor implementation. + * + * The Gpio class uses a gpio wire to determine presence state. + */ +class Gpio : public PresenceSensor +{ + public: + /** + * @brief + * + * Cannot move or copy due to this ptr as context + * for sdevent callbacks. + */ + Gpio() = delete; + Gpio(const Gpio&) = delete; + Gpio& operator=(const Gpio&) = delete; + Gpio(Gpio&&) = delete; + Gpio& operator=(Gpio&&) = delete; + ~Gpio() = default; + + /** + * @brief Construct a gpio sensor. + * + * @param[in] physDevice - The physical gpio device path. + * @param[in] physPin - The physical gpio pin number. + */ + Gpio(const std::string& physDevice, unsigned int physPin); + + /** + * @brief start + * + * Register for an sdevent io callback on the gpio. + * Query the initial state of the gpio. + * + * @return The current sensor state. + */ + bool start() override; + + /** + * @brief stop + * + * De-register sdevent io callback. + */ + void stop() override; + + /** + * @brief fail + * + * Call the gpio out. + */ + void fail() override; + + /** + * @brief Check the sensor. + * + * Query the gpio. + */ + bool present() override; + + private : + /** @brief Get the policy associated with this sensor. */ + virtual RedundancyPolicy& getPolicy() = 0; + + /** @brief sdevent io callback. */ + void ioCallback(sdevent::source::Source& source); + + /** The current state of the sensor. */ + bool currentState; + + /** Gpio event device file descriptor. */ + util::FileDescriptor evdevfd; + + /** Gpio event device. */ + evdevpp::evdev::EvDev evdev; + + /** Physical gpio device. */ + std::string phys; + + /** Gpio pin number. */ + unsigned int pin; + + /** sdevent io callback handle. */ + std::unique_ptr callback; +}; + +} // namespace presence +} // namespace fan +} // namespace phosphor -- cgit v1.2.1