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