10d7aca8cSGeorge Liu #pragma once
20d7aca8cSGeorge Liu
3d130e1a3SDeepak Kodihalli #include "common/utils.hpp"
40d7aca8cSGeorge Liu #include "libpldmresponder/pdr.hpp"
50d7aca8cSGeorge Liu #include "pdr_utils.hpp"
61521f6d1SDeepak Kodihalli #include "pldmd/handler.hpp"
70d7aca8cSGeorge Liu
8c453e164SGeorge Liu #include <libpldm/platform.h>
9c453e164SGeorge Liu #include <libpldm/states.h>
10c453e164SGeorge Liu
1149cfb138SRiya Dixit #include <phosphor-logging/lg2.hpp>
1249cfb138SRiya Dixit
130d7aca8cSGeorge Liu #include <cstdint>
140d7aca8cSGeorge Liu #include <map>
150d7aca8cSGeorge Liu
1649cfb138SRiya Dixit PHOSPHOR_LOG2_USING;
1749cfb138SRiya Dixit
180d7aca8cSGeorge Liu namespace pldm
190d7aca8cSGeorge Liu {
200d7aca8cSGeorge Liu namespace responder
210d7aca8cSGeorge Liu {
220d7aca8cSGeorge Liu namespace platform_state_effecter
230d7aca8cSGeorge Liu {
240d7aca8cSGeorge Liu /** @brief Function to set the effecter requested by pldm requester
250d7aca8cSGeorge Liu *
260d7aca8cSGeorge Liu * @tparam[in] DBusInterface - DBus interface type
270d7aca8cSGeorge Liu * @tparam[in] Handler - pldm::responder::platform::Handler
280d7aca8cSGeorge Liu * @param[in] dBusIntf - The interface object of DBusInterface
290d7aca8cSGeorge Liu * @param[in] handler - The interface object of
300d7aca8cSGeorge Liu * pldm::responder::platform::Handler
310d7aca8cSGeorge Liu * @param[in] effecterId - Effecter ID sent by the requester to act on
320d7aca8cSGeorge Liu * @param[in] stateField - The state field data for each of the states,
330d7aca8cSGeorge Liu * equal to composite effecter count in number
340d7aca8cSGeorge Liu * @return - Success or failure in setting the states. Returns failure in
350d7aca8cSGeorge Liu * terms of PLDM completion codes if at least one state fails to be set
360d7aca8cSGeorge Liu */
370d7aca8cSGeorge Liu template <class DBusInterface, class Handler>
setStateEffecterStatesHandler(const DBusInterface & dBusIntf,Handler & handler,uint16_t effecterId,const std::vector<set_effecter_state_field> & stateField)380d7aca8cSGeorge Liu int setStateEffecterStatesHandler(
390d7aca8cSGeorge Liu const DBusInterface& dBusIntf, Handler& handler, uint16_t effecterId,
400d7aca8cSGeorge Liu const std::vector<set_effecter_state_field>& stateField)
410d7aca8cSGeorge Liu {
420d7aca8cSGeorge Liu using namespace pldm::responder::pdr;
430d7aca8cSGeorge Liu using namespace pldm::utils;
440d7aca8cSGeorge Liu using StateSetNum = uint8_t;
450d7aca8cSGeorge Liu
460d7aca8cSGeorge Liu state_effecter_possible_states* states = nullptr;
470d7aca8cSGeorge Liu pldm_state_effecter_pdr* pdr = nullptr;
480d7aca8cSGeorge Liu uint8_t compEffecterCnt = stateField.size();
490d7aca8cSGeorge Liu
500d7aca8cSGeorge Liu std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)> stateEffecterPdrRepo(
510d7aca8cSGeorge Liu pldm_pdr_init(), pldm_pdr_destroy);
52acb20299SAndrew Jeffery if (!stateEffecterPdrRepo)
53acb20299SAndrew Jeffery {
54acb20299SAndrew Jeffery throw std::runtime_error(
55acb20299SAndrew Jeffery "Failed to instantiate state effecter PDR repository");
56acb20299SAndrew Jeffery }
575079ac4aSBrad Bishop pldm::responder::pdr_utils::Repo stateEffecterPDRs(
585079ac4aSBrad Bishop stateEffecterPdrRepo.get());
590d7aca8cSGeorge Liu getRepoByType(handler.getRepo(), stateEffecterPDRs,
600d7aca8cSGeorge Liu PLDM_STATE_EFFECTER_PDR);
610d7aca8cSGeorge Liu if (stateEffecterPDRs.empty())
620d7aca8cSGeorge Liu {
6389644441SRiya Dixit error("Failed to get StateEffecterPDR record");
640d7aca8cSGeorge Liu return PLDM_PLATFORM_INVALID_EFFECTER_ID;
650d7aca8cSGeorge Liu }
660d7aca8cSGeorge Liu
675079ac4aSBrad Bishop pldm::responder::pdr_utils::PdrEntry pdrEntry{};
680d7aca8cSGeorge Liu auto pdrRecord = stateEffecterPDRs.getFirstRecord(pdrEntry);
690d7aca8cSGeorge Liu while (pdrRecord)
700d7aca8cSGeorge Liu {
71*677a4552SPavithra Barithaya pdr = new (pdrEntry.data) pldm_state_effecter_pdr;
720d7aca8cSGeorge Liu if (pdr->effecter_id != effecterId)
730d7aca8cSGeorge Liu {
740d7aca8cSGeorge Liu pdr = nullptr;
750d7aca8cSGeorge Liu pdrRecord = stateEffecterPDRs.getNextRecord(pdrRecord, pdrEntry);
760d7aca8cSGeorge Liu continue;
770d7aca8cSGeorge Liu }
780d7aca8cSGeorge Liu
790d7aca8cSGeorge Liu states = reinterpret_cast<state_effecter_possible_states*>(
800d7aca8cSGeorge Liu pdr->possible_states);
810d7aca8cSGeorge Liu if (compEffecterCnt > pdr->composite_effecter_count)
820d7aca8cSGeorge Liu {
8349cfb138SRiya Dixit error(
8489644441SRiya Dixit "The requester sent wrong composite effecter count '{COMPOSITE_EFFECTER_COUNT}' for the effecter ID '{EFFECTERID}'",
8589644441SRiya Dixit "EFFECTERID", effecterId, "COMPOSITE_EFFECTER_COUNT",
8689644441SRiya Dixit compEffecterCnt);
870d7aca8cSGeorge Liu return PLDM_ERROR_INVALID_DATA;
880d7aca8cSGeorge Liu }
890d7aca8cSGeorge Liu break;
900d7aca8cSGeorge Liu }
910d7aca8cSGeorge Liu
920d7aca8cSGeorge Liu if (!pdr)
930d7aca8cSGeorge Liu {
940d7aca8cSGeorge Liu return PLDM_PLATFORM_INVALID_EFFECTER_ID;
950d7aca8cSGeorge Liu }
960d7aca8cSGeorge Liu
970d7aca8cSGeorge Liu int rc = PLDM_SUCCESS;
980d7aca8cSGeorge Liu try
990d7aca8cSGeorge Liu {
10016c2a0a0SPatrick Williams const auto& [dbusMappings, dbusValMaps] =
10116c2a0a0SPatrick Williams handler.getDbusObjMaps(effecterId);
1023daf7a1cSManojkiran Eda if (dbusMappings.empty() || dbusValMaps.empty())
1033daf7a1cSManojkiran Eda {
10489644441SRiya Dixit error("DbusMappings for effecter ID '{EFFECTER_ID}' is missing",
1053daf7a1cSManojkiran Eda "EFFECTER_ID", effecterId);
1063daf7a1cSManojkiran Eda return PLDM_ERROR;
1073daf7a1cSManojkiran Eda }
1083daf7a1cSManojkiran Eda
1093daf7a1cSManojkiran Eda for (uint8_t currState = 0;
1103daf7a1cSManojkiran Eda currState < compEffecterCnt && currState < dbusMappings.size() &&
1113daf7a1cSManojkiran Eda currState < dbusValMaps.size();
1123daf7a1cSManojkiran Eda ++currState)
1130d7aca8cSGeorge Liu {
1140d7aca8cSGeorge Liu std::vector<StateSetNum> allowed{};
1150d7aca8cSGeorge Liu // computation is based on table 79 from DSP0248 v1.1.1
1160d7aca8cSGeorge Liu uint8_t bitfieldIndex = stateField[currState].effecter_state / 8;
1176da4f91bSPatrick Williams uint8_t bit = stateField[currState].effecter_state -
1186da4f91bSPatrick Williams (8 * bitfieldIndex);
1190d7aca8cSGeorge Liu if (states->possible_states_size < bitfieldIndex ||
1200d7aca8cSGeorge Liu !(states->states[bitfieldIndex].byte & (1 << bit)))
1210d7aca8cSGeorge Liu {
1220d7aca8cSGeorge Liu rc = PLDM_PLATFORM_SET_EFFECTER_UNSUPPORTED_SENSORSTATE;
12389644441SRiya Dixit error(
12489644441SRiya Dixit "Invalid state set value for effecter ID '{EFFECTER_ID}', effecter state '{EFFECTER_STATE}', composite effecter ID '{COMPOSITE_EFFECTER_ID}' and path '{PATH}', response code '{RC}'",
12589644441SRiya Dixit "EFFECTER_ID", effecterId, "EFFECTER_STATE",
12689644441SRiya Dixit stateField[currState].effecter_state,
12789644441SRiya Dixit "COMPOSITE_EFFECTER_ID", currState, "PATH",
1281e5c81e0SRiya Dixit dbusMappings[currState].objectPath, "RC", rc);
1290d7aca8cSGeorge Liu break;
1300d7aca8cSGeorge Liu }
1310d7aca8cSGeorge Liu const DBusMapping& dbusMapping = dbusMappings[currState];
1325079ac4aSBrad Bishop const pldm::responder::pdr_utils::StatestoDbusVal& dbusValToMap =
1335079ac4aSBrad Bishop dbusValMaps[currState];
1340d7aca8cSGeorge Liu
1350d7aca8cSGeorge Liu if (stateField[currState].set_request == PLDM_REQUEST_SET)
1360d7aca8cSGeorge Liu {
1370d7aca8cSGeorge Liu try
1380d7aca8cSGeorge Liu {
1390d7aca8cSGeorge Liu dBusIntf.setDbusProperty(
1400d7aca8cSGeorge Liu dbusMapping,
1410d7aca8cSGeorge Liu dbusValToMap.at(stateField[currState].effecter_state));
1420d7aca8cSGeorge Liu }
1430d7aca8cSGeorge Liu catch (const std::exception& e)
1440d7aca8cSGeorge Liu {
14549cfb138SRiya Dixit error(
14689644441SRiya Dixit "Failed to set property '{PROPERTY}', interface '{INTERFACE}' and path '{PATH}', error - '{ERROR}'",
14789644441SRiya Dixit "PROPERTY", dbusMapping.propertyName, "INTERFACE",
1481e5c81e0SRiya Dixit dbusMapping.interface, "PATH", dbusMapping.objectPath,
1491e5c81e0SRiya Dixit "ERROR", e);
1500d7aca8cSGeorge Liu return PLDM_ERROR;
1510d7aca8cSGeorge Liu }
1520d7aca8cSGeorge Liu }
1530d7aca8cSGeorge Liu uint8_t* nextState =
1540d7aca8cSGeorge Liu reinterpret_cast<uint8_t*>(states) +
1550d7aca8cSGeorge Liu sizeof(state_effecter_possible_states) -
1560d7aca8cSGeorge Liu sizeof(states->states) +
1570d7aca8cSGeorge Liu (states->possible_states_size * sizeof(states->states));
1580d7aca8cSGeorge Liu states =
1590d7aca8cSGeorge Liu reinterpret_cast<state_effecter_possible_states*>(nextState);
1600d7aca8cSGeorge Liu }
1610d7aca8cSGeorge Liu }
1620d7aca8cSGeorge Liu catch (const std::out_of_range& e)
1630d7aca8cSGeorge Liu {
16489644441SRiya Dixit error("Unknown effecter ID '{EFFECTERID}', error - {ERROR}",
16589644441SRiya Dixit "EFFECTERID", effecterId, "ERROR", e);
166bd5e2eaaSGeorge Liu return PLDM_ERROR;
1670d7aca8cSGeorge Liu }
1680d7aca8cSGeorge Liu
1690d7aca8cSGeorge Liu return rc;
1700d7aca8cSGeorge Liu }
1710d7aca8cSGeorge Liu
1720d7aca8cSGeorge Liu } // namespace platform_state_effecter
1730d7aca8cSGeorge Liu } // namespace responder
1740d7aca8cSGeorge Liu } // namespace pldm
175