blob: 7b0f7d400494f1d55cebcdbc6214055d0013d706 [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 }
Sagar Srinivasdb436122021-10-20 06:44:07 -050061 else if (propertyType == "uint32_t")
62 {
63 auto tempValue = std::get<uint8_t>(value);
64 value = static_cast<uint32_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 }
Sagar Srinivasdb436122021-10-20 06:44:07 -050097 else if (propertyType == "uint32_t")
98 {
99 auto tempValue = std::get<uint16_t>(value);
100 value = static_cast<uint32_t>(tempValue);
101 }
George Liueccb0c52020-01-14 11:09:56 +0800102 break;
103 }
104 case PLDM_EFFECTER_DATA_SIZE_SINT16:
105 {
106 auto rawValue = static_cast<int16_t>(
107 round(effecterValue - pdr->offset) / pdr->resolution);
108 if (pdr->min_set_table.value_s16 < pdr->max_set_table.value_s16 &&
109 (rawValue < pdr->min_set_table.value_s16 ||
110 rawValue > pdr->max_set_table.value_s16))
111 {
112 rc = PLDM_ERROR_INVALID_DATA;
113 }
114 value = rawValue;
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500115 if (propertyType == "uint64_t")
116 {
117 auto tempValue = std::get<int16_t>(value);
118 value = static_cast<uint64_t>(tempValue);
119 }
Sagar Srinivasdb436122021-10-20 06:44:07 -0500120 else if (propertyType == "uint32_t")
121 {
122 auto tempValue = std::get<int16_t>(value);
123 value = static_cast<uint32_t>(tempValue);
124 }
George Liueccb0c52020-01-14 11:09:56 +0800125 break;
126 }
127 case PLDM_EFFECTER_DATA_SIZE_UINT32:
128 {
129 auto rawValue = static_cast<uint32_t>(
130 round(effecterValue - pdr->offset) / pdr->resolution);
131 if (pdr->min_set_table.value_u32 < pdr->max_set_table.value_u32 &&
132 (rawValue < pdr->min_set_table.value_u32 ||
133 rawValue > pdr->max_set_table.value_u32))
134 {
135 rc = PLDM_ERROR_INVALID_DATA;
136 }
137 value = rawValue;
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500138 if (propertyType == "uint64_t")
139 {
140 auto tempValue = std::get<uint32_t>(value);
141 value = static_cast<uint64_t>(tempValue);
142 }
Sagar Srinivasdb436122021-10-20 06:44:07 -0500143 else if (propertyType == "uint32_t")
144 {
145 auto tempValue = std::get<uint32_t>(value);
146 value = static_cast<uint32_t>(tempValue);
147 }
George Liueccb0c52020-01-14 11:09:56 +0800148 break;
149 }
150 case PLDM_EFFECTER_DATA_SIZE_SINT32:
151 {
152 auto rawValue = static_cast<int32_t>(
153 round(effecterValue - pdr->offset) / pdr->resolution);
154 if (pdr->min_set_table.value_s32 < pdr->max_set_table.value_s32 &&
155 (rawValue < pdr->min_set_table.value_s32 ||
156 rawValue > pdr->max_set_table.value_s32))
157 {
158 rc = PLDM_ERROR_INVALID_DATA;
159 }
160 value = rawValue;
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500161 if (propertyType == "uint64_t")
162 {
163 auto tempValue = std::get<int32_t>(value);
164 value = static_cast<uint64_t>(tempValue);
165 }
Sagar Srinivasdb436122021-10-20 06:44:07 -0500166 else if (propertyType == "uint32_t")
167 {
168 auto tempValue = std::get<int32_t>(value);
169 value = static_cast<uint32_t>(tempValue);
170 }
George Liueccb0c52020-01-14 11:09:56 +0800171 break;
172 }
173 }
174
175 return {rc, std::make_optional(std::move(value))};
176}
177
178/** @brief Function to convert the D-Bus value by PDR factor and effecter value.
179 * @param[in] pdr - The structure of pldm_numeric_effecter_value_pdr.
180 * @param[in] effecterDataSize - effecter value size.
181 * @param[in,out] effecterValue - effecter value.
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500182 * @param[in] propertyType - type of the D-Bus property.
George Liueccb0c52020-01-14 11:09:56 +0800183 *
184 * @return std::pair<int, std::optional<PropertyValue>> - rc:Success or
185 * failure, PropertyValue: The value to be set
186 */
Brad Bishop5079ac42021-08-19 18:35:06 -0400187std::pair<int, std::optional<pldm::utils::PropertyValue>>
George Liueccb0c52020-01-14 11:09:56 +0800188 convertToDbusValue(const pldm_numeric_effecter_value_pdr* pdr,
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500189 uint8_t effecterDataSize, uint8_t* effecterValue,
190 std::string propertyType)
George Liueccb0c52020-01-14 11:09:56 +0800191{
192 if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT8)
193 {
194 uint8_t currentValue = *(reinterpret_cast<uint8_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500195 return getEffecterRawValue<uint8_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800196 }
197 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT8)
198 {
199 int8_t currentValue = *(reinterpret_cast<int8_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500200 return getEffecterRawValue<int8_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800201 }
202 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT16)
203 {
204 uint16_t currentValue =
205 *(reinterpret_cast<uint16_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500206 return getEffecterRawValue<uint16_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800207 }
208 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT16)
209 {
210 int16_t currentValue = *(reinterpret_cast<int16_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500211 return getEffecterRawValue<int16_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800212 }
213 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT32)
214 {
215 uint32_t currentValue =
216 *(reinterpret_cast<uint32_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500217 return getEffecterRawValue<uint32_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800218 }
219 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT32)
220 {
221 int32_t currentValue = *(reinterpret_cast<int32_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500222 return getEffecterRawValue<int32_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800223 }
224 else
225 {
226 std::cerr << "Wrong field effecterDataSize...\n";
227 return {PLDM_ERROR, {}};
228 }
229}
230
231/** @brief Function to set the effecter value requested by pldm requester
232 * @tparam[in] DBusInterface - DBus interface type
233 * @tparam[in] Handler - pldm::responder::platform::Handler
234 * @param[in] dBusIntf - The interface object of DBusInterface
235 * @param[in] handler - The interface object of
236 * pldm::responder::platform::Handler
237 * @param[in] effecterId - Effecter ID sent by the requester to act on
238 * @param[in] effecterDataSize - The bit width and format of the setting
239 * value for the effecter
240 * @param[in] effecter_value - The setting value of numeric effecter being
241 * requested.
242 * @param[in] effecterValueLength - The setting value length of numeric
243 * effecter being requested.
244 * @return - Success or failure in setting the states. Returns failure in
245 * terms of PLDM completion codes if atleast one state fails to be set
246 */
247template <class DBusInterface, class Handler>
248int setNumericEffecterValueHandler(const DBusInterface& dBusIntf,
249 Handler& handler, uint16_t effecterId,
250 uint8_t effecterDataSize,
251 uint8_t* effecterValue,
252 size_t effecterValueLength)
253{
254 constexpr auto effecterValueArrayLength = 4;
255 pldm_numeric_effecter_value_pdr* pdr = nullptr;
256
257 std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)>
258 numericEffecterPdrRepo(pldm_pdr_init(), pldm_pdr_destroy);
Brad Bishop5079ac42021-08-19 18:35:06 -0400259 pldm::responder::pdr_utils::Repo numericEffecterPDRs(
260 numericEffecterPdrRepo.get());
261 pldm::responder::pdr::getRepoByType(handler.getRepo(), numericEffecterPDRs,
262 PLDM_NUMERIC_EFFECTER_PDR);
George Liueccb0c52020-01-14 11:09:56 +0800263 if (numericEffecterPDRs.empty())
264 {
265 std::cerr << "The Numeric Effecter PDR repo is empty." << std::endl;
266 return PLDM_ERROR;
267 }
268
269 // Get the pdr structure of pldm_numeric_effecter_value_pdr according
270 // to the effecterId
Brad Bishop5079ac42021-08-19 18:35:06 -0400271 pldm::responder::pdr_utils::PdrEntry pdrEntry{};
George Liueccb0c52020-01-14 11:09:56 +0800272 auto pdrRecord = numericEffecterPDRs.getFirstRecord(pdrEntry);
273 while (pdrRecord)
274 {
275 pdr = reinterpret_cast<pldm_numeric_effecter_value_pdr*>(pdrEntry.data);
276 if (pdr->effecter_id != effecterId)
277 {
278 pdr = nullptr;
279 pdrRecord = numericEffecterPDRs.getNextRecord(pdrRecord, pdrEntry);
280 continue;
281 }
282
283 break;
284 }
285
286 if (!pdr)
287 {
288 return PLDM_PLATFORM_INVALID_EFFECTER_ID;
289 }
290
291 if (effecterValueLength != effecterValueArrayLength)
292 {
293 std::cerr << "effecter data size is incorrect.\n";
294 return PLDM_ERROR_INVALID_DATA;
295 }
296
George Liueccb0c52020-01-14 11:09:56 +0800297 try
298 {
George Liubd5e2ea2021-04-22 20:33:06 +0800299 const auto& [dbusMappings, dbusValMaps] =
300 handler.getDbusObjMaps(effecterId);
Brad Bishop5079ac42021-08-19 18:35:06 -0400301 pldm::utils::DBusMapping dbusMapping{
George Liubd5e2ea2021-04-22 20:33:06 +0800302 dbusMappings[0].objectPath, dbusMappings[0].interface,
303 dbusMappings[0].propertyName, dbusMappings[0].propertyType};
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500304
305 // convert to dbus effectervalue according to the factor
306 auto [rc, dbusValue] = convertToDbusValue(
307 pdr, effecterDataSize, effecterValue, dbusMappings[0].propertyType);
308 if (rc != PLDM_SUCCESS)
309 {
310 return rc;
311 }
George Liubd5e2ea2021-04-22 20:33:06 +0800312 try
313 {
314
315 dBusIntf.setDbusProperty(dbusMapping, dbusValue.value());
316 }
317 catch (const std::exception& e)
318 {
319 std::cerr << "Error setting property, ERROR=" << e.what()
320 << " PROPERTY=" << dbusMapping.propertyName
321 << " INTERFACE=" << dbusMapping.interface << " PATH="
322 << dbusMapping.objectPath << "\n";
323 return PLDM_ERROR;
324 }
George Liueccb0c52020-01-14 11:09:56 +0800325 }
George Liubd5e2ea2021-04-22 20:33:06 +0800326 catch (const std::out_of_range& e)
George Liueccb0c52020-01-14 11:09:56 +0800327 {
George Liubd5e2ea2021-04-22 20:33:06 +0800328 std::cerr << "Unknown effecter ID : " << effecterId << e.what() << '\n';
George Liueccb0c52020-01-14 11:09:56 +0800329 return PLDM_ERROR;
330 }
331
332 return PLDM_SUCCESS;
333}
334
335} // namespace platform_numeric_effecter
336} // namespace responder
337} // namespace pldm