blob: b01d6b0ba0a9036ba7108e94e91868e7afd749b6 [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
Riya Dixit49cfb132023-03-02 04:26:53 -060015#include <phosphor-logging/lg2.hpp>
16
George Liueccb0c52020-01-14 11:09:56 +080017#include <map>
18#include <optional>
19
Riya Dixit49cfb132023-03-02 04:26:53 -060020PHOSPHOR_LOG2_USING;
21
George Liueccb0c52020-01-14 11:09:56 +080022namespace pldm
23{
24namespace responder
25{
26namespace platform_numeric_effecter
27{
George Liueccb0c52020-01-14 11:09:56 +080028/** @brief Function to get the effecter value by PDR factor coefficient, etc.
29 * @param[in] pdr - The structure of pldm_numeric_effecter_value_pdr.
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -050030 * @param[in] effecterValue - effecter value.
31 * @param[in] propertyType - type of the D-Bus property.
George Liueccb0c52020-01-14 11:09:56 +080032 *
33 * @return - std::pair<int, std::optional<PropertyValue>> - rc:Success or
34 * failure, PropertyValue: The value to be set
35 */
36template <typename T>
Brad Bishop5079ac42021-08-19 18:35:06 -040037std::pair<int, std::optional<pldm::utils::PropertyValue>>
George Liueccb0c52020-01-14 11:09:56 +080038 getEffecterRawValue(const pldm_numeric_effecter_value_pdr* pdr,
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -050039 T& effecterValue, std::string propertyType)
George Liueccb0c52020-01-14 11:09:56 +080040{
41 // X = Round [ (Y - B) / m ]
42 // refer to DSP0248_1.2.0 27.8
43 int rc = 0;
Brad Bishop5079ac42021-08-19 18:35:06 -040044 pldm::utils::PropertyValue value;
George Liueccb0c52020-01-14 11:09:56 +080045 switch (pdr->effecter_data_size)
46 {
47 case PLDM_EFFECTER_DATA_SIZE_UINT8:
48 {
49 auto rawValue = static_cast<uint8_t>(
50 round(effecterValue - pdr->offset) / pdr->resolution);
Manojkiran Edafc0ce972022-06-25 09:38:28 +053051 if (pdr->min_settable.value_u8 < pdr->max_settable.value_u8 &&
52 (rawValue < pdr->min_settable.value_u8 ||
53 rawValue > pdr->max_settable.value_u8))
George Liueccb0c52020-01-14 11:09:56 +080054 {
55 rc = PLDM_ERROR_INVALID_DATA;
56 }
57 value = rawValue;
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -050058 if (propertyType == "uint64_t")
59 {
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -050060 auto tempValue = std::get<uint8_t>(value);
61 value = static_cast<uint64_t>(tempValue);
62 }
Sagar Srinivasdb436122021-10-20 06:44:07 -050063 else if (propertyType == "uint32_t")
64 {
65 auto tempValue = std::get<uint8_t>(value);
66 value = static_cast<uint32_t>(tempValue);
67 }
George Liueccb0c52020-01-14 11:09:56 +080068 break;
69 }
70 case PLDM_EFFECTER_DATA_SIZE_SINT8:
71 {
72 auto rawValue = static_cast<int8_t>(
73 round(effecterValue - pdr->offset) / pdr->resolution);
Manojkiran Edafc0ce972022-06-25 09:38:28 +053074 if (pdr->min_settable.value_s8 < pdr->max_settable.value_s8 &&
75 (rawValue < pdr->min_settable.value_s8 ||
76 rawValue > pdr->max_settable.value_s8))
George Liueccb0c52020-01-14 11:09:56 +080077 {
78 rc = PLDM_ERROR_INVALID_DATA;
79 }
80 value = rawValue;
81 break;
82 }
83 case PLDM_EFFECTER_DATA_SIZE_UINT16:
84 {
85 auto rawValue = static_cast<uint16_t>(
86 round(effecterValue - pdr->offset) / pdr->resolution);
Manojkiran Edafc0ce972022-06-25 09:38:28 +053087 if (pdr->min_settable.value_u16 < pdr->max_settable.value_u16 &&
88 (rawValue < pdr->min_settable.value_u16 ||
89 rawValue > pdr->max_settable.value_u16))
George Liueccb0c52020-01-14 11:09:56 +080090 {
91 rc = PLDM_ERROR_INVALID_DATA;
92 }
93 value = rawValue;
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -050094 if (propertyType == "uint64_t")
95 {
96 auto tempValue = std::get<uint16_t>(value);
97 value = static_cast<uint64_t>(tempValue);
98 }
Sagar Srinivasdb436122021-10-20 06:44:07 -050099 else if (propertyType == "uint32_t")
100 {
101 auto tempValue = std::get<uint16_t>(value);
102 value = static_cast<uint32_t>(tempValue);
103 }
George Liueccb0c52020-01-14 11:09:56 +0800104 break;
105 }
106 case PLDM_EFFECTER_DATA_SIZE_SINT16:
107 {
108 auto rawValue = static_cast<int16_t>(
109 round(effecterValue - pdr->offset) / pdr->resolution);
Manojkiran Edafc0ce972022-06-25 09:38:28 +0530110 if (pdr->min_settable.value_s16 < pdr->max_settable.value_s16 &&
111 (rawValue < pdr->min_settable.value_s16 ||
112 rawValue > pdr->max_settable.value_s16))
George Liueccb0c52020-01-14 11:09:56 +0800113 {
114 rc = PLDM_ERROR_INVALID_DATA;
115 }
116 value = rawValue;
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500117 if (propertyType == "uint64_t")
118 {
119 auto tempValue = std::get<int16_t>(value);
120 value = static_cast<uint64_t>(tempValue);
121 }
Sagar Srinivasdb436122021-10-20 06:44:07 -0500122 else if (propertyType == "uint32_t")
123 {
124 auto tempValue = std::get<int16_t>(value);
125 value = static_cast<uint32_t>(tempValue);
126 }
George Liueccb0c52020-01-14 11:09:56 +0800127 break;
128 }
129 case PLDM_EFFECTER_DATA_SIZE_UINT32:
130 {
131 auto rawValue = static_cast<uint32_t>(
132 round(effecterValue - pdr->offset) / pdr->resolution);
Manojkiran Edafc0ce972022-06-25 09:38:28 +0530133 if (pdr->min_settable.value_u32 < pdr->max_settable.value_u32 &&
134 (rawValue < pdr->min_settable.value_u32 ||
135 rawValue > pdr->max_settable.value_u32))
George Liueccb0c52020-01-14 11:09:56 +0800136 {
137 rc = PLDM_ERROR_INVALID_DATA;
138 }
139 value = rawValue;
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500140 if (propertyType == "uint64_t")
141 {
142 auto tempValue = std::get<uint32_t>(value);
143 value = static_cast<uint64_t>(tempValue);
144 }
Sagar Srinivasdb436122021-10-20 06:44:07 -0500145 else if (propertyType == "uint32_t")
146 {
147 auto tempValue = std::get<uint32_t>(value);
148 value = static_cast<uint32_t>(tempValue);
149 }
George Liueccb0c52020-01-14 11:09:56 +0800150 break;
151 }
152 case PLDM_EFFECTER_DATA_SIZE_SINT32:
153 {
154 auto rawValue = static_cast<int32_t>(
155 round(effecterValue - pdr->offset) / pdr->resolution);
Manojkiran Edafc0ce972022-06-25 09:38:28 +0530156 if (pdr->min_settable.value_s32 < pdr->max_settable.value_s32 &&
157 (rawValue < pdr->min_settable.value_s32 ||
158 rawValue > pdr->max_settable.value_s32))
George Liueccb0c52020-01-14 11:09:56 +0800159 {
160 rc = PLDM_ERROR_INVALID_DATA;
161 }
162 value = rawValue;
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500163 if (propertyType == "uint64_t")
164 {
165 auto tempValue = std::get<int32_t>(value);
166 value = static_cast<uint64_t>(tempValue);
167 }
Sagar Srinivasdb436122021-10-20 06:44:07 -0500168 else if (propertyType == "uint32_t")
169 {
170 auto tempValue = std::get<int32_t>(value);
171 value = static_cast<uint32_t>(tempValue);
172 }
George Liueccb0c52020-01-14 11:09:56 +0800173 break;
174 }
175 }
176
177 return {rc, std::make_optional(std::move(value))};
178}
179
180/** @brief Function to convert the D-Bus value by PDR factor and effecter value.
181 * @param[in] pdr - The structure of pldm_numeric_effecter_value_pdr.
182 * @param[in] effecterDataSize - effecter value size.
183 * @param[in,out] effecterValue - effecter value.
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500184 * @param[in] propertyType - type of the D-Bus property.
George Liueccb0c52020-01-14 11:09:56 +0800185 *
186 * @return std::pair<int, std::optional<PropertyValue>> - rc:Success or
187 * failure, PropertyValue: The value to be set
188 */
Brad Bishop5079ac42021-08-19 18:35:06 -0400189std::pair<int, std::optional<pldm::utils::PropertyValue>>
George Liueccb0c52020-01-14 11:09:56 +0800190 convertToDbusValue(const pldm_numeric_effecter_value_pdr* pdr,
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500191 uint8_t effecterDataSize, uint8_t* effecterValue,
192 std::string propertyType)
George Liueccb0c52020-01-14 11:09:56 +0800193{
194 if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT8)
195 {
196 uint8_t currentValue = *(reinterpret_cast<uint8_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500197 return getEffecterRawValue<uint8_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800198 }
199 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT8)
200 {
201 int8_t currentValue = *(reinterpret_cast<int8_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500202 return getEffecterRawValue<int8_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800203 }
204 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT16)
205 {
206 uint16_t currentValue =
207 *(reinterpret_cast<uint16_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500208 return getEffecterRawValue<uint16_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800209 }
210 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT16)
211 {
212 int16_t currentValue = *(reinterpret_cast<int16_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500213 return getEffecterRawValue<int16_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800214 }
215 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT32)
216 {
217 uint32_t currentValue =
218 *(reinterpret_cast<uint32_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500219 return getEffecterRawValue<uint32_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800220 }
221 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT32)
222 {
223 int32_t currentValue = *(reinterpret_cast<int32_t*>(&effecterValue[0]));
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500224 return getEffecterRawValue<int32_t>(pdr, currentValue, propertyType);
George Liueccb0c52020-01-14 11:09:56 +0800225 }
226 else
227 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600228 error("Wrong field effecterDataSize...");
George Liueccb0c52020-01-14 11:09:56 +0800229 return {PLDM_ERROR, {}};
230 }
231}
232
233/** @brief Function to set the effecter value requested by pldm requester
234 * @tparam[in] DBusInterface - DBus interface type
235 * @tparam[in] Handler - pldm::responder::platform::Handler
236 * @param[in] dBusIntf - The interface object of DBusInterface
237 * @param[in] handler - The interface object of
238 * pldm::responder::platform::Handler
239 * @param[in] effecterId - Effecter ID sent by the requester to act on
240 * @param[in] effecterDataSize - The bit width and format of the setting
241 * value for the effecter
242 * @param[in] effecter_value - The setting value of numeric effecter being
243 * requested.
244 * @param[in] effecterValueLength - The setting value length of numeric
245 * effecter being requested.
246 * @return - Success or failure in setting the states. Returns failure in
247 * terms of PLDM completion codes if atleast one state fails to be set
248 */
249template <class DBusInterface, class Handler>
250int setNumericEffecterValueHandler(const DBusInterface& dBusIntf,
251 Handler& handler, uint16_t effecterId,
252 uint8_t effecterDataSize,
253 uint8_t* effecterValue,
254 size_t effecterValueLength)
255{
256 constexpr auto effecterValueArrayLength = 4;
257 pldm_numeric_effecter_value_pdr* pdr = nullptr;
258
259 std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)>
260 numericEffecterPdrRepo(pldm_pdr_init(), pldm_pdr_destroy);
Brad Bishop5079ac42021-08-19 18:35:06 -0400261 pldm::responder::pdr_utils::Repo numericEffecterPDRs(
262 numericEffecterPdrRepo.get());
263 pldm::responder::pdr::getRepoByType(handler.getRepo(), numericEffecterPDRs,
264 PLDM_NUMERIC_EFFECTER_PDR);
George Liueccb0c52020-01-14 11:09:56 +0800265 if (numericEffecterPDRs.empty())
266 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600267 error("The Numeric Effecter PDR repo is empty.");
George Liueccb0c52020-01-14 11:09:56 +0800268 return PLDM_ERROR;
269 }
270
271 // Get the pdr structure of pldm_numeric_effecter_value_pdr according
272 // to the effecterId
Brad Bishop5079ac42021-08-19 18:35:06 -0400273 pldm::responder::pdr_utils::PdrEntry pdrEntry{};
George Liueccb0c52020-01-14 11:09:56 +0800274 auto pdrRecord = numericEffecterPDRs.getFirstRecord(pdrEntry);
275 while (pdrRecord)
276 {
277 pdr = reinterpret_cast<pldm_numeric_effecter_value_pdr*>(pdrEntry.data);
278 if (pdr->effecter_id != effecterId)
279 {
280 pdr = nullptr;
281 pdrRecord = numericEffecterPDRs.getNextRecord(pdrRecord, pdrEntry);
282 continue;
283 }
284
285 break;
286 }
287
288 if (!pdr)
289 {
290 return PLDM_PLATFORM_INVALID_EFFECTER_ID;
291 }
292
293 if (effecterValueLength != effecterValueArrayLength)
294 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600295 error("effecter data size is incorrect.");
George Liueccb0c52020-01-14 11:09:56 +0800296 return PLDM_ERROR_INVALID_DATA;
297 }
298
George Liueccb0c52020-01-14 11:09:56 +0800299 try
300 {
George Liubd5e2ea2021-04-22 20:33:06 +0800301 const auto& [dbusMappings, dbusValMaps] =
302 handler.getDbusObjMaps(effecterId);
Brad Bishop5079ac42021-08-19 18:35:06 -0400303 pldm::utils::DBusMapping dbusMapping{
George Liubd5e2ea2021-04-22 20:33:06 +0800304 dbusMappings[0].objectPath, dbusMappings[0].interface,
305 dbusMappings[0].propertyName, dbusMappings[0].propertyType};
Pavithra Barithaya45cd16b2021-07-01 08:19:59 -0500306
307 // convert to dbus effectervalue according to the factor
308 auto [rc, dbusValue] = convertToDbusValue(
309 pdr, effecterDataSize, effecterValue, dbusMappings[0].propertyType);
310 if (rc != PLDM_SUCCESS)
311 {
312 return rc;
313 }
George Liubd5e2ea2021-04-22 20:33:06 +0800314 try
315 {
George Liubd5e2ea2021-04-22 20:33:06 +0800316 dBusIntf.setDbusProperty(dbusMapping, dbusValue.value());
317 }
318 catch (const std::exception& e)
319 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600320 error(
321 "Error setting property, ERROR={ERR_EXCEP} PROPERTY={DBUS_PROP} INTERFACE={DBUS_INTF} PATH={DBUS_OBJ_PATH}",
322 "ERR_EXCEP", e.what(), "DBUS_PROP", dbusMapping.propertyName,
323 "DBUS_INTF", dbusMapping.interface, "DBUS_OBJ_PATH",
324 dbusMapping.objectPath.c_str());
George Liubd5e2ea2021-04-22 20:33:06 +0800325 return PLDM_ERROR;
326 }
George Liueccb0c52020-01-14 11:09:56 +0800327 }
George Liubd5e2ea2021-04-22 20:33:06 +0800328 catch (const std::out_of_range& e)
George Liueccb0c52020-01-14 11:09:56 +0800329 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600330 error("Unknown effecter ID : {EFFECTER_ID} {ERR_EXCEP}", "EFFECTER_ID",
331 effecterId, "ERR_EXCEP", e.what());
George Liueccb0c52020-01-14 11:09:56 +0800332 return PLDM_ERROR;
333 }
334
335 return PLDM_SUCCESS;
336}
337
338} // namespace platform_numeric_effecter
339} // namespace responder
340} // namespace pldm