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