blob: 2d20392721d95a67f9c28d48794ebb1a75124ae0 [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>
Andrew Geisslerae4c95c2020-05-16 13:58:53 -05008#include <string>
Brad Bishopb1e329a2017-08-02 01:23:12 -04009#include <xyz/openbmc_project/Common/error.hpp>
10
11namespace util
12{
13namespace detail
14{
15namespace errors = sdbusplus::xyz::openbmc_project::Common::Error;
16} // namespace detail
17
18/** @brief Alias for PropertiesChanged signal callbacks. */
Brad Bishopd1eac882018-03-29 10:34:05 -040019template <typename... T>
Patrick Williams35b4f332020-05-13 17:53:09 -050020using Properties = std::map<std::string, std::variant<T...>>;
Brad Bishopb1e329a2017-08-02 01:23:12 -040021
22namespace sdbusplus
23{
24
25/** @brief Get the bus connection. */
26static auto& getBus() __attribute__((pure));
27static auto& getBus()
28{
29 static auto bus = ::sdbusplus::bus::new_default();
30 return bus;
31}
32
33/** @brief Invoke a method. */
Brad Bishopd1eac882018-03-29 10:34:05 -040034template <typename... Args>
35static auto callMethod(::sdbusplus::bus::bus& bus, const std::string& busName,
36 const std::string& path, const std::string& interface,
37 const std::string& method, Args&&... args)
Brad Bishopb1e329a2017-08-02 01:23:12 -040038{
Brad Bishopd1eac882018-03-29 10:34:05 -040039 auto reqMsg = bus.new_method_call(busName.c_str(), path.c_str(),
40 interface.c_str(), method.c_str());
Brad Bishopb1e329a2017-08-02 01:23:12 -040041 reqMsg.append(std::forward<Args>(args)...);
42 auto respMsg = bus.call(reqMsg);
43
44 if (respMsg.is_method_error())
45 {
46 phosphor::logging::log<phosphor::logging::level::INFO>(
Brad Bishopd1eac882018-03-29 10:34:05 -040047 "Failed to invoke DBus method.",
48 phosphor::logging::entry("PATH=%s", path.c_str()),
49 phosphor::logging::entry("INTERFACE=%s", interface.c_str()),
50 phosphor::logging::entry("METHOD=%s", method.c_str()));
Brad Bishopb1e329a2017-08-02 01:23:12 -040051 phosphor::logging::elog<detail::errors::InternalFailure>();
52 }
53
54 return respMsg;
55}
56
57/** @brief Invoke a method. */
Brad Bishopd1eac882018-03-29 10:34:05 -040058template <typename... Args>
59static auto callMethod(const std::string& busName, const std::string& path,
60 const std::string& interface, const std::string& method,
61 Args&&... args)
Brad Bishopb1e329a2017-08-02 01:23:12 -040062{
Brad Bishopd1eac882018-03-29 10:34:05 -040063 return callMethod(getBus(), busName, path, interface, method,
64 std::forward<Args>(args)...);
Brad Bishopb1e329a2017-08-02 01:23:12 -040065}
66
67/** @brief Invoke a method and read the response. */
Brad Bishopd1eac882018-03-29 10:34:05 -040068template <typename Ret, typename... Args>
69static auto
70 callMethodAndRead(::sdbusplus::bus::bus& bus, const std::string& busName,
71 const std::string& path, const std::string& interface,
72 const std::string& method, Args&&... args)
Brad Bishopb1e329a2017-08-02 01:23:12 -040073{
Brad Bishopd1eac882018-03-29 10:34:05 -040074 ::sdbusplus::message::message respMsg = callMethod<Args...>(
75 bus, busName, path, interface, method, std::forward<Args>(args)...);
Brad Bishopb1e329a2017-08-02 01:23:12 -040076 Ret resp;
77 respMsg.read(resp);
78 return resp;
79}
80
81/** @brief Invoke a method and read the response. */
Brad Bishopd1eac882018-03-29 10:34:05 -040082template <typename Ret, typename... Args>
83static auto callMethodAndRead(const std::string& busName,
84 const std::string& path,
85 const std::string& interface,
86 const std::string& method, Args&&... args)
Brad Bishopb1e329a2017-08-02 01:23:12 -040087{
Brad Bishopd1eac882018-03-29 10:34:05 -040088 return callMethodAndRead<Ret>(getBus(), busName, path, interface, method,
89 std::forward<Args>(args)...);
Brad Bishopb1e329a2017-08-02 01:23:12 -040090}
91
Brad Bishopb1e329a2017-08-02 01:23:12 -040092/** @brief Get service from the mapper. */
Brad Bishopd1eac882018-03-29 10:34:05 -040093static auto getService(::sdbusplus::bus::bus& bus, const std::string& path,
94 const std::string& interface)
Brad Bishopb1e329a2017-08-02 01:23:12 -040095{
96 using namespace std::literals::string_literals;
97 using GetObject = std::map<std::string, std::vector<std::string>>;
98
99 auto mapperResp = callMethodAndRead<GetObject>(
Brad Bishopd1eac882018-03-29 10:34:05 -0400100 bus, "xyz.openbmc_project.ObjectMapper"s,
101 "/xyz/openbmc_project/object_mapper"s,
102 "xyz.openbmc_project.ObjectMapper"s, "GetObject"s, path,
103 GetObject::mapped_type{interface});
Brad Bishopb1e329a2017-08-02 01:23:12 -0400104
105 if (mapperResp.empty())
106 {
107 phosphor::logging::log<phosphor::logging::level::INFO>(
Brad Bishopd1eac882018-03-29 10:34:05 -0400108 "Object not found.",
109 phosphor::logging::entry("PATH=%s", path.c_str()),
110 phosphor::logging::entry("INTERFACE=%s", interface.c_str()));
Brad Bishopb1e329a2017-08-02 01:23:12 -0400111 phosphor::logging::elog<detail::errors::InternalFailure>();
112 }
113 return mapperResp.begin()->first;
114}
115
116/** @brief Get a property without mapper lookup. */
117template <typename Property>
Brad Bishopd1eac882018-03-29 10:34:05 -0400118static auto getProperty(::sdbusplus::bus::bus& bus, const std::string& busName,
119 const std::string& path, const std::string& interface,
120 const std::string& property)
Brad Bishopb1e329a2017-08-02 01:23:12 -0400121{
122 using namespace std::literals::string_literals;
123
Brad Bishopd1eac882018-03-29 10:34:05 -0400124 auto msg =
125 callMethod(bus, busName, path, "org.freedesktop.DBus.Properties"s,
126 "Get"s, interface, property);
Patrick Williams35b4f332020-05-13 17:53:09 -0500127 ::std::variant<Property> value;
Brad Bishopb1e329a2017-08-02 01:23:12 -0400128 msg.read(value);
Patrick Williams34ef1e52020-05-13 11:07:43 -0500129 return std::get<Property>(value);
Brad Bishopb1e329a2017-08-02 01:23:12 -0400130}
131
132/** @brief Get a property without mapper lookup. */
133template <typename Property>
Brad Bishopd1eac882018-03-29 10:34:05 -0400134static auto getProperty(const std::string& busName, const std::string& path,
135 const std::string& interface,
136 const std::string& property)
Brad Bishopb1e329a2017-08-02 01:23:12 -0400137{
Brad Bishopd1eac882018-03-29 10:34:05 -0400138 return getProperty<Property>(getBus(), busName, path, interface, property);
Brad Bishopb1e329a2017-08-02 01:23:12 -0400139}
140
141/** @brief Get a property with mapper lookup. */
142template <typename Property>
Brad Bishopd1eac882018-03-29 10:34:05 -0400143static auto getProperty(::sdbusplus::bus::bus& bus, const std::string& path,
144 const std::string& interface,
145 const std::string& property)
Brad Bishopb1e329a2017-08-02 01:23:12 -0400146{
Brad Bishopd1eac882018-03-29 10:34:05 -0400147 return getProperty<Property>(bus, getService(bus, path, interface), path,
148 interface, property);
Brad Bishopb1e329a2017-08-02 01:23:12 -0400149}
150
151/** @brief Get a property with mapper lookup. */
152template <typename Property>
Brad Bishopd1eac882018-03-29 10:34:05 -0400153static auto getProperty(const std::string& path, const std::string& interface,
154 const std::string& property)
Brad Bishopb1e329a2017-08-02 01:23:12 -0400155{
Brad Bishopd1eac882018-03-29 10:34:05 -0400156 return getProperty<Property>(getBus(), path, interface, property);
Brad Bishopb1e329a2017-08-02 01:23:12 -0400157}
158
159} // namespace sdbusplus
160} // namespace util