| Brad Bishop | 6e9cfdb | 2017-06-08 11:59:58 -0400 | [diff] [blame] | 1 | #pragma once | 
 | 2 |  | 
| Brad Bishop | 6e9cfdb | 2017-06-08 11:59:58 -0400 | [diff] [blame] | 3 | #include <phosphor-logging/elog-errors.hpp> | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 4 | #include <phosphor-logging/elog.hpp> | 
 | 5 | #include <phosphor-logging/log.hpp> | 
 | 6 | #include <sdbusplus/bus.hpp> | 
 | 7 | #include <sdbusplus/bus/match.hpp> | 
 | 8 | #include <sdbusplus/message.hpp> | 
| Brad Bishop | 6e9cfdb | 2017-06-08 11:59:58 -0400 | [diff] [blame] | 9 | #include <xyz/openbmc_project/Common/error.hpp> | 
 | 10 |  | 
| Patrick Williams | fbf4703 | 2023-07-17 12:27:34 -0500 | [diff] [blame] | 11 | #include <format> | 
 | 12 |  | 
| Brad Bishop | 6e9cfdb | 2017-06-08 11:59:58 -0400 | [diff] [blame] | 13 | namespace phosphor | 
 | 14 | { | 
 | 15 | namespace fan | 
 | 16 | { | 
 | 17 | namespace util | 
 | 18 | { | 
 | 19 | namespace detail | 
 | 20 | { | 
 | 21 | namespace errors = sdbusplus::xyz::openbmc_project::Common::Error; | 
 | 22 | } // namespace detail | 
 | 23 |  | 
| Matt Spinler | ba7b5fe | 2018-04-25 15:26:10 -0500 | [diff] [blame] | 24 | /** | 
 | 25 |  * @class DBusError | 
 | 26 |  * | 
 | 27 |  * The base class for the exceptions thrown on fails in the various | 
 | 28 |  * SDBusPlus calls.  Used so that a single catch statement can catch | 
 | 29 |  * any type of these exceptions. | 
 | 30 |  * | 
 | 31 |  * None of these exceptions will log anything when they are created, | 
 | 32 |  * it is up to the handler to do that if desired. | 
 | 33 |  */ | 
 | 34 | class DBusError : public std::runtime_error | 
 | 35 | { | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 36 |   public: | 
| Patrick Williams | 61b7329 | 2023-05-10 07:50:12 -0500 | [diff] [blame] | 37 |     explicit DBusError(const std::string& msg) : std::runtime_error(msg) {} | 
| Matt Spinler | ba7b5fe | 2018-04-25 15:26:10 -0500 | [diff] [blame] | 38 | }; | 
 | 39 |  | 
 | 40 | /** | 
 | 41 |  * @class DBusMethodError | 
 | 42 |  * | 
 | 43 |  * Thrown on a DBus Method call failure | 
 | 44 |  */ | 
 | 45 | class DBusMethodError : public DBusError | 
 | 46 | { | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 47 |   public: | 
 | 48 |     DBusMethodError(const std::string& busName, const std::string& path, | 
 | 49 |                     const std::string& interface, const std::string& method) : | 
| Patrick Williams | fbf4703 | 2023-07-17 12:27:34 -0500 | [diff] [blame] | 50 |         DBusError(std::format("DBus method failed: {} {} {} {}", busName, path, | 
| Matt Spinler | 23f8757 | 2021-01-20 14:20:30 -0600 | [diff] [blame] | 51 |                               interface, method)), | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 52 |         busName(busName), path(path), interface(interface), method(method) | 
 | 53 |     {} | 
| Matt Spinler | ba7b5fe | 2018-04-25 15:26:10 -0500 | [diff] [blame] | 54 |  | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 55 |     const std::string busName; | 
 | 56 |     const std::string path; | 
 | 57 |     const std::string interface; | 
 | 58 |     const std::string method; | 
| Matt Spinler | ba7b5fe | 2018-04-25 15:26:10 -0500 | [diff] [blame] | 59 | }; | 
 | 60 |  | 
 | 61 | /** | 
 | 62 |  * @class DBusServiceError | 
 | 63 |  * | 
 | 64 |  * Thrown when a service lookup fails.  Usually this points to | 
 | 65 |  * the object path not being present in D-Bus. | 
 | 66 |  */ | 
 | 67 | class DBusServiceError : public DBusError | 
 | 68 | { | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 69 |   public: | 
 | 70 |     DBusServiceError(const std::string& path, const std::string& interface) : | 
| Matt Spinler | 23f8757 | 2021-01-20 14:20:30 -0600 | [diff] [blame] | 71 |         DBusError( | 
| Patrick Williams | fbf4703 | 2023-07-17 12:27:34 -0500 | [diff] [blame] | 72 |             std::format("DBus service lookup failed: {} {}", path, interface)), | 
| Matt Spinler | 23f8757 | 2021-01-20 14:20:30 -0600 | [diff] [blame] | 73 |         path(path), interface(interface) | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 74 |     {} | 
| Matt Spinler | ba7b5fe | 2018-04-25 15:26:10 -0500 | [diff] [blame] | 75 |  | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 76 |     const std::string path; | 
 | 77 |     const std::string interface; | 
| Matt Spinler | ba7b5fe | 2018-04-25 15:26:10 -0500 | [diff] [blame] | 78 | }; | 
 | 79 |  | 
| Matthew Barth | 88923a0 | 2018-05-11 10:14:44 -0500 | [diff] [blame] | 80 | /** | 
 | 81 |  * @class DBusPropertyError | 
 | 82 |  * | 
 | 83 |  * Thrown when a set/get property fails. | 
 | 84 |  */ | 
 | 85 | class DBusPropertyError : public DBusError | 
 | 86 | { | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 87 |   public: | 
| Matt Spinler | 23f8757 | 2021-01-20 14:20:30 -0600 | [diff] [blame] | 88 |     DBusPropertyError(const std::string& msg, const std::string& busName, | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 89 |                       const std::string& path, const std::string& interface, | 
 | 90 |                       const std::string& property) : | 
| Patrick Williams | fbf4703 | 2023-07-17 12:27:34 -0500 | [diff] [blame] | 91 |         DBusError(msg + std::format(": {} {} {} {}", busName, path, interface, | 
| Matt Spinler | 23f8757 | 2021-01-20 14:20:30 -0600 | [diff] [blame] | 92 |                                     property)), | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 93 |         busName(busName), path(path), interface(interface), property(property) | 
 | 94 |     {} | 
| Matthew Barth | 88923a0 | 2018-05-11 10:14:44 -0500 | [diff] [blame] | 95 |  | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 96 |     const std::string busName; | 
 | 97 |     const std::string path; | 
 | 98 |     const std::string interface; | 
 | 99 |     const std::string property; | 
| Matthew Barth | 88923a0 | 2018-05-11 10:14:44 -0500 | [diff] [blame] | 100 | }; | 
 | 101 |  | 
| Brad Bishop | 1e4922a | 2017-07-12 22:56:49 -0400 | [diff] [blame] | 102 | /** @brief Alias for PropertiesChanged signal callbacks. */ | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 103 | template <typename... T> | 
| Patrick Williams | c21d0b3 | 2020-05-13 17:55:14 -0500 | [diff] [blame] | 104 | using Properties = std::map<std::string, std::variant<T...>>; | 
| Brad Bishop | 1e4922a | 2017-07-12 22:56:49 -0400 | [diff] [blame] | 105 |  | 
| Brad Bishop | 6e9cfdb | 2017-06-08 11:59:58 -0400 | [diff] [blame] | 106 | /** @class SDBusPlus | 
 | 107 |  *  @brief DBus access delegate implementation for sdbusplus. | 
 | 108 |  */ | 
 | 109 | class SDBusPlus | 
 | 110 | { | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 111 |   public: | 
 | 112 |     /** @brief Get the bus connection. */ | 
 | 113 |     static auto& getBus() __attribute__((pure)) | 
 | 114 |     { | 
 | 115 |         static auto bus = sdbusplus::bus::new_default(); | 
 | 116 |         return bus; | 
 | 117 |     } | 
| Brad Bishop | 6e9cfdb | 2017-06-08 11:59:58 -0400 | [diff] [blame] | 118 |  | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 119 |     /** @brief Invoke a method. */ | 
 | 120 |     template <typename... Args> | 
| Patrick Williams | cb356d4 | 2022-07-22 19:26:53 -0500 | [diff] [blame] | 121 |     static auto callMethod(sdbusplus::bus_t& bus, const std::string& busName, | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 122 |                            const std::string& path, | 
 | 123 |                            const std::string& interface, | 
 | 124 |                            const std::string& method, Args&&... args) | 
 | 125 |     { | 
 | 126 |         auto reqMsg = bus.new_method_call(busName.c_str(), path.c_str(), | 
 | 127 |                                           interface.c_str(), method.c_str()); | 
 | 128 |         reqMsg.append(std::forward<Args>(args)...); | 
 | 129 |         try | 
| Brad Bishop | 6e9cfdb | 2017-06-08 11:59:58 -0400 | [diff] [blame] | 130 |         { | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 131 |             auto respMsg = bus.call(reqMsg); | 
 | 132 |             if (respMsg.is_method_error()) | 
| Brad Bishop | 6e9cfdb | 2017-06-08 11:59:58 -0400 | [diff] [blame] | 133 |             { | 
| Matt Spinler | ba7b5fe | 2018-04-25 15:26:10 -0500 | [diff] [blame] | 134 |                 throw DBusMethodError{busName, path, interface, method}; | 
| Brad Bishop | 6e9cfdb | 2017-06-08 11:59:58 -0400 | [diff] [blame] | 135 |             } | 
| Matthew Barth | 7c48d10 | 2018-05-09 14:52:36 -0500 | [diff] [blame] | 136 |             return respMsg; | 
 | 137 |         } | 
| Patrick Williams | cb356d4 | 2022-07-22 19:26:53 -0500 | [diff] [blame] | 138 |         catch (const sdbusplus::exception_t&) | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 139 |         { | 
 | 140 |             throw DBusMethodError{busName, path, interface, method}; | 
 | 141 |         } | 
 | 142 |     } | 
 | 143 |  | 
 | 144 |     /** @brief Invoke a method. */ | 
 | 145 |     template <typename... Args> | 
 | 146 |     static auto callMethod(const std::string& busName, const std::string& path, | 
 | 147 |                            const std::string& interface, | 
 | 148 |                            const std::string& method, Args&&... args) | 
 | 149 |     { | 
 | 150 |         return callMethod(getBus(), busName, path, interface, method, | 
 | 151 |                           std::forward<Args>(args)...); | 
 | 152 |     } | 
 | 153 |  | 
 | 154 |     /** @brief Invoke a method and read the response. */ | 
 | 155 |     template <typename Ret, typename... Args> | 
 | 156 |     static auto | 
| Patrick Williams | cb356d4 | 2022-07-22 19:26:53 -0500 | [diff] [blame] | 157 |         callMethodAndRead(sdbusplus::bus_t& bus, const std::string& busName, | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 158 |                           const std::string& path, const std::string& interface, | 
 | 159 |                           const std::string& method, Args&&... args) | 
 | 160 |     { | 
| Patrick Williams | cb356d4 | 2022-07-22 19:26:53 -0500 | [diff] [blame] | 161 |         sdbusplus::message_t respMsg = callMethod<Args...>( | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 162 |             bus, busName, path, interface, method, std::forward<Args>(args)...); | 
 | 163 |         Ret resp; | 
 | 164 |         respMsg.read(resp); | 
 | 165 |         return resp; | 
 | 166 |     } | 
 | 167 |  | 
 | 168 |     /** @brief Invoke a method and read the response. */ | 
 | 169 |     template <typename Ret, typename... Args> | 
| Patrick Williams | dfddd64 | 2024-08-16 15:21:51 -0400 | [diff] [blame] | 170 |     static auto callMethodAndRead( | 
 | 171 |         const std::string& busName, const std::string& path, | 
 | 172 |         const std::string& interface, const std::string& method, Args&&... args) | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 173 |     { | 
 | 174 |         return callMethodAndRead<Ret>(getBus(), busName, path, interface, | 
 | 175 |                                       method, std::forward<Args>(args)...); | 
 | 176 |     } | 
 | 177 |  | 
 | 178 |     /** @brief Get subtree from the mapper without checking response. */ | 
| Patrick Williams | cb356d4 | 2022-07-22 19:26:53 -0500 | [diff] [blame] | 179 |     static auto getSubTreeRaw(sdbusplus::bus_t& bus, const std::string& path, | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 180 |                               const std::string& interface, int32_t depth) | 
 | 181 |     { | 
 | 182 |         using namespace std::literals::string_literals; | 
 | 183 |  | 
 | 184 |         using Path = std::string; | 
 | 185 |         using Intf = std::string; | 
 | 186 |         using Serv = std::string; | 
 | 187 |         using Intfs = std::vector<Intf>; | 
 | 188 |         using Objects = std::map<Path, std::map<Serv, Intfs>>; | 
 | 189 |         Intfs intfs = {interface}; | 
 | 190 |  | 
| Patrick Williams | dfddd64 | 2024-08-16 15:21:51 -0400 | [diff] [blame] | 191 |         return callMethodAndRead<Objects>( | 
 | 192 |             bus, "xyz.openbmc_project.ObjectMapper"s, | 
 | 193 |             "/xyz/openbmc_project/object_mapper"s, | 
 | 194 |             "xyz.openbmc_project.ObjectMapper"s, "GetSubTree"s, path, depth, | 
 | 195 |             intfs); | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 196 |     } | 
 | 197 |  | 
| Mike Capps | 7a401a2 | 2021-07-12 13:59:31 -0400 | [diff] [blame] | 198 |     /** @brief Get subtree from the mapper without checking response, | 
 | 199 |      * (multiple interfaces version). */ | 
| Patrick Williams | cb356d4 | 2022-07-22 19:26:53 -0500 | [diff] [blame] | 200 |     static auto getSubTreeRaw(sdbusplus::bus_t& bus, const std::string& path, | 
| Mike Capps | 7a401a2 | 2021-07-12 13:59:31 -0400 | [diff] [blame] | 201 |                               const std::vector<std::string>& intfs, | 
 | 202 |                               int32_t depth) | 
 | 203 |     { | 
 | 204 |         using namespace std::literals::string_literals; | 
 | 205 |  | 
 | 206 |         using Path = std::string; | 
 | 207 |         using Intf = std::string; | 
 | 208 |         using Serv = std::string; | 
 | 209 |         using Intfs = std::vector<Intf>; | 
 | 210 |         using Objects = std::map<Path, std::map<Serv, Intfs>>; | 
 | 211 |  | 
| Patrick Williams | dfddd64 | 2024-08-16 15:21:51 -0400 | [diff] [blame] | 212 |         return callMethodAndRead<Objects>( | 
 | 213 |             bus, "xyz.openbmc_project.ObjectMapper"s, | 
 | 214 |             "/xyz/openbmc_project/object_mapper"s, | 
 | 215 |             "xyz.openbmc_project.ObjectMapper"s, "GetSubTree"s, path, depth, | 
 | 216 |             intfs); | 
| Mike Capps | 7a401a2 | 2021-07-12 13:59:31 -0400 | [diff] [blame] | 217 |     } | 
 | 218 |  | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 219 |     /** @brief Get subtree from the mapper. */ | 
| Patrick Williams | cb356d4 | 2022-07-22 19:26:53 -0500 | [diff] [blame] | 220 |     static auto getSubTree(sdbusplus::bus_t& bus, const std::string& path, | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 221 |                            const std::string& interface, int32_t depth) | 
 | 222 |     { | 
 | 223 |         auto mapperResp = getSubTreeRaw(bus, path, interface, depth); | 
 | 224 |         if (mapperResp.empty()) | 
 | 225 |         { | 
 | 226 |             phosphor::logging::log<phosphor::logging::level::ERR>( | 
 | 227 |                 "Empty response from mapper GetSubTree", | 
 | 228 |                 phosphor::logging::entry("SUBTREE=%s", path.c_str()), | 
 | 229 |                 phosphor::logging::entry("INTERFACE=%s", interface.c_str()), | 
 | 230 |                 phosphor::logging::entry("DEPTH=%u", depth)); | 
 | 231 |             phosphor::logging::elog<detail::errors::InternalFailure>(); | 
 | 232 |         } | 
 | 233 |         return mapperResp; | 
 | 234 |     } | 
 | 235 |  | 
| Matthew Barth | fcbdc0e | 2020-10-28 14:11:07 -0500 | [diff] [blame] | 236 |     /** @brief Get subtree paths from the mapper without checking response. */ | 
| Patrick Williams | cb356d4 | 2022-07-22 19:26:53 -0500 | [diff] [blame] | 237 |     static auto getSubTreePathsRaw(sdbusplus::bus_t& bus, | 
| Matthew Barth | fcbdc0e | 2020-10-28 14:11:07 -0500 | [diff] [blame] | 238 |                                    const std::string& path, | 
 | 239 |                                    const std::string& interface, int32_t depth) | 
 | 240 |     { | 
 | 241 |         using namespace std::literals::string_literals; | 
 | 242 |  | 
 | 243 |         using Path = std::string; | 
 | 244 |         using Intf = std::string; | 
 | 245 |         using Intfs = std::vector<Intf>; | 
 | 246 |         using ObjectPaths = std::vector<Path>; | 
 | 247 |         Intfs intfs = {interface}; | 
 | 248 |  | 
 | 249 |         return callMethodAndRead<ObjectPaths>( | 
 | 250 |             bus, "xyz.openbmc_project.ObjectMapper"s, | 
 | 251 |             "/xyz/openbmc_project/object_mapper"s, | 
 | 252 |             "xyz.openbmc_project.ObjectMapper"s, "GetSubTreePaths"s, path, | 
 | 253 |             depth, intfs); | 
 | 254 |     } | 
 | 255 |  | 
 | 256 |     /** @brief Get subtree paths from the mapper. */ | 
| Patrick Williams | cb356d4 | 2022-07-22 19:26:53 -0500 | [diff] [blame] | 257 |     static auto getSubTreePaths(sdbusplus::bus_t& bus, const std::string& path, | 
| Matthew Barth | fcbdc0e | 2020-10-28 14:11:07 -0500 | [diff] [blame] | 258 |                                 const std::string& interface, int32_t depth) | 
 | 259 |     { | 
 | 260 |         auto mapperResp = getSubTreePathsRaw(bus, path, interface, depth); | 
 | 261 |         if (mapperResp.empty()) | 
 | 262 |         { | 
 | 263 |             phosphor::logging::log<phosphor::logging::level::ERR>( | 
 | 264 |                 "Empty response from mapper GetSubTreePaths", | 
 | 265 |                 phosphor::logging::entry("SUBTREE=%s", path.c_str()), | 
 | 266 |                 phosphor::logging::entry("INTERFACE=%s", interface.c_str()), | 
 | 267 |                 phosphor::logging::entry("DEPTH=%u", depth)); | 
 | 268 |             phosphor::logging::elog<detail::errors::InternalFailure>(); | 
 | 269 |         } | 
 | 270 |         return mapperResp; | 
 | 271 |     } | 
 | 272 |  | 
| Mike Capps | ce6820a | 2021-05-26 10:40:19 -0400 | [diff] [blame] | 273 |     /** @brief Get service from the mapper without checking response. */ | 
| Patrick Williams | cb356d4 | 2022-07-22 19:26:53 -0500 | [diff] [blame] | 274 |     static auto getServiceRaw(sdbusplus::bus_t& bus, const std::string& path, | 
| Mike Capps | ce6820a | 2021-05-26 10:40:19 -0400 | [diff] [blame] | 275 |                               const std::string& interface) | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 276 |     { | 
 | 277 |         using namespace std::literals::string_literals; | 
 | 278 |         using GetObject = std::map<std::string, std::vector<std::string>>; | 
 | 279 |  | 
| Mike Capps | ce6820a | 2021-05-26 10:40:19 -0400 | [diff] [blame] | 280 |         return callMethodAndRead<GetObject>( | 
 | 281 |             bus, "xyz.openbmc_project.ObjectMapper"s, | 
 | 282 |             "/xyz/openbmc_project/object_mapper"s, | 
 | 283 |             "xyz.openbmc_project.ObjectMapper"s, "GetObject"s, path, | 
 | 284 |             GetObject::mapped_type{interface}); | 
 | 285 |     } | 
 | 286 |  | 
 | 287 |     /** @brief Get service from the mapper. */ | 
| Patrick Williams | cb356d4 | 2022-07-22 19:26:53 -0500 | [diff] [blame] | 288 |     static auto getService(sdbusplus::bus_t& bus, const std::string& path, | 
| Mike Capps | ce6820a | 2021-05-26 10:40:19 -0400 | [diff] [blame] | 289 |                            const std::string& interface) | 
 | 290 |     { | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 291 |         try | 
 | 292 |         { | 
| Mike Capps | ce6820a | 2021-05-26 10:40:19 -0400 | [diff] [blame] | 293 |             auto mapperResp = getServiceRaw(bus, path, interface); | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 294 |  | 
 | 295 |             if (mapperResp.empty()) | 
 | 296 |             { | 
 | 297 |                 // Should never happen.  A missing object would fail | 
 | 298 |                 // in callMethodAndRead() | 
 | 299 |                 phosphor::logging::log<phosphor::logging::level::ERR>( | 
 | 300 |                     "Empty mapper response on service lookup"); | 
 | 301 |                 throw DBusServiceError{path, interface}; | 
 | 302 |             } | 
 | 303 |             return mapperResp.begin()->first; | 
 | 304 |         } | 
| Patrick Williams | ddb773b | 2021-10-06 11:24:49 -0500 | [diff] [blame] | 305 |         catch (const DBusMethodError& e) | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 306 |         { | 
 | 307 |             throw DBusServiceError{path, interface}; | 
 | 308 |         } | 
 | 309 |     } | 
 | 310 |  | 
 | 311 |     /** @brief Get service from the mapper. */ | 
 | 312 |     static auto getService(const std::string& path, | 
 | 313 |                            const std::string& interface) | 
 | 314 |     { | 
 | 315 |         return getService(getBus(), path, interface); | 
 | 316 |     } | 
 | 317 |  | 
| Matthew Barth | a355363 | 2021-05-03 14:40:59 -0500 | [diff] [blame] | 318 |     /** @brief Get managed objects. */ | 
 | 319 |     template <typename Variant> | 
| Patrick Williams | cb356d4 | 2022-07-22 19:26:53 -0500 | [diff] [blame] | 320 |     static auto getManagedObjects(sdbusplus::bus_t& bus, | 
| Matthew Barth | a355363 | 2021-05-03 14:40:59 -0500 | [diff] [blame] | 321 |                                   const std::string& service, | 
 | 322 |                                   const std::string& path) | 
 | 323 |     { | 
 | 324 |         using namespace std::literals::string_literals; | 
 | 325 |  | 
 | 326 |         using Path = sdbusplus::message::object_path; | 
 | 327 |         using Intf = std::string; | 
 | 328 |         using Prop = std::string; | 
 | 329 |         using GetManagedObjects = | 
 | 330 |             std::map<Path, std::map<Intf, std::map<Prop, Variant>>>; | 
 | 331 |  | 
 | 332 |         return callMethodAndRead<GetManagedObjects>( | 
 | 333 |             bus, service, path, "org.freedesktop.DBus.ObjectManager"s, | 
 | 334 |             "GetManagedObjects"s); | 
 | 335 |     } | 
 | 336 |  | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 337 |     /** @brief Get a property with mapper lookup. */ | 
 | 338 |     template <typename Property> | 
| Patrick Williams | cb356d4 | 2022-07-22 19:26:53 -0500 | [diff] [blame] | 339 |     static auto getProperty(sdbusplus::bus_t& bus, const std::string& path, | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 340 |                             const std::string& interface, | 
 | 341 |                             const std::string& property) | 
 | 342 |     { | 
 | 343 |         using namespace std::literals::string_literals; | 
 | 344 |  | 
 | 345 |         auto service = getService(bus, path, interface); | 
| Patrick Williams | dfddd64 | 2024-08-16 15:21:51 -0400 | [diff] [blame] | 346 |         auto msg = | 
 | 347 |             callMethod(bus, service, path, "org.freedesktop.DBus.Properties"s, | 
 | 348 |                        "Get"s, interface, property); | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 349 |         if (msg.is_method_error()) | 
 | 350 |         { | 
 | 351 |             throw DBusPropertyError{"DBus get property failed", service, path, | 
 | 352 |                                     interface, property}; | 
 | 353 |         } | 
 | 354 |         std::variant<Property> value; | 
 | 355 |         msg.read(value); | 
 | 356 |         return std::get<Property>(value); | 
 | 357 |     } | 
 | 358 |  | 
 | 359 |     /** @brief Get a property with mapper lookup. */ | 
 | 360 |     template <typename Property> | 
 | 361 |     static auto getProperty(const std::string& path, | 
 | 362 |                             const std::string& interface, | 
 | 363 |                             const std::string& property) | 
 | 364 |     { | 
 | 365 |         return getProperty<Property>(getBus(), path, interface, property); | 
 | 366 |     } | 
 | 367 |  | 
 | 368 |     /** @brief Get a property variant with mapper lookup. */ | 
 | 369 |     template <typename Variant> | 
| Patrick Williams | dfddd64 | 2024-08-16 15:21:51 -0400 | [diff] [blame] | 370 |     static auto getPropertyVariant( | 
 | 371 |         sdbusplus::bus_t& bus, const std::string& path, | 
 | 372 |         const std::string& interface, const std::string& property) | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 373 |     { | 
 | 374 |         using namespace std::literals::string_literals; | 
 | 375 |  | 
 | 376 |         auto service = getService(bus, path, interface); | 
| Patrick Williams | dfddd64 | 2024-08-16 15:21:51 -0400 | [diff] [blame] | 377 |         auto msg = | 
 | 378 |             callMethod(bus, service, path, "org.freedesktop.DBus.Properties"s, | 
 | 379 |                        "Get"s, interface, property); | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 380 |         if (msg.is_method_error()) | 
 | 381 |         { | 
 | 382 |             throw DBusPropertyError{"DBus get property variant failed", service, | 
 | 383 |                                     path, interface, property}; | 
 | 384 |         } | 
 | 385 |         Variant value; | 
 | 386 |         msg.read(value); | 
 | 387 |         return value; | 
 | 388 |     } | 
 | 389 |  | 
 | 390 |     /** @brief Get a property variant with mapper lookup. */ | 
 | 391 |     template <typename Variant> | 
 | 392 |     static auto getPropertyVariant(const std::string& path, | 
 | 393 |                                    const std::string& interface, | 
 | 394 |                                    const std::string& property) | 
 | 395 |     { | 
 | 396 |         return getPropertyVariant<Variant>(getBus(), path, interface, property); | 
 | 397 |     } | 
 | 398 |  | 
| Mike Capps | 808d7fe | 2022-06-13 10:12:16 -0400 | [diff] [blame] | 399 |     /** @brief Invoke a method and return without checking for error. */ | 
 | 400 |     template <typename... Args> | 
| Patrick Williams | dfddd64 | 2024-08-16 15:21:51 -0400 | [diff] [blame] | 401 |     static auto callMethodAndReturn( | 
 | 402 |         sdbusplus::bus_t& bus, const std::string& busName, | 
 | 403 |         const std::string& path, const std::string& interface, | 
 | 404 |         const std::string& method, Args&&... args) | 
| Mike Capps | 808d7fe | 2022-06-13 10:12:16 -0400 | [diff] [blame] | 405 |     { | 
 | 406 |         auto reqMsg = bus.new_method_call(busName.c_str(), path.c_str(), | 
 | 407 |                                           interface.c_str(), method.c_str()); | 
 | 408 |         reqMsg.append(std::forward<Args>(args)...); | 
 | 409 |         auto respMsg = bus.call(reqMsg); | 
 | 410 |  | 
 | 411 |         return respMsg; | 
 | 412 |     } | 
 | 413 |  | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 414 |     /** @brief Get a property without mapper lookup. */ | 
 | 415 |     template <typename Property> | 
| Patrick Williams | cb356d4 | 2022-07-22 19:26:53 -0500 | [diff] [blame] | 416 |     static auto getProperty(sdbusplus::bus_t& bus, const std::string& service, | 
 | 417 |                             const std::string& path, | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 418 |                             const std::string& interface, | 
 | 419 |                             const std::string& property) | 
 | 420 |     { | 
 | 421 |         using namespace std::literals::string_literals; | 
 | 422 |  | 
 | 423 |         auto msg = callMethodAndReturn(bus, service, path, | 
 | 424 |                                        "org.freedesktop.DBus.Properties"s, | 
 | 425 |                                        "Get"s, interface, property); | 
 | 426 |         if (msg.is_method_error()) | 
 | 427 |         { | 
 | 428 |             throw DBusPropertyError{"DBus get property failed", service, path, | 
 | 429 |                                     interface, property}; | 
 | 430 |         } | 
 | 431 |         std::variant<Property> value; | 
 | 432 |         msg.read(value); | 
 | 433 |         return std::get<Property>(value); | 
 | 434 |     } | 
 | 435 |  | 
 | 436 |     /** @brief Get a property without mapper lookup. */ | 
 | 437 |     template <typename Property> | 
 | 438 |     static auto getProperty(const std::string& service, const std::string& path, | 
 | 439 |                             const std::string& interface, | 
 | 440 |                             const std::string& property) | 
 | 441 |     { | 
 | 442 |         return getProperty<Property>(getBus(), service, path, interface, | 
 | 443 |                                      property); | 
 | 444 |     } | 
 | 445 |  | 
 | 446 |     /** @brief Get a property variant without mapper lookup. */ | 
 | 447 |     template <typename Variant> | 
| Patrick Williams | dfddd64 | 2024-08-16 15:21:51 -0400 | [diff] [blame] | 448 |     static auto getPropertyVariant( | 
 | 449 |         sdbusplus::bus_t& bus, const std::string& service, | 
 | 450 |         const std::string& path, const std::string& interface, | 
 | 451 |         const std::string& property) | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 452 |     { | 
 | 453 |         using namespace std::literals::string_literals; | 
 | 454 |  | 
 | 455 |         auto msg = callMethodAndReturn(bus, service, path, | 
 | 456 |                                        "org.freedesktop.DBus.Properties"s, | 
 | 457 |                                        "Get"s, interface, property); | 
 | 458 |         if (msg.is_method_error()) | 
 | 459 |         { | 
 | 460 |             throw DBusPropertyError{"DBus get property variant failed", service, | 
 | 461 |                                     path, interface, property}; | 
 | 462 |         } | 
 | 463 |         Variant value; | 
 | 464 |         msg.read(value); | 
 | 465 |         return value; | 
 | 466 |     } | 
 | 467 |  | 
 | 468 |     /** @brief Get a property variant without mapper lookup. */ | 
 | 469 |     template <typename Variant> | 
| Patrick Williams | dfddd64 | 2024-08-16 15:21:51 -0400 | [diff] [blame] | 470 |     static auto getPropertyVariant( | 
 | 471 |         const std::string& service, const std::string& path, | 
 | 472 |         const std::string& interface, const std::string& property) | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 473 |     { | 
 | 474 |         return getPropertyVariant<Variant>(getBus(), service, path, interface, | 
 | 475 |                                            property); | 
 | 476 |     } | 
 | 477 |  | 
 | 478 |     /** @brief Set a property with mapper lookup. */ | 
 | 479 |     template <typename Property> | 
| Patrick Williams | cb356d4 | 2022-07-22 19:26:53 -0500 | [diff] [blame] | 480 |     static void setProperty(sdbusplus::bus_t& bus, const std::string& path, | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 481 |                             const std::string& interface, | 
 | 482 |                             const std::string& property, Property&& value) | 
 | 483 |     { | 
 | 484 |         using namespace std::literals::string_literals; | 
 | 485 |  | 
 | 486 |         std::variant<Property> varValue(std::forward<Property>(value)); | 
 | 487 |  | 
 | 488 |         auto service = getService(bus, path, interface); | 
 | 489 |         auto msg = callMethodAndReturn(bus, service, path, | 
 | 490 |                                        "org.freedesktop.DBus.Properties"s, | 
 | 491 |                                        "Set"s, interface, property, varValue); | 
 | 492 |         if (msg.is_method_error()) | 
 | 493 |         { | 
 | 494 |             throw DBusPropertyError{"DBus set property failed", service, path, | 
 | 495 |                                     interface, property}; | 
 | 496 |         } | 
 | 497 |     } | 
 | 498 |  | 
 | 499 |     /** @brief Set a property with mapper lookup. */ | 
 | 500 |     template <typename Property> | 
 | 501 |     static void setProperty(const std::string& path, | 
 | 502 |                             const std::string& interface, | 
 | 503 |                             const std::string& property, Property&& value) | 
 | 504 |     { | 
 | 505 |         return setProperty(getBus(), path, interface, property, | 
 | 506 |                            std::forward<Property>(value)); | 
 | 507 |     } | 
 | 508 |  | 
 | 509 |     /** @brief Set a property without mapper lookup. */ | 
 | 510 |     template <typename Property> | 
| Patrick Williams | cb356d4 | 2022-07-22 19:26:53 -0500 | [diff] [blame] | 511 |     static void setProperty(sdbusplus::bus_t& bus, const std::string& service, | 
 | 512 |                             const std::string& path, | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 513 |                             const std::string& interface, | 
 | 514 |                             const std::string& property, Property&& value) | 
 | 515 |     { | 
 | 516 |         using namespace std::literals::string_literals; | 
 | 517 |  | 
 | 518 |         std::variant<Property> varValue(std::forward<Property>(value)); | 
 | 519 |  | 
 | 520 |         auto msg = callMethodAndReturn(bus, service, path, | 
 | 521 |                                        "org.freedesktop.DBus.Properties"s, | 
 | 522 |                                        "Set"s, interface, property, varValue); | 
 | 523 |         if (msg.is_method_error()) | 
 | 524 |         { | 
 | 525 |             throw DBusPropertyError{"DBus set property failed", service, path, | 
 | 526 |                                     interface, property}; | 
 | 527 |         } | 
 | 528 |     } | 
 | 529 |  | 
 | 530 |     /** @brief Set a property without mapper lookup. */ | 
 | 531 |     template <typename Property> | 
 | 532 |     static void setProperty(const std::string& service, const std::string& path, | 
 | 533 |                             const std::string& interface, | 
 | 534 |                             const std::string& property, Property&& value) | 
 | 535 |     { | 
 | 536 |         return setProperty(getBus(), service, path, interface, property, | 
 | 537 |                            std::forward<Property>(value)); | 
 | 538 |     } | 
 | 539 |  | 
 | 540 |     /** @brief Invoke method with mapper lookup. */ | 
 | 541 |     template <typename... Args> | 
| Patrick Williams | dfddd64 | 2024-08-16 15:21:51 -0400 | [diff] [blame] | 542 |     static auto lookupAndCallMethod( | 
 | 543 |         sdbusplus::bus_t& bus, const std::string& path, | 
 | 544 |         const std::string& interface, const std::string& method, Args&&... args) | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 545 |     { | 
 | 546 |         return callMethod(bus, getService(bus, path, interface), path, | 
 | 547 |                           interface, method, std::forward<Args>(args)...); | 
 | 548 |     } | 
 | 549 |  | 
 | 550 |     /** @brief Invoke method with mapper lookup. */ | 
 | 551 |     template <typename... Args> | 
 | 552 |     static auto lookupAndCallMethod(const std::string& path, | 
 | 553 |                                     const std::string& interface, | 
 | 554 |                                     const std::string& method, Args&&... args) | 
 | 555 |     { | 
 | 556 |         return lookupAndCallMethod(getBus(), path, interface, method, | 
 | 557 |                                    std::forward<Args>(args)...); | 
 | 558 |     } | 
 | 559 |  | 
 | 560 |     /** @brief Invoke method and read with mapper lookup. */ | 
 | 561 |     template <typename Ret, typename... Args> | 
| Patrick Williams | dfddd64 | 2024-08-16 15:21:51 -0400 | [diff] [blame] | 562 |     static auto lookupCallMethodAndRead( | 
 | 563 |         sdbusplus::bus_t& bus, const std::string& path, | 
 | 564 |         const std::string& interface, const std::string& method, Args&&... args) | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 565 |     { | 
 | 566 |         return callMethodAndRead(bus, getService(bus, path, interface), path, | 
 | 567 |                                  interface, method, | 
 | 568 |                                  std::forward<Args>(args)...); | 
 | 569 |     } | 
 | 570 |  | 
 | 571 |     /** @brief Invoke method and read with mapper lookup. */ | 
 | 572 |     template <typename Ret, typename... Args> | 
| Patrick Williams | dfddd64 | 2024-08-16 15:21:51 -0400 | [diff] [blame] | 573 |     static auto lookupCallMethodAndRead( | 
 | 574 |         const std::string& path, const std::string& interface, | 
 | 575 |         const std::string& method, Args&&... args) | 
| Matthew Barth | 9e80c87 | 2020-05-26 10:50:29 -0500 | [diff] [blame] | 576 |     { | 
 | 577 |         return lookupCallMethodAndRead<Ret>(getBus(), path, interface, method, | 
 | 578 |                                             std::forward<Args>(args)...); | 
 | 579 |     } | 
| Brad Bishop | 6e9cfdb | 2017-06-08 11:59:58 -0400 | [diff] [blame] | 580 | }; | 
 | 581 |  | 
 | 582 | } // namespace util | 
 | 583 | } // namespace fan | 
 | 584 | } // namespace phosphor |