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