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