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. Defaults to one in this 74 * class 75 * @param[in] useEvDev - Whether to use EvDev to retrieve events 76 */ 77 Evdev(const std::string& path, 78 const unsigned int key, 79 EventPtr& event, 80 sd_event_io_handler_t handler, 81 bool useEvDev = true) : 82 path(path), 83 key(key), 84 event(event), 85 callbackHandler(handler), 86 fd(openDevice()) 87 88 { 89 if (useEvDev) 90 { 91 // If we are asked to use EvDev, do that initialization. 92 initEvDev(); 93 } 94 95 // Register callback handler when FD has some data 96 registerCallback(); 97 } 98 99 protected: 100 /** @brief Device path to read for GPIO pin state */ 101 const std::string path; 102 103 /** @brief GPIO key to monitor */ 104 const unsigned int key; 105 106 /** @brief Event structure */ 107 EvdevPtr devicePtr; 108 109 /** @brief Monitor to sd_event */ 110 EventPtr& event; 111 112 /** @brief Callback handler when the FD has some data */ 113 sd_event_io_handler_t callbackHandler; 114 115 /** @brief event source */ 116 EventSourcePtr eventSource; 117 118 /** @brief Opens the device and populates the descriptor */ 119 int openDevice(); 120 121 /** @brief attaches FD to events and sets up callback handler */ 122 void registerCallback(); 123 124 /** @brief File descriptor manager */ 125 FileDescriptor fd; 126 127 /** @brief Initializes evdev handle with the fd */ 128 void initEvDev(); 129 }; 130 131 } // namespace gpio 132 } // namespace phosphor 133