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