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