blob: 37929084a8e6f3cf911b6cd2dfc1dae3cad1ce2d [file] [log] [blame]
Brad Bishopb1e329a2017-08-02 01:23:12 -04001#pragma once
2
Patrick Venture3d6d3182018-08-31 09:33:09 -07003#include <phosphor-logging/elog-errors.hpp>
4#include <phosphor-logging/elog.hpp>
5#include <phosphor-logging/log.hpp>
Brad Bishopb1e329a2017-08-02 01:23:12 -04006#include <sdbusplus/bus.hpp>
7#include <sdbusplus/message.hpp>
Brad Bishopb1e329a2017-08-02 01:23:12 -04008#include <xyz/openbmc_project/Common/error.hpp>
9
George Liu3fe976c2022-06-21 09:37:04 +080010#include <string>
11
Brad Bishopb1e329a2017-08-02 01:23:12 -040012namespace util
13{
14namespace detail
15{
16namespace errors = sdbusplus::xyz::openbmc_project::Common::Error;
17} // namespace detail
18
19/** @brief Alias for PropertiesChanged signal callbacks. */
Brad Bishopd1eac882018-03-29 10:34:05 -040020template <typename... T>
Patrick Williams35b4f332020-05-13 17:53:09 -050021using Properties = std::map<std::string, std::variant<T...>>;
Brad Bishopb1e329a2017-08-02 01:23:12 -040022
23namespace sdbusplus
24{
25
26/** @brief Get the bus connection. */
27static auto& getBus() __attribute__((pure));
28static auto& getBus()
29{
30 static auto bus = ::sdbusplus::bus::new_default();
31 return bus;
32}
33
34/** @brief Invoke a method. */
Brad Bishopd1eac882018-03-29 10:34:05 -040035template <typename... Args>
36static auto callMethod(::sdbusplus::bus::bus& bus, const std::string& busName,
37 const std::string& path, const std::string& interface,
38 const std::string& method, Args&&... args)
Brad Bishopb1e329a2017-08-02 01:23:12 -040039{
Brad Bishopd1eac882018-03-29 10:34:05 -040040 auto reqMsg = bus.new_method_call(busName.c_str(), path.c_str(),
41 interface.c_str(), method.c_str());
Brad Bishopb1e329a2017-08-02 01:23:12 -040042 reqMsg.append(std::forward<Args>(args)...);
43 auto respMsg = bus.call(reqMsg);
44
45 if (respMsg.is_method_error())
46 {
47 phosphor::logging::log<phosphor::logging::level::INFO>(
Brad Bishopd1eac882018-03-29 10:34:05 -040048 "Failed to invoke DBus method.",
49 phosphor::logging::entry("PATH=%s", path.c_str()),
50 phosphor::logging::entry("INTERFACE=%s", interface.c_str()),
51 phosphor::logging::entry("METHOD=%s", method.c_str()));
Brad Bishopb1e329a2017-08-02 01:23:12 -040052 phosphor::logging::elog<detail::errors::InternalFailure>();
53 }
54
55 return respMsg;
56}
57
58/** @brief Invoke a method. */
Brad Bishopd1eac882018-03-29 10:34:05 -040059template <typename... Args>
60static auto callMethod(const std::string& busName, const std::string& path,
61 const std::string& interface, const std::string& method,
62 Args&&... args)
Brad Bishopb1e329a2017-08-02 01:23:12 -040063{
Brad Bishopd1eac882018-03-29 10:34:05 -040064 return callMethod(getBus(), busName, path, interface, method,
65 std::forward<Args>(args)...);
Brad Bishopb1e329a2017-08-02 01:23:12 -040066}
67
68/** @brief Invoke a method and read the response. */
Brad Bishopd1eac882018-03-29 10:34:05 -040069template <typename Ret, typename... Args>
70static auto
71 callMethodAndRead(::sdbusplus::bus::bus& bus, const std::string& busName,
72 const std::string& path, const std::string& interface,
73 const std::string& method, Args&&... args)
Brad Bishopb1e329a2017-08-02 01:23:12 -040074{
Brad Bishopd1eac882018-03-29 10:34:05 -040075 ::sdbusplus::message::message respMsg = callMethod<Args...>(
76 bus, busName, path, interface, method, std::forward<Args>(args)...);
Brad Bishopb1e329a2017-08-02 01:23:12 -040077 Ret resp;
78 respMsg.read(resp);
79 return resp;
80}
81
82/** @brief Invoke a method and read the response. */
Brad Bishopd1eac882018-03-29 10:34:05 -040083template <typename Ret, typename... Args>
84static auto callMethodAndRead(const std::string& busName,
85 const std::string& path,
86 const std::string& interface,
87 const std::string& method, Args&&... args)
Brad Bishopb1e329a2017-08-02 01:23:12 -040088{
Brad Bishopd1eac882018-03-29 10:34:05 -040089 return callMethodAndRead<Ret>(getBus(), busName, path, interface, method,
90 std::forward<Args>(args)...);
Brad Bishopb1e329a2017-08-02 01:23:12 -040091}
92
Brad Bishopb1e329a2017-08-02 01:23:12 -040093/** @brief Get service from the mapper. */
Brad Bishopd1eac882018-03-29 10:34:05 -040094static auto getService(::sdbusplus::bus::bus& bus, const std::string& path,
95 const std::string& interface)
Brad Bishopb1e329a2017-08-02 01:23:12 -040096{
97 using namespace std::literals::string_literals;
98 using GetObject = std::map<std::string, std::vector<std::string>>;
99
100 auto mapperResp = callMethodAndRead<GetObject>(
Brad Bishopd1eac882018-03-29 10:34:05 -0400101 bus, "xyz.openbmc_project.ObjectMapper"s,
102 "/xyz/openbmc_project/object_mapper"s,
103 "xyz.openbmc_project.ObjectMapper"s, "GetObject"s, path,
104 GetObject::mapped_type{interface});
Brad Bishopb1e329a2017-08-02 01:23:12 -0400105
106 if (mapperResp.empty())
107 {
108 phosphor::logging::log<phosphor::logging::level::INFO>(
Brad Bishopd1eac882018-03-29 10:34:05 -0400109 "Object not found.",
110 phosphor::logging::entry("PATH=%s", path.c_str()),
111 phosphor::logging::entry("INTERFACE=%s", interface.c_str()));
Brad Bishopb1e329a2017-08-02 01:23:12 -0400112 phosphor::logging::elog<detail::errors::InternalFailure>();
113 }
114 return mapperResp.begin()->first;
115}
116
117/** @brief Get a property without mapper lookup. */
118template <typename Property>
Brad Bishopd1eac882018-03-29 10:34:05 -0400119static auto getProperty(::sdbusplus::bus::bus& bus, const std::string& busName,
120 const std::string& path, const std::string& interface,
121 const std::string& property)
Brad Bishopb1e329a2017-08-02 01:23:12 -0400122{
123 using namespace std::literals::string_literals;
124
Brad Bishopd1eac882018-03-29 10:34:05 -0400125 auto msg =
126 callMethod(bus, busName, path, "org.freedesktop.DBus.Properties"s,
127 "Get"s, interface, property);
Patrick Williams35b4f332020-05-13 17:53:09 -0500128 ::std::variant<Property> value;
Brad Bishopb1e329a2017-08-02 01:23:12 -0400129 msg.read(value);
Patrick Williams34ef1e52020-05-13 11:07:43 -0500130 return std::get<Property>(value);
Brad Bishopb1e329a2017-08-02 01:23:12 -0400131}
132
133/** @brief Get a property without mapper lookup. */
134template <typename Property>
Brad Bishopd1eac882018-03-29 10:34:05 -0400135static auto getProperty(const std::string& busName, const std::string& path,
136 const std::string& interface,
137 const std::string& property)
Brad Bishopb1e329a2017-08-02 01:23:12 -0400138{
Brad Bishopd1eac882018-03-29 10:34:05 -0400139 return getProperty<Property>(getBus(), busName, path, interface, property);
Brad Bishopb1e329a2017-08-02 01:23:12 -0400140}
141
142/** @brief Get a property with mapper lookup. */
143template <typename Property>
Brad Bishopd1eac882018-03-29 10:34:05 -0400144static auto getProperty(::sdbusplus::bus::bus& bus, const std::string& path,
145 const std::string& interface,
146 const std::string& property)
Brad Bishopb1e329a2017-08-02 01:23:12 -0400147{
Brad Bishopd1eac882018-03-29 10:34:05 -0400148 return getProperty<Property>(bus, getService(bus, path, interface), path,
149 interface, property);
Brad Bishopb1e329a2017-08-02 01:23:12 -0400150}
151
152/** @brief Get a property with mapper lookup. */
153template <typename Property>
Brad Bishopd1eac882018-03-29 10:34:05 -0400154static auto getProperty(const std::string& path, const std::string& interface,
155 const std::string& property)
Brad Bishopb1e329a2017-08-02 01:23:12 -0400156{
Brad Bishopd1eac882018-03-29 10:34:05 -0400157 return getProperty<Property>(getBus(), path, interface, property);
Brad Bishopb1e329a2017-08-02 01:23:12 -0400158}
159
160} // namespace sdbusplus
161} // namespace util