blob: b5d13940a15417883a99b11ac56f94e46cbeddb2 [file] [log] [blame]
#pragma once
#include "file.hpp"
#include <libevdev/libevdev.h>
#include <systemd/sd-event.h>
#include <map>
#include <memory>
#include <sdbusplus/message.hpp>
#include <string>
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 = std::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.
* @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