1 #pragma once 2 3 #include "common/utils.hpp" 4 #include "host-bmc/dbus_to_event_handler.hpp" 5 #include "libpldmresponder/pdr.hpp" 6 #include "pdr_utils.hpp" 7 #include "pldmd/handler.hpp" 8 9 #include <libpldm/platform.h> 10 #include <libpldm/states.h> 11 12 #include <phosphor-logging/lg2.hpp> 13 14 #include <cstdint> 15 #include <map> 16 17 PHOSPHOR_LOG2_USING; 18 19 namespace pldm 20 { 21 namespace responder 22 { 23 namespace platform_state_sensor 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<pldm::responder::pdr_utils::State, 38 pldm::utils::PropertyValue>& stateToDbusValue, 39 const pldm::utils::DBusMapping& dbusMapping) 40 { 41 try 42 { 43 auto propertyValue = dBusIntf.getDbusPropertyVariant( 44 dbusMapping.objectPath.c_str(), dbusMapping.propertyName.c_str(), 45 dbusMapping.interface.c_str()); 46 47 for (const auto& stateValue : stateToDbusValue) 48 { 49 if (stateValue.second == propertyValue) 50 { 51 return stateValue.first; 52 } 53 } 54 } 55 catch (const std::exception& e) 56 { 57 error( 58 "Failed to get state sensor event state from dbus interface '{PATH}', error - {ERROR}.", 59 "PATH", dbusMapping.objectPath, "ERROR", e); 60 } 61 62 return PLDM_SENSOR_UNKNOWN; 63 } 64 65 /** @brief Function to get the state sensor readings requested by pldm requester 66 * 67 * @tparam[in] DBusInterface - DBus interface type 68 * @tparam[in] Handler - pldm::responder::platform::Handler 69 * @param[in] dBusIntf - The interface object of DBusInterface 70 * @param[in] handler - The interface object of 71 * pldm::responder::platform::Handler 72 * @param[in] sensorId - Sensor ID sent by the requester to act on 73 * @param[in] sensorRearmCnt - Each bit location in this field corresponds to a 74 * particular sensor within the state sensor 75 * @param[out] compSensorCnt - composite sensor count 76 * @param[out] stateField - The state field data for each of the states, 77 * equal to composite sensor count in number 78 * @return - Success or failure in setting the states. Returns failure in 79 * terms of PLDM completion codes if at least one state fails to be set 80 */ 81 template <class DBusInterface, class Handler> 82 int getStateSensorReadingsHandler( 83 const DBusInterface& dBusIntf, Handler& handler, uint16_t sensorId, 84 uint8_t sensorRearmCnt, uint8_t& compSensorCnt, 85 std::vector<get_sensor_state_field>& stateField, 86 const stateSensorCacheMaps& sensorCache) 87 { 88 using namespace pldm::responder::pdr; 89 using namespace pldm::utils; 90 91 pldm_state_sensor_pdr* pdr = nullptr; 92 93 std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)> stateSensorPdrRepo( 94 pldm_pdr_init(), pldm_pdr_destroy); 95 if (!stateSensorPdrRepo) 96 { 97 throw std::runtime_error( 98 "Failed to instantiate state sensor PDR repository"); 99 } 100 pldm::responder::pdr_utils::Repo stateSensorPDRs(stateSensorPdrRepo.get()); 101 getRepoByType(handler.getRepo(), stateSensorPDRs, PLDM_STATE_SENSOR_PDR); 102 if (stateSensorPDRs.empty()) 103 { 104 error("Failed to get StateSensorPDR record."); 105 return PLDM_PLATFORM_INVALID_SENSOR_ID; 106 } 107 108 pldm::responder::pdr_utils::PdrEntry pdrEntry{}; 109 auto pdrRecord = stateSensorPDRs.getFirstRecord(pdrEntry); 110 while (pdrRecord) 111 { 112 pdr = reinterpret_cast<pldm_state_sensor_pdr*>(pdrEntry.data); 113 assert(pdr != NULL); 114 if (pdr->sensor_id != sensorId) 115 { 116 pdr = nullptr; 117 pdrRecord = stateSensorPDRs.getNextRecord(pdrRecord, pdrEntry); 118 continue; 119 } 120 121 compSensorCnt = pdr->composite_sensor_count; 122 if (sensorRearmCnt > compSensorCnt) 123 { 124 error( 125 "The requester sent wrong sensor rearm count '{SENSOR_REARM_COUNT}' for the sensor ID '{SENSORID}'", 126 "SENSORID", sensorId, "SENSOR_REARM_COUNT", sensorRearmCnt); 127 return PLDM_PLATFORM_REARM_UNAVAILABLE_IN_PRESENT_STATE; 128 } 129 130 if (sensorRearmCnt == 0) 131 { 132 sensorRearmCnt = compSensorCnt; 133 stateField.resize(sensorRearmCnt); 134 } 135 136 break; 137 } 138 139 if (!pdr) 140 { 141 return PLDM_PLATFORM_INVALID_SENSOR_ID; 142 } 143 144 int rc = PLDM_SUCCESS; 145 try 146 { 147 const auto& [dbusMappings, dbusValMaps] = handler.getDbusObjMaps( 148 sensorId, pldm::responder::pdr_utils::TypeId::PLDM_SENSOR_ID); 149 150 if (dbusMappings.empty() || dbusValMaps.empty()) 151 { 152 error("DbusMappings for sensor ID '{SENSOR_ID}' is missing", 153 "SENSOR_ID", sensorId); 154 return PLDM_ERROR; 155 } 156 pldm::responder::pdr_utils::EventStates sensorCacheforSensor{}; 157 if (sensorCache.contains(sensorId)) 158 { 159 sensorCacheforSensor = sensorCache.at(sensorId); 160 } 161 stateField.clear(); 162 for (std::size_t offset{0}; 163 offset < sensorRearmCnt && offset < dbusMappings.size() && 164 offset < dbusValMaps.size(); 165 offset++) 166 { 167 auto& dbusMapping = dbusMappings[offset]; 168 169 uint8_t sensorEvent = getStateSensorEventState<DBusInterface>( 170 dBusIntf, dbusValMaps[offset], dbusMapping); 171 172 uint8_t previousState = PLDM_SENSOR_UNKNOWN; 173 174 // if sensor cache is empty, then its the first 175 // get_state_sensor_reading on this sensor, set the previous state 176 // as the current state 177 178 if (sensorCacheforSensor.at(offset) == PLDM_SENSOR_UNKNOWN) 179 { 180 previousState = sensorEvent; 181 handler.updateSensorCache(sensorId, offset, previousState); 182 } 183 else 184 { 185 // sensor cache is not empty, so get the previous state from 186 // the sensor cache 187 previousState = sensorCacheforSensor[offset]; 188 } 189 uint8_t opState = PLDM_SENSOR_ENABLED; 190 if (sensorEvent == PLDM_SENSOR_UNKNOWN) 191 { 192 opState = PLDM_SENSOR_UNAVAILABLE; 193 } 194 195 stateField.push_back( 196 {opState, PLDM_SENSOR_NORMAL, previousState, sensorEvent}); 197 } 198 } 199 catch (const std::out_of_range& e) 200 { 201 error("The sensor ID '{SENSORID}' does not exist, error - {ERROR}", 202 "SENSORID", sensorId, "ERROR", e); 203 rc = PLDM_ERROR; 204 } 205 206 return rc; 207 } 208 209 } // namespace platform_state_sensor 210 } // namespace responder 211 } // namespace pldm 212