1 #pragma once
2 
3 #include "evdev.hpp"
4 
5 #include <linux/input.h>
6 #include <systemd/sd-event.h>
7 #include <unistd.h>
8 
9 #include <sdbusplus/bus.hpp>
10 
11 #include <string>
12 
13 namespace phosphor
14 {
15 namespace gpio
16 {
17 
18 /** @class Monitor
19  *  @brief Responsible for catching GPIO state change
20  *  condition and starting systemd targets.
21  */
22 class Monitor : public Evdev
23 {
24   public:
25     Monitor() = delete;
26     ~Monitor() = default;
27     Monitor(const Monitor&) = delete;
28     Monitor& operator=(const Monitor&) = delete;
29     Monitor(Monitor&&) = delete;
30     Monitor& operator=(Monitor&&) = delete;
31 
32     /** @brief Constructs Monitor object.
33      *
34      *  @param[in] path     - Path to gpio input device
35      *  @param[in] key      - GPIO key to monitor
36      *  @param[in] polarity - GPIO assertion polarity to look for
37      *  @param[in] target   - systemd unit to be started on GPIO
38      *                        value change
39      *  @param[in] event    - sd_event handler
40      *  @param[in] continueRun - Whether to continue after key pressed
41      *  @param[in] handler  - IO callback handler. Defaults to one in this
42      *                        class
43      *  @param[in] useEvDev - Whether to use EvDev to retrieve events
44      */
45     Monitor(const std::string& path, decltype(input_event::code) key,
46             decltype(input_event::value) polarity, const std::string& target,
47             EventPtr& event, bool continueRun,
48             sd_event_io_handler_t handler = Monitor::processEvents,
49             bool useEvDev = true) :
50         Evdev(path, key, event, handler, useEvDev),
51         polarity(polarity), target(target),
52         continueAfterKeyPress(continueRun){};
53 
54     /** @brief Callback handler when the FD has some activity on it
55      *
56      *  @param[in] es       - Populated event source
57      *  @param[in] fd       - Associated File descriptor
58      *  @param[in] revents  - Type of event
59      *  @param[in] userData - User data that was passed during registration
60      *
61      *  @return             - 0 or positive number on success and negative
62      *                        errno otherwise
63      */
64     static int processEvents(sd_event_source* es, int fd, uint32_t revents,
65                              void* userData);
66 
67     /** @brief Returns the completion state of this handler */
68     inline auto completed() const
69     {
70         return complete;
71     }
72 
73   private:
74     /** @brief GPIO key value that is of interest */
75     decltype(input_event::value) polarity;
76 
77     /** @brief Systemd unit to be started when the condition is met */
78     const std::string& target;
79 
80     /** @brief If the monitor should continue after key press */
81     bool continueAfterKeyPress;
82 
83     /** @brief Completion indicator */
84     bool complete = false;
85 
86     /** @brief Analyzes the GPIO event and starts configured target */
87     void analyzeEvent();
88 };
89 
90 } // namespace gpio
91 } // namespace phosphor
92