1 #pragma once
2
3 #include "common/utils.hpp"
4 #include "libpldmresponder/pdr.hpp"
5 #include "pdr_utils.hpp"
6 #include "pldmd/handler.hpp"
7
8 #include <libpldm/platform.h>
9 #include <libpldm/states.h>
10
11 #include <phosphor-logging/lg2.hpp>
12
13 #include <cstdint>
14 #include <map>
15
16 PHOSPHOR_LOG2_USING;
17
18 namespace pldm
19 {
20 namespace responder
21 {
22 namespace platform_state_sensor
23 {
24 /** @brief Function to get the sensor state
25 *
26 * @tparam[in] DBusInterface - DBus interface type
27 * @param[in] dBusIntf - The interface object of DBusInterface
28 * @param[in] stateToDbusValue - Map of DBus property State to attribute value
29 * @param[in] dbusMapping - The d-bus object
30 *
31 * @return - Enumeration of SensorState
32 */
33 template <class DBusInterface>
getStateSensorEventState(const DBusInterface & dBusIntf,const std::map<pldm::responder::pdr_utils::State,pldm::utils::PropertyValue> & stateToDbusValue,const pldm::utils::DBusMapping & dbusMapping)34 uint8_t getStateSensorEventState(
35 const DBusInterface& dBusIntf,
36 const std::map<pldm::responder::pdr_utils::State,
37 pldm::utils::PropertyValue>& stateToDbusValue,
38 const pldm::utils::DBusMapping& dbusMapping)
39 {
40 try
41 {
42 auto propertyValue = dBusIntf.getDbusPropertyVariant(
43 dbusMapping.objectPath.c_str(), dbusMapping.propertyName.c_str(),
44 dbusMapping.interface.c_str());
45
46 for (const auto& stateValue : stateToDbusValue)
47 {
48 if (stateValue.second == propertyValue)
49 {
50 return stateValue.first;
51 }
52 }
53 }
54 catch (const std::exception& e)
55 {
56 error(
57 "Failed to get state sensor event state from dbus interface '{PATH}', error - {ERROR}.",
58 "PATH", dbusMapping.objectPath, "ERROR", e);
59 }
60
61 return PLDM_SENSOR_UNKNOWN;
62 }
63
64 /** @brief Function to get the state sensor readings requested by pldm requester
65 *
66 * @tparam[in] DBusInterface - DBus interface type
67 * @tparam[in] Handler - pldm::responder::platform::Handler
68 * @param[in] dBusIntf - The interface object of DBusInterface
69 * @param[in] handler - The interface object of
70 * pldm::responder::platform::Handler
71 * @param[in] sensorId - Sensor ID sent by the requester to act on
72 * @param[in] sensorRearmCnt - Each bit location in this field corresponds to a
73 * particular sensor within the state sensor
74 * @param[out] compSensorCnt - composite sensor count
75 * @param[out] stateField - The state field data for each of the states,
76 * equal to composite sensor count in number
77 * @return - Success or failure in setting the states. Returns failure in
78 * terms of PLDM completion codes if at least one state fails to be set
79 */
80 template <class DBusInterface, class Handler>
getStateSensorReadingsHandler(const DBusInterface & dBusIntf,Handler & handler,uint16_t sensorId,uint8_t sensorRearmCnt,uint8_t & compSensorCnt,std::vector<get_sensor_state_field> & stateField,const stateSensorCacheMaps & sensorCache)81 int getStateSensorReadingsHandler(
82 const DBusInterface& dBusIntf, Handler& handler, uint16_t sensorId,
83 uint8_t sensorRearmCnt, uint8_t& compSensorCnt,
84 std::vector<get_sensor_state_field>& stateField,
85 const stateSensorCacheMaps& sensorCache)
86 {
87 using namespace pldm::responder::pdr;
88 using namespace pldm::utils;
89
90 pldm_state_sensor_pdr* pdr = nullptr;
91
92 std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)> stateSensorPdrRepo(
93 pldm_pdr_init(), pldm_pdr_destroy);
94 if (!stateSensorPdrRepo)
95 {
96 throw std::runtime_error(
97 "Failed to instantiate state sensor PDR repository");
98 }
99 pldm::responder::pdr_utils::Repo stateSensorPDRs(stateSensorPdrRepo.get());
100 getRepoByType(handler.getRepo(), stateSensorPDRs, PLDM_STATE_SENSOR_PDR);
101 if (stateSensorPDRs.empty())
102 {
103 error("Failed to get StateSensorPDR record.");
104 return PLDM_PLATFORM_INVALID_SENSOR_ID;
105 }
106
107 pldm::responder::pdr_utils::PdrEntry pdrEntry{};
108 auto pdrRecord = stateSensorPDRs.getFirstRecord(pdrEntry);
109 while (pdrRecord)
110 {
111 pdr = reinterpret_cast<pldm_state_sensor_pdr*>(pdrEntry.data);
112 assert(pdr != NULL);
113 if (pdr->sensor_id != sensorId)
114 {
115 pdr = nullptr;
116 pdrRecord = stateSensorPDRs.getNextRecord(pdrRecord, pdrEntry);
117 continue;
118 }
119
120 compSensorCnt = pdr->composite_sensor_count;
121 if (sensorRearmCnt > compSensorCnt)
122 {
123 error(
124 "The requester sent wrong sensor rearm count '{SENSOR_REARM_COUNT}' for the sensor ID '{SENSORID}'",
125 "SENSORID", sensorId, "SENSOR_REARM_COUNT", sensorRearmCnt);
126 return PLDM_PLATFORM_REARM_UNAVAILABLE_IN_PRESENT_STATE;
127 }
128
129 if (sensorRearmCnt == 0)
130 {
131 sensorRearmCnt = compSensorCnt;
132 stateField.resize(sensorRearmCnt);
133 }
134
135 break;
136 }
137
138 if (!pdr)
139 {
140 return PLDM_PLATFORM_INVALID_SENSOR_ID;
141 }
142
143 int rc = PLDM_SUCCESS;
144 try
145 {
146 const auto& [dbusMappings, dbusValMaps] = handler.getDbusObjMaps(
147 sensorId, pldm::responder::pdr_utils::TypeId::PLDM_SENSOR_ID);
148
149 if (dbusMappings.empty() || dbusValMaps.empty())
150 {
151 error("DbusMappings for sensor ID '{SENSOR_ID}' is missing",
152 "SENSOR_ID", sensorId);
153 return PLDM_ERROR;
154 }
155 pldm::responder::pdr_utils::EventStates sensorCacheforSensor{};
156 if (sensorCache.contains(sensorId))
157 {
158 sensorCacheforSensor = sensorCache.at(sensorId);
159 }
160 stateField.clear();
161 for (std::size_t offset{0};
162 offset < sensorRearmCnt && offset < dbusMappings.size() &&
163 offset < dbusValMaps.size();
164 offset++)
165 {
166 auto& dbusMapping = dbusMappings[offset];
167
168 uint8_t sensorEvent = getStateSensorEventState<DBusInterface>(
169 dBusIntf, dbusValMaps[offset], dbusMapping);
170
171 uint8_t previousState = PLDM_SENSOR_UNKNOWN;
172
173 // if sensor cache is empty, then its the first
174 // get_state_sensor_reading on this sensor, set the previous state
175 // as the current state
176
177 if (sensorCacheforSensor.at(offset) == PLDM_SENSOR_UNKNOWN)
178 {
179 previousState = sensorEvent;
180 handler.updateSensorCache(sensorId, offset, previousState);
181 }
182 else
183 {
184 // sensor cache is not empty, so get the previous state from
185 // the sensor cache
186 previousState = sensorCacheforSensor[offset];
187 }
188 uint8_t opState = PLDM_SENSOR_ENABLED;
189 if (sensorEvent == PLDM_SENSOR_UNKNOWN)
190 {
191 opState = PLDM_SENSOR_UNAVAILABLE;
192 }
193
194 stateField.push_back(
195 {opState, PLDM_SENSOR_NORMAL, previousState, sensorEvent});
196 }
197 }
198 catch (const std::out_of_range& e)
199 {
200 error("The sensor ID '{SENSORID}' does not exist, error - {ERROR}",
201 "SENSORID", sensorId, "ERROR", e);
202 rc = PLDM_ERROR;
203 }
204
205 return rc;
206 }
207
208 } // namespace platform_state_sensor
209 } // namespace responder
210 } // namespace pldm
211