xref: /openbmc/phosphor-gpio-monitor/evdev.hpp (revision 8377d59c61c653a34df1c3c4ca72219eceb0b43b)
1 #pragma once
2 #include "file.hpp"
3 
4 #include <libevdev/libevdev.h>
5 #include <systemd/sd-event.h>
6 
7 #include <sdbusplus/message.hpp>
8 
9 #include <map>
10 #include <memory>
11 #include <string>
12 
13 namespace phosphor
14 {
15 namespace gpio
16 {
17 
18 /* Need a custom deleter for freeing up sd_event */
19 struct EventDeleter
20 {
operator ()phosphor::gpio::EventDeleter21     void operator()(sd_event* event) const
22     {
23         sd_event_unref(event);
24     }
25 };
26 using EventPtr = std::unique_ptr<sd_event, EventDeleter>;
27 
28 /* Need a custom deleter for freeing up sd_event_source */
29 struct EventSourceDeleter
30 {
operator ()phosphor::gpio::EventSourceDeleter31     void operator()(sd_event_source* eventSource) const
32     {
33         sd_event_source_unref(eventSource);
34     }
35 };
36 using EventSourcePtr = std::unique_ptr<sd_event_source, EventSourceDeleter>;
37 
38 /* Need a custom deleter for freeing up evdev struct */
39 struct FreeEvDev
40 {
operator ()phosphor::gpio::FreeEvDev41     void operator()(struct libevdev* device) const
42     {
43         libevdev_free(device);
44     }
45 };
46 using EvdevPtr = std::unique_ptr<struct libevdev, FreeEvDev>;
47 
48 /** @class Evdev
49  *  @brief Responsible for catching GPIO state changes conditions and taking
50  *  actions
51  */
52 class Evdev
53 {
54     using Property = std::string;
55     using Value = std::variant<bool, std::string>;
56     // Association between property and its value
57     using PropertyMap = std::map<Property, Value>;
58     using Interface = std::string;
59     // Association between interface and the D-Bus property
60     using InterfaceMap = std::map<Interface, PropertyMap>;
61     using Object = sdbusplus::message::object_path;
62     // Association between object and the interface
63     using ObjectMap = std::map<Object, InterfaceMap>;
64 
65   public:
66     Evdev() = delete;
67     ~Evdev() = default;
68     Evdev(const Evdev&) = delete;
69     Evdev& operator=(const Evdev&) = delete;
70     Evdev(Evdev&&) = delete;
71     Evdev& operator=(Evdev&&) = delete;
72 
73     /** @brief Constructs Evdev object.
74      *
75      *  @param[in] path      - Device path to read for GPIO pin state
76      *  @param[in] key       - GPIO key to monitor
77      *  @param[in] event     - sd_event handler
78      *  @param[in] handler   - IO callback handler.
79      *  @param[in] useEvDev  - Whether to use EvDev to retrieve events
80      */
Evdev(const std::string & path,const unsigned int key,EventPtr & event,sd_event_io_handler_t handler,bool useEvDev=true)81     Evdev(const std::string& path, const unsigned int key, EventPtr& event,
82           sd_event_io_handler_t handler, bool useEvDev = true) :
83         path(path), key(key), event(event), callbackHandler(handler),
84         fd(openDevice())
85 
86     {
87         if (useEvDev)
88         {
89             // If we are asked to use EvDev, do that initialization.
90             initEvDev();
91         }
92 
93         // Register callback handler when FD has some data
94         registerCallback();
95     }
96 
97   protected:
98     /** @brief Device path to read for GPIO pin state */
99     const std::string path;
100 
101     /** @brief GPIO key to monitor */
102     const unsigned int key;
103 
104     /** @brief Event structure */
105     EvdevPtr devicePtr;
106 
107     /** @brief Monitor to sd_event */
108     EventPtr& event;
109 
110     /** @brief Callback handler when the FD has some data */
111     sd_event_io_handler_t callbackHandler;
112 
113     /** @brief event source */
114     EventSourcePtr eventSource;
115 
116     /** @brief Opens the device and populates the descriptor */
117     int openDevice();
118 
119     /** @brief attaches FD to events and sets up callback handler */
120     void registerCallback();
121 
122     /** @brief File descriptor manager */
123     FileDescriptor fd;
124 
125     /** @brief Initializes evdev handle with the fd */
126     void initEvDev();
127 };
128 
129 } // namespace gpio
130 } // namespace phosphor
131