blob: 7c4cd3c3e88952bcacbfe98f2dde7ff6b30ecb83 [file] [log] [blame]
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -05001#include <bitset>
2#include <phosphor-logging/elog-errors.hpp>
3#include <phosphor-logging/log.hpp>
4#include "xyz/openbmc_project/Common/error.hpp"
5#include "types.hpp"
6#include "sensordatahandler.hpp"
7
8namespace ipmi
9{
10namespace sensor
11{
12
13using namespace phosphor::logging;
14using InternalFailure =
15 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
16
17static constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
18static constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";
19static constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";
20
21/** @brief get the D-Bus service and service path
22 * @param[in] bus - The Dbus bus object
23 * @param[in] interface - interface to the service
24 * @param[in] path - interested path in the list of objects
25 * @return pair of service path and service
26 */
27ServicePath getServiceAndPath(sdbusplus::bus::bus& bus,
28 const std::string& interface,
29 const std::string& path)
30{
31 auto depth = 0;
32 auto mapperCall = bus.new_method_call(MAPPER_BUSNAME,
33 MAPPER_PATH,
34 MAPPER_INTERFACE,
35 "GetSubTree");
36 mapperCall.append("/");
37 mapperCall.append(depth);
38 mapperCall.append(std::vector<Interface>({interface}));
39
40 auto mapperResponseMsg = bus.call(mapperCall);
41 if (mapperResponseMsg.is_method_error())
42 {
Dhruvaraj Subhashchandran18e99992017-08-09 09:10:47 -050043 log<level::ERR>("Mapper GetSubTree failed",
44 entry("PATH=%s", path),
45 entry("INTERFACE=%s", interface));
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050046 elog<InternalFailure>();
47 }
48
49 MapperResponseType mapperResponse;
50 mapperResponseMsg.read(mapperResponse);
51 if (mapperResponse.empty())
52 {
Dhruvaraj Subhashchandran18e99992017-08-09 09:10:47 -050053 log<level::ERR>("Invalid mapper response",
54 entry("PATH=%s", path),
55 entry("INTERFACE=%s", interface));
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050056 elog<InternalFailure>();
57 }
58
59 if (path.empty())
60 {
61 //Get the first one if the path is not in list.
62 return std::make_pair(mapperResponse.begin()->first,
63 mapperResponse.begin()->second.begin()->first);
64 }
65 const auto& iter = mapperResponse.find(path);
66 if (iter == mapperResponse.end())
67 {
Dhruvaraj Subhashchandran18e99992017-08-09 09:10:47 -050068 log<level::ERR>("Coudn't find d-bus path",
69 entry("PATH=%s", path),
70 entry("INTERFACE=%s", interface));
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050071 elog<InternalFailure>();
72 }
73 return std::make_pair(iter->first, iter->second.begin()->first);
74}
75
76AssertionSet getAssertionSet(const SetSensorReadingReq& cmdData)
77{
78 Assertion assertionStates =
79 (static_cast<Assertion>(cmdData.assertOffset8_14)) << 8 |
80 cmdData.assertOffset0_7;
81 Deassertion deassertionStates =
82 (static_cast<Deassertion>(cmdData.deassertOffset8_14)) << 8 |
83 cmdData.deassertOffset0_7;
84 return std::make_pair(assertionStates, deassertionStates);
85}
86
87ipmi_ret_t updateToDbus(IpmiUpdateData& msg)
88{
89 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
90 try
91 {
92 auto serviceResponseMsg = bus.call(msg);
93 if (serviceResponseMsg.is_method_error())
94 {
95 log<level::ERR>("Error in D-Bus call");
96 return IPMI_CC_UNSPECIFIED_ERROR;
97 }
98 }
99 catch (InternalFailure& e)
100 {
101 commit<InternalFailure>();
102 return IPMI_CC_UNSPECIFIED_ERROR;
103 }
104 return IPMI_CC_OK;
105}
106
107namespace set
108{
109
110IpmiUpdateData makeDbusMsg(const std::string& updateInterface,
111 const std::string& sensorPath,
112 const std::string& command,
113 const std::string& sensorInterface)
114{
115 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
116 using namespace std::string_literals;
117
118 std::string dbusService;
119 std::string dbusPath;
120
121 std::tie(dbusPath, dbusService) = getServiceAndPath(bus,
122 sensorInterface,
123 sensorPath);
124 return bus.new_method_call(dbusService.c_str(),
125 dbusPath.c_str(),
126 updateInterface.c_str(),
127 command.c_str());
128}
129
130ipmi_ret_t appendDiscreteSignalData(IpmiUpdateData& msg,
131 const DbusInterfaceMap& interfaceMap,
132 uint8_t data)
133{
134 const auto& interface = interfaceMap.begin();
135 msg.append(interface->first);
136 for (const auto& property : interface->second)
137 {
138 msg.append(property.first);
139 const auto& iter = property.second.find(data);
140 if (iter == property.second.end())
141 {
142 log<level::ERR>("Invalid event data");
143 return IPMI_CC_PARM_OUT_OF_RANGE;
144 }
145 msg.append(iter->second.assert);
146 }
147 return IPMI_CC_OK;
148}
149
150ipmi_ret_t appendReadingData(IpmiUpdateData& msg,
151 const DbusInterfaceMap& interfaceMap,
152 const Value &data)
153{
154 const auto& interface = interfaceMap.begin();
155 msg.append(interface->first);
156 for (const auto& property : interface->second)
157 {
158 msg.append(property.first);
159 msg.append(data);
160 }
161 return IPMI_CC_OK;
162}
163
164ipmi_ret_t appendAssertion(IpmiUpdateData& msg,
165 const DbusInterfaceMap& interfaceMap,
166 const std::string& sensorPath,
167 const SetSensorReadingReq& cmdData)
168{
169 std::bitset<16> assertionSet(getAssertionSet(cmdData).first);
170 std::bitset<16> deassertionSet(getAssertionSet(cmdData).second);
171
172 const auto& interface = interfaceMap.begin();
173 msg.append(interface->first);
174 for (const auto& property : interface->second)
175 {
176 msg.append(property.first);
177 for (const auto& value : property.second)
178 {
179 if (assertionSet.test(value.first))
180 {
181 msg.append(value.second.assert);
182 }
183 if (deassertionSet.test(value.first))
184 {
185 msg.append(value.second.deassert);
186 }
187 }
188 }
189 return IPMI_CC_OK;
190}
191}//namespace set
192
193namespace notify
194{
195
196IpmiUpdateData makeDbusMsg(const std::string& updateInterface,
197 const std::string& sensorPath,
198 const std::string& command,
199 const std::string& sensorInterface)
200{
201 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
202 using namespace std::string_literals;
203
204 std::string dbusService;
205 std::string dbusPath;
206
207 std::tie(dbusPath, dbusService) = getServiceAndPath(bus,
208 updateInterface);
209
210 return bus.new_method_call(dbusService.c_str(),
211 dbusPath.c_str(),
212 updateInterface.c_str(),
213 command.c_str());
214}
215
216ipmi_ret_t appendAssertion(IpmiUpdateData& msg,
217 const DbusInterfaceMap& interfaceMap,
218 const std::string& sensorPath,
219 const SetSensorReadingReq& cmdData)
220{
221 std::bitset<16> assertionSet(getAssertionSet(cmdData).first);
222 std::bitset<16> deassertionSet(getAssertionSet(cmdData).second);
223 ipmi::sensor::ObjectMap objects;
224 ipmi::sensor::InterfaceMap interfaces;
225 for (const auto& interface : interfaceMap)
226 {
227 for (const auto& property : interface.second)
228 {
229 ipmi::sensor::PropertyMap props;
230 bool valid = false;
231 for (const auto& value : property.second)
232 {
233 if (assertionSet.test(value.first))
234 {
235 props.emplace(property.first, value.second.assert);
236 valid = true;
237 }
238 else if (deassertionSet.test(value.first))
239 {
240 props.emplace(property.first, value.second.deassert);
241 valid = true;
242 }
243 }
244 if (valid)
245 {
246 interfaces.emplace(interface.first, std::move(props));
247 }
248 }
249 }
250 objects.emplace(sensorPath, std::move(interfaces));
251 msg.append(std::move(objects));
252 return IPMI_CC_OK;
253}
254}//namespace notify
255}//namespace sensor
256}//namespace ipmi