blob: 68bf4472cf5d33cc2e350c01842a0b2f57424bdf [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 Subbanna4902a102017-04-04 14:05:09 +053069 */
70 Monitor(const std::string& path,
71 decltype(input_event::code) key,
72 decltype(input_event::value) polarity,
Vishwanatha Subbanna0b956032017-04-04 14:07:25 +053073 const std::string& target,
74 EventPtr& event,
75 sd_event_io_handler_t handler = Monitor::processEvents)
Vishwanatha Subbanna4902a102017-04-04 14:05:09 +053076 : path(path),
77 key(key),
78 polarity(polarity),
79 target(target),
Vishwanatha Subbanna0b956032017-04-04 14:07:25 +053080 event(event),
81 callbackHandler(handler),
Vishwanatha Subbanna4902a102017-04-04 14:05:09 +053082 fd(openDevice())
83 {
Vishwanatha Subbanna0b956032017-04-04 14:07:25 +053084 // And register callback handler when FD has some data
85 registerCallback();
Vishwanatha Subbanna4902a102017-04-04 14:05:09 +053086 }
87
Vishwanatha Subbanna0b956032017-04-04 14:07:25 +053088 /** @brief Callback handler when the FD has some activity on it
89 *
90 * @param[in] es - Populated event source
91 * @param[in] fd - Associated File descriptor
92 * @param[in] revents - Type of event
93 * @param[in] userData - User data that was passed during registration
94 *
95 * @return - 0 or positive number on success and negative
96 * errno otherwise
97 */
98 static int processEvents(sd_event_source* es, int fd,
99 uint32_t revents, void* userData);
100
Vishwanatha Subbannaba730132017-04-04 14:08:26 +0530101 /** @brief Returns the completion state of this handler */
102 inline auto completed() const
103 {
104 return complete;
105 }
106
Vishwanatha Subbanna4902a102017-04-04 14:05:09 +0530107 private:
108 /** @brief Absolute path of GPIO input device */
109 const std::string& path;
110
111 /** @brief GPIO key code that is of interest */
112 decltype(input_event::code) key;
113
114 /** @brief GPIO key value that is of interest */
115 decltype(input_event::value) polarity;
116
117 /** @brief Systemd unit to be started when the condition is met */
118 const std::string& target;
119
Vishwanatha Subbanna0b956032017-04-04 14:07:25 +0530120 /** @brief Monitor to sd_event */
121 EventPtr& event;
122
123 /** @brief event source */
124 EventSourcePtr eventSource;
125
126 /** @brief Callback handler when the FD has some data */
127 sd_event_io_handler_t callbackHandler;
128
129 /** @brief File descriptor manager */
Vishwanatha Subbanna4902a102017-04-04 14:05:09 +0530130 FileDescriptor fd;
131
Vishwanatha Subbanna77ec4792017-04-10 15:43:47 +0530132 /** event structure */
133 EvdevPtr device;
134
Vishwanatha Subbannaba730132017-04-04 14:08:26 +0530135 /** @brief Completion indicator */
136 bool complete = false;
137
Vishwanatha Subbanna4902a102017-04-04 14:05:09 +0530138 /** @brief Opens the device and populates the descriptor */
139 int openDevice();
Vishwanatha Subbanna0b956032017-04-04 14:07:25 +0530140
141 /** @brief attaches FD to events and sets up callback handler */
142 void registerCallback();
Vishwanatha Subbannaba730132017-04-04 14:08:26 +0530143
Vishwanatha Subbanna77ec4792017-04-10 15:43:47 +0530144 /** @brief Analyzes the GPIO event and starts configured target */
145 void analyzeEvent();
146
147 /** @brief Initializes evdev handle with the fd */
148 void initEvDev();
Vishwanatha Subbanna4902a102017-04-04 14:05:09 +0530149};
150
151} // namespace gpio
152} // namespace phosphor