10d7aca8cSGeorge Liu #pragma once
20d7aca8cSGeorge Liu 
30d7aca8cSGeorge Liu #include "config.h"
40d7aca8cSGeorge Liu 
56492f524SGeorge Liu #include "libpldm/platform.h"
66492f524SGeorge Liu #include "libpldm/states.h"
76492f524SGeorge Liu 
8d130e1a3SDeepak Kodihalli #include "common/utils.hpp"
90d7aca8cSGeorge Liu #include "libpldmresponder/pdr.hpp"
100d7aca8cSGeorge Liu #include "pdr_utils.hpp"
111521f6d1SDeepak Kodihalli #include "pldmd/handler.hpp"
120d7aca8cSGeorge Liu 
130d7aca8cSGeorge Liu #include <cstdint>
140d7aca8cSGeorge Liu #include <map>
150d7aca8cSGeorge Liu 
160d7aca8cSGeorge Liu using namespace pldm::responder::pdr;
170d7aca8cSGeorge Liu 
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 atleast one state fails to be set
360d7aca8cSGeorge Liu  */
370d7aca8cSGeorge Liu template <class DBusInterface, class Handler>
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);
520d7aca8cSGeorge Liu     Repo stateEffecterPDRs(stateEffecterPdrRepo.get());
530d7aca8cSGeorge Liu     getRepoByType(handler.getRepo(), stateEffecterPDRs,
540d7aca8cSGeorge Liu                   PLDM_STATE_EFFECTER_PDR);
550d7aca8cSGeorge Liu     if (stateEffecterPDRs.empty())
560d7aca8cSGeorge Liu     {
570d7aca8cSGeorge Liu         std::cerr << "Failed to get record by PDR type\n";
580d7aca8cSGeorge Liu         return PLDM_PLATFORM_INVALID_EFFECTER_ID;
590d7aca8cSGeorge Liu     }
600d7aca8cSGeorge Liu 
610d7aca8cSGeorge Liu     PdrEntry pdrEntry{};
620d7aca8cSGeorge Liu     auto pdrRecord = stateEffecterPDRs.getFirstRecord(pdrEntry);
630d7aca8cSGeorge Liu     while (pdrRecord)
640d7aca8cSGeorge Liu     {
650d7aca8cSGeorge Liu         pdr = reinterpret_cast<pldm_state_effecter_pdr*>(pdrEntry.data);
660d7aca8cSGeorge Liu         if (pdr->effecter_id != effecterId)
670d7aca8cSGeorge Liu         {
680d7aca8cSGeorge Liu             pdr = nullptr;
690d7aca8cSGeorge Liu             pdrRecord = stateEffecterPDRs.getNextRecord(pdrRecord, pdrEntry);
700d7aca8cSGeorge Liu             continue;
710d7aca8cSGeorge Liu         }
720d7aca8cSGeorge Liu 
730d7aca8cSGeorge Liu         states = reinterpret_cast<state_effecter_possible_states*>(
740d7aca8cSGeorge Liu             pdr->possible_states);
750d7aca8cSGeorge Liu         if (compEffecterCnt > pdr->composite_effecter_count)
760d7aca8cSGeorge Liu         {
770d7aca8cSGeorge Liu             std::cerr << "The requester sent wrong composite effecter"
780d7aca8cSGeorge Liu                       << " count for the effecter, EFFECTER_ID=" << effecterId
790d7aca8cSGeorge Liu                       << "COMP_EFF_CNT=" << compEffecterCnt << "\n";
800d7aca8cSGeorge Liu             return PLDM_ERROR_INVALID_DATA;
810d7aca8cSGeorge Liu         }
820d7aca8cSGeorge Liu         break;
830d7aca8cSGeorge Liu     }
840d7aca8cSGeorge Liu 
850d7aca8cSGeorge Liu     if (!pdr)
860d7aca8cSGeorge Liu     {
870d7aca8cSGeorge Liu         return PLDM_PLATFORM_INVALID_EFFECTER_ID;
880d7aca8cSGeorge Liu     }
890d7aca8cSGeorge Liu 
900d7aca8cSGeorge Liu     int rc = PLDM_SUCCESS;
910d7aca8cSGeorge Liu     try
920d7aca8cSGeorge Liu     {
930d7aca8cSGeorge Liu         const auto& [dbusMappings, dbusValMaps] =
940d7aca8cSGeorge Liu             handler.getDbusObjMaps(effecterId);
950d7aca8cSGeorge Liu         for (uint8_t currState = 0; currState < compEffecterCnt; ++currState)
960d7aca8cSGeorge Liu         {
970d7aca8cSGeorge Liu             std::vector<StateSetNum> allowed{};
980d7aca8cSGeorge Liu             // computation is based on table 79 from DSP0248 v1.1.1
990d7aca8cSGeorge Liu             uint8_t bitfieldIndex = stateField[currState].effecter_state / 8;
1000d7aca8cSGeorge Liu             uint8_t bit =
1010d7aca8cSGeorge Liu                 stateField[currState].effecter_state - (8 * bitfieldIndex);
1020d7aca8cSGeorge Liu             if (states->possible_states_size < bitfieldIndex ||
1030d7aca8cSGeorge Liu                 !(states->states[bitfieldIndex].byte & (1 << bit)))
1040d7aca8cSGeorge Liu             {
1050d7aca8cSGeorge Liu                 std::cerr << "Invalid state set value, EFFECTER_ID="
1060d7aca8cSGeorge Liu                           << effecterId
1070d7aca8cSGeorge Liu                           << " VALUE=" << stateField[currState].effecter_state
1080d7aca8cSGeorge Liu                           << " COMPOSITE_EFFECTER_ID=" << currState
1090d7aca8cSGeorge Liu                           << " DBUS_PATH=" << dbusMappings[currState].objectPath
1100d7aca8cSGeorge Liu                           << "\n";
1110d7aca8cSGeorge Liu                 rc = PLDM_PLATFORM_SET_EFFECTER_UNSUPPORTED_SENSORSTATE;
1120d7aca8cSGeorge Liu                 break;
1130d7aca8cSGeorge Liu             }
1140d7aca8cSGeorge Liu             const DBusMapping& dbusMapping = dbusMappings[currState];
1150d7aca8cSGeorge Liu             const StatestoDbusVal& dbusValToMap = dbusValMaps[currState];
1160d7aca8cSGeorge Liu 
1170d7aca8cSGeorge Liu             if (stateField[currState].set_request == PLDM_REQUEST_SET)
1180d7aca8cSGeorge Liu             {
1190d7aca8cSGeorge Liu                 try
1200d7aca8cSGeorge Liu                 {
1210d7aca8cSGeorge Liu                     dBusIntf.setDbusProperty(
1220d7aca8cSGeorge Liu                         dbusMapping,
1230d7aca8cSGeorge Liu                         dbusValToMap.at(stateField[currState].effecter_state));
1240d7aca8cSGeorge Liu                 }
1250d7aca8cSGeorge Liu                 catch (const std::exception& e)
1260d7aca8cSGeorge Liu                 {
1270d7aca8cSGeorge Liu                     std::cerr
1280d7aca8cSGeorge Liu                         << "Error setting property, ERROR=" << e.what()
1290d7aca8cSGeorge Liu                         << " PROPERTY=" << dbusMapping.propertyName
1300d7aca8cSGeorge Liu                         << " INTERFACE=" << dbusMapping.interface << " PATH="
1310d7aca8cSGeorge Liu                         << dbusMapping.objectPath << "\n";
1320d7aca8cSGeorge Liu                     return PLDM_ERROR;
1330d7aca8cSGeorge Liu                 }
1340d7aca8cSGeorge Liu             }
1350d7aca8cSGeorge Liu             uint8_t* nextState =
1360d7aca8cSGeorge Liu                 reinterpret_cast<uint8_t*>(states) +
1370d7aca8cSGeorge Liu                 sizeof(state_effecter_possible_states) -
1380d7aca8cSGeorge Liu                 sizeof(states->states) +
1390d7aca8cSGeorge Liu                 (states->possible_states_size * sizeof(states->states));
1400d7aca8cSGeorge Liu             states =
1410d7aca8cSGeorge Liu                 reinterpret_cast<state_effecter_possible_states*>(nextState);
1420d7aca8cSGeorge Liu         }
1430d7aca8cSGeorge Liu     }
1440d7aca8cSGeorge Liu     catch (const std::out_of_range& e)
1450d7aca8cSGeorge Liu     {
146*bd5e2eaaSGeorge Liu         std::cerr << "Unknown effecter ID : " << effecterId << e.what() << '\n';
147*bd5e2eaaSGeorge Liu         return PLDM_ERROR;
1480d7aca8cSGeorge Liu     }
1490d7aca8cSGeorge Liu 
1500d7aca8cSGeorge Liu     return rc;
1510d7aca8cSGeorge Liu }
1520d7aca8cSGeorge Liu 
1530d7aca8cSGeorge Liu } // namespace platform_state_effecter
1540d7aca8cSGeorge Liu } // namespace responder
1550d7aca8cSGeorge Liu } // namespace pldm
156