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 "Get StateSensor EventState from dbus Error, interface : {DBUS_OBJ_PATH}, exception : {ERR_EXCEP}", 58 "DBUS_OBJ_PATH", dbusMapping.objectPath.c_str(), "ERR_EXCEP", 59 e.what()); 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 atleast 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 record by PDR type"); 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 sensorRearm count for the sensor, SENSOR_ID={SENSOR_ID} SENSOR_REARM_COUNT={SENSOR_REARM_CNT}", 126 "SENSOR_ID", sensorId, "SENSOR_REARM_CNT", 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 pldm::responder::pdr_utils::EventStates sensorCacheforSensor{}; 151 if (sensorCache.contains(sensorId)) 152 { 153 sensorCacheforSensor = sensorCache.at(sensorId); 154 } 155 stateField.clear(); 156 for (std::size_t i{0}; i < sensorRearmCnt; i++) 157 { 158 auto& dbusMapping = dbusMappings[i]; 159 160 uint8_t sensorEvent = getStateSensorEventState<DBusInterface>( 161 dBusIntf, dbusValMaps[i], dbusMapping); 162 163 uint8_t previousState = PLDM_SENSOR_UNKNOWN; 164 165 // if sensor cache is empty, then its the first 166 // get_state_sensor_reading on this sensor, set the previous state 167 // as the current state 168 169 if (sensorCacheforSensor.at(i) == PLDM_SENSOR_UNKNOWN) 170 { 171 previousState = sensorEvent; 172 handler.updateSensorCache(sensorId, i, previousState); 173 } 174 else 175 { 176 // sensor cache is not empty, so get the previous state from 177 // the sensor cache 178 previousState = sensorCacheforSensor[i]; 179 } 180 uint8_t opState = PLDM_SENSOR_ENABLED; 181 if (sensorEvent == PLDM_SENSOR_UNKNOWN) 182 { 183 opState = PLDM_SENSOR_UNAVAILABLE; 184 } 185 186 stateField.push_back( 187 {opState, PLDM_SENSOR_NORMAL, previousState, sensorEvent}); 188 } 189 } 190 catch (const std::out_of_range& e) 191 { 192 error("the sensorId does not exist. sensor id: {SENSOR_ID} {ERR_EXCEP}", 193 "SENSOR_ID", sensorId, "ERR_EXCEP", e.what()); 194 rc = PLDM_ERROR; 195 } 196 197 return rc; 198 } 199 200 } // namespace platform_state_sensor 201 } // namespace responder 202 } // namespace pldm 203