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