blob: b9ef5e2d6252197ebddf250a4312c27264739cb2 [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
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500130ipmi_ret_t eventdata(const SetSensorReadingReq& cmdData,
131 const Info& sensorInfo,
132 uint8_t data)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500133{
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500134 auto msg = makeDbusMsg(
135 "org.freedesktop.DBus.Properties",
136 sensorInfo.sensorPath,
137 "Set",
138 sensorInfo.sensorInterface);
139
140 const auto& interface = sensorInfo.propertyInterfaces.begin();
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500141 msg.append(interface->first);
142 for (const auto& property : interface->second)
143 {
144 msg.append(property.first);
145 const auto& iter = property.second.find(data);
146 if (iter == property.second.end())
147 {
148 log<level::ERR>("Invalid event data");
149 return IPMI_CC_PARM_OUT_OF_RANGE;
150 }
151 msg.append(iter->second.assert);
152 }
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500153 return updateToDbus(msg);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500154}
155
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500156ipmi_ret_t assertion(const SetSensorReadingReq& cmdData,
157 const Info& sensorInfo)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500158{
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500159 auto msg = makeDbusMsg(
160 "org.freedesktop.DBus.Properties",
161 sensorInfo.sensorPath,
162 "Set",
163 sensorInfo.sensorInterface);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500164
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500165 std::bitset<16> assertionSet(getAssertionSet(cmdData).first);
166 std::bitset<16> deassertionSet(getAssertionSet(cmdData).second);
167
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500168 const auto& interface = sensorInfo.propertyInterfaces.begin();
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500169 msg.append(interface->first);
170 for (const auto& property : interface->second)
171 {
172 msg.append(property.first);
173 for (const auto& value : property.second)
174 {
175 if (assertionSet.test(value.first))
176 {
177 msg.append(value.second.assert);
178 }
179 if (deassertionSet.test(value.first))
180 {
181 msg.append(value.second.deassert);
182 }
183 }
184 }
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500185 return updateToDbus(msg);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500186}
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500187
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500188}//namespace set
189
190namespace notify
191{
192
193IpmiUpdateData makeDbusMsg(const std::string& updateInterface,
194 const std::string& sensorPath,
195 const std::string& command,
196 const std::string& sensorInterface)
197{
198 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
199 using namespace std::string_literals;
200
201 std::string dbusService;
202 std::string dbusPath;
203
204 std::tie(dbusPath, dbusService) = getServiceAndPath(bus,
205 updateInterface);
206
207 return bus.new_method_call(dbusService.c_str(),
208 dbusPath.c_str(),
209 updateInterface.c_str(),
210 command.c_str());
211}
212
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500213ipmi_ret_t assertion(const SetSensorReadingReq& cmdData,
214 const Info& sensorInfo)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500215{
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500216 auto msg = makeDbusMsg(
217 sensorInfo.sensorInterface,
218 sensorInfo.sensorPath,
219 "Notify",
220 sensorInfo.sensorInterface);
221
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500222 std::bitset<16> assertionSet(getAssertionSet(cmdData).first);
223 std::bitset<16> deassertionSet(getAssertionSet(cmdData).second);
224 ipmi::sensor::ObjectMap objects;
225 ipmi::sensor::InterfaceMap interfaces;
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500226 for (const auto& interface : sensorInfo.propertyInterfaces)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500227 {
228 for (const auto& property : interface.second)
229 {
230 ipmi::sensor::PropertyMap props;
231 bool valid = false;
232 for (const auto& value : property.second)
233 {
234 if (assertionSet.test(value.first))
235 {
236 props.emplace(property.first, value.second.assert);
237 valid = true;
238 }
239 else if (deassertionSet.test(value.first))
240 {
241 props.emplace(property.first, value.second.deassert);
242 valid = true;
243 }
244 }
245 if (valid)
246 {
247 interfaces.emplace(interface.first, std::move(props));
248 }
249 }
250 }
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500251 objects.emplace(sensorInfo.sensorPath, std::move(interfaces));
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500252 msg.append(std::move(objects));
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500253 return updateToDbus(msg);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500254}
255}//namespace notify
256}//namespace sensor
257}//namespace ipmi