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> 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.c_str(), "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 atleast one state fails to be set 79 */ 80 template <class DBusInterface, class Handler> 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