blob: 454fde8d4d42bbae63c78ccf01860c30da6a8076 [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 Barth7311c392018-05-03 16:50:47 -0500248 /** @brief Get a property variant with mapper lookup. */
249 template <typename Variant>
250 static auto getPropertyVariant(
251 sdbusplus::bus::bus& bus,
252 const std::string& path,
253 const std::string& interface,
254 const std::string& property)
255 {
256 using namespace std::literals::string_literals;
257
258 auto msg = callMethod(
259 bus,
260 getService(bus, path, interface),
261 path,
262 "org.freedesktop.DBus.Properties"s,
263 "Get"s,
264 interface,
265 property);
266 Variant value;
267 msg.read(value);
268 return value;
269 }
270
271 /** @brief Get a property variant with mapper lookup. */
272 template <typename Variant>
273 static auto getPropertyVariant(
274 const std::string& path,
275 const std::string& interface,
276 const std::string& property)
277 {
278 return getPropertyVariant<Variant>(
279 getBus(),
280 path,
281 interface,
282 property);
283 }
284
Matthew Barth5a796e62018-01-19 17:14:08 -0600285 /** @brief Get a property without mapper lookup. */
286 template <typename Property>
287 static auto getProperty(
288 sdbusplus::bus::bus& bus,
289 const std::string& service,
290 const std::string& path,
291 const std::string& interface,
292 const std::string& property)
293 {
294 using namespace std::literals::string_literals;
295
296 auto msg = callMethod(
297 bus,
298 service,
299 path,
300 "org.freedesktop.DBus.Properties"s,
301 "Get"s,
302 interface,
303 property);
304 sdbusplus::message::variant<Property> value;
305 msg.read(value);
306 return value.template get<Property>();
307 }
308
309 /** @brief Get a property without mapper lookup. */
310 template <typename Property>
311 static auto getProperty(
312 const std::string& service,
313 const std::string& path,
314 const std::string& interface,
315 const std::string& property)
316 {
317 return getProperty<Property>(
318 getBus(),
319 service,
320 path,
321 interface,
322 property);
323 }
324
Matthew Barth7311c392018-05-03 16:50:47 -0500325 /** @brief Get a property variant without mapper lookup. */
326 template <typename Variant>
327 static auto getPropertyVariant(
328 sdbusplus::bus::bus& bus,
329 const std::string& service,
330 const std::string& path,
331 const std::string& interface,
332 const std::string& property)
333 {
334 using namespace std::literals::string_literals;
335
336 auto msg = callMethod(
337 bus,
338 service,
339 path,
340 "org.freedesktop.DBus.Properties"s,
341 "Get"s,
342 interface,
343 property);
344 Variant value;
345 msg.read(value);
346 return value;
347 }
348
349 /** @brief Get a property variant without mapper lookup. */
350 template <typename Variant>
351 static auto getPropertyVariant(
352 const std::string& service,
353 const std::string& path,
354 const std::string& interface,
355 const std::string& property)
356 {
357 return getPropertyVariant<Variant>(
358 getBus(),
359 service,
360 path,
361 interface,
362 property);
363 }
364
Brad Bishop6e9cfdb2017-06-08 11:59:58 -0400365 /** @brief Set a property with mapper lookup. */
366 template <typename Property>
367 static void setProperty(
Brad Bishopf2238ae2017-07-30 13:32:23 -0400368 sdbusplus::bus::bus& bus,
Brad Bishop6e9cfdb2017-06-08 11:59:58 -0400369 const std::string& path,
370 const std::string& interface,
371 const std::string& property,
372 Property&& value)
373 {
374 using namespace std::literals::string_literals;
375
376 sdbusplus::message::variant<Property> varValue(
Brad Bishope67b41b2017-07-30 13:20:37 -0400377 std::forward<Property>(value));
Brad Bishop6e9cfdb2017-06-08 11:59:58 -0400378
379 callMethod(
Brad Bishopf2238ae2017-07-30 13:32:23 -0400380 bus,
381 getService(bus, path, interface),
Brad Bishope67b41b2017-07-30 13:20:37 -0400382 path,
383 "org.freedesktop.DBus.Properties"s,
384 "Set"s,
385 interface,
386 property,
387 varValue);
Brad Bishop6e9cfdb2017-06-08 11:59:58 -0400388 }
389
Brad Bishopf2238ae2017-07-30 13:32:23 -0400390 /** @brief Set a property with mapper lookup. */
391 template <typename Property>
392 static void setProperty(
393 const std::string& path,
394 const std::string& interface,
395 const std::string& property,
396 Property&& value)
397 {
398 return setProperty(
399 getBus(),
400 path,
401 interface,
402 property,
403 std::forward<Property>(value));
404 }
405
406 /** @brief Invoke method with mapper lookup. */
407 template <typename ...Args>
408 static auto lookupAndCallMethod(
409 sdbusplus::bus::bus& bus,
410 const std::string& path,
411 const std::string& interface,
412 const std::string& method,
413 Args&& ... args)
414 {
415 return callMethod(
416 bus,
417 getService(bus, path, interface),
418 path,
419 interface,
420 method,
421 std::forward<Args>(args)...);
422 }
423
Brad Bishop6e9cfdb2017-06-08 11:59:58 -0400424 /** @brief Invoke method with mapper lookup. */
425 template <typename ...Args>
426 static auto lookupAndCallMethod(
427 const std::string& path,
428 const std::string& interface,
429 const std::string& method,
430 Args&& ... args)
431 {
Brad Bishopf2238ae2017-07-30 13:32:23 -0400432 return lookupAndCallMethod(
433 getBus(),
434 path,
435 interface,
436 method,
437 std::forward<Args>(args)...);
438 }
439
440 /** @brief Invoke method and read with mapper lookup. */
441 template <typename Ret, typename ...Args>
442 static auto lookupCallMethodAndRead(
443 sdbusplus::bus::bus& bus,
444 const std::string& path,
445 const std::string& interface,
446 const std::string& method,
447 Args&& ... args)
448 {
449 return callMethodAndRead(
450 bus,
451 getService(bus, path, interface),
Brad Bishope67b41b2017-07-30 13:20:37 -0400452 path,
453 interface,
454 method,
455 std::forward<Args>(args)...);
Brad Bishop6e9cfdb2017-06-08 11:59:58 -0400456 }
457
458 /** @brief Invoke method and read with mapper lookup. */
459 template <typename Ret, typename ...Args>
460 static auto lookupCallMethodAndRead(
461 const std::string& path,
462 const std::string& interface,
463 const std::string& method,
464 Args&& ... args)
465 {
Brad Bishopf2238ae2017-07-30 13:32:23 -0400466 return lookupCallMethodAndRead<Ret>(
467 getBus(),
Brad Bishope67b41b2017-07-30 13:20:37 -0400468 path,
469 interface,
470 method,
471 std::forward<Args>(args)...);
Brad Bishop6e9cfdb2017-06-08 11:59:58 -0400472 }
473};
474
475} // namespace util
476} // namespace fan
477} // namespace phosphor