blob: 93f659b6956d991a3107abd6b2b04f8809d3d3fd [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 +080019namespace pldm
20{
21namespace responder
22{
23namespace platform_numeric_effecter
24{
25
26/** @brief Function to get the effecter value by PDR factor coefficient, etc.
27 * @param[in] pdr - The structure of pldm_numeric_effecter_value_pdr.
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -050028 * @param[in] effecterValue - effecter value.
29 * @param[in] propertyType - type of the D-Bus property.
George Liueccb0c52020-01-14 11:09:56 +080030 *
31 * @return - std::pair<int, std::optional<PropertyValue>> - rc:Success or
32 * failure, PropertyValue: The value to be set
33 */
34template <typename T>
Brad Bishop5079ac42021-08-19 18:35:06 -040035std::pair<int, std::optional<pldm::utils::PropertyValue>>
George Liueccb0c52020-01-14 11:09:56 +080036 getEffecterRawValue(const pldm_numeric_effecter_value_pdr* pdr,
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -050037 T& effecterValue, std::string propertyType)
George Liueccb0c52020-01-14 11:09:56 +080038{
39 // X = Round [ (Y - B) / m ]
40 // refer to DSP0248_1.2.0 27.8
41 int rc = 0;
Brad Bishop5079ac42021-08-19 18:35:06 -040042 pldm::utils::PropertyValue value;
George Liueccb0c52020-01-14 11:09:56 +080043 switch (pdr->effecter_data_size)
44 {
45 case PLDM_EFFECTER_DATA_SIZE_UINT8:
46 {
47 auto rawValue = static_cast<uint8_t>(
48 round(effecterValue - pdr->offset) / pdr->resolution);
49 if (pdr->min_set_table.value_u8 < pdr->max_set_table.value_u8 &&
50 (rawValue < pdr->min_set_table.value_u8 ||
51 rawValue > pdr->max_set_table.value_u8))
52 {
53 rc = PLDM_ERROR_INVALID_DATA;
54 }
55 value = rawValue;
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -050056 if (propertyType == "uint64_t")
57 {
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -050058 auto tempValue = std::get<uint8_t>(value);
59 value = static_cast<uint64_t>(tempValue);
60 }
George Liueccb0c52020-01-14 11:09:56 +080061 break;
62 }
63 case PLDM_EFFECTER_DATA_SIZE_SINT8:
64 {
65 auto rawValue = static_cast<int8_t>(
66 round(effecterValue - pdr->offset) / pdr->resolution);
67 if (pdr->min_set_table.value_s8 < pdr->max_set_table.value_s8 &&
68 (rawValue < pdr->min_set_table.value_s8 ||
69 rawValue > pdr->max_set_table.value_s8))
70 {
71 rc = PLDM_ERROR_INVALID_DATA;
72 }
73 value = rawValue;
74 break;
75 }
76 case PLDM_EFFECTER_DATA_SIZE_UINT16:
77 {
78 auto rawValue = static_cast<uint16_t>(
79 round(effecterValue - pdr->offset) / pdr->resolution);
80 if (pdr->min_set_table.value_u16 < pdr->max_set_table.value_u16 &&
81 (rawValue < pdr->min_set_table.value_u16 ||
82 rawValue > pdr->max_set_table.value_u16))
83 {
84 rc = PLDM_ERROR_INVALID_DATA;
85 }
86 value = rawValue;
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -050087 if (propertyType == "uint64_t")
88 {
89 auto tempValue = std::get<uint16_t>(value);
90 value = static_cast<uint64_t>(tempValue);
91 }
George Liueccb0c52020-01-14 11:09:56 +080092 break;
93 }
94 case PLDM_EFFECTER_DATA_SIZE_SINT16:
95 {
96 auto rawValue = static_cast<int16_t>(
97 round(effecterValue - pdr->offset) / pdr->resolution);
98 if (pdr->min_set_table.value_s16 < pdr->max_set_table.value_s16 &&
99 (rawValue < pdr->min_set_table.value_s16 ||
100 rawValue > pdr->max_set_table.value_s16))
101 {
102 rc = PLDM_ERROR_INVALID_DATA;
103 }
104 value = rawValue;
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500105 if (propertyType == "uint64_t")
106 {
107 auto tempValue = std::get<int16_t>(value);
108 value = static_cast<uint64_t>(tempValue);
109 }
George Liueccb0c52020-01-14 11:09:56 +0800110 break;
111 }
112 case PLDM_EFFECTER_DATA_SIZE_UINT32:
113 {
114 auto rawValue = static_cast<uint32_t>(
115 round(effecterValue - pdr->offset) / pdr->resolution);
116 if (pdr->min_set_table.value_u32 < pdr->max_set_table.value_u32 &&
117 (rawValue < pdr->min_set_table.value_u32 ||
118 rawValue > pdr->max_set_table.value_u32))
119 {
120 rc = PLDM_ERROR_INVALID_DATA;
121 }
122 value = rawValue;
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500123 if (propertyType == "uint64_t")
124 {
125 auto tempValue = std::get<uint32_t>(value);
126 value = static_cast<uint64_t>(tempValue);
127 }
George Liueccb0c52020-01-14 11:09:56 +0800128 break;
129 }
130 case PLDM_EFFECTER_DATA_SIZE_SINT32:
131 {
132 auto rawValue = static_cast<int32_t>(
133 round(effecterValue - pdr->offset) / pdr->resolution);
134 if (pdr->min_set_table.value_s32 < pdr->max_set_table.value_s32 &&
135 (rawValue < pdr->min_set_table.value_s32 ||
136 rawValue > pdr->max_set_table.value_s32))
137 {
138 rc = PLDM_ERROR_INVALID_DATA;
139 }
140 value = rawValue;
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500141 if (propertyType == "uint64_t")
142 {
143 auto tempValue = std::get<int32_t>(value);
144 value = static_cast<uint64_t>(tempValue);
145 }
George Liueccb0c52020-01-14 11:09:56 +0800146 break;
147 }
148 }
149
150 return {rc, std::make_optional(std::move(value))};
151}
152
153/** @brief Function to convert the D-Bus value by PDR factor and effecter value.
154 * @param[in] pdr - The structure of pldm_numeric_effecter_value_pdr.
155 * @param[in] effecterDataSize - effecter value size.
156 * @param[in,out] effecterValue - effecter value.
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500157 * @param[in] propertyType - type of the D-Bus property.
George Liueccb0c52020-01-14 11:09:56 +0800158 *
159 * @return std::pair<int, std::optional<PropertyValue>> - rc:Success or
160 * failure, PropertyValue: The value to be set
161 */
Brad Bishop5079ac42021-08-19 18:35:06 -0400162std::pair<int, std::optional<pldm::utils::PropertyValue>>
George Liueccb0c52020-01-14 11:09:56 +0800163 convertToDbusValue(const pldm_numeric_effecter_value_pdr* pdr,
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500164 uint8_t effecterDataSize, uint8_t* effecterValue,
165 std::string propertyType)
George Liueccb0c52020-01-14 11:09:56 +0800166{
167 if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT8)
168 {
169 uint8_t currentValue = *(reinterpret_cast<uint8_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500170 return getEffecterRawValue<uint8_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800171 }
172 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT8)
173 {
174 int8_t currentValue = *(reinterpret_cast<int8_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500175 return getEffecterRawValue<int8_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800176 }
177 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT16)
178 {
179 uint16_t currentValue =
180 *(reinterpret_cast<uint16_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500181 return getEffecterRawValue<uint16_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800182 }
183 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT16)
184 {
185 int16_t currentValue = *(reinterpret_cast<int16_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500186 return getEffecterRawValue<int16_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800187 }
188 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT32)
189 {
190 uint32_t currentValue =
191 *(reinterpret_cast<uint32_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500192 return getEffecterRawValue<uint32_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800193 }
194 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT32)
195 {
196 int32_t currentValue = *(reinterpret_cast<int32_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500197 return getEffecterRawValue<int32_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800198 }
199 else
200 {
201 std::cerr << "Wrong field effecterDataSize...\n";
202 return {PLDM_ERROR, {}};
203 }
204}
205
206/** @brief Function to set the effecter value requested by pldm requester
207 * @tparam[in] DBusInterface - DBus interface type
208 * @tparam[in] Handler - pldm::responder::platform::Handler
209 * @param[in] dBusIntf - The interface object of DBusInterface
210 * @param[in] handler - The interface object of
211 * pldm::responder::platform::Handler
212 * @param[in] effecterId - Effecter ID sent by the requester to act on
213 * @param[in] effecterDataSize - The bit width and format of the setting
214 * value for the effecter
215 * @param[in] effecter_value - The setting value of numeric effecter being
216 * requested.
217 * @param[in] effecterValueLength - The setting value length of numeric
218 * effecter being requested.
219 * @return - Success or failure in setting the states. Returns failure in
220 * terms of PLDM completion codes if atleast one state fails to be set
221 */
222template <class DBusInterface, class Handler>
223int setNumericEffecterValueHandler(const DBusInterface& dBusIntf,
224 Handler& handler, uint16_t effecterId,
225 uint8_t effecterDataSize,
226 uint8_t* effecterValue,
227 size_t effecterValueLength)
228{
229 constexpr auto effecterValueArrayLength = 4;
230 pldm_numeric_effecter_value_pdr* pdr = nullptr;
231
232 std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)>
233 numericEffecterPdrRepo(pldm_pdr_init(), pldm_pdr_destroy);
Brad Bishop5079ac42021-08-19 18:35:06 -0400234 pldm::responder::pdr_utils::Repo numericEffecterPDRs(
235 numericEffecterPdrRepo.get());
236 pldm::responder::pdr::getRepoByType(handler.getRepo(), numericEffecterPDRs,
237 PLDM_NUMERIC_EFFECTER_PDR);
George Liueccb0c52020-01-14 11:09:56 +0800238 if (numericEffecterPDRs.empty())
239 {
240 std::cerr << "The Numeric Effecter PDR repo is empty." << std::endl;
241 return PLDM_ERROR;
242 }
243
244 // Get the pdr structure of pldm_numeric_effecter_value_pdr according
245 // to the effecterId
Brad Bishop5079ac42021-08-19 18:35:06 -0400246 pldm::responder::pdr_utils::PdrEntry pdrEntry{};
George Liueccb0c52020-01-14 11:09:56 +0800247 auto pdrRecord = numericEffecterPDRs.getFirstRecord(pdrEntry);
248 while (pdrRecord)
249 {
250 pdr = reinterpret_cast<pldm_numeric_effecter_value_pdr*>(pdrEntry.data);
251 if (pdr->effecter_id != effecterId)
252 {
253 pdr = nullptr;
254 pdrRecord = numericEffecterPDRs.getNextRecord(pdrRecord, pdrEntry);
255 continue;
256 }
257
258 break;
259 }
260
261 if (!pdr)
262 {
263 return PLDM_PLATFORM_INVALID_EFFECTER_ID;
264 }
265
266 if (effecterValueLength != effecterValueArrayLength)
267 {
268 std::cerr << "effecter data size is incorrect.\n";
269 return PLDM_ERROR_INVALID_DATA;
270 }
271
George Liueccb0c52020-01-14 11:09:56 +0800272 try
273 {
George Liubd5e2ea2021-04-22 20:33:06 +0800274 const auto& [dbusMappings, dbusValMaps] =
275 handler.getDbusObjMaps(effecterId);
Brad Bishop5079ac42021-08-19 18:35:06 -0400276 pldm::utils::DBusMapping dbusMapping{
George Liubd5e2ea2021-04-22 20:33:06 +0800277 dbusMappings[0].objectPath, dbusMappings[0].interface,
278 dbusMappings[0].propertyName, dbusMappings[0].propertyType};
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500279
280 // convert to dbus effectervalue according to the factor
281 auto [rc, dbusValue] = convertToDbusValue(
282 pdr, effecterDataSize, effecterValue, dbusMappings[0].propertyType);
283 if (rc != PLDM_SUCCESS)
284 {
285 return rc;
286 }
George Liubd5e2ea2021-04-22 20:33:06 +0800287 try
288 {
289
290 dBusIntf.setDbusProperty(dbusMapping, dbusValue.value());
291 }
292 catch (const std::exception& e)
293 {
294 std::cerr << "Error setting property, ERROR=" << e.what()
295 << " PROPERTY=" << dbusMapping.propertyName
296 << " INTERFACE=" << dbusMapping.interface << " PATH="
297 << dbusMapping.objectPath << "\n";
298 return PLDM_ERROR;
299 }
George Liueccb0c52020-01-14 11:09:56 +0800300 }
George Liubd5e2ea2021-04-22 20:33:06 +0800301 catch (const std::out_of_range& e)
George Liueccb0c52020-01-14 11:09:56 +0800302 {
George Liubd5e2ea2021-04-22 20:33:06 +0800303 std::cerr << "Unknown effecter ID : " << effecterId << e.what() << '\n';
George Liueccb0c52020-01-14 11:09:56 +0800304 return PLDM_ERROR;
305 }
306
307 return PLDM_SUCCESS;
308}
309
310} // namespace platform_numeric_effecter
311} // namespace responder
312} // namespace pldm