blob: bffb1d4a4cf4c6af61780d7cbf4f240df68bfd5c [file] [log] [blame]
Vishwanatha Subbanna4902a102017-04-04 14:05:09 +05301#pragma once
2
3#include <unistd.h>
4#include <string>
5#include <linux/input.h>
Vishwanatha Subbanna77ec4792017-04-10 15:43:47 +05306#include <libevdev/libevdev.h>
Vishwanatha Subbanna0b956032017-04-04 14:07:25 +05307#include <systemd/sd-event.h>
Vishwanatha Subbannaba730132017-04-04 14:08:26 +05308#include <sdbusplus/bus.hpp>
Vishwanatha Subbanna4902a102017-04-04 14:05:09 +05309#include "file.hpp"
10namespace phosphor
11{
12namespace gpio
13{
Vishwanatha Subbanna0b956032017-04-04 14:07:25 +053014
15/* Need a custom deleter for freeing up sd_event */
16struct EventDeleter
17{
18 void operator()(sd_event* event) const
19 {
20 event = sd_event_unref(event);
21 }
22};
23using EventPtr = std::unique_ptr<sd_event, EventDeleter>;
24
25/* Need a custom deleter for freeing up sd_event_source */
26struct EventSourceDeleter
27{
28 void operator()(sd_event_source* eventSource) const
29 {
30 eventSource = sd_event_source_unref(eventSource);
31 }
32};
33using EventSourcePtr = std::unique_ptr<sd_event_source, EventSourceDeleter>;
34
Vishwanatha Subbanna77ec4792017-04-10 15:43:47 +053035/* Need a custom deleter for freeing up evdev struct */
36struct EvdevDeleter
37{
38 void operator()(struct libevdev* device) const
39 {
40 libevdev_free(device);
41 }
42};
43using EvdevPtr = std::unique_ptr<struct libevdev, EvdevDeleter>;
44
Vishwanatha Subbanna4902a102017-04-04 14:05:09 +053045/** @class Monitor
46 * @brief Responsible for catching GPIO state change
47 * condition and taking actions
48 */
49class Monitor
50{
51 public:
52 Monitor() = delete;
Vishwanatha Subbanna0b956032017-04-04 14:07:25 +053053 ~Monitor() = default;
Vishwanatha Subbanna4902a102017-04-04 14:05:09 +053054 Monitor(const Monitor&) = delete;
55 Monitor& operator=(const Monitor&) = delete;
56 Monitor(Monitor&&) = delete;
57 Monitor& operator=(Monitor&&) = delete;
58
59 /** @brief Constructs Monitor object.
60 *
61 * @param[in] path - Path to gpio input device
62 * @param[in] key - GPIO key to monitor
63 * @param[in] polarity - GPIO assertion polarity to look for
64 * @param[in] target - systemd unit to be started on GPIO
65 * value change
Vishwanatha Subbanna0b956032017-04-04 14:07:25 +053066 * @param[in] event - sd_event handler
67 * @param[in] handler - IO callback handler. Defaults to one in this
68 * class
Vishwanatha Subbannaba8de422017-06-19 15:51:01 +053069 * @param[in] useEvDev - Whether to use EvDev to retrieve events
Vishwanatha Subbanna4902a102017-04-04 14:05:09 +053070 */
71 Monitor(const std::string& path,
72 decltype(input_event::code) key,
73 decltype(input_event::value) polarity,
Vishwanatha Subbanna0b956032017-04-04 14:07:25 +053074 const std::string& target,
75 EventPtr& event,
Vishwanatha Subbannaba8de422017-06-19 15:51:01 +053076 sd_event_io_handler_t handler = Monitor::processEvents,
77 bool useEvDev = true)
Vishwanatha Subbanna4902a102017-04-04 14:05:09 +053078 : path(path),
79 key(key),
80 polarity(polarity),
81 target(target),
Vishwanatha Subbanna0b956032017-04-04 14:07:25 +053082 event(event),
83 callbackHandler(handler),
Vishwanatha Subbanna4902a102017-04-04 14:05:09 +053084 fd(openDevice())
85 {
Vishwanatha Subbannaba8de422017-06-19 15:51:01 +053086 if (useEvDev)
87 {
88 // If we are asked to use EvDev, do that initialization.
89 initEvDev();
90 }
91
Vishwanatha Subbanna0b956032017-04-04 14:07:25 +053092 // And register callback handler when FD has some data
93 registerCallback();
Vishwanatha Subbanna4902a102017-04-04 14:05:09 +053094 }
95
Vishwanatha Subbanna0b956032017-04-04 14:07:25 +053096 /** @brief Callback handler when the FD has some activity on it
97 *
98 * @param[in] es - Populated event source
99 * @param[in] fd - Associated File descriptor
100 * @param[in] revents - Type of event
101 * @param[in] userData - User data that was passed during registration
102 *
103 * @return - 0 or positive number on success and negative
104 * errno otherwise
105 */
106 static int processEvents(sd_event_source* es, int fd,
107 uint32_t revents, void* userData);
108
Vishwanatha Subbannaba730132017-04-04 14:08:26 +0530109 /** @brief Returns the completion state of this handler */
110 inline auto completed() const
111 {
112 return complete;
113 }
114
Vishwanatha Subbanna4902a102017-04-04 14:05:09 +0530115 private:
116 /** @brief Absolute path of GPIO input device */
117 const std::string& path;
118
119 /** @brief GPIO key code that is of interest */
120 decltype(input_event::code) key;
121
122 /** @brief GPIO key value that is of interest */
123 decltype(input_event::value) polarity;
124
125 /** @brief Systemd unit to be started when the condition is met */
126 const std::string& target;
127
Vishwanatha Subbanna0b956032017-04-04 14:07:25 +0530128 /** @brief Monitor to sd_event */
129 EventPtr& event;
130
131 /** @brief event source */
132 EventSourcePtr eventSource;
133
134 /** @brief Callback handler when the FD has some data */
135 sd_event_io_handler_t callbackHandler;
136
137 /** @brief File descriptor manager */
Vishwanatha Subbanna4902a102017-04-04 14:05:09 +0530138 FileDescriptor fd;
139
Vishwanatha Subbanna77ec4792017-04-10 15:43:47 +0530140 /** event structure */
141 EvdevPtr device;
142
Vishwanatha Subbannaba730132017-04-04 14:08:26 +0530143 /** @brief Completion indicator */
144 bool complete = false;
145
Vishwanatha Subbanna4902a102017-04-04 14:05:09 +0530146 /** @brief Opens the device and populates the descriptor */
147 int openDevice();
Vishwanatha Subbanna0b956032017-04-04 14:07:25 +0530148
149 /** @brief attaches FD to events and sets up callback handler */
150 void registerCallback();
Vishwanatha Subbannaba730132017-04-04 14:08:26 +0530151
Vishwanatha Subbanna77ec4792017-04-10 15:43:47 +0530152 /** @brief Analyzes the GPIO event and starts configured target */
153 void analyzeEvent();
154
155 /** @brief Initializes evdev handle with the fd */
156 void initEvDev();
Vishwanatha Subbanna4902a102017-04-04 14:05:09 +0530157};
158
159} // namespace gpio
160} // namespace phosphor