blob: 6c7b9ac69245fd5cf5d98bd8ec305d34ca057774 [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 {
43 std::string err = "Error in mapper GetSubTree "
44 "Interface: " + interface;
45 log<level::ERR>(err.c_str());
46 elog<InternalFailure>();
47 }
48
49 MapperResponseType mapperResponse;
50 mapperResponseMsg.read(mapperResponse);
51 if (mapperResponse.empty())
52 {
53 std::string err = "Invalid response from mapper "
54 "Command: GetSubTree "
55 "Interface:" + interface;
56 log<level::ERR>(err.c_str());
57 elog<InternalFailure>();
58 }
59
60 if (path.empty())
61 {
62 //Get the first one if the path is not in list.
63 return std::make_pair(mapperResponse.begin()->first,
64 mapperResponse.begin()->second.begin()->first);
65 }
66 const auto& iter = mapperResponse.find(path);
67 if (iter == mapperResponse.end())
68 {
69 std::string err = "Error in finding sensor dbus"
70 "Command: GetSubTree "
71 "Interface:" + interface;
72 log<level::ERR>(err.c_str());
73 elog<InternalFailure>();
74 }
75 return std::make_pair(iter->first, iter->second.begin()->first);
76}
77
78AssertionSet getAssertionSet(const SetSensorReadingReq& cmdData)
79{
80 Assertion assertionStates =
81 (static_cast<Assertion>(cmdData.assertOffset8_14)) << 8 |
82 cmdData.assertOffset0_7;
83 Deassertion deassertionStates =
84 (static_cast<Deassertion>(cmdData.deassertOffset8_14)) << 8 |
85 cmdData.deassertOffset0_7;
86 return std::make_pair(assertionStates, deassertionStates);
87}
88
89ipmi_ret_t updateToDbus(IpmiUpdateData& msg)
90{
91 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
92 try
93 {
94 auto serviceResponseMsg = bus.call(msg);
95 if (serviceResponseMsg.is_method_error())
96 {
97 log<level::ERR>("Error in D-Bus call");
98 return IPMI_CC_UNSPECIFIED_ERROR;
99 }
100 }
101 catch (InternalFailure& e)
102 {
103 commit<InternalFailure>();
104 return IPMI_CC_UNSPECIFIED_ERROR;
105 }
106 return IPMI_CC_OK;
107}
108
109namespace set
110{
111
112IpmiUpdateData makeDbusMsg(const std::string& updateInterface,
113 const std::string& sensorPath,
114 const std::string& command,
115 const std::string& sensorInterface)
116{
117 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
118 using namespace std::string_literals;
119
120 std::string dbusService;
121 std::string dbusPath;
122
123 std::tie(dbusPath, dbusService) = getServiceAndPath(bus,
124 sensorInterface,
125 sensorPath);
126 return bus.new_method_call(dbusService.c_str(),
127 dbusPath.c_str(),
128 updateInterface.c_str(),
129 command.c_str());
130}
131
132ipmi_ret_t appendDiscreteSignalData(IpmiUpdateData& msg,
133 const DbusInterfaceMap& interfaceMap,
134 uint8_t data)
135{
136 const auto& interface = interfaceMap.begin();
137 msg.append(interface->first);
138 for (const auto& property : interface->second)
139 {
140 msg.append(property.first);
141 const auto& iter = property.second.find(data);
142 if (iter == property.second.end())
143 {
144 log<level::ERR>("Invalid event data");
145 return IPMI_CC_PARM_OUT_OF_RANGE;
146 }
147 msg.append(iter->second.assert);
148 }
149 return IPMI_CC_OK;
150}
151
152ipmi_ret_t appendReadingData(IpmiUpdateData& msg,
153 const DbusInterfaceMap& interfaceMap,
154 const Value &data)
155{
156 const auto& interface = interfaceMap.begin();
157 msg.append(interface->first);
158 for (const auto& property : interface->second)
159 {
160 msg.append(property.first);
161 msg.append(data);
162 }
163 return IPMI_CC_OK;
164}
165
166ipmi_ret_t appendAssertion(IpmiUpdateData& msg,
167 const DbusInterfaceMap& interfaceMap,
168 const std::string& sensorPath,
169 const SetSensorReadingReq& cmdData)
170{
171 std::bitset<16> assertionSet(getAssertionSet(cmdData).first);
172 std::bitset<16> deassertionSet(getAssertionSet(cmdData).second);
173
174 const auto& interface = interfaceMap.begin();
175 msg.append(interface->first);
176 for (const auto& property : interface->second)
177 {
178 msg.append(property.first);
179 for (const auto& value : property.second)
180 {
181 if (assertionSet.test(value.first))
182 {
183 msg.append(value.second.assert);
184 }
185 if (deassertionSet.test(value.first))
186 {
187 msg.append(value.second.deassert);
188 }
189 }
190 }
191 return IPMI_CC_OK;
192}
193}//namespace set
194
195namespace notify
196{
197
198IpmiUpdateData makeDbusMsg(const std::string& updateInterface,
199 const std::string& sensorPath,
200 const std::string& command,
201 const std::string& sensorInterface)
202{
203 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
204 using namespace std::string_literals;
205
206 std::string dbusService;
207 std::string dbusPath;
208
209 std::tie(dbusPath, dbusService) = getServiceAndPath(bus,
210 updateInterface);
211
212 return bus.new_method_call(dbusService.c_str(),
213 dbusPath.c_str(),
214 updateInterface.c_str(),
215 command.c_str());
216}
217
218ipmi_ret_t appendAssertion(IpmiUpdateData& msg,
219 const DbusInterfaceMap& interfaceMap,
220 const std::string& sensorPath,
221 const SetSensorReadingReq& cmdData)
222{
223 std::bitset<16> assertionSet(getAssertionSet(cmdData).first);
224 std::bitset<16> deassertionSet(getAssertionSet(cmdData).second);
225 ipmi::sensor::ObjectMap objects;
226 ipmi::sensor::InterfaceMap interfaces;
227 for (const auto& interface : interfaceMap)
228 {
229 for (const auto& property : interface.second)
230 {
231 ipmi::sensor::PropertyMap props;
232 bool valid = false;
233 for (const auto& value : property.second)
234 {
235 if (assertionSet.test(value.first))
236 {
237 props.emplace(property.first, value.second.assert);
238 valid = true;
239 }
240 else if (deassertionSet.test(value.first))
241 {
242 props.emplace(property.first, value.second.deassert);
243 valid = true;
244 }
245 }
246 if (valid)
247 {
248 interfaces.emplace(interface.first, std::move(props));
249 }
250 }
251 }
252 objects.emplace(sensorPath, std::move(interfaces));
253 msg.append(std::move(objects));
254 return IPMI_CC_OK;
255}
256}//namespace notify
257}//namespace sensor
258}//namespace ipmi