blob: b9195163c4d372a23640dff486505cef002fe145 [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 {
58 std::cerr << " Inside if when propertytype is uint64_t"
59 << std::endl;
60 auto tempValue = std::get<uint8_t>(value);
61 value = static_cast<uint64_t>(tempValue);
62 }
George Liueccb0c52020-01-14 11:09:56 +080063 break;
64 }
65 case PLDM_EFFECTER_DATA_SIZE_SINT8:
66 {
67 auto rawValue = static_cast<int8_t>(
68 round(effecterValue - pdr->offset) / pdr->resolution);
69 if (pdr->min_set_table.value_s8 < pdr->max_set_table.value_s8 &&
70 (rawValue < pdr->min_set_table.value_s8 ||
71 rawValue > pdr->max_set_table.value_s8))
72 {
73 rc = PLDM_ERROR_INVALID_DATA;
74 }
75 value = rawValue;
76 break;
77 }
78 case PLDM_EFFECTER_DATA_SIZE_UINT16:
79 {
80 auto rawValue = static_cast<uint16_t>(
81 round(effecterValue - pdr->offset) / pdr->resolution);
82 if (pdr->min_set_table.value_u16 < pdr->max_set_table.value_u16 &&
83 (rawValue < pdr->min_set_table.value_u16 ||
84 rawValue > pdr->max_set_table.value_u16))
85 {
86 rc = PLDM_ERROR_INVALID_DATA;
87 }
88 value = rawValue;
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -050089 if (propertyType == "uint64_t")
90 {
91 auto tempValue = std::get<uint16_t>(value);
92 value = static_cast<uint64_t>(tempValue);
93 }
George Liueccb0c52020-01-14 11:09:56 +080094 break;
95 }
96 case PLDM_EFFECTER_DATA_SIZE_SINT16:
97 {
98 auto rawValue = static_cast<int16_t>(
99 round(effecterValue - pdr->offset) / pdr->resolution);
100 if (pdr->min_set_table.value_s16 < pdr->max_set_table.value_s16 &&
101 (rawValue < pdr->min_set_table.value_s16 ||
102 rawValue > pdr->max_set_table.value_s16))
103 {
104 rc = PLDM_ERROR_INVALID_DATA;
105 }
106 value = rawValue;
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500107 if (propertyType == "uint64_t")
108 {
109 auto tempValue = std::get<int16_t>(value);
110 value = static_cast<uint64_t>(tempValue);
111 }
George Liueccb0c52020-01-14 11:09:56 +0800112 break;
113 }
114 case PLDM_EFFECTER_DATA_SIZE_UINT32:
115 {
116 auto rawValue = static_cast<uint32_t>(
117 round(effecterValue - pdr->offset) / pdr->resolution);
118 if (pdr->min_set_table.value_u32 < pdr->max_set_table.value_u32 &&
119 (rawValue < pdr->min_set_table.value_u32 ||
120 rawValue > pdr->max_set_table.value_u32))
121 {
122 rc = PLDM_ERROR_INVALID_DATA;
123 }
124 value = rawValue;
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500125 if (propertyType == "uint64_t")
126 {
127 auto tempValue = std::get<uint32_t>(value);
128 value = static_cast<uint64_t>(tempValue);
129 }
George Liueccb0c52020-01-14 11:09:56 +0800130 break;
131 }
132 case PLDM_EFFECTER_DATA_SIZE_SINT32:
133 {
134 auto rawValue = static_cast<int32_t>(
135 round(effecterValue - pdr->offset) / pdr->resolution);
136 if (pdr->min_set_table.value_s32 < pdr->max_set_table.value_s32 &&
137 (rawValue < pdr->min_set_table.value_s32 ||
138 rawValue > pdr->max_set_table.value_s32))
139 {
140 rc = PLDM_ERROR_INVALID_DATA;
141 }
142 value = rawValue;
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500143 if (propertyType == "uint64_t")
144 {
145 auto tempValue = std::get<int32_t>(value);
146 value = static_cast<uint64_t>(tempValue);
147 }
George Liueccb0c52020-01-14 11:09:56 +0800148 break;
149 }
150 }
151
152 return {rc, std::make_optional(std::move(value))};
153}
154
155/** @brief Function to convert the D-Bus value by PDR factor and effecter value.
156 * @param[in] pdr - The structure of pldm_numeric_effecter_value_pdr.
157 * @param[in] effecterDataSize - effecter value size.
158 * @param[in,out] effecterValue - effecter value.
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500159 * @param[in] propertyType - type of the D-Bus property.
George Liueccb0c52020-01-14 11:09:56 +0800160 *
161 * @return std::pair<int, std::optional<PropertyValue>> - rc:Success or
162 * failure, PropertyValue: The value to be set
163 */
Brad Bishop5079ac42021-08-19 18:35:06 -0400164std::pair<int, std::optional<pldm::utils::PropertyValue>>
George Liueccb0c52020-01-14 11:09:56 +0800165 convertToDbusValue(const pldm_numeric_effecter_value_pdr* pdr,
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500166 uint8_t effecterDataSize, uint8_t* effecterValue,
167 std::string propertyType)
George Liueccb0c52020-01-14 11:09:56 +0800168{
169 if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT8)
170 {
171 uint8_t currentValue = *(reinterpret_cast<uint8_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500172 return getEffecterRawValue<uint8_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800173 }
174 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT8)
175 {
176 int8_t currentValue = *(reinterpret_cast<int8_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500177 return getEffecterRawValue<int8_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800178 }
179 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT16)
180 {
181 uint16_t currentValue =
182 *(reinterpret_cast<uint16_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500183 return getEffecterRawValue<uint16_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800184 }
185 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT16)
186 {
187 int16_t currentValue = *(reinterpret_cast<int16_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500188 return getEffecterRawValue<int16_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800189 }
190 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT32)
191 {
192 uint32_t currentValue =
193 *(reinterpret_cast<uint32_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500194 return getEffecterRawValue<uint32_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800195 }
196 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT32)
197 {
198 int32_t currentValue = *(reinterpret_cast<int32_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500199 return getEffecterRawValue<int32_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800200 }
201 else
202 {
203 std::cerr << "Wrong field effecterDataSize...\n";
204 return {PLDM_ERROR, {}};
205 }
206}
207
208/** @brief Function to set the effecter value requested by pldm requester
209 * @tparam[in] DBusInterface - DBus interface type
210 * @tparam[in] Handler - pldm::responder::platform::Handler
211 * @param[in] dBusIntf - The interface object of DBusInterface
212 * @param[in] handler - The interface object of
213 * pldm::responder::platform::Handler
214 * @param[in] effecterId - Effecter ID sent by the requester to act on
215 * @param[in] effecterDataSize - The bit width and format of the setting
216 * value for the effecter
217 * @param[in] effecter_value - The setting value of numeric effecter being
218 * requested.
219 * @param[in] effecterValueLength - The setting value length of numeric
220 * effecter being requested.
221 * @return - Success or failure in setting the states. Returns failure in
222 * terms of PLDM completion codes if atleast one state fails to be set
223 */
224template <class DBusInterface, class Handler>
225int setNumericEffecterValueHandler(const DBusInterface& dBusIntf,
226 Handler& handler, uint16_t effecterId,
227 uint8_t effecterDataSize,
228 uint8_t* effecterValue,
229 size_t effecterValueLength)
230{
231 constexpr auto effecterValueArrayLength = 4;
232 pldm_numeric_effecter_value_pdr* pdr = nullptr;
233
234 std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)>
235 numericEffecterPdrRepo(pldm_pdr_init(), pldm_pdr_destroy);
Brad Bishop5079ac42021-08-19 18:35:06 -0400236 pldm::responder::pdr_utils::Repo numericEffecterPDRs(
237 numericEffecterPdrRepo.get());
238 pldm::responder::pdr::getRepoByType(handler.getRepo(), numericEffecterPDRs,
239 PLDM_NUMERIC_EFFECTER_PDR);
George Liueccb0c52020-01-14 11:09:56 +0800240 if (numericEffecterPDRs.empty())
241 {
242 std::cerr << "The Numeric Effecter PDR repo is empty." << std::endl;
243 return PLDM_ERROR;
244 }
245
246 // Get the pdr structure of pldm_numeric_effecter_value_pdr according
247 // to the effecterId
Brad Bishop5079ac42021-08-19 18:35:06 -0400248 pldm::responder::pdr_utils::PdrEntry pdrEntry{};
George Liueccb0c52020-01-14 11:09:56 +0800249 auto pdrRecord = numericEffecterPDRs.getFirstRecord(pdrEntry);
250 while (pdrRecord)
251 {
252 pdr = reinterpret_cast<pldm_numeric_effecter_value_pdr*>(pdrEntry.data);
253 if (pdr->effecter_id != effecterId)
254 {
255 pdr = nullptr;
256 pdrRecord = numericEffecterPDRs.getNextRecord(pdrRecord, pdrEntry);
257 continue;
258 }
259
260 break;
261 }
262
263 if (!pdr)
264 {
265 return PLDM_PLATFORM_INVALID_EFFECTER_ID;
266 }
267
268 if (effecterValueLength != effecterValueArrayLength)
269 {
270 std::cerr << "effecter data size is incorrect.\n";
271 return PLDM_ERROR_INVALID_DATA;
272 }
273
George Liueccb0c52020-01-14 11:09:56 +0800274 try
275 {
George Liubd5e2ea2021-04-22 20:33:06 +0800276 const auto& [dbusMappings, dbusValMaps] =
277 handler.getDbusObjMaps(effecterId);
Brad Bishop5079ac42021-08-19 18:35:06 -0400278 pldm::utils::DBusMapping dbusMapping{
George Liubd5e2ea2021-04-22 20:33:06 +0800279 dbusMappings[0].objectPath, dbusMappings[0].interface,
280 dbusMappings[0].propertyName, dbusMappings[0].propertyType};
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500281
282 // convert to dbus effectervalue according to the factor
283 auto [rc, dbusValue] = convertToDbusValue(
284 pdr, effecterDataSize, effecterValue, dbusMappings[0].propertyType);
285 if (rc != PLDM_SUCCESS)
286 {
287 return rc;
288 }
George Liubd5e2ea2021-04-22 20:33:06 +0800289 try
290 {
291
292 dBusIntf.setDbusProperty(dbusMapping, dbusValue.value());
293 }
294 catch (const std::exception& e)
295 {
296 std::cerr << "Error setting property, ERROR=" << e.what()
297 << " PROPERTY=" << dbusMapping.propertyName
298 << " INTERFACE=" << dbusMapping.interface << " PATH="
299 << dbusMapping.objectPath << "\n";
300 return PLDM_ERROR;
301 }
George Liueccb0c52020-01-14 11:09:56 +0800302 }
George Liubd5e2ea2021-04-22 20:33:06 +0800303 catch (const std::out_of_range& e)
George Liueccb0c52020-01-14 11:09:56 +0800304 {
George Liubd5e2ea2021-04-22 20:33:06 +0800305 std::cerr << "Unknown effecter ID : " << effecterId << e.what() << '\n';
George Liueccb0c52020-01-14 11:09:56 +0800306 return PLDM_ERROR;
307 }
308
309 return PLDM_SUCCESS;
310}
311
312} // namespace platform_numeric_effecter
313} // namespace responder
314} // namespace pldm