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.
74          *  @param[in] useEvDev  - Whether to use EvDev to retrieve events
75          */
76         Evdev(const std::string& path,
77               const unsigned int key,
78               EventPtr& event,
79               sd_event_io_handler_t handler,
80               bool useEvDev = true) :
81             path(path),
82             key(key),
83             event(event),
84             callbackHandler(handler),
85             fd(openDevice())
86 
87         {
88             if (useEvDev)
89             {
90                 // If we are asked to use EvDev, do that initialization.
91                 initEvDev();
92             }
93 
94             // Register callback handler when FD has some data
95             registerCallback();
96         }
97 
98     protected:
99         /** @brief Device path to read for GPIO pin state */
100         const std::string path;
101 
102         /** @brief GPIO key to monitor */
103         const unsigned int key;
104 
105         /** @brief Event structure */
106         EvdevPtr devicePtr;
107 
108         /** @brief Monitor to sd_event */
109         EventPtr& event;
110 
111         /** @brief Callback handler when the FD has some data */
112         sd_event_io_handler_t callbackHandler;
113 
114         /** @brief event source */
115         EventSourcePtr eventSource;
116 
117         /** @brief Opens the device and populates the descriptor */
118         int openDevice();
119 
120         /** @brief attaches FD to events and sets up callback handler */
121         void registerCallback();
122 
123         /** @brief File descriptor manager */
124         FileDescriptor fd;
125 
126         /** @brief Initializes evdev handle with the fd */
127         void initEvDev();
128 };
129 
130 } // namespace gpio
131 } // namespace phosphor
132