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 <experimental/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::experimental::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 */ 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), 75 bus(bus), inventory(inventory), name(name), drivers(drivers), 76 ifaces(ifaces) 77 { 78 // See if the environment (from configuration file?) has a 79 // DRIVER_BIND_DELAY_MS set. 80 if (char* envDelay = std::getenv("DRIVER_BIND_DELAY_MS")) 81 { 82 // DRIVER_BIND_DELAY_MS environment variable is set. 83 // Update the bind delay (in milliseconds) to the value from the 84 // environment. 85 delay = std::strtoull(envDelay, NULL, 10); 86 } 87 determinePresence(); 88 } 89 90 /** @brief Callback handler when the FD has some activity on it 91 * 92 * @param[in] es - Populated event source 93 * @param[in] fd - Associated File descriptor 94 * @param[in] revents - Type of event 95 * @param[in] userData - User data that was passed during registration 96 * 97 * @return - 0 or positive number on success and negative 98 * errno otherwise 99 */ 100 static int processEvents(sd_event_source* es, int fd, uint32_t revents, 101 void* userData); 102 103 private: 104 /** 105 * @brief Update the present property for the inventory item. 106 * 107 * @param[in] present - What the present property should be set to. 108 */ 109 void updateInventory(bool present); 110 111 /** 112 * @brief Construct the inventory object map for the inventory item. 113 * 114 * @param[in] present - What the present property should be set to. 115 * 116 * @return The inventory object map to update inventory 117 */ 118 ObjectMap getObjectMap(bool present); 119 120 /** @brief Connection for sdbusplus bus */ 121 sdbusplus::bus_t& bus; 122 123 /** 124 * @brief Read the GPIO device to determine initial presence and set 125 * present property at D-Bus path. 126 */ 127 void determinePresence(); 128 129 /** @brief Object path under inventory to display this inventory item */ 130 const std::string inventory; 131 132 /** @brief Delay in milliseconds from present to bind device driver */ 133 unsigned int delay = 0; 134 135 /** @brief Pretty name of the inventory item*/ 136 const std::string name; 137 138 /** @brief Analyzes the GPIO event and update present property*/ 139 void analyzeEvent(); 140 141 /** @brief Vector of path and device tuples to bind/unbind*/ 142 const std::vector<Driver> drivers; 143 144 /** @brief Vector of extra inventory interfaces to associate with the 145 * inventory item 146 */ 147 const std::vector<Interface> ifaces; 148 149 /** 150 * @brief Binds or unbinds drivers 151 * 152 * Called when a presence change is detected to either 153 * bind the drivers for the new card or unbind them for 154 * the just removed card. Operates on the drivers vector. 155 * 156 * Writes <device> to <path>/bind (or unbind) 157 * 158 * @param present - when true, will bind the drivers 159 * when false, will unbind them 160 */ 161 void bindOrUnbindDrivers(bool present); 162 }; 163 164 /** 165 * @brief Get the service name from the mapper for the 166 * interface and path passed in. 167 * 168 * @param[in] path - The D-Bus path name 169 * @param[in] interface - The D-Bus interface name 170 * @param[in] bus - The D-Bus bus object 171 * 172 * @return The service name 173 */ 174 std::string getService(const std::string& path, const std::string& interface, 175 sdbusplus::bus_t& bus); 176 177 } // namespace presence 178 } // namespace gpio 179 } // namespace phosphor 180