blob: 961aa7f7b2a274c8133988d51012fc41b34211be [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
George Liu0d7aca82020-03-30 15:01:36 +08008#include "libpldmresponder/pdr.hpp"
9#include "pdr_utils.hpp"
Deepak Kodihalli1521f6d2020-06-16 08:51:02 -050010#include "pldmd/handler.hpp"
George Liu0d7aca82020-03-30 15:01:36 +080011#include "utils.hpp"
12
13#include <cstdint>
14#include <map>
15
George Liu0d7aca82020-03-30 15:01:36 +080016using namespace pldm::responder::pdr;
17
18namespace pldm
19{
20namespace responder
21{
22namespace platform_state_effecter
23{
24/** @brief Function to set the effecter requested by pldm requester
25 *
26 * @tparam[in] DBusInterface - DBus interface type
27 * @tparam[in] Handler - pldm::responder::platform::Handler
28 * @param[in] dBusIntf - The interface object of DBusInterface
29 * @param[in] handler - The interface object of
30 * pldm::responder::platform::Handler
31 * @param[in] effecterId - Effecter ID sent by the requester to act on
32 * @param[in] stateField - The state field data for each of the states,
33 * equal to composite effecter count in number
34 * @return - Success or failure in setting the states. Returns failure in
35 * terms of PLDM completion codes if atleast one state fails to be set
36 */
37template <class DBusInterface, class Handler>
38int setStateEffecterStatesHandler(
39 const DBusInterface& dBusIntf, Handler& handler, uint16_t effecterId,
40 const std::vector<set_effecter_state_field>& stateField)
41{
42 using namespace pldm::responder::pdr;
43 using namespace pldm::utils;
44 using StateSetNum = uint8_t;
45
46 state_effecter_possible_states* states = nullptr;
47 pldm_state_effecter_pdr* pdr = nullptr;
48 uint8_t compEffecterCnt = stateField.size();
49
50 std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)> stateEffecterPdrRepo(
51 pldm_pdr_init(), pldm_pdr_destroy);
52 Repo stateEffecterPDRs(stateEffecterPdrRepo.get());
53 getRepoByType(handler.getRepo(), stateEffecterPDRs,
54 PLDM_STATE_EFFECTER_PDR);
55 if (stateEffecterPDRs.empty())
56 {
57 std::cerr << "Failed to get record by PDR type\n";
58 return PLDM_PLATFORM_INVALID_EFFECTER_ID;
59 }
60
61 PdrEntry pdrEntry{};
62 auto pdrRecord = stateEffecterPDRs.getFirstRecord(pdrEntry);
63 while (pdrRecord)
64 {
65 pdr = reinterpret_cast<pldm_state_effecter_pdr*>(pdrEntry.data);
66 if (pdr->effecter_id != effecterId)
67 {
68 pdr = nullptr;
69 pdrRecord = stateEffecterPDRs.getNextRecord(pdrRecord, pdrEntry);
70 continue;
71 }
72
73 states = reinterpret_cast<state_effecter_possible_states*>(
74 pdr->possible_states);
75 if (compEffecterCnt > pdr->composite_effecter_count)
76 {
77 std::cerr << "The requester sent wrong composite effecter"
78 << " count for the effecter, EFFECTER_ID=" << effecterId
79 << "COMP_EFF_CNT=" << compEffecterCnt << "\n";
80 return PLDM_ERROR_INVALID_DATA;
81 }
82 break;
83 }
84
85 if (!pdr)
86 {
87 return PLDM_PLATFORM_INVALID_EFFECTER_ID;
88 }
89
90 int rc = PLDM_SUCCESS;
91 try
92 {
93 const auto& [dbusMappings, dbusValMaps] =
94 handler.getDbusObjMaps(effecterId);
95 for (uint8_t currState = 0; currState < compEffecterCnt; ++currState)
96 {
97 std::vector<StateSetNum> allowed{};
98 // computation is based on table 79 from DSP0248 v1.1.1
99 uint8_t bitfieldIndex = stateField[currState].effecter_state / 8;
100 uint8_t bit =
101 stateField[currState].effecter_state - (8 * bitfieldIndex);
102 if (states->possible_states_size < bitfieldIndex ||
103 !(states->states[bitfieldIndex].byte & (1 << bit)))
104 {
105 std::cerr << "Invalid state set value, EFFECTER_ID="
106 << effecterId
107 << " VALUE=" << stateField[currState].effecter_state
108 << " COMPOSITE_EFFECTER_ID=" << currState
109 << " DBUS_PATH=" << dbusMappings[currState].objectPath
110 << "\n";
111 rc = PLDM_PLATFORM_SET_EFFECTER_UNSUPPORTED_SENSORSTATE;
112 break;
113 }
114 const DBusMapping& dbusMapping = dbusMappings[currState];
115 const StatestoDbusVal& dbusValToMap = dbusValMaps[currState];
116
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 {
146 std::cerr << "the effecterId does not exist. effecter id: "
147 << effecterId << e.what() << '\n';
148 }
149
150 return rc;
151}
152
153} // namespace platform_state_effecter
154} // namespace responder
155} // namespace pldm