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