1 #pragma once 2 #include <string> 3 #include <systemd/sd-event.h> 4 #include <libevdev/libevdev.h> 5 #include "file.hpp" 6 7 namespace phosphor 8 { 9 namespace gpio 10 { 11 12 /* Need a custom deleter for freeing up sd_event */ 13 struct EventDeleter 14 { 15 void operator()(sd_event* event) const 16 { 17 event = sd_event_unref(event); 18 } 19 }; 20 using EventPtr = std::unique_ptr<sd_event, EventDeleter>; 21 22 /* Need a custom deleter for freeing up sd_event_source */ 23 struct EventSourceDeleter 24 { 25 void operator()(sd_event_source* eventSource) const 26 { 27 eventSource = sd_event_source_unref(eventSource); 28 } 29 }; 30 using EventSourcePtr = std::unique_ptr<sd_event_source, EventSourceDeleter>; 31 32 /* Need a custom deleter for freeing up evdev struct */ 33 struct FreeEvDev 34 { 35 void operator()(struct libevdev* device) const 36 { 37 libevdev_free(device); 38 } 39 }; 40 using EvdevPtr = std::unique_ptr<struct libevdev, FreeEvDev>; 41 42 /** @class Evdev 43 * @brief Responsible for catching GPIO state changes conditions and taking 44 * actions 45 */ 46 class Evdev 47 { 48 49 using Property = std::string; 50 using Value = sdbusplus::message::variant<bool, std::string>; 51 // Association between property and its value 52 using PropertyMap = std::map<Property, Value>; 53 using Interface = std::string; 54 // Association between interface and the D-Bus property 55 using InterfaceMap = std::map<Interface, PropertyMap>; 56 using Object = sdbusplus::message::object_path; 57 // Association between object and the interface 58 using ObjectMap = std::map<Object, InterfaceMap>; 59 60 public: 61 Evdev() = delete; 62 ~Evdev() = default; 63 Evdev(const Evdev&) = delete; 64 Evdev& operator=(const Evdev&) = delete; 65 Evdev(Evdev&&) = delete; 66 Evdev& operator=(Evdev&&) = delete; 67 68 /** @brief Constructs Evdev object. 69 * 70 * @param[in] path - Device path to read for GPIO pin state 71 * @param[in] key - GPIO key to monitor 72 * @param[in] event - sd_event handler 73 * @param[in] handler - IO callback handler. 74 * @param[in] useEvDev - Whether to use EvDev to retrieve events 75 */ 76 Evdev(const std::string& path, 77 const unsigned int key, 78 EventPtr& event, 79 sd_event_io_handler_t handler, 80 bool useEvDev = true) : 81 path(path), 82 key(key), 83 event(event), 84 callbackHandler(handler), 85 fd(openDevice()) 86 87 { 88 if (useEvDev) 89 { 90 // If we are asked to use EvDev, do that initialization. 91 initEvDev(); 92 } 93 94 // Register callback handler when FD has some data 95 registerCallback(); 96 } 97 98 protected: 99 /** @brief Device path to read for GPIO pin state */ 100 const std::string path; 101 102 /** @brief GPIO key to monitor */ 103 const unsigned int key; 104 105 /** @brief Event structure */ 106 EvdevPtr devicePtr; 107 108 /** @brief Monitor to sd_event */ 109 EventPtr& event; 110 111 /** @brief Callback handler when the FD has some data */ 112 sd_event_io_handler_t callbackHandler; 113 114 /** @brief event source */ 115 EventSourcePtr eventSource; 116 117 /** @brief Opens the device and populates the descriptor */ 118 int openDevice(); 119 120 /** @brief attaches FD to events and sets up callback handler */ 121 void registerCallback(); 122 123 /** @brief File descriptor manager */ 124 FileDescriptor fd; 125 126 /** @brief Initializes evdev handle with the fd */ 127 void initEvDev(); 128 }; 129 130 } // namespace gpio 131 } // namespace phosphor 132