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