blob: 4c1ea00687eb72e4eaec41a0a99f9ba52bc9d789 [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>
George Liu13e3df62022-06-22 15:03:06 +08005#include <phosphor-logging/lg2.hpp>
Brad Bishopb1e329a2017-08-02 01:23:12 -04006#include <sdbusplus/bus.hpp>
George Liu6f04b222022-06-22 14:23:19 +08007#include <sdbusplus/exception.hpp>
Brad Bishopb1e329a2017-08-02 01:23:12 -04008#include <sdbusplus/message.hpp>
Brad Bishopb1e329a2017-08-02 01:23:12 -04009#include <xyz/openbmc_project/Common/error.hpp>
10
George Liu3fe976c2022-06-21 09:37:04 +080011#include <string>
12
Brad Bishopb1e329a2017-08-02 01:23:12 -040013namespace util
14{
15namespace detail
16{
17namespace errors = sdbusplus::xyz::openbmc_project::Common::Error;
18} // namespace detail
19
20/** @brief Alias for PropertiesChanged signal callbacks. */
Brad Bishopd1eac882018-03-29 10:34:05 -040021template <typename... T>
Patrick Williams35b4f332020-05-13 17:53:09 -050022using Properties = std::map<std::string, std::variant<T...>>;
Brad Bishopb1e329a2017-08-02 01:23:12 -040023
24namespace sdbusplus
25{
26
27/** @brief Get the bus connection. */
28static auto& getBus() __attribute__((pure));
29static auto& getBus()
30{
31 static auto bus = ::sdbusplus::bus::new_default();
32 return bus;
33}
34
35/** @brief Invoke a method. */
Brad Bishopd1eac882018-03-29 10:34:05 -040036template <typename... Args>
Patrick Williams413a4852022-07-22 19:26:52 -050037static auto callMethod(::sdbusplus::bus_t& bus, const std::string& busName,
Brad Bishopd1eac882018-03-29 10:34:05 -040038 const std::string& path, const std::string& interface,
39 const std::string& method, Args&&... args)
Brad Bishopb1e329a2017-08-02 01:23:12 -040040{
Brad Bishopd1eac882018-03-29 10:34:05 -040041 auto reqMsg = bus.new_method_call(busName.c_str(), path.c_str(),
42 interface.c_str(), method.c_str());
Brad Bishopb1e329a2017-08-02 01:23:12 -040043 reqMsg.append(std::forward<Args>(args)...);
George Liu6f04b222022-06-22 14:23:19 +080044 try
Brad Bishopb1e329a2017-08-02 01:23:12 -040045 {
George Liu6f04b222022-06-22 14:23:19 +080046 return bus.call(reqMsg);
47 }
48 catch (const std::exception& e)
49 {
50 lg2::error("Failed to invoke DBus method: {PATH}, {INTF}, {METHOD}",
George Liu13e3df62022-06-22 15:03:06 +080051 "PATH", path, "INTF", interface, "METHOD", method);
Brad Bishopb1e329a2017-08-02 01:23:12 -040052 phosphor::logging::elog<detail::errors::InternalFailure>();
53 }
Brad Bishopb1e329a2017-08-02 01:23:12 -040054}
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
Patrick Williams413a4852022-07-22 19:26:52 -050069 callMethodAndRead(::sdbusplus::bus_t& bus, const std::string& busName,
Brad Bishopd1eac882018-03-29 10:34:05 -040070 const std::string& path, const std::string& interface,
71 const std::string& method, Args&&... args)
Brad Bishopb1e329a2017-08-02 01:23:12 -040072{
Patrick Williams413a4852022-07-22 19:26:52 -050073 ::sdbusplus::message_t respMsg = callMethod<Args...>(
Brad Bishopd1eac882018-03-29 10:34:05 -040074 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. */
Patrick Williams413a4852022-07-22 19:26:52 -050092static auto getService(::sdbusplus::bus_t& bus, const std::string& path,
Brad Bishopd1eac882018-03-29 10:34:05 -040093 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 {
George Liu13e3df62022-06-22 15:03:06 +0800106 lg2::error("Object not found. {PATH}, {INTF}", "PATH", path, "INTF",
107 interface);
Brad Bishopb1e329a2017-08-02 01:23:12 -0400108 phosphor::logging::elog<detail::errors::InternalFailure>();
109 }
110 return mapperResp.begin()->first;
111}
112
113/** @brief Get a property without mapper lookup. */
114template <typename Property>
Patrick Williams413a4852022-07-22 19:26:52 -0500115static auto getProperty(::sdbusplus::bus_t& bus, const std::string& busName,
Brad Bishopd1eac882018-03-29 10:34:05 -0400116 const std::string& path, const std::string& interface,
117 const std::string& property)
Brad Bishopb1e329a2017-08-02 01:23:12 -0400118{
119 using namespace std::literals::string_literals;
120
Patrick Williamsc5fe26a2023-05-10 07:50:25 -0500121 auto msg = callMethod(bus, busName, path,
122 "org.freedesktop.DBus.Properties"s, "Get"s, interface,
123 property);
Patrick Williams35b4f332020-05-13 17:53:09 -0500124 ::std::variant<Property> value;
Brad Bishopb1e329a2017-08-02 01:23:12 -0400125 msg.read(value);
Patrick Williams34ef1e52020-05-13 11:07:43 -0500126 return std::get<Property>(value);
Brad Bishopb1e329a2017-08-02 01:23:12 -0400127}
128
129/** @brief Get a property without mapper lookup. */
130template <typename Property>
Brad Bishopd1eac882018-03-29 10:34:05 -0400131static auto getProperty(const std::string& busName, const std::string& path,
132 const std::string& interface,
133 const std::string& property)
Brad Bishopb1e329a2017-08-02 01:23:12 -0400134{
Brad Bishopd1eac882018-03-29 10:34:05 -0400135 return getProperty<Property>(getBus(), busName, path, interface, property);
Brad Bishopb1e329a2017-08-02 01:23:12 -0400136}
137
138/** @brief Get a property with mapper lookup. */
139template <typename Property>
Patrick Williams413a4852022-07-22 19:26:52 -0500140static auto getProperty(::sdbusplus::bus_t& bus, const std::string& path,
Brad Bishopd1eac882018-03-29 10:34:05 -0400141 const std::string& interface,
142 const std::string& property)
Brad Bishopb1e329a2017-08-02 01:23:12 -0400143{
Brad Bishopd1eac882018-03-29 10:34:05 -0400144 return getProperty<Property>(bus, getService(bus, path, interface), path,
145 interface, property);
Brad Bishopb1e329a2017-08-02 01:23:12 -0400146}
147
148/** @brief Get a property with mapper lookup. */
149template <typename Property>
Brad Bishopd1eac882018-03-29 10:34:05 -0400150static auto getProperty(const std::string& path, const std::string& interface,
151 const std::string& property)
Brad Bishopb1e329a2017-08-02 01:23:12 -0400152{
Brad Bishopd1eac882018-03-29 10:34:05 -0400153 return getProperty<Property>(getBus(), path, interface, property);
Brad Bishopb1e329a2017-08-02 01:23:12 -0400154}
155
156} // namespace sdbusplus
157} // namespace util