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