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