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