diff options
author | Gunnar Mills <gmills@us.ibm.com> | 2017-07-26 16:15:21 -0500 |
---|---|---|
committer | Gunnar Mills <gmills@us.ibm.com> | 2017-07-27 14:58:11 -0500 |
commit | 835dfb8877fd2e78281e22b8b08dc29e0e9ef5a5 (patch) | |
tree | 778575523167f4db36f39bf835046e3d8556809f | |
parent | 765725e057046784ceb4e7595e44f2e4c2ef6ae2 (diff) | |
download | phosphor-gpio-monitor-835dfb8877fd2e78281e22b8b08dc29e0e9ef5a5.tar.gz phosphor-gpio-monitor-835dfb8877fd2e78281e22b8b08dc29e0e9ef5a5.zip |
Refactor GPIO Presence class
Refactor the GPIO Presence class to use a common class, Evdev,
to inherit from. Evdev does the basic libevdev handling.
A later commit moves monitor.hpp to this common class as well.
Change-Id: I3c872680c88f8f400fefe3af49eb9b84c7491ceb
Signed-off-by: Gunnar Mills <gmills@us.ibm.com>
-rw-r--r-- | evdev.cpp | 72 | ||||
-rw-r--r-- | evdev.hpp | 132 | ||||
-rw-r--r-- | presence/Makefile.am | 1 | ||||
-rw-r--r-- | presence/gpio_presence.cpp | 53 | ||||
-rw-r--r-- | presence/gpio_presence.hpp | 83 |
5 files changed, 212 insertions, 129 deletions
diff --git a/evdev.cpp b/evdev.cpp new file mode 100644 index 0000000..e8e98e2 --- /dev/null +++ b/evdev.cpp @@ -0,0 +1,72 @@ +#include <libevdev/libevdev.h> +#include <fcntl.h> +#include <phosphor-logging/elog.hpp> +#include <phosphor-logging/log.hpp> +#include <phosphor-logging/elog-errors.hpp> +#include "xyz/openbmc_project/Common/error.hpp" +#include "evdev.hpp" + +namespace phosphor +{ +namespace gpio +{ + +using namespace phosphor::logging; +using namespace sdbusplus::xyz::openbmc_project::Common::Error; + +// Populate the file descriptor for passed in device +int Evdev::openDevice() +{ + using namespace phosphor::logging; + + auto fd = open(path.c_str(), O_RDONLY | O_NONBLOCK); + if (fd < 0) + { + log<level::ERR>("Failed to open device path", + entry("DEVICEPATH=%s", path.c_str()), + entry("ERRNO=%d", errno)); + elog<InternalFailure>(); + } + return fd; +} + +// Initializes the event device with the fd +void Evdev::initEvDev() +{ + if (devicePtr) + { + // Init can be done only once per device + return; + } + + struct libevdev* evdev = nullptr; + auto rc = libevdev_new_from_fd((fd)(), &evdev); + if (rc < 0) + { + log<level::ERR>("Failed to initialize evdev"); + elog<InternalFailure>(); + return; + } + + // Packing in the unique_ptr + devicePtr.reset(evdev); +} + +// Attaches the FD to event loop and registers the callback handler +void Evdev::registerCallback() +{ + decltype(eventSource.get()) sourcePtr = nullptr; + auto rc = sd_event_add_io(event.get(), &sourcePtr, (fd)(), + EPOLLIN, callbackHandler, this); + eventSource.reset(sourcePtr); + + if (rc < 0) + { + log<level::ERR>("Failed to register callback handler", + entry("ERROR=%s", strerror(-rc))); + elog<InternalFailure>(); + } +} + +} // namespace gpio +} // namespace phosphor diff --git a/evdev.hpp b/evdev.hpp new file mode 100644 index 0000000..b3189f1 --- /dev/null +++ b/evdev.hpp @@ -0,0 +1,132 @@ +#pragma once +#include <string> +#include <systemd/sd-event.h> +#include <libevdev/libevdev.h> +#include "file.hpp" + +namespace phosphor +{ +namespace gpio +{ + +/* Need a custom deleter for freeing up sd_event */ +struct EventDeleter +{ + void operator()(sd_event* event) const + { + event = sd_event_unref(event); + } +}; +using EventPtr = std::unique_ptr<sd_event, EventDeleter>; + +/* Need a custom deleter for freeing up sd_event_source */ +struct EventSourceDeleter +{ + void operator()(sd_event_source* eventSource) const + { + eventSource = sd_event_source_unref(eventSource); + } +}; +using EventSourcePtr = std::unique_ptr<sd_event_source, EventSourceDeleter>; + +/* Need a custom deleter for freeing up evdev struct */ +struct FreeEvDev +{ + void operator()(struct libevdev* device) const + { + libevdev_free(device); + } +}; +using EvdevPtr = std::unique_ptr<struct libevdev, FreeEvDev>; + +/** @class Evdev + * @brief Responsible for catching GPIO state changes conditions and taking + * actions + */ +class Evdev +{ + + using Property = std::string; + using Value = sdbusplus::message::variant<bool, std::string>; + // Association between property and its value + using PropertyMap = std::map<Property, Value>; + using Interface = std::string; + // Association between interface and the D-Bus property + using InterfaceMap = std::map<Interface, PropertyMap>; + using Object = sdbusplus::message::object_path; + // Association between object and the interface + using ObjectMap = std::map<Object, InterfaceMap>; + + public: + Evdev() = delete; + ~Evdev() = default; + Evdev(const Evdev&) = delete; + Evdev& operator=(const Evdev&) = delete; + Evdev(Evdev&&) = delete; + Evdev& operator=(Evdev&&) = delete; + + /** @brief Constructs Evdev object. + * + * @param[in] path - Device path to read for GPIO pin state + * @param[in] key - GPIO key to monitor + * @param[in] event - sd_event handler + * @param[in] handler - IO callback handler. Defaults to one in this + * class + * @param[in] useEvDev - Whether to use EvDev to retrieve events + */ + Evdev(const std::string& path, + const unsigned int key, + EventPtr& event, + sd_event_io_handler_t handler, + bool useEvDev = true) : + path(path), + key(key), + event(event), + callbackHandler(handler), + fd(openDevice()) + + { + if (useEvDev) + { + // If we are asked to use EvDev, do that initialization. + initEvDev(); + } + + // Register callback handler when FD has some data + registerCallback(); + } + + protected: + /** @brief Device path to read for GPIO pin state */ + const std::string path; + + /** @brief GPIO key to monitor */ + const unsigned int key; + + /** @brief Event structure */ + EvdevPtr devicePtr; + + /** @brief Monitor to sd_event */ + EventPtr& event; + + /** @brief Callback handler when the FD has some data */ + sd_event_io_handler_t callbackHandler; + + /** @brief event source */ + EventSourcePtr eventSource; + + /** @brief Opens the device and populates the descriptor */ + int openDevice(); + + /** @brief attaches FD to events and sets up callback handler */ + void registerCallback(); + + /** @brief File descriptor manager */ + FileDescriptor fd; + + /** @brief Initializes evdev handle with the fd */ + void initEvDev(); +}; + +} // namespace gpio +} // namespace phosphor diff --git a/presence/Makefile.am b/presence/Makefile.am index 8af030c..7cc80d4 100644 --- a/presence/Makefile.am +++ b/presence/Makefile.am @@ -7,6 +7,7 @@ sbin_PROGRAMS = \ phosphor_gpio_presence_SOURCES = \ main.cpp \ argument.cpp \ + ../evdev.cpp \ gpio_presence.cpp phosphor_gpio_presence_CXXFLAGS = \ diff --git a/presence/gpio_presence.cpp b/presence/gpio_presence.cpp index 0390af6..b87e139 100644 --- a/presence/gpio_presence.cpp +++ b/presence/gpio_presence.cpp @@ -60,44 +60,6 @@ std::string getService(const std::string& path, return mapperResponse.begin()->first; } -// Populate the file descriptor for passed in device -int Presence::openDevice() -{ - using namespace phosphor::logging; - - auto fd = open(path.c_str(), O_RDONLY | O_NONBLOCK); - if (fd < 0) - { - log<level::ERR>("Failed to open device path", - entry("DEVICEPATH=%s", path.c_str()), - entry("ERRNO=%d", errno)); - elog<InternalFailure>(); - } - return fd; -} - -// Initializes the event device with the fd -void Presence::initEvDev() -{ - if (devicePtr) - { - // Init can be done only once per device - return; - } - - struct libevdev* evdev = nullptr; - auto rc = libevdev_new_from_fd((fd)(), &evdev); - if (rc < 0) - { - log<level::ERR>("Failed to initialize evdev"); - elog<InternalFailure>(); - return; - } - - // Packing in the unique_ptr - devicePtr.reset(evdev); -} - void Presence::determinePresence() { auto present = false; @@ -213,21 +175,6 @@ void Presence::updateInventory(bool present) } } -// Attaches the FD to event loop and registers the callback handler -void Presence::registerCallback() -{ - decltype(eventSource.get()) sourcePtr = nullptr; - auto rc = sd_event_add_io(event.get(), &sourcePtr, (fd)(), - EPOLLIN, callbackHandler, this); - eventSource.reset(sourcePtr); - - if (rc < 0) - { - log<level::ERR>("Failed to register callback handler", - entry("ERROR=%s", strerror(-rc))); - elog<InternalFailure>(); - } -} } // namespace presence } // namespace gpio diff --git a/presence/gpio_presence.hpp b/presence/gpio_presence.hpp index e8f68ca..986dbe6 100644 --- a/presence/gpio_presence.hpp +++ b/presence/gpio_presence.hpp @@ -1,8 +1,7 @@ #pragma once #include <string> #include <systemd/sd-event.h> -#include <libevdev/libevdev.h> -#include "file.hpp" +#include "evdev.hpp" namespace phosphor { @@ -11,41 +10,12 @@ namespace gpio namespace presence { -/* Need a custom deleter for freeing up sd_event */ -struct EventDeleter -{ - void operator()(sd_event* event) const - { - event = sd_event_unref(event); - } -}; -using EventPtr = std::unique_ptr<sd_event, EventDeleter>; - -/* Need a custom deleter for freeing up sd_event_source */ -struct EventSourceDeleter -{ - void operator()(sd_event_source* eventSource) const - { - eventSource = sd_event_source_unref(eventSource); - } -}; -using EventSourcePtr = std::unique_ptr<sd_event_source, EventSourceDeleter>; - -/* Need a custom deleter for freeing up evdev struct */ -struct FreeEvDev -{ - void operator()(struct libevdev* device) const - { - libevdev_free(device); - } -}; -using EvdevPtr = std::unique_ptr<struct libevdev, FreeEvDev>; - /** @class Presence - * @brief Responsible for determining and monitoring presence of - * inventory items and updating D-Bus accordingly. + * @brief Responsible for determining and monitoring presence, + * by monitoring GPIO state changes, of inventory items and + * updating D-Bus accordingly. */ -class Presence +class Presence : public Evdev { using Property = std::string; @@ -87,20 +57,12 @@ class Presence const std::string& name, EventPtr& event, sd_event_io_handler_t handler = Presence::processEvents) : + Evdev(path, key, event, handler, true), bus(bus), inventory(inventory), - path(path), - key(key), - name(name), - event(event), - callbackHandler(handler), - fd(openDevice()) - + name(name) { - initEvDev(); determinePresence(); - // Register callback handler when FD has some data - registerCallback(); } /** @brief Callback handler when the FD has some activity on it @@ -145,42 +107,11 @@ class Presence /** @brief Object path under inventory to display this inventory item */ const std::string inventory; - /** @brief Device path to read for GPIO pin state - to determine presence of inventory item */ - const std::string path; - - /** @brief GPIO key to monitor */ - const unsigned int key; - /** @brief Pretty name of the inventory item*/ const std::string name; - /** @brief Event structure */ - EvdevPtr devicePtr; - - /** @brief Monitor to sd_event */ - EventPtr& event; - - /** @brief Callback handler when the FD has some data */ - sd_event_io_handler_t callbackHandler; - - /** @brief event source */ - EventSourcePtr eventSource; - - /** @brief Opens the device and populates the descriptor */ - int openDevice(); - - /** @brief attaches FD to events and sets up callback handler */ - void registerCallback(); - - /** @brief File descriptor manager */ - FileDescriptor fd; - /** @brief Analyzes the GPIO event and update present property*/ void analyzeEvent(); - - /** @brief Initializes evdev handle with the fd */ - void initEvDev(); }; /** |