1 #pragma once 2 3 #include <unistd.h> 4 #include <string> 5 #include <linux/input.h> 6 #include <systemd/sd-event.h> 7 #include <sdbusplus/bus.hpp> 8 #include "file.hpp" 9 namespace phosphor 10 { 11 namespace gpio 12 { 13 14 /* Need a custom deleter for freeing up sd_event */ 15 struct EventDeleter 16 { 17 void operator()(sd_event* event) const 18 { 19 event = sd_event_unref(event); 20 } 21 }; 22 using EventPtr = std::unique_ptr<sd_event, EventDeleter>; 23 24 /* Need a custom deleter for freeing up sd_event_source */ 25 struct EventSourceDeleter 26 { 27 void operator()(sd_event_source* eventSource) const 28 { 29 eventSource = sd_event_source_unref(eventSource); 30 } 31 }; 32 using EventSourcePtr = std::unique_ptr<sd_event_source, EventSourceDeleter>; 33 34 /** @class Monitor 35 * @brief Responsible for catching GPIO state change 36 * condition and taking actions 37 */ 38 class Monitor 39 { 40 public: 41 Monitor() = delete; 42 ~Monitor() = default; 43 Monitor(const Monitor&) = delete; 44 Monitor& operator=(const Monitor&) = delete; 45 Monitor(Monitor&&) = delete; 46 Monitor& operator=(Monitor&&) = delete; 47 48 /** @brief Constructs Monitor object. 49 * 50 * @param[in] path - Path to gpio input device 51 * @param[in] key - GPIO key to monitor 52 * @param[in] polarity - GPIO assertion polarity to look for 53 * @param[in] target - systemd unit to be started on GPIO 54 * value change 55 * @param[in] event - sd_event handler 56 * @param[in] handler - IO callback handler. Defaults to one in this 57 * class 58 */ 59 Monitor(const std::string& path, 60 decltype(input_event::code) key, 61 decltype(input_event::value) polarity, 62 const std::string& target, 63 EventPtr& event, 64 sd_event_io_handler_t handler = Monitor::processEvents) 65 : path(path), 66 key(key), 67 polarity(polarity), 68 target(target), 69 event(event), 70 callbackHandler(handler), 71 fd(openDevice()) 72 { 73 // And register callback handler when FD has some data 74 registerCallback(); 75 } 76 77 /** @brief Callback handler when the FD has some activity on it 78 * 79 * @param[in] es - Populated event source 80 * @param[in] fd - Associated File descriptor 81 * @param[in] revents - Type of event 82 * @param[in] userData - User data that was passed during registration 83 * 84 * @return - 0 or positive number on success and negative 85 * errno otherwise 86 */ 87 static int processEvents(sd_event_source* es, int fd, 88 uint32_t revents, void* userData); 89 90 /** @brief Returns the completion state of this handler */ 91 inline auto completed() const 92 { 93 return complete; 94 } 95 96 private: 97 /** @brief Absolute path of GPIO input device */ 98 const std::string& path; 99 100 /** @brief GPIO key code that is of interest */ 101 decltype(input_event::code) key; 102 103 /** @brief GPIO key value that is of interest */ 104 decltype(input_event::value) polarity; 105 106 /** @brief Systemd unit to be started when the condition is met */ 107 const std::string& target; 108 109 /** @brief Monitor to sd_event */ 110 EventPtr& event; 111 112 /** @brief event source */ 113 EventSourcePtr eventSource; 114 115 /** @brief Callback handler when the FD has some data */ 116 sd_event_io_handler_t callbackHandler; 117 118 /** @brief File descriptor manager */ 119 FileDescriptor fd; 120 121 /** @brief Completion indicator */ 122 bool complete = false; 123 124 /** @brief Opens the device and populates the descriptor */ 125 int openDevice(); 126 127 /** @brief attaches FD to events and sets up callback handler */ 128 void registerCallback(); 129 130 /** @brief Analyzes the GPIO event and starts configured target 131 * 132 * @return - For now, returns zero 133 */ 134 int analyzeEvent(); 135 }; 136 137 } // namespace gpio 138 } // namespace phosphor 139