blob: 1d8ce63fb847e7eb17854755bde49276d070331f [file] [log] [blame]
George Liu0d7aca82020-03-30 15:01:36 +08001#pragma once
2
3#include "config.h"
4
George Liu6492f522020-06-16 10:34:05 +08005#include "libpldm/platform.h"
6#include "libpldm/states.h"
7
Deepak Kodihallid130e1a2020-06-17 05:55:32 -05008#include "common/utils.hpp"
George Liu0d7aca82020-03-30 15:01:36 +08009#include "libpldmresponder/pdr.hpp"
10#include "pdr_utils.hpp"
Deepak Kodihalli1521f6d2020-06-16 08:51:02 -050011#include "pldmd/handler.hpp"
George Liu0d7aca82020-03-30 15:01:36 +080012
13#include <cstdint>
14#include <map>
15
George Liu0d7aca82020-03-30 15:01:36 +080016namespace pldm
17{
18namespace responder
19{
20namespace platform_state_effecter
21{
22/** @brief Function to set the effecter requested by pldm requester
23 *
24 * @tparam[in] DBusInterface - DBus interface type
25 * @tparam[in] Handler - pldm::responder::platform::Handler
26 * @param[in] dBusIntf - The interface object of DBusInterface
27 * @param[in] handler - The interface object of
28 * pldm::responder::platform::Handler
29 * @param[in] effecterId - Effecter ID sent by the requester to act on
30 * @param[in] stateField - The state field data for each of the states,
31 * equal to composite effecter count in number
32 * @return - Success or failure in setting the states. Returns failure in
33 * terms of PLDM completion codes if atleast one state fails to be set
34 */
35template <class DBusInterface, class Handler>
36int setStateEffecterStatesHandler(
37 const DBusInterface& dBusIntf, Handler& handler, uint16_t effecterId,
38 const std::vector<set_effecter_state_field>& stateField)
39{
40 using namespace pldm::responder::pdr;
41 using namespace pldm::utils;
42 using StateSetNum = uint8_t;
43
44 state_effecter_possible_states* states = nullptr;
45 pldm_state_effecter_pdr* pdr = nullptr;
46 uint8_t compEffecterCnt = stateField.size();
47
48 std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)> stateEffecterPdrRepo(
49 pldm_pdr_init(), pldm_pdr_destroy);
Brad Bishop5079ac42021-08-19 18:35:06 -040050 pldm::responder::pdr_utils::Repo stateEffecterPDRs(
51 stateEffecterPdrRepo.get());
George Liu0d7aca82020-03-30 15:01:36 +080052 getRepoByType(handler.getRepo(), stateEffecterPDRs,
53 PLDM_STATE_EFFECTER_PDR);
54 if (stateEffecterPDRs.empty())
55 {
56 std::cerr << "Failed to get record by PDR type\n";
57 return PLDM_PLATFORM_INVALID_EFFECTER_ID;
58 }
59
Brad Bishop5079ac42021-08-19 18:35:06 -040060 pldm::responder::pdr_utils::PdrEntry pdrEntry{};
George Liu0d7aca82020-03-30 15:01:36 +080061 auto pdrRecord = stateEffecterPDRs.getFirstRecord(pdrEntry);
62 while (pdrRecord)
63 {
64 pdr = reinterpret_cast<pldm_state_effecter_pdr*>(pdrEntry.data);
65 if (pdr->effecter_id != effecterId)
66 {
67 pdr = nullptr;
68 pdrRecord = stateEffecterPDRs.getNextRecord(pdrRecord, pdrEntry);
69 continue;
70 }
71
72 states = reinterpret_cast<state_effecter_possible_states*>(
73 pdr->possible_states);
74 if (compEffecterCnt > pdr->composite_effecter_count)
75 {
76 std::cerr << "The requester sent wrong composite effecter"
77 << " count for the effecter, EFFECTER_ID=" << effecterId
78 << "COMP_EFF_CNT=" << compEffecterCnt << "\n";
79 return PLDM_ERROR_INVALID_DATA;
80 }
81 break;
82 }
83
84 if (!pdr)
85 {
86 return PLDM_PLATFORM_INVALID_EFFECTER_ID;
87 }
88
89 int rc = PLDM_SUCCESS;
90 try
91 {
92 const auto& [dbusMappings, dbusValMaps] =
93 handler.getDbusObjMaps(effecterId);
94 for (uint8_t currState = 0; currState < compEffecterCnt; ++currState)
95 {
96 std::vector<StateSetNum> allowed{};
97 // computation is based on table 79 from DSP0248 v1.1.1
98 uint8_t bitfieldIndex = stateField[currState].effecter_state / 8;
99 uint8_t bit =
100 stateField[currState].effecter_state - (8 * bitfieldIndex);
101 if (states->possible_states_size < bitfieldIndex ||
102 !(states->states[bitfieldIndex].byte & (1 << bit)))
103 {
104 std::cerr << "Invalid state set value, EFFECTER_ID="
105 << effecterId
106 << " VALUE=" << stateField[currState].effecter_state
107 << " COMPOSITE_EFFECTER_ID=" << currState
108 << " DBUS_PATH=" << dbusMappings[currState].objectPath
109 << "\n";
110 rc = PLDM_PLATFORM_SET_EFFECTER_UNSUPPORTED_SENSORSTATE;
111 break;
112 }
113 const DBusMapping& dbusMapping = dbusMappings[currState];
Brad Bishop5079ac42021-08-19 18:35:06 -0400114 const pldm::responder::pdr_utils::StatestoDbusVal& dbusValToMap =
115 dbusValMaps[currState];
George Liu0d7aca82020-03-30 15:01:36 +0800116
117 if (stateField[currState].set_request == PLDM_REQUEST_SET)
118 {
119 try
120 {
121 dBusIntf.setDbusProperty(
122 dbusMapping,
123 dbusValToMap.at(stateField[currState].effecter_state));
124 }
125 catch (const std::exception& e)
126 {
127 std::cerr
128 << "Error setting property, ERROR=" << e.what()
129 << " PROPERTY=" << dbusMapping.propertyName
130 << " INTERFACE=" << dbusMapping.interface << " PATH="
131 << dbusMapping.objectPath << "\n";
132 return PLDM_ERROR;
133 }
134 }
135 uint8_t* nextState =
136 reinterpret_cast<uint8_t*>(states) +
137 sizeof(state_effecter_possible_states) -
138 sizeof(states->states) +
139 (states->possible_states_size * sizeof(states->states));
140 states =
141 reinterpret_cast<state_effecter_possible_states*>(nextState);
142 }
143 }
144 catch (const std::out_of_range& e)
145 {
George Liubd5e2ea2021-04-22 20:33:06 +0800146 std::cerr << "Unknown effecter ID : " << effecterId << e.what() << '\n';
147 return PLDM_ERROR;
George Liu0d7aca82020-03-30 15:01:36 +0800148 }
149
150 return rc;
151}
152
153} // namespace platform_state_effecter
154} // namespace responder
155} // namespace pldm