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