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