1 #pragma once
2 
3 #include "sensorhandler.h"
4 #include "types.hpp"
5 #include "utils.hpp"
6 #include "host-ipmid/ipmid-api.h"
7 
8 namespace ipmi
9 {
10 namespace sensor
11 {
12 
13 using Assertion = uint16_t;
14 using Deassertion = uint16_t;
15 using AssertionSet = std::pair<Assertion, Deassertion>;
16 
17 using Service = std::string;
18 using Path = std::string;
19 using Interface = std::string;
20 
21 using ServicePath = std::pair<Path, Service>;
22 
23 using Interfaces = std::vector<Interface>;
24 
25 using MapperResponseType = std::map<Path, std::map<Service, Interfaces>>;
26 
27 /** @brief get the D-Bus service and service path
28  *  @param[in] bus - The Dbus bus object
29  *  @param[in] interface - interface to the service
30  *  @param[in] path - interested path in the list of objects
31  *  @return pair of service path and service
32  */
33 ServicePath getServiceAndPath(sdbusplus::bus::bus& bus,
34                               const std::string& interface,
35                               const std::string& path = std::string());
36 
37 /** @brief Make assertion set from input data
38  *  @param[in] cmdData - Input sensor data
39  *  @return pair of assertion and deassertion set
40  */
41 AssertionSet getAssertionSet(const SetSensorReadingReq& cmdData);
42 
43 /** @brief send the message to DBus
44  *  @param[in] msg - message to send
45  *  @return failure status in IPMI error code
46  */
47 ipmi_ret_t updateToDbus(IpmiUpdateData& msg);
48 
49 namespace get
50 {
51 
52 /**
53  *  @brief Helper function to map the dbus info to sensor's assertion status
54  *         for the get sensor reading command.
55  *
56  *  @param[in] sensorInfo - Dbus info related to sensor.
57  *  @param[in] path - Dbus object path.
58  *  @param[in] interface - Dbus interface.
59  *
60  *  @return Response for get sensor reading command.
61  */
62 GetSensorResponse mapDbusToAssertion(const Info& sensorInfo,
63                                      const InstancePath& path,
64                                      const DbusInterface& interface);
65 
66 /**
67  *  @brief Map the Dbus info to sensor's assertion status in the Get sensor
68  *         reading command response.
69  *
70  *  @param[in] sensorInfo - Dbus info related to sensor.
71  *
72  *  @return Response for get sensor reading command.
73  */
74 GetSensorResponse assertion(const Info& sensorInfo);
75 
76 /**
77  *  @brief Maps the Dbus info to the reading field in the Get sensor reading
78  *         command response.
79  *
80  *  @param[in] sensorInfo - Dbus info related to sensor.
81  *
82  *  @return Response for get sensor reading command.
83  */
84 GetSensorResponse eventdata2(const Info& sensorInfo);
85 
86 /**
87  *  @brief readingAssertion is a case where the entire assertion state field
88  *         serves as the sensor value.
89  *
90  *  @tparam T - type of the dbus property related to sensor.
91  *  @param[in] sensorInfo - Dbus info related to sensor.
92  *
93  *  @return Response for get sensor reading command.
94  */
95 template<typename T>
96 GetSensorResponse readingAssertion(const Info& sensorInfo)
97 {
98     sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
99     GetSensorResponse response {};
100     auto responseData = reinterpret_cast<GetReadingResponse*>(response.data());
101 
102     auto service = ipmi::getService(bus,
103                                     sensorInfo.sensorInterface,
104                                     sensorInfo.sensorPath);
105 
106     auto propValue = ipmi::getDbusProperty(
107             bus,
108             service,
109             sensorInfo.sensorPath,
110             sensorInfo.propertyInterfaces.begin()->first,
111             sensorInfo.propertyInterfaces.begin()->second.begin()->first);
112 
113     setAssertionBytes(static_cast<uint16_t>(propValue.get<T>()), responseData);
114 
115     return response;
116 }
117 
118 /** @brief Map the Dbus info to the reading field in the Get sensor reading
119  *         command response
120  *
121  *  @tparam T - type of the dbus property related to sensor.
122  *  @param[in] sensorInfo - Dbus info related to sensor.
123  *
124  *  @return Response for get sensor reading command.
125  */
126 template<typename T>
127 GetSensorResponse readingData(const Info& sensorInfo)
128 {
129     sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
130     GetSensorResponse response {};
131     auto responseData = reinterpret_cast<GetReadingResponse*>(response.data());
132 
133     enableScanning(responseData);
134 
135     auto service = ipmi::getService(bus,
136                                     sensorInfo.sensorInterface,
137                                     sensorInfo.sensorPath);
138 
139     auto propValue = ipmi::getDbusProperty(
140             bus,
141             service,
142             sensorInfo.sensorPath,
143             sensorInfo.propertyInterfaces.begin()->first,
144             sensorInfo.propertyInterfaces.begin()->second.begin()->first);
145 
146     auto value = static_cast<uint8_t>(
147             (propValue.get<T>() - sensorInfo.scaledOffset) /
148             (sensorInfo.coefficientM ? sensorInfo.coefficientM : 1));
149 
150     setReading(value, responseData);
151 
152     return response;
153 }
154 
155 } //namespace get
156 
157 namespace set
158 {
159 
160 /** @brief Make a DBus message for a Dbus call
161  *  @param[in] updateInterface - Interface name
162  *  @param[in] sensorPath - Path of the sensor
163  *  @param[in] command - command to be executed
164  *  @param[in] sensorInterface - DBus interface of sensor
165  *  @return a dbus message
166  */
167 IpmiUpdateData makeDbusMsg(const std::string& updateInterface,
168                            const std::string& sensorPath,
169                            const std::string& command,
170                            const std::string& sensorInterface);
171 
172 /** @brief Update d-bus based on assertion type sensor data
173  *  @param[in] cmdData - input sensor data
174  *  @param[in] sensorInfo - sensor d-bus info
175  *  @return a IPMI error code
176  */
177 ipmi_ret_t assertion(const SetSensorReadingReq& cmdData,
178                      const Info& sensorInfo);
179 
180 /** @brief Update d-bus based on a reading assertion
181  *  @tparam T - type of d-bus property mapping this sensor
182  *  @param[in] cmdData - input sensor data
183  *  @param[in] sensorInfo - sensor d-bus info
184  *  @return a IPMI error code
185  */
186 template<typename T>
187 ipmi_ret_t readingAssertion(const SetSensorReadingReq& cmdData,
188                             const Info& sensorInfo)
189 {
190     auto msg = makeDbusMsg(
191                    "org.freedesktop.DBus.Properties",
192                    sensorInfo.sensorPath,
193                    "Set",
194                    sensorInfo.sensorInterface);
195 
196     const auto& interface = sensorInfo.propertyInterfaces.begin();
197     msg.append(interface->first);
198     for (const auto& property : interface->second)
199     {
200         msg.append(property.first);
201         sdbusplus::message::variant<T> value =
202             (cmdData.assertOffset8_14 << 8) | cmdData.assertOffset0_7;
203         msg.append(value);
204     }
205     return updateToDbus(msg);
206 }
207 
208 /** @brief Update d-bus based on a discrete reading
209  *  @param[in] cmdData - input sensor data
210  *  @param[in] sensorInfo - sensor d-bus info
211  *  @return an IPMI error code
212  */
213 template<typename T>
214 ipmi_ret_t readingData(const SetSensorReadingReq& cmdData,
215                        const Info& sensorInfo)
216 {
217     auto msg = makeDbusMsg(
218                    "org.freedesktop.DBus.Properties",
219                    sensorInfo.sensorPath,
220                    "Set",
221                    sensorInfo.sensorInterface);
222 
223     const auto& interface = sensorInfo.propertyInterfaces.begin();
224     msg.append(interface->first);
225 
226     ipmi::sensor::Multiplier m = sensorInfo.coefficientM;
227     if (0 == m)
228     {
229         m = 1;  // Avoid * 0
230     }
231 
232     // TODO: Refactor this into a generated function depending on the type
233     // of conversion for the value between IPMI and dbus.
234     T raw_value = (m * cmdData.reading) + sensorInfo.scaledOffset;
235 
236     for (const auto& property : interface->second)
237     {
238         msg.append(property.first);
239         sdbusplus::message::variant<T> value = raw_value;
240         msg.append(value);
241     }
242     return updateToDbus(msg);
243 }
244 
245 /** @brief Update d-bus based on eventdata type sensor data
246  *  @param[in] cmdData - input sensor data
247  *  @param[in] sensorInfo - sensor d-bus info
248  *  @return a IPMI error code
249  */
250 ipmi_ret_t eventdata(const SetSensorReadingReq& cmdData,
251                      const Info& sensorInfo,
252                      uint8_t data);
253 
254 /** @brief Update d-bus based on eventdata1 type sensor data
255  *  @param[in] cmdData - input sensor data
256  *  @param[in] sensorInfo - sensor d-bus info
257  *  @return a IPMI error code
258  */
259 inline ipmi_ret_t eventdata1(const SetSensorReadingReq& cmdData,
260                              const Info& sensorInfo)
261 {
262     return eventdata(cmdData, sensorInfo, cmdData.eventData1);
263 }
264 
265 /** @brief Update d-bus based on eventdata2 type sensor data
266  *  @param[in] cmdData - input sensor data
267  *  @param[in] sensorInfo - sensor d-bus info
268  *  @return a IPMI error code
269  */
270 inline ipmi_ret_t eventdata2(const SetSensorReadingReq& cmdData,
271                              const Info& sensorInfo)
272 {
273     return eventdata(cmdData, sensorInfo, cmdData.eventData2);
274 }
275 
276 /** @brief Update d-bus based on eventdata3 type sensor data
277  *  @param[in] cmdData - input sensor data
278  *  @param[in] sensorInfo - sensor d-bus info
279  *  @return a IPMI error code
280  */
281 inline ipmi_ret_t eventdata3(const SetSensorReadingReq& cmdData,
282                              const Info& sensorInfo)
283 {
284     return eventdata(cmdData, sensorInfo, cmdData.eventData3);
285 }
286 
287 }//namespace set
288 
289 namespace notify
290 {
291 
292 /** @brief Make a DBus message for a Dbus call
293  *  @param[in] updateInterface - Interface name
294  *  @param[in] sensorPath - Path of the sensor
295  *  @param[in] command - command to be executed
296  *  @param[in] sensorInterface - DBus interface of sensor
297  *  @return a dbus message
298  */
299 IpmiUpdateData makeDbusMsg(const std::string& updateInterface,
300                            const std::string& sensorPath,
301                            const std::string& command,
302                            const std::string& sensorInterface);
303 
304 /** @brief Update d-bus based on assertion type sensor data
305  *  @param[in] interfaceMap - sensor interface
306  *  @param[in] cmdData - input sensor data
307  *  @param[in] sensorInfo - sensor d-bus info
308  *  @return a IPMI error code
309  */
310 ipmi_ret_t assertion(const SetSensorReadingReq& cmdData,
311                      const Info& sensorInfo);
312 
313 }//namespace notify
314 
315 namespace inventory
316 {
317 
318 namespace get
319 {
320 
321 /**
322  *  @brief Map the Dbus info to sensor's assertion status in the Get sensor
323  *         reading command response.
324  *
325  *  @param[in] sensorInfo - Dbus info related to sensor.
326  *
327  *  @return Response for get sensor reading command.
328  */
329 GetSensorResponse assertion(const Info& sensorInfo);
330 
331 } // namespace get
332 
333 } // namespace inventory
334 }//namespace sensor
335 }//namespace ipmi
336