1 #pragma once 2 #include "file.hpp" 3 4 #include <libevdev/libevdev.h> 5 #include <systemd/sd-event.h> 6 7 #include <sdbusplus/message.hpp> 8 9 #include <map> 10 #include <memory> 11 #include <string> 12 13 namespace phosphor 14 { 15 namespace gpio 16 { 17 18 /* Need a custom deleter for freeing up sd_event */ 19 struct EventDeleter 20 { operator ()phosphor::gpio::EventDeleter21 void operator()(sd_event* event) const 22 { 23 sd_event_unref(event); 24 } 25 }; 26 using EventPtr = std::unique_ptr<sd_event, EventDeleter>; 27 28 /* Need a custom deleter for freeing up sd_event_source */ 29 struct EventSourceDeleter 30 { operator ()phosphor::gpio::EventSourceDeleter31 void operator()(sd_event_source* eventSource) const 32 { 33 sd_event_source_unref(eventSource); 34 } 35 }; 36 using EventSourcePtr = std::unique_ptr<sd_event_source, EventSourceDeleter>; 37 38 /* Need a custom deleter for freeing up evdev struct */ 39 struct FreeEvDev 40 { operator ()phosphor::gpio::FreeEvDev41 void operator()(struct libevdev* device) const 42 { 43 libevdev_free(device); 44 } 45 }; 46 using EvdevPtr = std::unique_ptr<struct libevdev, FreeEvDev>; 47 48 /** @class Evdev 49 * @brief Responsible for catching GPIO state changes conditions and taking 50 * actions 51 */ 52 class Evdev 53 { 54 using Property = std::string; 55 using Value = std::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 */ Evdev(const std::string & path,const unsigned int key,EventPtr & event,sd_event_io_handler_t handler,bool useEvDev=true)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), key(key), event(event), callbackHandler(handler), 84 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