blob: eea53e62967a92462e4cff9f160ed96c663b7708 [file] [log] [blame]
George Liueccb0c52020-01-14 11:09:56 +08001#pragma once
2
3#include "config.h"
4
George Liu6492f522020-06-16 10:34:05 +08005#include "libpldm/platform.h"
6#include "libpldm/states.h"
7
Deepak Kodihallid130e1a2020-06-17 05:55:32 -05008#include "common/utils.hpp"
George Liueccb0c52020-01-14 11:09:56 +08009#include "libpldmresponder/pdr.hpp"
10#include "pdr_utils.hpp"
Deepak Kodihalli1521f6d2020-06-16 08:51:02 -050011#include "pldmd/handler.hpp"
George Liueccb0c52020-01-14 11:09:56 +080012
13#include <math.h>
14#include <stdint.h>
15
16#include <map>
17#include <optional>
18
George Liueccb0c52020-01-14 11:09:56 +080019using namespace pldm::responder::pdr;
20using namespace pldm::utils;
21
22namespace pldm
23{
24namespace responder
25{
26namespace platform_numeric_effecter
27{
28
29/** @brief Function to get the effecter value by PDR factor coefficient, etc.
30 * @param[in] pdr - The structure of pldm_numeric_effecter_value_pdr.
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -050031 * @param[in] effecterValue - effecter value.
32 * @param[in] propertyType - type of the D-Bus property.
George Liueccb0c52020-01-14 11:09:56 +080033 *
34 * @return - std::pair<int, std::optional<PropertyValue>> - rc:Success or
35 * failure, PropertyValue: The value to be set
36 */
37template <typename T>
38std::pair<int, std::optional<PropertyValue>>
39 getEffecterRawValue(const pldm_numeric_effecter_value_pdr* pdr,
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -050040 T& effecterValue, std::string propertyType)
George Liueccb0c52020-01-14 11:09:56 +080041{
42 // X = Round [ (Y - B) / m ]
43 // refer to DSP0248_1.2.0 27.8
44 int rc = 0;
45 PropertyValue value;
46 switch (pdr->effecter_data_size)
47 {
48 case PLDM_EFFECTER_DATA_SIZE_UINT8:
49 {
50 auto rawValue = static_cast<uint8_t>(
51 round(effecterValue - pdr->offset) / pdr->resolution);
52 if (pdr->min_set_table.value_u8 < pdr->max_set_table.value_u8 &&
53 (rawValue < pdr->min_set_table.value_u8 ||
54 rawValue > pdr->max_set_table.value_u8))
55 {
56 rc = PLDM_ERROR_INVALID_DATA;
57 }
58 value = rawValue;
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -050059 if (propertyType == "uint64_t")
60 {
61 std::cerr << " Inside if when propertytype is uint64_t"
62 << std::endl;
63 auto tempValue = std::get<uint8_t>(value);
64 value = static_cast<uint64_t>(tempValue);
65 }
George Liueccb0c52020-01-14 11:09:56 +080066 break;
67 }
68 case PLDM_EFFECTER_DATA_SIZE_SINT8:
69 {
70 auto rawValue = static_cast<int8_t>(
71 round(effecterValue - pdr->offset) / pdr->resolution);
72 if (pdr->min_set_table.value_s8 < pdr->max_set_table.value_s8 &&
73 (rawValue < pdr->min_set_table.value_s8 ||
74 rawValue > pdr->max_set_table.value_s8))
75 {
76 rc = PLDM_ERROR_INVALID_DATA;
77 }
78 value = rawValue;
79 break;
80 }
81 case PLDM_EFFECTER_DATA_SIZE_UINT16:
82 {
83 auto rawValue = static_cast<uint16_t>(
84 round(effecterValue - pdr->offset) / pdr->resolution);
85 if (pdr->min_set_table.value_u16 < pdr->max_set_table.value_u16 &&
86 (rawValue < pdr->min_set_table.value_u16 ||
87 rawValue > pdr->max_set_table.value_u16))
88 {
89 rc = PLDM_ERROR_INVALID_DATA;
90 }
91 value = rawValue;
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -050092 if (propertyType == "uint64_t")
93 {
94 auto tempValue = std::get<uint16_t>(value);
95 value = static_cast<uint64_t>(tempValue);
96 }
George Liueccb0c52020-01-14 11:09:56 +080097 break;
98 }
99 case PLDM_EFFECTER_DATA_SIZE_SINT16:
100 {
101 auto rawValue = static_cast<int16_t>(
102 round(effecterValue - pdr->offset) / pdr->resolution);
103 if (pdr->min_set_table.value_s16 < pdr->max_set_table.value_s16 &&
104 (rawValue < pdr->min_set_table.value_s16 ||
105 rawValue > pdr->max_set_table.value_s16))
106 {
107 rc = PLDM_ERROR_INVALID_DATA;
108 }
109 value = rawValue;
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500110 if (propertyType == "uint64_t")
111 {
112 auto tempValue = std::get<int16_t>(value);
113 value = static_cast<uint64_t>(tempValue);
114 }
George Liueccb0c52020-01-14 11:09:56 +0800115 break;
116 }
117 case PLDM_EFFECTER_DATA_SIZE_UINT32:
118 {
119 auto rawValue = static_cast<uint32_t>(
120 round(effecterValue - pdr->offset) / pdr->resolution);
121 if (pdr->min_set_table.value_u32 < pdr->max_set_table.value_u32 &&
122 (rawValue < pdr->min_set_table.value_u32 ||
123 rawValue > pdr->max_set_table.value_u32))
124 {
125 rc = PLDM_ERROR_INVALID_DATA;
126 }
127 value = rawValue;
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500128 if (propertyType == "uint64_t")
129 {
130 auto tempValue = std::get<uint32_t>(value);
131 value = static_cast<uint64_t>(tempValue);
132 }
George Liueccb0c52020-01-14 11:09:56 +0800133 break;
134 }
135 case PLDM_EFFECTER_DATA_SIZE_SINT32:
136 {
137 auto rawValue = static_cast<int32_t>(
138 round(effecterValue - pdr->offset) / pdr->resolution);
139 if (pdr->min_set_table.value_s32 < pdr->max_set_table.value_s32 &&
140 (rawValue < pdr->min_set_table.value_s32 ||
141 rawValue > pdr->max_set_table.value_s32))
142 {
143 rc = PLDM_ERROR_INVALID_DATA;
144 }
145 value = rawValue;
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500146 if (propertyType == "uint64_t")
147 {
148 auto tempValue = std::get<int32_t>(value);
149 value = static_cast<uint64_t>(tempValue);
150 }
George Liueccb0c52020-01-14 11:09:56 +0800151 break;
152 }
153 }
154
155 return {rc, std::make_optional(std::move(value))};
156}
157
158/** @brief Function to convert the D-Bus value by PDR factor and effecter value.
159 * @param[in] pdr - The structure of pldm_numeric_effecter_value_pdr.
160 * @param[in] effecterDataSize - effecter value size.
161 * @param[in,out] effecterValue - effecter value.
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500162 * @param[in] propertyType - type of the D-Bus property.
George Liueccb0c52020-01-14 11:09:56 +0800163 *
164 * @return std::pair<int, std::optional<PropertyValue>> - rc:Success or
165 * failure, PropertyValue: The value to be set
166 */
167std::pair<int, std::optional<PropertyValue>>
168 convertToDbusValue(const pldm_numeric_effecter_value_pdr* pdr,
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500169 uint8_t effecterDataSize, uint8_t* effecterValue,
170 std::string propertyType)
George Liueccb0c52020-01-14 11:09:56 +0800171{
172 if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT8)
173 {
174 uint8_t currentValue = *(reinterpret_cast<uint8_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500175 return getEffecterRawValue<uint8_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800176 }
177 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT8)
178 {
179 int8_t currentValue = *(reinterpret_cast<int8_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500180 return getEffecterRawValue<int8_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800181 }
182 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT16)
183 {
184 uint16_t currentValue =
185 *(reinterpret_cast<uint16_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500186 return getEffecterRawValue<uint16_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800187 }
188 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT16)
189 {
190 int16_t currentValue = *(reinterpret_cast<int16_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500191 return getEffecterRawValue<int16_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800192 }
193 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT32)
194 {
195 uint32_t currentValue =
196 *(reinterpret_cast<uint32_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500197 return getEffecterRawValue<uint32_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800198 }
199 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT32)
200 {
201 int32_t currentValue = *(reinterpret_cast<int32_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500202 return getEffecterRawValue<int32_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800203 }
204 else
205 {
206 std::cerr << "Wrong field effecterDataSize...\n";
207 return {PLDM_ERROR, {}};
208 }
209}
210
211/** @brief Function to set the effecter value requested by pldm requester
212 * @tparam[in] DBusInterface - DBus interface type
213 * @tparam[in] Handler - pldm::responder::platform::Handler
214 * @param[in] dBusIntf - The interface object of DBusInterface
215 * @param[in] handler - The interface object of
216 * pldm::responder::platform::Handler
217 * @param[in] effecterId - Effecter ID sent by the requester to act on
218 * @param[in] effecterDataSize - The bit width and format of the setting
219 * value for the effecter
220 * @param[in] effecter_value - The setting value of numeric effecter being
221 * requested.
222 * @param[in] effecterValueLength - The setting value length of numeric
223 * effecter being requested.
224 * @return - Success or failure in setting the states. Returns failure in
225 * terms of PLDM completion codes if atleast one state fails to be set
226 */
227template <class DBusInterface, class Handler>
228int setNumericEffecterValueHandler(const DBusInterface& dBusIntf,
229 Handler& handler, uint16_t effecterId,
230 uint8_t effecterDataSize,
231 uint8_t* effecterValue,
232 size_t effecterValueLength)
233{
234 constexpr auto effecterValueArrayLength = 4;
235 pldm_numeric_effecter_value_pdr* pdr = nullptr;
236
237 std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)>
238 numericEffecterPdrRepo(pldm_pdr_init(), pldm_pdr_destroy);
239 Repo numericEffecterPDRs(numericEffecterPdrRepo.get());
240 getRepoByType(handler.getRepo(), numericEffecterPDRs,
241 PLDM_NUMERIC_EFFECTER_PDR);
242 if (numericEffecterPDRs.empty())
243 {
244 std::cerr << "The Numeric Effecter PDR repo is empty." << std::endl;
245 return PLDM_ERROR;
246 }
247
248 // Get the pdr structure of pldm_numeric_effecter_value_pdr according
249 // to the effecterId
250 PdrEntry pdrEntry{};
251 auto pdrRecord = numericEffecterPDRs.getFirstRecord(pdrEntry);
252 while (pdrRecord)
253 {
254 pdr = reinterpret_cast<pldm_numeric_effecter_value_pdr*>(pdrEntry.data);
255 if (pdr->effecter_id != effecterId)
256 {
257 pdr = nullptr;
258 pdrRecord = numericEffecterPDRs.getNextRecord(pdrRecord, pdrEntry);
259 continue;
260 }
261
262 break;
263 }
264
265 if (!pdr)
266 {
267 return PLDM_PLATFORM_INVALID_EFFECTER_ID;
268 }
269
270 if (effecterValueLength != effecterValueArrayLength)
271 {
272 std::cerr << "effecter data size is incorrect.\n";
273 return PLDM_ERROR_INVALID_DATA;
274 }
275
George Liueccb0c52020-01-14 11:09:56 +0800276 try
277 {
George Liubd5e2ea2021-04-22 20:33:06 +0800278 const auto& [dbusMappings, dbusValMaps] =
279 handler.getDbusObjMaps(effecterId);
280 DBusMapping dbusMapping{
281 dbusMappings[0].objectPath, dbusMappings[0].interface,
282 dbusMappings[0].propertyName, dbusMappings[0].propertyType};
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500283
284 // convert to dbus effectervalue according to the factor
285 auto [rc, dbusValue] = convertToDbusValue(
286 pdr, effecterDataSize, effecterValue, dbusMappings[0].propertyType);
287 if (rc != PLDM_SUCCESS)
288 {
289 return rc;
290 }
George Liubd5e2ea2021-04-22 20:33:06 +0800291 try
292 {
293
294 dBusIntf.setDbusProperty(dbusMapping, dbusValue.value());
295 }
296 catch (const std::exception& e)
297 {
298 std::cerr << "Error setting property, ERROR=" << e.what()
299 << " PROPERTY=" << dbusMapping.propertyName
300 << " INTERFACE=" << dbusMapping.interface << " PATH="
301 << dbusMapping.objectPath << "\n";
302 return PLDM_ERROR;
303 }
George Liueccb0c52020-01-14 11:09:56 +0800304 }
George Liubd5e2ea2021-04-22 20:33:06 +0800305 catch (const std::out_of_range& e)
George Liueccb0c52020-01-14 11:09:56 +0800306 {
George Liubd5e2ea2021-04-22 20:33:06 +0800307 std::cerr << "Unknown effecter ID : " << effecterId << e.what() << '\n';
George Liueccb0c52020-01-14 11:09:56 +0800308 return PLDM_ERROR;
309 }
310
311 return PLDM_SUCCESS;
312}
313
314} // namespace platform_numeric_effecter
315} // namespace responder
316} // namespace pldm