1 #pragma once 2 3 #include <unistd.h> 4 #include <string> 5 #include <linux/input.h> 6 #include <libevdev/libevdev.h> 7 #include <systemd/sd-event.h> 8 #include <sdbusplus/bus.hpp> 9 #include "file.hpp" 10 namespace phosphor 11 { 12 namespace gpio 13 { 14 15 /* Need a custom deleter for freeing up sd_event */ 16 struct EventDeleter 17 { 18 void operator()(sd_event* event) const 19 { 20 event = sd_event_unref(event); 21 } 22 }; 23 using EventPtr = std::unique_ptr<sd_event, EventDeleter>; 24 25 /* Need a custom deleter for freeing up sd_event_source */ 26 struct EventSourceDeleter 27 { 28 void operator()(sd_event_source* eventSource) const 29 { 30 eventSource = sd_event_source_unref(eventSource); 31 } 32 }; 33 using EventSourcePtr = std::unique_ptr<sd_event_source, EventSourceDeleter>; 34 35 /* Need a custom deleter for freeing up evdev struct */ 36 struct EvdevDeleter 37 { 38 void operator()(struct libevdev* device) const 39 { 40 libevdev_free(device); 41 } 42 }; 43 using EvdevPtr = std::unique_ptr<struct libevdev, EvdevDeleter>; 44 45 /** @class Monitor 46 * @brief Responsible for catching GPIO state change 47 * condition and taking actions 48 */ 49 class Monitor 50 { 51 public: 52 Monitor() = delete; 53 ~Monitor() = default; 54 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 66 * @param[in] event - sd_event handler 67 * @param[in] handler - IO callback handler. Defaults to one in this 68 * class 69 */ 70 Monitor(const std::string& path, 71 decltype(input_event::code) key, 72 decltype(input_event::value) polarity, 73 const std::string& target, 74 EventPtr& event, 75 sd_event_io_handler_t handler = Monitor::processEvents) 76 : path(path), 77 key(key), 78 polarity(polarity), 79 target(target), 80 event(event), 81 callbackHandler(handler), 82 fd(openDevice()) 83 { 84 // And register callback handler when FD has some data 85 registerCallback(); 86 } 87 88 /** @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 101 /** @brief Returns the completion state of this handler */ 102 inline auto completed() const 103 { 104 return complete; 105 } 106 107 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 120 /** @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 */ 130 FileDescriptor fd; 131 132 /** event structure */ 133 EvdevPtr device; 134 135 /** @brief Completion indicator */ 136 bool complete = false; 137 138 /** @brief Opens the device and populates the descriptor */ 139 int openDevice(); 140 141 /** @brief attaches FD to events and sets up callback handler */ 142 void registerCallback(); 143 144 /** @brief Analyzes the GPIO event and starts configured target */ 145 void analyzeEvent(); 146 147 /** @brief Initializes evdev handle with the fd */ 148 void initEvDev(); 149 }; 150 151 } // namespace gpio 152 } // namespace phosphor 153