blob: fb6c51c4ca7220cd9dde6dfbfdbeb536df44d934 [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(
43 const std::string& busName,
44 const std::string& path,
45 const std::string& interface,
46 const std::string& method,
47 Args&& ... args)
48 {
49 auto reqMsg = getBus().new_method_call(
50 busName.c_str(),
51 path.c_str(),
52 interface.c_str(),
53 method.c_str());
54 reqMsg.append(std::forward<Args>(args)...);
55 auto respMsg = getBus().call(reqMsg);
56
57 if (respMsg.is_method_error())
58 {
59 phosphor::logging::log<phosphor::logging::level::INFO>(
60 "Failed to invoke DBus method.",
61 phosphor::logging::entry("PATH=%s", path.c_str()),
62 phosphor::logging::entry(
63 "INTERFACE=%s", interface.c_str()),
64 phosphor::logging::entry("METHOD=%s", method.c_str()));
65 phosphor::logging::elog<detail::errors::InternalFailure>();
66 }
67
68 return respMsg;
69 }
70
71 /** @brief Invoke a method and read the response. */
72 template <typename Ret, typename ...Args>
73 static auto callMethodAndRead(
74 const std::string& busName,
75 const std::string& path,
76 const std::string& interface,
77 const std::string& method,
78 Args&& ... args)
79 {
80 sdbusplus::message::message respMsg =
81 callMethod<Args...>(
82 busName,
83 path,
84 interface,
85 method,
86 std::forward<Args>(args)...);
87 Ret resp;
88 respMsg.read(resp);
89 return resp;
90 }
91
92 /** @brief Get service from the mapper. */
93 static auto getService(
94 const std::string& path,
95 const std::string& interface)
96 {
97 using namespace std::literals::string_literals;
98 using GetObject = std::map<std::string, std::vector<std::string>>;
99
100 auto mapperResp = callMethodAndRead<GetObject>(
101 "xyz.openbmc_project.ObjectMapper"s,
102 "/xyz/openbmc_project/object_mapper"s,
103 "xyz.openbmc_project.ObjectMapper"s,
104 "GetObject"s,
105 path,
106 GetObject::mapped_type{interface});
107
108 if (mapperResp.empty())
109 {
110 phosphor::logging::log<phosphor::logging::level::INFO>(
111 "Object not found.",
112 phosphor::logging::entry("PATH=%s", path.c_str()),
113 phosphor::logging::entry(
114 "INTERFACE=%s", interface.c_str()));
115 phosphor::logging::elog<detail::errors::InternalFailure>();
116 }
117 return mapperResp.begin()->first;
118 }
119
120 /** @brief Get a property with mapper lookup. */
121 template <typename Property>
122 static auto getProperty(
123 const std::string& path,
124 const std::string& interface,
125 const std::string& property)
126 {
127 using namespace std::literals::string_literals;
128
129 auto msg = callMethod(
130 getService(path, interface),
131 path,
132 "org.freedesktop.DBus.Properties"s,
133 "Get"s,
134 interface,
135 property);
136 sdbusplus::message::variant<Property> value;
137 msg.read(value);
138 return value.template get<Property>();
139 }
140
141 /** @brief Set a property with mapper lookup. */
142 template <typename Property>
143 static void setProperty(
144 const std::string& path,
145 const std::string& interface,
146 const std::string& property,
147 Property&& value)
148 {
149 using namespace std::literals::string_literals;
150
151 sdbusplus::message::variant<Property> varValue(
152 std::forward<Property>(value));
153
154 callMethod(
155 getService(path, interface),
156 path,
157 "org.freedesktop.DBus.Properties"s,
158 "Set"s,
159 interface,
160 property,
161 varValue);
162 }
163
164 /** @brief Invoke method with mapper lookup. */
165 template <typename ...Args>
166 static auto lookupAndCallMethod(
167 const std::string& path,
168 const std::string& interface,
169 const std::string& method,
170 Args&& ... args)
171 {
172 return callMethod(
173 getService(path, interface),
174 path,
175 interface,
176 method,
177 std::forward<Args>(args)...);
178 }
179
180 /** @brief Invoke method and read with mapper lookup. */
181 template <typename Ret, typename ...Args>
182 static auto lookupCallMethodAndRead(
183 const std::string& path,
184 const std::string& interface,
185 const std::string& method,
186 Args&& ... args)
187 {
188 return callMethodAndRead(
189 getService(path, interface),
190 path,
191 interface,
192 method,
193 std::forward<Args>(args)...);
194 }
195};
196
197} // namespace util
198} // namespace fan
199} // namespace phosphor