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     {
710d7aca8cSGeorge Liu         pdr = reinterpret_cast<pldm_state_effecter_pdr*>(pdrEntry.data);
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     {
1006da4f91bSPatrick Williams         const auto& [dbusMappings,
1016da4f91bSPatrick Williams                      dbusValMaps] = 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",
128*1e5c81e0SRiya 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",
148*1e5c81e0SRiya Dixit                         dbusMapping.interface, "PATH", dbusMapping.objectPath,
149*1e5c81e0SRiya 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