blob: 0c70b9c5c2f9e720e1472f0908c6130e924b097a [file] [log] [blame]
Brad Bishop6e9cfdb2017-06-08 11:59:58 -04001#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
11namespace phosphor
12{
13namespace fan
14{
15namespace util
16{
17namespace detail
18{
19namespace errors = sdbusplus::xyz::openbmc_project::Common::Error;
20} // namespace detail
21
Brad Bishop1e4922a2017-07-12 22:56:49 -040022/** @brief Alias for PropertiesChanged signal callbacks. */
23template <typename ...T>
24using Properties = std::map<std::string, sdbusplus::message::variant<T...>>;
25
Brad Bishop6e9cfdb2017-06-08 11:59:58 -040026/** @class SDBusPlus
27 * @brief DBus access delegate implementation for sdbusplus.
28 */
29class 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(
Brad Bishopf2238ae2017-07-30 13:32:23 -040043 sdbusplus::bus::bus& bus,
Brad Bishop6e9cfdb2017-06-08 11:59:58 -040044 const std::string& busName,
45 const std::string& path,
46 const std::string& interface,
47 const std::string& method,
48 Args&& ... args)
49 {
Brad Bishopf2238ae2017-07-30 13:32:23 -040050 auto reqMsg = bus.new_method_call(
Brad Bishope67b41b2017-07-30 13:20:37 -040051 busName.c_str(),
52 path.c_str(),
53 interface.c_str(),
54 method.c_str());
Brad Bishop6e9cfdb2017-06-08 11:59:58 -040055 reqMsg.append(std::forward<Args>(args)...);
Brad Bishopf2238ae2017-07-30 13:32:23 -040056 auto respMsg = bus.call(reqMsg);
Brad Bishop6e9cfdb2017-06-08 11:59:58 -040057
58 if (respMsg.is_method_error())
59 {
60 phosphor::logging::log<phosphor::logging::level::INFO>(
61 "Failed to invoke DBus method.",
62 phosphor::logging::entry("PATH=%s", path.c_str()),
63 phosphor::logging::entry(
Brad Bishope67b41b2017-07-30 13:20:37 -040064 "INTERFACE=%s", interface.c_str()),
Brad Bishop6e9cfdb2017-06-08 11:59:58 -040065 phosphor::logging::entry("METHOD=%s", method.c_str()));
66 phosphor::logging::elog<detail::errors::InternalFailure>();
67 }
68
69 return respMsg;
70 }
71
Brad Bishopf2238ae2017-07-30 13:32:23 -040072 /** @brief Invoke a method. */
73 template <typename ...Args>
74 static auto callMethod(
75 const std::string& busName,
76 const std::string& path,
77 const std::string& interface,
78 const std::string& method,
79 Args&& ... args)
80 {
81 return callMethod(
82 getBus(),
83 busName,
84 path,
85 interface,
86 method,
87 std::forward<Args>(args)...);
88 }
89
Brad Bishop6e9cfdb2017-06-08 11:59:58 -040090 /** @brief Invoke a method and read the response. */
91 template <typename Ret, typename ...Args>
92 static auto callMethodAndRead(
Brad Bishopf2238ae2017-07-30 13:32:23 -040093 sdbusplus::bus::bus& bus,
Brad Bishop6e9cfdb2017-06-08 11:59:58 -040094 const std::string& busName,
95 const std::string& path,
96 const std::string& interface,
97 const std::string& method,
98 Args&& ... args)
99 {
100 sdbusplus::message::message respMsg =
Brad Bishope67b41b2017-07-30 13:20:37 -0400101 callMethod<Args...>(
Brad Bishopf2238ae2017-07-30 13:32:23 -0400102 bus,
Brad Bishope67b41b2017-07-30 13:20:37 -0400103 busName,
104 path,
105 interface,
106 method,
107 std::forward<Args>(args)...);
Brad Bishop6e9cfdb2017-06-08 11:59:58 -0400108 Ret resp;
109 respMsg.read(resp);
110 return resp;
111 }
112
Brad Bishopf2238ae2017-07-30 13:32:23 -0400113 /** @brief Invoke a method and read the response. */
114 template <typename Ret, typename ...Args>
115 static auto callMethodAndRead(
116 const std::string& busName,
117 const std::string& path,
118 const std::string& interface,
119 const std::string& method,
120 Args&& ... args)
121 {
122 return callMethodAndRead<Ret>(
123 getBus(),
124 busName,
125 path,
126 interface,
127 method,
128 std::forward<Args>(args)...);
129 }
130
Matthew Bartheca94df2018-01-19 16:42:49 -0600131 /** @brief Get subtree from the mapper. */
132 static auto getSubTree(
133 sdbusplus::bus::bus& bus,
134 const std::string& path,
135 const std::string& interface,
136 int32_t depth)
137 {
138 using namespace std::literals::string_literals;
139
140 using Path = std::string;
141 using Intf = std::string;
142 using Serv = std::string;
143 using Intfs = std::vector<Intf>;
144 using Objects = std::map<Path, std::map<Serv, Intfs>>;
145 Intfs intfs = {interface};
146
147 auto mapperResp = callMethodAndRead<Objects>(
148 bus,
149 "xyz.openbmc_project.ObjectMapper"s,
150 "/xyz/openbmc_project/object_mapper"s,
151 "xyz.openbmc_project.ObjectMapper"s,
152 "GetSubTree"s,
153 path,
154 depth,
155 intfs);
156
157 if (mapperResp.empty())
158 {
159 phosphor::logging::log<phosphor::logging::level::ERR>(
160 "Empty response from mapper GetSubTree",
161 phosphor::logging::entry("SUBTREE=%s", path.c_str()),
162 phosphor::logging::entry(
163 "INTERFACE=%s", interface.c_str()),
164 phosphor::logging::entry("DEPTH=%u", depth));
165 phosphor::logging::elog<detail::errors::InternalFailure>();
166 }
167 return mapperResp;
168 }
Brad Bishopf2238ae2017-07-30 13:32:23 -0400169
Brad Bishop6e9cfdb2017-06-08 11:59:58 -0400170 /** @brief Get service from the mapper. */
171 static auto getService(
Brad Bishopf2238ae2017-07-30 13:32:23 -0400172 sdbusplus::bus::bus& bus,
Brad Bishop6e9cfdb2017-06-08 11:59:58 -0400173 const std::string& path,
174 const std::string& interface)
175 {
176 using namespace std::literals::string_literals;
177 using GetObject = std::map<std::string, std::vector<std::string>>;
178
179 auto mapperResp = callMethodAndRead<GetObject>(
Brad Bishopf2238ae2017-07-30 13:32:23 -0400180 bus,
Brad Bishope67b41b2017-07-30 13:20:37 -0400181 "xyz.openbmc_project.ObjectMapper"s,
182 "/xyz/openbmc_project/object_mapper"s,
183 "xyz.openbmc_project.ObjectMapper"s,
184 "GetObject"s,
185 path,
186 GetObject::mapped_type{interface});
Brad Bishop6e9cfdb2017-06-08 11:59:58 -0400187
188 if (mapperResp.empty())
189 {
190 phosphor::logging::log<phosphor::logging::level::INFO>(
191 "Object not found.",
192 phosphor::logging::entry("PATH=%s", path.c_str()),
193 phosphor::logging::entry(
Brad Bishope67b41b2017-07-30 13:20:37 -0400194 "INTERFACE=%s", interface.c_str()));
Brad Bishop6e9cfdb2017-06-08 11:59:58 -0400195 phosphor::logging::elog<detail::errors::InternalFailure>();
196 }
197 return mapperResp.begin()->first;
198 }
199
Brad Bishopf2238ae2017-07-30 13:32:23 -0400200 /** @brief Get service from the mapper. */
201 static auto getService(
202 const std::string& path,
203 const std::string& interface)
204 {
205 return getService(
206 getBus(),
207 path,
208 interface);
209 }
210
Brad Bishop6e9cfdb2017-06-08 11:59:58 -0400211 /** @brief Get a property with mapper lookup. */
212 template <typename Property>
213 static auto getProperty(
Brad Bishopf2238ae2017-07-30 13:32:23 -0400214 sdbusplus::bus::bus& bus,
Brad Bishop6e9cfdb2017-06-08 11:59:58 -0400215 const std::string& path,
216 const std::string& interface,
217 const std::string& property)
218 {
219 using namespace std::literals::string_literals;
220
221 auto msg = callMethod(
Brad Bishopf2238ae2017-07-30 13:32:23 -0400222 bus,
223 getService(bus, path, interface),
Brad Bishope67b41b2017-07-30 13:20:37 -0400224 path,
225 "org.freedesktop.DBus.Properties"s,
226 "Get"s,
227 interface,
228 property);
Brad Bishop6e9cfdb2017-06-08 11:59:58 -0400229 sdbusplus::message::variant<Property> value;
230 msg.read(value);
231 return value.template get<Property>();
232 }
233
Brad Bishopf2238ae2017-07-30 13:32:23 -0400234 /** @brief Get a property with mapper lookup. */
235 template <typename Property>
236 static auto getProperty(
237 const std::string& path,
238 const std::string& interface,
239 const std::string& property)
240 {
241 return getProperty<Property>(
242 getBus(),
243 path,
244 interface,
245 property);
246 }
247
Matthew Barth5a796e62018-01-19 17:14:08 -0600248 /** @brief Get a property without mapper lookup. */
249 template <typename Property>
250 static auto getProperty(
251 sdbusplus::bus::bus& bus,
252 const std::string& service,
253 const std::string& path,
254 const std::string& interface,
255 const std::string& property)
256 {
257 using namespace std::literals::string_literals;
258
259 auto msg = callMethod(
260 bus,
261 service,
262 path,
263 "org.freedesktop.DBus.Properties"s,
264 "Get"s,
265 interface,
266 property);
267 sdbusplus::message::variant<Property> value;
268 msg.read(value);
269 return value.template get<Property>();
270 }
271
272 /** @brief Get a property without mapper lookup. */
273 template <typename Property>
274 static auto getProperty(
275 const std::string& service,
276 const std::string& path,
277 const std::string& interface,
278 const std::string& property)
279 {
280 return getProperty<Property>(
281 getBus(),
282 service,
283 path,
284 interface,
285 property);
286 }
287
Brad Bishop6e9cfdb2017-06-08 11:59:58 -0400288 /** @brief Set a property with mapper lookup. */
289 template <typename Property>
290 static void setProperty(
Brad Bishopf2238ae2017-07-30 13:32:23 -0400291 sdbusplus::bus::bus& bus,
Brad Bishop6e9cfdb2017-06-08 11:59:58 -0400292 const std::string& path,
293 const std::string& interface,
294 const std::string& property,
295 Property&& value)
296 {
297 using namespace std::literals::string_literals;
298
299 sdbusplus::message::variant<Property> varValue(
Brad Bishope67b41b2017-07-30 13:20:37 -0400300 std::forward<Property>(value));
Brad Bishop6e9cfdb2017-06-08 11:59:58 -0400301
302 callMethod(
Brad Bishopf2238ae2017-07-30 13:32:23 -0400303 bus,
304 getService(bus, path, interface),
Brad Bishope67b41b2017-07-30 13:20:37 -0400305 path,
306 "org.freedesktop.DBus.Properties"s,
307 "Set"s,
308 interface,
309 property,
310 varValue);
Brad Bishop6e9cfdb2017-06-08 11:59:58 -0400311 }
312
Brad Bishopf2238ae2017-07-30 13:32:23 -0400313 /** @brief Set a property with mapper lookup. */
314 template <typename Property>
315 static void setProperty(
316 const std::string& path,
317 const std::string& interface,
318 const std::string& property,
319 Property&& value)
320 {
321 return setProperty(
322 getBus(),
323 path,
324 interface,
325 property,
326 std::forward<Property>(value));
327 }
328
329 /** @brief Invoke method with mapper lookup. */
330 template <typename ...Args>
331 static auto lookupAndCallMethod(
332 sdbusplus::bus::bus& bus,
333 const std::string& path,
334 const std::string& interface,
335 const std::string& method,
336 Args&& ... args)
337 {
338 return callMethod(
339 bus,
340 getService(bus, path, interface),
341 path,
342 interface,
343 method,
344 std::forward<Args>(args)...);
345 }
346
Brad Bishop6e9cfdb2017-06-08 11:59:58 -0400347 /** @brief Invoke method with mapper lookup. */
348 template <typename ...Args>
349 static auto lookupAndCallMethod(
350 const std::string& path,
351 const std::string& interface,
352 const std::string& method,
353 Args&& ... args)
354 {
Brad Bishopf2238ae2017-07-30 13:32:23 -0400355 return lookupAndCallMethod(
356 getBus(),
357 path,
358 interface,
359 method,
360 std::forward<Args>(args)...);
361 }
362
363 /** @brief Invoke method and read with mapper lookup. */
364 template <typename Ret, typename ...Args>
365 static auto lookupCallMethodAndRead(
366 sdbusplus::bus::bus& bus,
367 const std::string& path,
368 const std::string& interface,
369 const std::string& method,
370 Args&& ... args)
371 {
372 return callMethodAndRead(
373 bus,
374 getService(bus, path, interface),
Brad Bishope67b41b2017-07-30 13:20:37 -0400375 path,
376 interface,
377 method,
378 std::forward<Args>(args)...);
Brad Bishop6e9cfdb2017-06-08 11:59:58 -0400379 }
380
381 /** @brief Invoke method and read with mapper lookup. */
382 template <typename Ret, typename ...Args>
383 static auto lookupCallMethodAndRead(
384 const std::string& path,
385 const std::string& interface,
386 const std::string& method,
387 Args&& ... args)
388 {
Brad Bishopf2238ae2017-07-30 13:32:23 -0400389 return lookupCallMethodAndRead<Ret>(
390 getBus(),
Brad Bishope67b41b2017-07-30 13:20:37 -0400391 path,
392 interface,
393 method,
394 std::forward<Args>(args)...);
Brad Bishop6e9cfdb2017-06-08 11:59:58 -0400395 }
396};
397
398} // namespace util
399} // namespace fan
400} // namespace phosphor