blob: 2c26fc298270f6b6226bef2fc2358d4c82340db6 [file] [log] [blame]
Brad Bishopb1e329a2017-08-02 01:23:12 -04001#pragma once
2
3#include <sdbusplus/bus.hpp>
4#include <sdbusplus/message.hpp>
5#include <phosphor-logging/log.hpp>
6#include <phosphor-logging/elog.hpp>
7#include <phosphor-logging/elog-errors.hpp>
8#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. */
18template <typename ...T>
19using 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. */
33template <typename ...Args>
34static auto callMethod(
35 ::sdbusplus::bus::bus& bus,
36 const std::string& busName,
37 const std::string& path,
38 const std::string& interface,
39 const std::string& method,
40 Args&& ... args)
41{
42 auto reqMsg = bus.new_method_call(
43 busName.c_str(),
44 path.c_str(),
45 interface.c_str(),
46 method.c_str());
47 reqMsg.append(std::forward<Args>(args)...);
48 auto respMsg = bus.call(reqMsg);
49
50 if (respMsg.is_method_error())
51 {
52 phosphor::logging::log<phosphor::logging::level::INFO>(
53 "Failed to invoke DBus method.",
54 phosphor::logging::entry("PATH=%s", path.c_str()),
55 phosphor::logging::entry(
56 "INTERFACE=%s", interface.c_str()),
57 phosphor::logging::entry("METHOD=%s", method.c_str()));
58 phosphor::logging::elog<detail::errors::InternalFailure>();
59 }
60
61 return respMsg;
62}
63
64/** @brief Invoke a method. */
65template <typename ...Args>
66static auto callMethod(
67 const std::string& busName,
68 const std::string& path,
69 const std::string& interface,
70 const std::string& method,
71 Args&& ... args)
72{
73 return callMethod(
74 getBus(),
75 busName,
76 path,
77 interface,
78 method,
79 std::forward<Args>(args)...);
80}
81
82/** @brief Invoke a method and read the response. */
83template <typename Ret, typename ...Args>
84static auto callMethodAndRead(
85 ::sdbusplus::bus::bus& bus,
86 const std::string& busName,
87 const std::string& path,
88 const std::string& interface,
89 const std::string& method,
90 Args&& ... args)
91{
92 ::sdbusplus::message::message respMsg =
93 callMethod<Args...>(
94 bus,
95 busName,
96 path,
97 interface,
98 method,
99 std::forward<Args>(args)...);
100 Ret resp;
101 respMsg.read(resp);
102 return resp;
103}
104
105/** @brief Invoke a method and read the response. */
106 template <typename Ret, typename ...Args>
107static auto callMethodAndRead(
108 const std::string& busName,
109 const std::string& path,
110 const std::string& interface,
111 const std::string& method,
112 Args&& ... args)
113{
114 return callMethodAndRead<Ret>(
115 getBus(),
116 busName,
117 path,
118 interface,
119 method,
120 std::forward<Args>(args)...);
121}
122
123
124/** @brief Get service from the mapper. */
125static auto getService(
126 ::sdbusplus::bus::bus& bus,
127 const std::string& path,
128 const std::string& interface)
129{
130 using namespace std::literals::string_literals;
131 using GetObject = std::map<std::string, std::vector<std::string>>;
132
133 auto mapperResp = callMethodAndRead<GetObject>(
134 bus,
135 "xyz.openbmc_project.ObjectMapper"s,
136 "/xyz/openbmc_project/object_mapper"s,
137 "xyz.openbmc_project.ObjectMapper"s,
138 "GetObject"s,
139 path,
140 GetObject::mapped_type{interface});
141
142 if (mapperResp.empty())
143 {
144 phosphor::logging::log<phosphor::logging::level::INFO>(
145 "Object not found.",
146 phosphor::logging::entry("PATH=%s", path.c_str()),
147 phosphor::logging::entry(
148 "INTERFACE=%s", interface.c_str()));
149 phosphor::logging::elog<detail::errors::InternalFailure>();
150 }
151 return mapperResp.begin()->first;
152}
153
154/** @brief Get a property without mapper lookup. */
155template <typename Property>
156static auto getProperty(
157 ::sdbusplus::bus::bus& bus,
158 const std::string& busName,
159 const std::string& path,
160 const std::string& interface,
161 const std::string& property)
162{
163 using namespace std::literals::string_literals;
164
165 auto msg = callMethod(
166 bus,
167 busName,
168 path,
169 "org.freedesktop.DBus.Properties"s,
170 "Get"s,
171 interface,
172 property);
173 ::sdbusplus::message::variant<Property> value;
174 msg.read(value);
175 return value.template get<Property>();
176}
177
178/** @brief Get a property without mapper lookup. */
179template <typename Property>
180static auto getProperty(
181 const std::string& busName,
182 const std::string& path,
183 const std::string& interface,
184 const std::string& property)
185{
186 return getProperty<Property>(
187 getBus(),
188 busName,
189 path,
190 interface,
191 property);
192}
193
194/** @brief Get a property with mapper lookup. */
195template <typename Property>
196static auto getProperty(
197 ::sdbusplus::bus::bus& bus,
198 const std::string& path,
199 const std::string& interface,
200 const std::string& property)
201{
202 return getProperty<Property>(
203 bus,
204 getService(bus, path, interface),
205 path,
206 interface,
207 property);
208}
209
210/** @brief Get a property with mapper lookup. */
211template <typename Property>
212static auto getProperty(
213 const std::string& path,
214 const std::string& interface,
215 const std::string& property)
216{
217 return getProperty<Property>(
218 getBus(),
219 path,
220 interface,
221 property);
222}
223
224} // namespace sdbusplus
225} // namespace util