blob: 76c22672e5909ac2e7244d5189d4e53f3cdad0cd [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
George Liueccb0c52020-01-14 11:09:56 +08008#include "handler.hpp"
9#include "libpldmresponder/pdr.hpp"
10#include "pdr_utils.hpp"
11#include "utils.hpp"
12
13#include <math.h>
14#include <stdint.h>
15
16#include <map>
17#include <optional>
18
George Liueccb0c52020-01-14 11:09:56 +080019using namespace pldm::responder::pdr;
20using namespace pldm::utils;
21
22namespace pldm
23{
24namespace responder
25{
26namespace platform_numeric_effecter
27{
28
29/** @brief Function to get the effecter value by PDR factor coefficient, etc.
30 * @param[in] pdr - The structure of pldm_numeric_effecter_value_pdr.
31 * @tparam[in] effecterValue - effecter value.
32 *
33 * @return - std::pair<int, std::optional<PropertyValue>> - rc:Success or
34 * failure, PropertyValue: The value to be set
35 */
36template <typename T>
37std::pair<int, std::optional<PropertyValue>>
38 getEffecterRawValue(const pldm_numeric_effecter_value_pdr* pdr,
39 T& effecterValue)
40{
41 // X = Round [ (Y - B) / m ]
42 // refer to DSP0248_1.2.0 27.8
43 int rc = 0;
44 PropertyValue value;
45 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);
51 if (pdr->min_set_table.value_u8 < pdr->max_set_table.value_u8 &&
52 (rawValue < pdr->min_set_table.value_u8 ||
53 rawValue > pdr->max_set_table.value_u8))
54 {
55 rc = PLDM_ERROR_INVALID_DATA;
56 }
57 value = rawValue;
58 break;
59 }
60 case PLDM_EFFECTER_DATA_SIZE_SINT8:
61 {
62 auto rawValue = static_cast<int8_t>(
63 round(effecterValue - pdr->offset) / pdr->resolution);
64 if (pdr->min_set_table.value_s8 < pdr->max_set_table.value_s8 &&
65 (rawValue < pdr->min_set_table.value_s8 ||
66 rawValue > pdr->max_set_table.value_s8))
67 {
68 rc = PLDM_ERROR_INVALID_DATA;
69 }
70 value = rawValue;
71 break;
72 }
73 case PLDM_EFFECTER_DATA_SIZE_UINT16:
74 {
75 auto rawValue = static_cast<uint16_t>(
76 round(effecterValue - pdr->offset) / pdr->resolution);
77 if (pdr->min_set_table.value_u16 < pdr->max_set_table.value_u16 &&
78 (rawValue < pdr->min_set_table.value_u16 ||
79 rawValue > pdr->max_set_table.value_u16))
80 {
81 rc = PLDM_ERROR_INVALID_DATA;
82 }
83 value = rawValue;
84 break;
85 }
86 case PLDM_EFFECTER_DATA_SIZE_SINT16:
87 {
88 auto rawValue = static_cast<int16_t>(
89 round(effecterValue - pdr->offset) / pdr->resolution);
90 if (pdr->min_set_table.value_s16 < pdr->max_set_table.value_s16 &&
91 (rawValue < pdr->min_set_table.value_s16 ||
92 rawValue > pdr->max_set_table.value_s16))
93 {
94 rc = PLDM_ERROR_INVALID_DATA;
95 }
96 value = rawValue;
97 break;
98 }
99 case PLDM_EFFECTER_DATA_SIZE_UINT32:
100 {
101 auto rawValue = static_cast<uint32_t>(
102 round(effecterValue - pdr->offset) / pdr->resolution);
103 if (pdr->min_set_table.value_u32 < pdr->max_set_table.value_u32 &&
104 (rawValue < pdr->min_set_table.value_u32 ||
105 rawValue > pdr->max_set_table.value_u32))
106 {
107 rc = PLDM_ERROR_INVALID_DATA;
108 }
109 value = rawValue;
110 break;
111 }
112 case PLDM_EFFECTER_DATA_SIZE_SINT32:
113 {
114 auto rawValue = static_cast<int32_t>(
115 round(effecterValue - pdr->offset) / pdr->resolution);
116 if (pdr->min_set_table.value_s32 < pdr->max_set_table.value_s32 &&
117 (rawValue < pdr->min_set_table.value_s32 ||
118 rawValue > pdr->max_set_table.value_s32))
119 {
120 rc = PLDM_ERROR_INVALID_DATA;
121 }
122 value = rawValue;
123 break;
124 }
125 }
126
127 return {rc, std::make_optional(std::move(value))};
128}
129
130/** @brief Function to convert the D-Bus value by PDR factor and effecter value.
131 * @param[in] pdr - The structure of pldm_numeric_effecter_value_pdr.
132 * @param[in] effecterDataSize - effecter value size.
133 * @param[in,out] effecterValue - effecter value.
134 *
135 * @return std::pair<int, std::optional<PropertyValue>> - rc:Success or
136 * failure, PropertyValue: The value to be set
137 */
138std::pair<int, std::optional<PropertyValue>>
139 convertToDbusValue(const pldm_numeric_effecter_value_pdr* pdr,
140 uint8_t effecterDataSize, uint8_t* effecterValue)
141{
142 if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT8)
143 {
144 uint8_t currentValue = *(reinterpret_cast<uint8_t*>(&effecterValue[0]));
145 return getEffecterRawValue<uint8_t>(pdr, currentValue);
146 }
147 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT8)
148 {
149 int8_t currentValue = *(reinterpret_cast<int8_t*>(&effecterValue[0]));
150 return getEffecterRawValue<int8_t>(pdr, currentValue);
151 }
152 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT16)
153 {
154 uint16_t currentValue =
155 *(reinterpret_cast<uint16_t*>(&effecterValue[0]));
156 return getEffecterRawValue<uint16_t>(pdr, currentValue);
157 }
158 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT16)
159 {
160 int16_t currentValue = *(reinterpret_cast<int16_t*>(&effecterValue[0]));
161 return getEffecterRawValue<int16_t>(pdr, currentValue);
162 }
163 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT32)
164 {
165 uint32_t currentValue =
166 *(reinterpret_cast<uint32_t*>(&effecterValue[0]));
167 return getEffecterRawValue<uint32_t>(pdr, currentValue);
168 }
169 else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT32)
170 {
171 int32_t currentValue = *(reinterpret_cast<int32_t*>(&effecterValue[0]));
172 return getEffecterRawValue<int32_t>(pdr, currentValue);
173 }
174 else
175 {
176 std::cerr << "Wrong field effecterDataSize...\n";
177 return {PLDM_ERROR, {}};
178 }
179}
180
181/** @brief Function to set the effecter value requested by pldm requester
182 * @tparam[in] DBusInterface - DBus interface type
183 * @tparam[in] Handler - pldm::responder::platform::Handler
184 * @param[in] dBusIntf - The interface object of DBusInterface
185 * @param[in] handler - The interface object of
186 * pldm::responder::platform::Handler
187 * @param[in] effecterId - Effecter ID sent by the requester to act on
188 * @param[in] effecterDataSize - The bit width and format of the setting
189 * value for the effecter
190 * @param[in] effecter_value - The setting value of numeric effecter being
191 * requested.
192 * @param[in] effecterValueLength - The setting value length of numeric
193 * effecter being requested.
194 * @return - Success or failure in setting the states. Returns failure in
195 * terms of PLDM completion codes if atleast one state fails to be set
196 */
197template <class DBusInterface, class Handler>
198int setNumericEffecterValueHandler(const DBusInterface& dBusIntf,
199 Handler& handler, uint16_t effecterId,
200 uint8_t effecterDataSize,
201 uint8_t* effecterValue,
202 size_t effecterValueLength)
203{
204 constexpr auto effecterValueArrayLength = 4;
205 pldm_numeric_effecter_value_pdr* pdr = nullptr;
206
207 std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)>
208 numericEffecterPdrRepo(pldm_pdr_init(), pldm_pdr_destroy);
209 Repo numericEffecterPDRs(numericEffecterPdrRepo.get());
210 getRepoByType(handler.getRepo(), numericEffecterPDRs,
211 PLDM_NUMERIC_EFFECTER_PDR);
212 if (numericEffecterPDRs.empty())
213 {
214 std::cerr << "The Numeric Effecter PDR repo is empty." << std::endl;
215 return PLDM_ERROR;
216 }
217
218 // Get the pdr structure of pldm_numeric_effecter_value_pdr according
219 // to the effecterId
220 PdrEntry pdrEntry{};
221 auto pdrRecord = numericEffecterPDRs.getFirstRecord(pdrEntry);
222 while (pdrRecord)
223 {
224 pdr = reinterpret_cast<pldm_numeric_effecter_value_pdr*>(pdrEntry.data);
225 if (pdr->effecter_id != effecterId)
226 {
227 pdr = nullptr;
228 pdrRecord = numericEffecterPDRs.getNextRecord(pdrRecord, pdrEntry);
229 continue;
230 }
231
232 break;
233 }
234
235 if (!pdr)
236 {
237 return PLDM_PLATFORM_INVALID_EFFECTER_ID;
238 }
239
240 if (effecterValueLength != effecterValueArrayLength)
241 {
242 std::cerr << "effecter data size is incorrect.\n";
243 return PLDM_ERROR_INVALID_DATA;
244 }
245
246 // convert to dbus effectervalue according to the factor
247 auto [rc, dbusValue] =
248 convertToDbusValue(pdr, effecterDataSize, effecterValue);
249 if (rc != PLDM_SUCCESS)
250 {
251 return rc;
252 }
253
254 const auto& [dbusMappings, dbusValMaps] =
255 handler.getDbusObjMaps(effecterId);
256 DBusMapping dbusMapping{
257 dbusMappings[0].objectPath, dbusMappings[0].interface,
258 dbusMappings[0].propertyName, dbusMappings[0].propertyType};
259 try
260 {
261 dBusIntf.setDbusProperty(dbusMapping, dbusValue.value());
262 }
263 catch (const std::exception& e)
264 {
265 std::cerr << "Error setting property, ERROR=" << e.what()
266 << " PROPERTY=" << dbusMapping.propertyName << " INTERFACE="
267 << dbusMapping.interface << " PATH=" << dbusMapping.objectPath
268 << "\n";
269 return PLDM_ERROR;
270 }
271
272 return PLDM_SUCCESS;
273}
274
275} // namespace platform_numeric_effecter
276} // namespace responder
277} // namespace pldm