blob: 3fc9b9e16eb9123168f96c05717fa7a8b3359dd7 [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
Brad Bishop6e9cfdb2017-06-08 11:59:58 -0400248 /** @brief Set a property with mapper lookup. */
249 template <typename Property>
250 static void setProperty(
Brad Bishopf2238ae2017-07-30 13:32:23 -0400251 sdbusplus::bus::bus& bus,
Brad Bishop6e9cfdb2017-06-08 11:59:58 -0400252 const std::string& path,
253 const std::string& interface,
254 const std::string& property,
255 Property&& value)
256 {
257 using namespace std::literals::string_literals;
258
259 sdbusplus::message::variant<Property> varValue(
Brad Bishope67b41b2017-07-30 13:20:37 -0400260 std::forward<Property>(value));
Brad Bishop6e9cfdb2017-06-08 11:59:58 -0400261
262 callMethod(
Brad Bishopf2238ae2017-07-30 13:32:23 -0400263 bus,
264 getService(bus, path, interface),
Brad Bishope67b41b2017-07-30 13:20:37 -0400265 path,
266 "org.freedesktop.DBus.Properties"s,
267 "Set"s,
268 interface,
269 property,
270 varValue);
Brad Bishop6e9cfdb2017-06-08 11:59:58 -0400271 }
272
Brad Bishopf2238ae2017-07-30 13:32:23 -0400273 /** @brief Set a property with mapper lookup. */
274 template <typename Property>
275 static void setProperty(
276 const std::string& path,
277 const std::string& interface,
278 const std::string& property,
279 Property&& value)
280 {
281 return setProperty(
282 getBus(),
283 path,
284 interface,
285 property,
286 std::forward<Property>(value));
287 }
288
289 /** @brief Invoke method with mapper lookup. */
290 template <typename ...Args>
291 static auto lookupAndCallMethod(
292 sdbusplus::bus::bus& bus,
293 const std::string& path,
294 const std::string& interface,
295 const std::string& method,
296 Args&& ... args)
297 {
298 return callMethod(
299 bus,
300 getService(bus, path, interface),
301 path,
302 interface,
303 method,
304 std::forward<Args>(args)...);
305 }
306
Brad Bishop6e9cfdb2017-06-08 11:59:58 -0400307 /** @brief Invoke method with mapper lookup. */
308 template <typename ...Args>
309 static auto lookupAndCallMethod(
310 const std::string& path,
311 const std::string& interface,
312 const std::string& method,
313 Args&& ... args)
314 {
Brad Bishopf2238ae2017-07-30 13:32:23 -0400315 return lookupAndCallMethod(
316 getBus(),
317 path,
318 interface,
319 method,
320 std::forward<Args>(args)...);
321 }
322
323 /** @brief Invoke method and read with mapper lookup. */
324 template <typename Ret, typename ...Args>
325 static auto lookupCallMethodAndRead(
326 sdbusplus::bus::bus& bus,
327 const std::string& path,
328 const std::string& interface,
329 const std::string& method,
330 Args&& ... args)
331 {
332 return callMethodAndRead(
333 bus,
334 getService(bus, path, interface),
Brad Bishope67b41b2017-07-30 13:20:37 -0400335 path,
336 interface,
337 method,
338 std::forward<Args>(args)...);
Brad Bishop6e9cfdb2017-06-08 11:59:58 -0400339 }
340
341 /** @brief Invoke method and read with mapper lookup. */
342 template <typename Ret, typename ...Args>
343 static auto lookupCallMethodAndRead(
344 const std::string& path,
345 const std::string& interface,
346 const std::string& method,
347 Args&& ... args)
348 {
Brad Bishopf2238ae2017-07-30 13:32:23 -0400349 return lookupCallMethodAndRead<Ret>(
350 getBus(),
Brad Bishope67b41b2017-07-30 13:20:37 -0400351 path,
352 interface,
353 method,
354 std::forward<Args>(args)...);
Brad Bishop6e9cfdb2017-06-08 11:59:58 -0400355 }
356};
357
358} // namespace util
359} // namespace fan
360} // namespace phosphor