1 #pragma once 2 3 #include <sdbusplus/bus.hpp> 4 #include <sdbusplus/message.hpp> 5 #include <sdbusplus/bus/match.hpp> 6 #include <phosphor-logging/log.hpp> 7 #include <phosphor-logging/elog.hpp> 8 #include <phosphor-logging/elog-errors.hpp> 9 #include <xyz/openbmc_project/Common/error.hpp> 10 11 namespace phosphor 12 { 13 namespace fan 14 { 15 namespace util 16 { 17 namespace detail 18 { 19 namespace errors = sdbusplus::xyz::openbmc_project::Common::Error; 20 } // namespace detail 21 22 /** @brief Alias for PropertiesChanged signal callbacks. */ 23 template <typename ...T> 24 using Properties = std::map<std::string, sdbusplus::message::variant<T...>>; 25 26 /** @class SDBusPlus 27 * @brief DBus access delegate implementation for sdbusplus. 28 */ 29 class SDBusPlus 30 { 31 32 public: 33 /** @brief Get the bus connection. */ 34 static auto& getBus() __attribute__((pure)) 35 { 36 static auto bus = sdbusplus::bus::new_default(); 37 return bus; 38 } 39 40 /** @brief Invoke a method. */ 41 template <typename ...Args> 42 static auto callMethod( 43 const std::string& busName, 44 const std::string& path, 45 const std::string& interface, 46 const std::string& method, 47 Args&& ... args) 48 { 49 auto reqMsg = getBus().new_method_call( 50 busName.c_str(), 51 path.c_str(), 52 interface.c_str(), 53 method.c_str()); 54 reqMsg.append(std::forward<Args>(args)...); 55 auto respMsg = getBus().call(reqMsg); 56 57 if (respMsg.is_method_error()) 58 { 59 phosphor::logging::log<phosphor::logging::level::INFO>( 60 "Failed to invoke DBus method.", 61 phosphor::logging::entry("PATH=%s", path.c_str()), 62 phosphor::logging::entry( 63 "INTERFACE=%s", interface.c_str()), 64 phosphor::logging::entry("METHOD=%s", method.c_str())); 65 phosphor::logging::elog<detail::errors::InternalFailure>(); 66 } 67 68 return respMsg; 69 } 70 71 /** @brief Invoke a method and read the response. */ 72 template <typename Ret, typename ...Args> 73 static auto callMethodAndRead( 74 const std::string& busName, 75 const std::string& path, 76 const std::string& interface, 77 const std::string& method, 78 Args&& ... args) 79 { 80 sdbusplus::message::message respMsg = 81 callMethod<Args...>( 82 busName, 83 path, 84 interface, 85 method, 86 std::forward<Args>(args)...); 87 Ret resp; 88 respMsg.read(resp); 89 return resp; 90 } 91 92 /** @brief Get service from the mapper. */ 93 static auto getService( 94 const std::string& path, 95 const std::string& interface) 96 { 97 using namespace std::literals::string_literals; 98 using GetObject = std::map<std::string, std::vector<std::string>>; 99 100 auto mapperResp = callMethodAndRead<GetObject>( 101 "xyz.openbmc_project.ObjectMapper"s, 102 "/xyz/openbmc_project/object_mapper"s, 103 "xyz.openbmc_project.ObjectMapper"s, 104 "GetObject"s, 105 path, 106 GetObject::mapped_type{interface}); 107 108 if (mapperResp.empty()) 109 { 110 phosphor::logging::log<phosphor::logging::level::INFO>( 111 "Object not found.", 112 phosphor::logging::entry("PATH=%s", path.c_str()), 113 phosphor::logging::entry( 114 "INTERFACE=%s", interface.c_str())); 115 phosphor::logging::elog<detail::errors::InternalFailure>(); 116 } 117 return mapperResp.begin()->first; 118 } 119 120 /** @brief Get a property with mapper lookup. */ 121 template <typename Property> 122 static auto getProperty( 123 const std::string& path, 124 const std::string& interface, 125 const std::string& property) 126 { 127 using namespace std::literals::string_literals; 128 129 auto msg = callMethod( 130 getService(path, interface), 131 path, 132 "org.freedesktop.DBus.Properties"s, 133 "Get"s, 134 interface, 135 property); 136 sdbusplus::message::variant<Property> value; 137 msg.read(value); 138 return value.template get<Property>(); 139 } 140 141 /** @brief Set a property with mapper lookup. */ 142 template <typename Property> 143 static void setProperty( 144 const std::string& path, 145 const std::string& interface, 146 const std::string& property, 147 Property&& value) 148 { 149 using namespace std::literals::string_literals; 150 151 sdbusplus::message::variant<Property> varValue( 152 std::forward<Property>(value)); 153 154 callMethod( 155 getService(path, interface), 156 path, 157 "org.freedesktop.DBus.Properties"s, 158 "Set"s, 159 interface, 160 property, 161 varValue); 162 } 163 164 /** @brief Invoke method with mapper lookup. */ 165 template <typename ...Args> 166 static auto lookupAndCallMethod( 167 const std::string& path, 168 const std::string& interface, 169 const std::string& method, 170 Args&& ... args) 171 { 172 return callMethod( 173 getService(path, interface), 174 path, 175 interface, 176 method, 177 std::forward<Args>(args)...); 178 } 179 180 /** @brief Invoke method and read with mapper lookup. */ 181 template <typename Ret, typename ...Args> 182 static auto lookupCallMethodAndRead( 183 const std::string& path, 184 const std::string& interface, 185 const std::string& method, 186 Args&& ... args) 187 { 188 return callMethodAndRead( 189 getService(path, interface), 190 path, 191 interface, 192 method, 193 std::forward<Args>(args)...); 194 } 195 }; 196 197 } // namespace util 198 } // namespace fan 199 } // namespace phosphor 200