#pragma once #include "config.h" #include "libpldm/platform.h" #include "libpldm/states.h" #include "common/utils.hpp" #include "libpldmresponder/pdr.hpp" #include "pdr_utils.hpp" #include "pldmd/handler.hpp" #include #include #include #include namespace pldm { namespace responder { namespace platform_numeric_effecter { /** @brief Function to get the effecter value by PDR factor coefficient, etc. * @param[in] pdr - The structure of pldm_numeric_effecter_value_pdr. * @param[in] effecterValue - effecter value. * @param[in] propertyType - type of the D-Bus property. * * @return - std::pair> - rc:Success or * failure, PropertyValue: The value to be set */ template std::pair> getEffecterRawValue(const pldm_numeric_effecter_value_pdr* pdr, T& effecterValue, std::string propertyType) { // X = Round [ (Y - B) / m ] // refer to DSP0248_1.2.0 27.8 int rc = 0; pldm::utils::PropertyValue value; switch (pdr->effecter_data_size) { case PLDM_EFFECTER_DATA_SIZE_UINT8: { auto rawValue = static_cast( round(effecterValue - pdr->offset) / pdr->resolution); if (pdr->min_set_table.value_u8 < pdr->max_set_table.value_u8 && (rawValue < pdr->min_set_table.value_u8 || rawValue > pdr->max_set_table.value_u8)) { rc = PLDM_ERROR_INVALID_DATA; } value = rawValue; if (propertyType == "uint64_t") { auto tempValue = std::get(value); value = static_cast(tempValue); } break; } case PLDM_EFFECTER_DATA_SIZE_SINT8: { auto rawValue = static_cast( round(effecterValue - pdr->offset) / pdr->resolution); if (pdr->min_set_table.value_s8 < pdr->max_set_table.value_s8 && (rawValue < pdr->min_set_table.value_s8 || rawValue > pdr->max_set_table.value_s8)) { rc = PLDM_ERROR_INVALID_DATA; } value = rawValue; break; } case PLDM_EFFECTER_DATA_SIZE_UINT16: { auto rawValue = static_cast( round(effecterValue - pdr->offset) / pdr->resolution); if (pdr->min_set_table.value_u16 < pdr->max_set_table.value_u16 && (rawValue < pdr->min_set_table.value_u16 || rawValue > pdr->max_set_table.value_u16)) { rc = PLDM_ERROR_INVALID_DATA; } value = rawValue; if (propertyType == "uint64_t") { auto tempValue = std::get(value); value = static_cast(tempValue); } break; } case PLDM_EFFECTER_DATA_SIZE_SINT16: { auto rawValue = static_cast( round(effecterValue - pdr->offset) / pdr->resolution); if (pdr->min_set_table.value_s16 < pdr->max_set_table.value_s16 && (rawValue < pdr->min_set_table.value_s16 || rawValue > pdr->max_set_table.value_s16)) { rc = PLDM_ERROR_INVALID_DATA; } value = rawValue; if (propertyType == "uint64_t") { auto tempValue = std::get(value); value = static_cast(tempValue); } break; } case PLDM_EFFECTER_DATA_SIZE_UINT32: { auto rawValue = static_cast( round(effecterValue - pdr->offset) / pdr->resolution); if (pdr->min_set_table.value_u32 < pdr->max_set_table.value_u32 && (rawValue < pdr->min_set_table.value_u32 || rawValue > pdr->max_set_table.value_u32)) { rc = PLDM_ERROR_INVALID_DATA; } value = rawValue; if (propertyType == "uint64_t") { auto tempValue = std::get(value); value = static_cast(tempValue); } break; } case PLDM_EFFECTER_DATA_SIZE_SINT32: { auto rawValue = static_cast( round(effecterValue - pdr->offset) / pdr->resolution); if (pdr->min_set_table.value_s32 < pdr->max_set_table.value_s32 && (rawValue < pdr->min_set_table.value_s32 || rawValue > pdr->max_set_table.value_s32)) { rc = PLDM_ERROR_INVALID_DATA; } value = rawValue; if (propertyType == "uint64_t") { auto tempValue = std::get(value); value = static_cast(tempValue); } break; } } return {rc, std::make_optional(std::move(value))}; } /** @brief Function to convert the D-Bus value by PDR factor and effecter value. * @param[in] pdr - The structure of pldm_numeric_effecter_value_pdr. * @param[in] effecterDataSize - effecter value size. * @param[in,out] effecterValue - effecter value. * @param[in] propertyType - type of the D-Bus property. * * @return std::pair> - rc:Success or * failure, PropertyValue: The value to be set */ std::pair> convertToDbusValue(const pldm_numeric_effecter_value_pdr* pdr, uint8_t effecterDataSize, uint8_t* effecterValue, std::string propertyType) { if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT8) { uint8_t currentValue = *(reinterpret_cast(&effecterValue[0])); return getEffecterRawValue(pdr, currentValue, propertyType); } else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT8) { int8_t currentValue = *(reinterpret_cast(&effecterValue[0])); return getEffecterRawValue(pdr, currentValue, propertyType); } else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT16) { uint16_t currentValue = *(reinterpret_cast(&effecterValue[0])); return getEffecterRawValue(pdr, currentValue, propertyType); } else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT16) { int16_t currentValue = *(reinterpret_cast(&effecterValue[0])); return getEffecterRawValue(pdr, currentValue, propertyType); } else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_UINT32) { uint32_t currentValue = *(reinterpret_cast(&effecterValue[0])); return getEffecterRawValue(pdr, currentValue, propertyType); } else if (effecterDataSize == PLDM_EFFECTER_DATA_SIZE_SINT32) { int32_t currentValue = *(reinterpret_cast(&effecterValue[0])); return getEffecterRawValue(pdr, currentValue, propertyType); } else { std::cerr << "Wrong field effecterDataSize...\n"; return {PLDM_ERROR, {}}; } } /** @brief Function to set the effecter value requested by pldm requester * @tparam[in] DBusInterface - DBus interface type * @tparam[in] Handler - pldm::responder::platform::Handler * @param[in] dBusIntf - The interface object of DBusInterface * @param[in] handler - The interface object of * pldm::responder::platform::Handler * @param[in] effecterId - Effecter ID sent by the requester to act on * @param[in] effecterDataSize - The bit width and format of the setting * value for the effecter * @param[in] effecter_value - The setting value of numeric effecter being * requested. * @param[in] effecterValueLength - The setting value length of numeric * effecter being requested. * @return - Success or failure in setting the states. Returns failure in * terms of PLDM completion codes if atleast one state fails to be set */ template int setNumericEffecterValueHandler(const DBusInterface& dBusIntf, Handler& handler, uint16_t effecterId, uint8_t effecterDataSize, uint8_t* effecterValue, size_t effecterValueLength) { constexpr auto effecterValueArrayLength = 4; pldm_numeric_effecter_value_pdr* pdr = nullptr; std::unique_ptr numericEffecterPdrRepo(pldm_pdr_init(), pldm_pdr_destroy); pldm::responder::pdr_utils::Repo numericEffecterPDRs( numericEffecterPdrRepo.get()); pldm::responder::pdr::getRepoByType(handler.getRepo(), numericEffecterPDRs, PLDM_NUMERIC_EFFECTER_PDR); if (numericEffecterPDRs.empty()) { std::cerr << "The Numeric Effecter PDR repo is empty." << std::endl; return PLDM_ERROR; } // Get the pdr structure of pldm_numeric_effecter_value_pdr according // to the effecterId pldm::responder::pdr_utils::PdrEntry pdrEntry{}; auto pdrRecord = numericEffecterPDRs.getFirstRecord(pdrEntry); while (pdrRecord) { pdr = reinterpret_cast(pdrEntry.data); if (pdr->effecter_id != effecterId) { pdr = nullptr; pdrRecord = numericEffecterPDRs.getNextRecord(pdrRecord, pdrEntry); continue; } break; } if (!pdr) { return PLDM_PLATFORM_INVALID_EFFECTER_ID; } if (effecterValueLength != effecterValueArrayLength) { std::cerr << "effecter data size is incorrect.\n"; return PLDM_ERROR_INVALID_DATA; } try { const auto& [dbusMappings, dbusValMaps] = handler.getDbusObjMaps(effecterId); pldm::utils::DBusMapping dbusMapping{ dbusMappings[0].objectPath, dbusMappings[0].interface, dbusMappings[0].propertyName, dbusMappings[0].propertyType}; // convert to dbus effectervalue according to the factor auto [rc, dbusValue] = convertToDbusValue( pdr, effecterDataSize, effecterValue, dbusMappings[0].propertyType); if (rc != PLDM_SUCCESS) { return rc; } try { dBusIntf.setDbusProperty(dbusMapping, dbusValue.value()); } catch (const std::exception& e) { std::cerr << "Error setting property, ERROR=" << e.what() << " PROPERTY=" << dbusMapping.propertyName << " INTERFACE=" << dbusMapping.interface << " PATH=" << dbusMapping.objectPath << "\n"; return PLDM_ERROR; } } catch (const std::out_of_range& e) { std::cerr << "Unknown effecter ID : " << effecterId << e.what() << '\n'; return PLDM_ERROR; } return PLDM_SUCCESS; } } // namespace platform_numeric_effecter } // namespace responder } // namespace pldm