1 #pragma once 2 #include "evdev.hpp" 3 4 #include <systemd/sd-event.h> 5 6 #include <sdbusplus/bus.hpp> 7 8 #include <cstdlib> 9 #include <filesystem> 10 #include <string> 11 12 namespace phosphor 13 { 14 namespace gpio 15 { 16 namespace presence 17 { 18 19 static constexpr auto deviceField = 0; 20 static constexpr auto pathField = 1; 21 using Device = std::string; 22 using Path = std::filesystem::path; 23 using Driver = std::tuple<Device, Path>; 24 using Interface = std::string; 25 26 /** @class Presence 27 * @brief Responsible for determining and monitoring presence, 28 * by monitoring GPIO state changes, of inventory items and 29 * updating D-Bus accordingly. 30 */ 31 class Presence : public Evdev 32 { 33 using Property = std::string; 34 using Value = std::variant<bool, std::string>; 35 // Association between property and its value 36 using PropertyMap = std::map<Property, Value>; 37 using Interface = std::string; 38 // Association between interface and the D-Bus property 39 using InterfaceMap = std::map<Interface, PropertyMap>; 40 using Object = sdbusplus::message::object_path; 41 // Association between object and the interface 42 using ObjectMap = std::map<Object, InterfaceMap>; 43 44 public: 45 Presence() = delete; 46 ~Presence() = default; 47 Presence(const Presence&) = delete; 48 Presence& operator=(const Presence&) = delete; 49 Presence(Presence&&) = delete; 50 Presence& operator=(Presence&&) = delete; 51 52 /** @brief Constructs Presence object. 53 * 54 * @param[in] bus - D-Bus bus Object 55 * @param[in] inventory - Object path under inventory 56 to display this inventory item 57 * @param[in] path - Device path to read for GPIO pin state 58 to determine presence of inventory item 59 * @param[in] key - GPIO key to monitor 60 * @param[in] name - Pretty name of the inventory item 61 * @param[in] event - sd_event handler 62 * @param[in] drivers - list of device drivers to bind and unbind 63 * @param[in] ifaces - list of extra interfaces to associate with the 64 * inventory item 65 * @param[in] handler - IO callback handler. Defaults to one in this 66 * class 67 */ Presence(sdbusplus::bus_t & bus,const std::string & inventory,const std::string & path,const unsigned int key,const std::string & name,EventPtr & event,const std::vector<Driver> & drivers,const std::vector<Interface> & ifaces,sd_event_io_handler_t handler=Presence::processEvents)68 Presence(sdbusplus::bus_t& bus, const std::string& inventory, 69 const std::string& path, const unsigned int key, 70 const std::string& name, EventPtr& event, 71 const std::vector<Driver>& drivers, 72 const std::vector<Interface>& ifaces, 73 sd_event_io_handler_t handler = Presence::processEvents) : 74 Evdev(path, key, event, handler, true), bus(bus), inventory(inventory), 75 name(name), drivers(drivers), ifaces(ifaces) 76 { 77 // See if the environment (from configuration file?) has a 78 // DRIVER_BIND_DELAY_MS set. 79 if (char* envDelay = std::getenv("DRIVER_BIND_DELAY_MS")) 80 { 81 // DRIVER_BIND_DELAY_MS environment variable is set. 82 // Update the bind delay (in milliseconds) to the value from the 83 // environment. 84 delay = std::strtoull(envDelay, nullptr, 10); 85 } 86 determinePresence(); 87 } 88 89 /** @brief Callback handler when the FD has some activity on it 90 * 91 * @param[in] es - Populated event source 92 * @param[in] fd - Associated File descriptor 93 * @param[in] revents - Type of event 94 * @param[in] userData - User data that was passed during registration 95 * 96 * @return - 0 or positive number on success and negative 97 * errno otherwise 98 */ 99 static int processEvents(sd_event_source* es, int fd, uint32_t revents, 100 void* userData); 101 102 private: 103 /** 104 * @brief Update the present property for the inventory item. 105 * 106 * @param[in] present - What the present property should be set to. 107 */ 108 void updateInventory(bool present); 109 110 /** 111 * @brief Construct the inventory object map for the inventory item. 112 * 113 * @param[in] present - What the present property should be set to. 114 * 115 * @return The inventory object map to update inventory 116 */ 117 ObjectMap getObjectMap(bool present); 118 119 /** @brief Connection for sdbusplus bus */ 120 sdbusplus::bus_t& bus; 121 122 /** 123 * @brief Read the GPIO device to determine initial presence and set 124 * present property at D-Bus path. 125 */ 126 void determinePresence(); 127 128 /** @brief Object path under inventory to display this inventory item */ 129 const std::string inventory; 130 131 /** @brief Delay in milliseconds from present to bind device driver */ 132 unsigned int delay = 0; 133 134 /** @brief Pretty name of the inventory item*/ 135 const std::string name; 136 137 /** @brief Analyzes the GPIO event and update present property*/ 138 void analyzeEvent(); 139 140 /** @brief Vector of path and device tuples to bind/unbind*/ 141 const std::vector<Driver> drivers; 142 143 /** @brief Vector of extra inventory interfaces to associate with the 144 * inventory item 145 */ 146 const std::vector<Interface> ifaces; 147 148 /** 149 * @brief Binds or unbinds drivers 150 * 151 * Called when a presence change is detected to either 152 * bind the drivers for the new card or unbind them for 153 * the just removed card. Operates on the drivers vector. 154 * 155 * Writes <device> to <path>/bind (or unbind) 156 * 157 * @param present - when true, will bind the drivers 158 * when false, will unbind them 159 */ 160 void bindOrUnbindDrivers(bool present); 161 }; 162 163 /** 164 * @brief Get the service name from the mapper for the 165 * interface and path passed in. 166 * 167 * @param[in] path - The D-Bus path name 168 * @param[in] interface - The D-Bus interface name 169 * @param[in] bus - The D-Bus bus object 170 * 171 * @return The service name 172 */ 173 std::string getService(const std::string& path, const std::string& interface, 174 sdbusplus::bus_t& bus); 175 176 } // namespace presence 177 } // namespace gpio 178 } // namespace phosphor 179