blob: eefc1cdf9144a00baa99f0c12411629cbd7f6af0 [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
10namespace util
11{
12namespace detail
13{
14namespace errors = sdbusplus::xyz::openbmc_project::Common::Error;
15} // namespace detail
16
17/** @brief Alias for PropertiesChanged signal callbacks. */
Brad Bishopd1eac882018-03-29 10:34:05 -040018template <typename... T>
Brad Bishopb1e329a2017-08-02 01:23:12 -040019using Properties = std::map<std::string, sdbusplus::message::variant<T...>>;
20
21namespace sdbusplus
22{
23
24/** @brief Get the bus connection. */
25static auto& getBus() __attribute__((pure));
26static auto& getBus()
27{
28 static auto bus = ::sdbusplus::bus::new_default();
29 return bus;
30}
31
32/** @brief Invoke a method. */
Brad Bishopd1eac882018-03-29 10:34:05 -040033template <typename... Args>
34static auto callMethod(::sdbusplus::bus::bus& bus, const std::string& busName,
35 const std::string& path, const std::string& interface,
36 const std::string& method, Args&&... args)
Brad Bishopb1e329a2017-08-02 01:23:12 -040037{
Brad Bishopd1eac882018-03-29 10:34:05 -040038 auto reqMsg = bus.new_method_call(busName.c_str(), path.c_str(),
39 interface.c_str(), method.c_str());
Brad Bishopb1e329a2017-08-02 01:23:12 -040040 reqMsg.append(std::forward<Args>(args)...);
41 auto respMsg = bus.call(reqMsg);
42
43 if (respMsg.is_method_error())
44 {
45 phosphor::logging::log<phosphor::logging::level::INFO>(
Brad Bishopd1eac882018-03-29 10:34:05 -040046 "Failed to invoke DBus method.",
47 phosphor::logging::entry("PATH=%s", path.c_str()),
48 phosphor::logging::entry("INTERFACE=%s", interface.c_str()),
49 phosphor::logging::entry("METHOD=%s", method.c_str()));
Brad Bishopb1e329a2017-08-02 01:23:12 -040050 phosphor::logging::elog<detail::errors::InternalFailure>();
51 }
52
53 return respMsg;
54}
55
56/** @brief Invoke a method. */
Brad Bishopd1eac882018-03-29 10:34:05 -040057template <typename... Args>
58static auto callMethod(const std::string& busName, const std::string& path,
59 const std::string& interface, const std::string& method,
60 Args&&... args)
Brad Bishopb1e329a2017-08-02 01:23:12 -040061{
Brad Bishopd1eac882018-03-29 10:34:05 -040062 return callMethod(getBus(), busName, path, interface, method,
63 std::forward<Args>(args)...);
Brad Bishopb1e329a2017-08-02 01:23:12 -040064}
65
66/** @brief Invoke a method and read the response. */
Brad Bishopd1eac882018-03-29 10:34:05 -040067template <typename Ret, typename... Args>
68static auto
69 callMethodAndRead(::sdbusplus::bus::bus& bus, const std::string& busName,
70 const std::string& path, const std::string& interface,
71 const std::string& method, Args&&... args)
Brad Bishopb1e329a2017-08-02 01:23:12 -040072{
Brad Bishopd1eac882018-03-29 10:34:05 -040073 ::sdbusplus::message::message respMsg = callMethod<Args...>(
74 bus, busName, path, interface, method, std::forward<Args>(args)...);
Brad Bishopb1e329a2017-08-02 01:23:12 -040075 Ret resp;
76 respMsg.read(resp);
77 return resp;
78}
79
80/** @brief Invoke a method and read the response. */
Brad Bishopd1eac882018-03-29 10:34:05 -040081template <typename Ret, typename... Args>
82static auto callMethodAndRead(const std::string& busName,
83 const std::string& path,
84 const std::string& interface,
85 const std::string& method, Args&&... args)
Brad Bishopb1e329a2017-08-02 01:23:12 -040086{
Brad Bishopd1eac882018-03-29 10:34:05 -040087 return callMethodAndRead<Ret>(getBus(), busName, path, interface, method,
88 std::forward<Args>(args)...);
Brad Bishopb1e329a2017-08-02 01:23:12 -040089}
90
Brad Bishopb1e329a2017-08-02 01:23:12 -040091/** @brief Get service from the mapper. */
Brad Bishopd1eac882018-03-29 10:34:05 -040092static auto getService(::sdbusplus::bus::bus& bus, const std::string& path,
93 const std::string& interface)
Brad Bishopb1e329a2017-08-02 01:23:12 -040094{
95 using namespace std::literals::string_literals;
96 using GetObject = std::map<std::string, std::vector<std::string>>;
97
98 auto mapperResp = callMethodAndRead<GetObject>(
Brad Bishopd1eac882018-03-29 10:34:05 -040099 bus, "xyz.openbmc_project.ObjectMapper"s,
100 "/xyz/openbmc_project/object_mapper"s,
101 "xyz.openbmc_project.ObjectMapper"s, "GetObject"s, path,
102 GetObject::mapped_type{interface});
Brad Bishopb1e329a2017-08-02 01:23:12 -0400103
104 if (mapperResp.empty())
105 {
106 phosphor::logging::log<phosphor::logging::level::INFO>(
Brad Bishopd1eac882018-03-29 10:34:05 -0400107 "Object not found.",
108 phosphor::logging::entry("PATH=%s", path.c_str()),
109 phosphor::logging::entry("INTERFACE=%s", interface.c_str()));
Brad Bishopb1e329a2017-08-02 01:23:12 -0400110 phosphor::logging::elog<detail::errors::InternalFailure>();
111 }
112 return mapperResp.begin()->first;
113}
114
115/** @brief Get a property without mapper lookup. */
116template <typename Property>
Brad Bishopd1eac882018-03-29 10:34:05 -0400117static auto getProperty(::sdbusplus::bus::bus& bus, const std::string& busName,
118 const std::string& path, const std::string& interface,
119 const std::string& property)
Brad Bishopb1e329a2017-08-02 01:23:12 -0400120{
121 using namespace std::literals::string_literals;
122
Brad Bishopd1eac882018-03-29 10:34:05 -0400123 auto msg =
124 callMethod(bus, busName, path, "org.freedesktop.DBus.Properties"s,
125 "Get"s, interface, property);
Brad Bishopb1e329a2017-08-02 01:23:12 -0400126 ::sdbusplus::message::variant<Property> value;
127 msg.read(value);
William A. Kennington IIIefcd6532018-11-12 15:54:32 -0800128 return ::sdbusplus::message::variant_ns::get<Property>(value);
Brad Bishopb1e329a2017-08-02 01:23:12 -0400129}
130
131/** @brief Get a property without mapper lookup. */
132template <typename Property>
Brad Bishopd1eac882018-03-29 10:34:05 -0400133static auto getProperty(const std::string& busName, const std::string& path,
134 const std::string& interface,
135 const std::string& property)
Brad Bishopb1e329a2017-08-02 01:23:12 -0400136{
Brad Bishopd1eac882018-03-29 10:34:05 -0400137 return getProperty<Property>(getBus(), busName, path, interface, property);
Brad Bishopb1e329a2017-08-02 01:23:12 -0400138}
139
140/** @brief Get a property with mapper lookup. */
141template <typename Property>
Brad Bishopd1eac882018-03-29 10:34:05 -0400142static auto getProperty(::sdbusplus::bus::bus& bus, const std::string& path,
143 const std::string& interface,
144 const std::string& property)
Brad Bishopb1e329a2017-08-02 01:23:12 -0400145{
Brad Bishopd1eac882018-03-29 10:34:05 -0400146 return getProperty<Property>(bus, getService(bus, path, interface), path,
147 interface, property);
Brad Bishopb1e329a2017-08-02 01:23:12 -0400148}
149
150/** @brief Get a property with mapper lookup. */
151template <typename Property>
Brad Bishopd1eac882018-03-29 10:34:05 -0400152static auto getProperty(const std::string& path, const std::string& interface,
153 const std::string& property)
Brad Bishopb1e329a2017-08-02 01:23:12 -0400154{
Brad Bishopd1eac882018-03-29 10:34:05 -0400155 return getProperty<Property>(getBus(), path, interface, property);
Brad Bishopb1e329a2017-08-02 01:23:12 -0400156}
157
158} // namespace sdbusplus
159} // namespace util