blob: 37d5c0011f4a5bec113c22775bb8cd6ab57d2e52 [file] [log] [blame]
George Liueccb0c52020-01-14 11:09:56 +08001#pragma once
2
3#include "config.h"
4
Deepak Kodihallid130e1a2020-06-17 05:55:32 -05005#include "common/utils.hpp"
George Liueccb0c52020-01-14 11:09:56 +08006#include "libpldmresponder/pdr.hpp"
7#include "pdr_utils.hpp"
Deepak Kodihalli1521f6d2020-06-16 08:51:02 -05008#include "pldmd/handler.hpp"
George Liueccb0c52020-01-14 11:09:56 +08009
George Liuc453e162022-12-21 17:16:23 +080010#include <libpldm/platform.h>
11#include <libpldm/states.h>
George Liueccb0c52020-01-14 11:09:56 +080012#include <math.h>
13#include <stdint.h>
14
15#include <map>
16#include <optional>
17
George Liueccb0c52020-01-14 11:09:56 +080018namespace pldm
19{
20namespace responder
21{
22namespace platform_numeric_effecter
23{
24
25/** @brief Function to get the effecter value by PDR factor coefficient, etc.
26 * @param[in] pdr - The structure of pldm_numeric_effecter_value_pdr.
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -050027 * @param[in] effecterValue - effecter value.
28 * @param[in] propertyType - type of the D-Bus property.
George Liueccb0c52020-01-14 11:09:56 +080029 *
30 * @return - std::pair<int, std::optional<PropertyValue>> - rc:Success or
31 * failure, PropertyValue: The value to be set
32 */
33template <typename T>
Brad Bishop5079ac42021-08-19 18:35:06 -040034std::pair<int, std::optional<pldm::utils::PropertyValue>>
George Liueccb0c52020-01-14 11:09:56 +080035 getEffecterRawValue(const pldm_numeric_effecter_value_pdr* pdr,
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -050036 T& effecterValue, std::string propertyType)
George Liueccb0c52020-01-14 11:09:56 +080037{
38 // X = Round [ (Y - B) / m ]
39 // refer to DSP0248_1.2.0 27.8
40 int rc = 0;
Brad Bishop5079ac42021-08-19 18:35:06 -040041 pldm::utils::PropertyValue value;
George Liueccb0c52020-01-14 11:09:56 +080042 switch (pdr->effecter_data_size)
43 {
44 case PLDM_EFFECTER_DATA_SIZE_UINT8:
45 {
46 auto rawValue = static_cast<uint8_t>(
47 round(effecterValue - pdr->offset) / pdr->resolution);
Manojkiran Edafc0ce972022-06-25 09:38:28 +053048 if (pdr->min_settable.value_u8 < pdr->max_settable.value_u8 &&
49 (rawValue < pdr->min_settable.value_u8 ||
50 rawValue > pdr->max_settable.value_u8))
George Liueccb0c52020-01-14 11:09:56 +080051 {
52 rc = PLDM_ERROR_INVALID_DATA;
53 }
54 value = rawValue;
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -050055 if (propertyType == "uint64_t")
56 {
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -050057 auto tempValue = std::get<uint8_t>(value);
58 value = static_cast<uint64_t>(tempValue);
59 }
Sagar Srinivasdb436122021-10-20 06:44:07 -050060 else if (propertyType == "uint32_t")
61 {
62 auto tempValue = std::get<uint8_t>(value);
63 value = static_cast<uint32_t>(tempValue);
64 }
George Liueccb0c52020-01-14 11:09:56 +080065 break;
66 }
67 case PLDM_EFFECTER_DATA_SIZE_SINT8:
68 {
69 auto rawValue = static_cast<int8_t>(
70 round(effecterValue - pdr->offset) / pdr->resolution);
Manojkiran Edafc0ce972022-06-25 09:38:28 +053071 if (pdr->min_settable.value_s8 < pdr->max_settable.value_s8 &&
72 (rawValue < pdr->min_settable.value_s8 ||
73 rawValue > pdr->max_settable.value_s8))
George Liueccb0c52020-01-14 11:09:56 +080074 {
75 rc = PLDM_ERROR_INVALID_DATA;
76 }
77 value = rawValue;
78 break;
79 }
80 case PLDM_EFFECTER_DATA_SIZE_UINT16:
81 {
82 auto rawValue = static_cast<uint16_t>(
83 round(effecterValue - pdr->offset) / pdr->resolution);
Manojkiran Edafc0ce972022-06-25 09:38:28 +053084 if (pdr->min_settable.value_u16 < pdr->max_settable.value_u16 &&
85 (rawValue < pdr->min_settable.value_u16 ||
86 rawValue > pdr->max_settable.value_u16))
George Liueccb0c52020-01-14 11:09:56 +080087 {
88 rc = PLDM_ERROR_INVALID_DATA;
89 }
90 value = rawValue;
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -050091 if (propertyType == "uint64_t")
92 {
93 auto tempValue = std::get<uint16_t>(value);
94 value = static_cast<uint64_t>(tempValue);
95 }
Sagar Srinivasdb436122021-10-20 06:44:07 -050096 else if (propertyType == "uint32_t")
97 {
98 auto tempValue = std::get<uint16_t>(value);
99 value = static_cast<uint32_t>(tempValue);
100 }
George Liueccb0c52020-01-14 11:09:56 +0800101 break;
102 }
103 case PLDM_EFFECTER_DATA_SIZE_SINT16:
104 {
105 auto rawValue = static_cast<int16_t>(
106 round(effecterValue - pdr->offset) / pdr->resolution);
Manojkiran Edafc0ce972022-06-25 09:38:28 +0530107 if (pdr->min_settable.value_s16 < pdr->max_settable.value_s16 &&
108 (rawValue < pdr->min_settable.value_s16 ||
109 rawValue > pdr->max_settable.value_s16))
George Liueccb0c52020-01-14 11:09:56 +0800110 {
111 rc = PLDM_ERROR_INVALID_DATA;
112 }
113 value = rawValue;
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500114 if (propertyType == "uint64_t")
115 {
116 auto tempValue = std::get<int16_t>(value);
117 value = static_cast<uint64_t>(tempValue);
118 }
Sagar Srinivasdb436122021-10-20 06:44:07 -0500119 else if (propertyType == "uint32_t")
120 {
121 auto tempValue = std::get<int16_t>(value);
122 value = static_cast<uint32_t>(tempValue);
123 }
George Liueccb0c52020-01-14 11:09:56 +0800124 break;
125 }
126 case PLDM_EFFECTER_DATA_SIZE_UINT32:
127 {
128 auto rawValue = static_cast<uint32_t>(
129 round(effecterValue - pdr->offset) / pdr->resolution);
Manojkiran Edafc0ce972022-06-25 09:38:28 +0530130 if (pdr->min_settable.value_u32 < pdr->max_settable.value_u32 &&
131 (rawValue < pdr->min_settable.value_u32 ||
132 rawValue > pdr->max_settable.value_u32))
George Liueccb0c52020-01-14 11:09:56 +0800133 {
134 rc = PLDM_ERROR_INVALID_DATA;
135 }
136 value = rawValue;
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500137 if (propertyType == "uint64_t")
138 {
139 auto tempValue = std::get<uint32_t>(value);
140 value = static_cast<uint64_t>(tempValue);
141 }
Sagar Srinivasdb436122021-10-20 06:44:07 -0500142 else if (propertyType == "uint32_t")
143 {
144 auto tempValue = std::get<uint32_t>(value);
145 value = static_cast<uint32_t>(tempValue);
146 }
George Liueccb0c52020-01-14 11:09:56 +0800147 break;
148 }
149 case PLDM_EFFECTER_DATA_SIZE_SINT32:
150 {
151 auto rawValue = static_cast<int32_t>(
152 round(effecterValue - pdr->offset) / pdr->resolution);
Manojkiran Edafc0ce972022-06-25 09:38:28 +0530153 if (pdr->min_settable.value_s32 < pdr->max_settable.value_s32 &&
154 (rawValue < pdr->min_settable.value_s32 ||
155 rawValue > pdr->max_settable.value_s32))
George Liueccb0c52020-01-14 11:09:56 +0800156 {
157 rc = PLDM_ERROR_INVALID_DATA;
158 }
159 value = rawValue;
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500160 if (propertyType == "uint64_t")
161 {
162 auto tempValue = std::get<int32_t>(value);
163 value = static_cast<uint64_t>(tempValue);
164 }
Sagar Srinivasdb436122021-10-20 06:44:07 -0500165 else if (propertyType == "uint32_t")
166 {
167 auto tempValue = std::get<int32_t>(value);
168 value = static_cast<uint32_t>(tempValue);
169 }
George Liueccb0c52020-01-14 11:09:56 +0800170 break;
171 }
172 }
173
174 return {rc, std::make_optional(std::move(value))};
175}
176
177/** @brief Function to convert the D-Bus value by PDR factor and effecter value.
178 * @param[in] pdr - The structure of pldm_numeric_effecter_value_pdr.
179 * @param[in] effecterDataSize - effecter value size.
180 * @param[in,out] effecterValue - effecter value.
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500181 * @param[in] propertyType - type of the D-Bus property.
George Liueccb0c52020-01-14 11:09:56 +0800182 *
183 * @return std::pair<int, std::optional<PropertyValue>> - rc:Success or
184 * failure, PropertyValue: The value to be set
185 */
Brad Bishop5079ac42021-08-19 18:35:06 -0400186std::pair<int, std::optional<pldm::utils::PropertyValue>>
George Liueccb0c52020-01-14 11:09:56 +0800187 convertToDbusValue(const pldm_numeric_effecter_value_pdr* pdr,
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500188 uint8_t effecterDataSize, uint8_t* effecterValue,
189 std::string propertyType)
George Liueccb0c52020-01-14 11:09:56 +0800190{
191 if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT8)
192 {
193 uint8_t currentValue = *(reinterpret_cast<uint8_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500194 return getEffecterRawValue<uint8_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800195 }
196 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT8)
197 {
198 int8_t currentValue = *(reinterpret_cast<int8_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500199 return getEffecterRawValue<int8_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800200 }
201 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT16)
202 {
203 uint16_t currentValue =
204 *(reinterpret_cast<uint16_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500205 return getEffecterRawValue<uint16_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800206 }
207 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT16)
208 {
209 int16_t currentValue = *(reinterpret_cast<int16_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500210 return getEffecterRawValue<int16_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800211 }
212 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT32)
213 {
214 uint32_t currentValue =
215 *(reinterpret_cast<uint32_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500216 return getEffecterRawValue<uint32_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800217 }
218 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT32)
219 {
220 int32_t currentValue = *(reinterpret_cast<int32_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500221 return getEffecterRawValue<int32_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800222 }
223 else
224 {
225 std::cerr << "Wrong field effecterDataSize...\n";
226 return {PLDM_ERROR, {}};
227 }
228}
229
230/** @brief Function to set the effecter value requested by pldm requester
231 * @tparam[in] DBusInterface - DBus interface type
232 * @tparam[in] Handler - pldm::responder::platform::Handler
233 * @param[in] dBusIntf - The interface object of DBusInterface
234 * @param[in] handler - The interface object of
235 * pldm::responder::platform::Handler
236 * @param[in] effecterId - Effecter ID sent by the requester to act on
237 * @param[in] effecterDataSize - The bit width and format of the setting
238 * value for the effecter
239 * @param[in] effecter_value - The setting value of numeric effecter being
240 * requested.
241 * @param[in] effecterValueLength - The setting value length of numeric
242 * effecter being requested.
243 * @return - Success or failure in setting the states. Returns failure in
244 * terms of PLDM completion codes if atleast one state fails to be set
245 */
246template <class DBusInterface, class Handler>
247int setNumericEffecterValueHandler(const DBusInterface& dBusIntf,
248 Handler& handler, uint16_t effecterId,
249 uint8_t effecterDataSize,
250 uint8_t* effecterValue,
251 size_t effecterValueLength)
252{
253 constexpr auto effecterValueArrayLength = 4;
254 pldm_numeric_effecter_value_pdr* pdr = nullptr;
255
256 std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)>
257 numericEffecterPdrRepo(pldm_pdr_init(), pldm_pdr_destroy);
Brad Bishop5079ac42021-08-19 18:35:06 -0400258 pldm::responder::pdr_utils::Repo numericEffecterPDRs(
259 numericEffecterPdrRepo.get());
260 pldm::responder::pdr::getRepoByType(handler.getRepo(), numericEffecterPDRs,
261 PLDM_NUMERIC_EFFECTER_PDR);
George Liueccb0c52020-01-14 11:09:56 +0800262 if (numericEffecterPDRs.empty())
263 {
264 std::cerr << "The Numeric Effecter PDR repo is empty." << std::endl;
265 return PLDM_ERROR;
266 }
267
268 // Get the pdr structure of pldm_numeric_effecter_value_pdr according
269 // to the effecterId
Brad Bishop5079ac42021-08-19 18:35:06 -0400270 pldm::responder::pdr_utils::PdrEntry pdrEntry{};
George Liueccb0c52020-01-14 11:09:56 +0800271 auto pdrRecord = numericEffecterPDRs.getFirstRecord(pdrEntry);
272 while (pdrRecord)
273 {
274 pdr = reinterpret_cast<pldm_numeric_effecter_value_pdr*>(pdrEntry.data);
275 if (pdr->effecter_id != effecterId)
276 {
277 pdr = nullptr;
278 pdrRecord = numericEffecterPDRs.getNextRecord(pdrRecord, pdrEntry);
279 continue;
280 }
281
282 break;
283 }
284
285 if (!pdr)
286 {
287 return PLDM_PLATFORM_INVALID_EFFECTER_ID;
288 }
289
290 if (effecterValueLength != effecterValueArrayLength)
291 {
292 std::cerr << "effecter data size is incorrect.\n";
293 return PLDM_ERROR_INVALID_DATA;
294 }
295
George Liueccb0c52020-01-14 11:09:56 +0800296 try
297 {
George Liubd5e2ea2021-04-22 20:33:06 +0800298 const auto& [dbusMappings, dbusValMaps] =
299 handler.getDbusObjMaps(effecterId);
Brad Bishop5079ac42021-08-19 18:35:06 -0400300 pldm::utils::DBusMapping dbusMapping{
George Liubd5e2ea2021-04-22 20:33:06 +0800301 dbusMappings[0].objectPath, dbusMappings[0].interface,
302 dbusMappings[0].propertyName, dbusMappings[0].propertyType};
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500303
304 // convert to dbus effectervalue according to the factor
305 auto [rc, dbusValue] = convertToDbusValue(
306 pdr, effecterDataSize, effecterValue, dbusMappings[0].propertyType);
307 if (rc != PLDM_SUCCESS)
308 {
309 return rc;
310 }
George Liubd5e2ea2021-04-22 20:33:06 +0800311 try
312 {
George Liubd5e2ea2021-04-22 20:33:06 +0800313 dBusIntf.setDbusProperty(dbusMapping, dbusValue.value());
314 }
315 catch (const std::exception& e)
316 {
317 std::cerr << "Error setting property, ERROR=" << e.what()
318 << " PROPERTY=" << dbusMapping.propertyName
319 << " INTERFACE=" << dbusMapping.interface << " PATH="
320 << dbusMapping.objectPath << "\n";
321 return PLDM_ERROR;
322 }
George Liueccb0c52020-01-14 11:09:56 +0800323 }
George Liubd5e2ea2021-04-22 20:33:06 +0800324 catch (const std::out_of_range& e)
George Liueccb0c52020-01-14 11:09:56 +0800325 {
George Liubd5e2ea2021-04-22 20:33:06 +0800326 std::cerr << "Unknown effecter ID : " << effecterId << e.what() << '\n';
George Liueccb0c52020-01-14 11:09:56 +0800327 return PLDM_ERROR;
328 }
329
330 return PLDM_SUCCESS;
331}
332
333} // namespace platform_numeric_effecter
334} // namespace responder
335} // namespace pldm