summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGunnar Mills <gmills@us.ibm.com>2017-07-26 16:15:21 -0500
committerGunnar Mills <gmills@us.ibm.com>2017-07-27 14:58:11 -0500
commit835dfb8877fd2e78281e22b8b08dc29e0e9ef5a5 (patch)
tree778575523167f4db36f39bf835046e3d8556809f
parent765725e057046784ceb4e7595e44f2e4c2ef6ae2 (diff)
downloadphosphor-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.cpp72
-rw-r--r--evdev.hpp132
-rw-r--r--presence/Makefile.am1
-rw-r--r--presence/gpio_presence.cpp53
-rw-r--r--presence/gpio_presence.hpp83
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();
};
/**
OpenPOWER on IntegriCloud