#include "dbus_to_event_handler.hpp" #include "libpldmresponder/pdr.hpp" #include PHOSPHOR_LOG2_USING; namespace pldm { using namespace pldm::responder; using namespace pldm::responder::pdr; using namespace pldm::responder::pdr_utils; using namespace pldm::utils; using namespace sdbusplus::bus::match::rules; namespace state_sensor { const std::vector pdrTypes{PLDM_STATE_SENSOR_PDR}; DbusToPLDMEvent::DbusToPLDMEvent( int mctp_fd, uint8_t mctp_eid, pldm::InstanceIdDb& instanceIdDb, pldm::requester::Handler* handler) : mctp_fd(mctp_fd), mctp_eid(mctp_eid), instanceIdDb(instanceIdDb), handler(handler) {} void DbusToPLDMEvent::sendEventMsg(uint8_t eventType, const std::vector& eventDataVec) { auto instanceId = instanceIdDb.next(mctp_eid); std::vector requestMsg(sizeof(pldm_msg_hdr) + PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES + eventDataVec.size()); auto request = reinterpret_cast(requestMsg.data()); auto rc = encode_platform_event_message_req( instanceId, 1 /*formatVersion*/, TERMINUS_ID /*tId*/, eventType, eventDataVec.data(), eventDataVec.size(), request, eventDataVec.size() + PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES); if (rc != PLDM_SUCCESS) { instanceIdDb.free(mctp_eid, instanceId); error( "Failed to encode platform event message request, response code '{RC}'", "RC", rc); return; } auto platformEventMessageResponseHandler = [](mctp_eid_t /*eid*/, const pldm_msg* response, size_t respMsgLen) { if (response == nullptr || !respMsgLen) { error("Failed to receive response for platform event message"); return; } uint8_t completionCode{}; uint8_t status{}; auto rc = decode_platform_event_message_resp(response, respMsgLen, &completionCode, &status); if (rc || completionCode) { error( "Failed to decode response of platform_event message, response code '{RC}' and completion code '{CC}'", "RC", rc, "CC", completionCode); } }; rc = handler->registerRequest( mctp_eid, instanceId, PLDM_PLATFORM, PLDM_PLATFORM_EVENT_MESSAGE, std::move(requestMsg), std::move(platformEventMessageResponseHandler)); if (rc) { error("Failed to send the platform event message, response code '{RC}'", "RC", rc); } } void DbusToPLDMEvent::sendStateSensorEvent(SensorId sensorId, const DbusObjMaps& dbusMaps) { // Encode PLDM platform event msg to indicate a state sensor change. // DSP0248_1.2.0 Table 19 if (!dbusMaps.contains(sensorId)) { // this is not an error condition, if we end up here // that means that the sensor with the sensor id has // custom behaviour(or probably an oem sensor) in // sending events that cannot be captured via standard // dbus-json infastructure return; } size_t sensorEventSize = PLDM_SENSOR_EVENT_DATA_MIN_LENGTH + 1; const auto& [dbusMappings, dbusValMaps] = dbusMaps.at(sensorId); for (uint8_t offset = 0; offset < dbusMappings.size(); ++offset) { std::vector sensorEventDataVec{}; sensorEventDataVec.resize(sensorEventSize); auto eventData = reinterpret_cast( sensorEventDataVec.data()); eventData->sensor_id = sensorId; eventData->sensor_event_class_type = PLDM_STATE_SENSOR_STATE; eventData->event_class[0] = offset; eventData->event_class[1] = PLDM_SENSOR_UNKNOWN; eventData->event_class[2] = PLDM_SENSOR_UNKNOWN; const auto& dbusMapping = dbusMappings[offset]; const auto& dbusValueMapping = dbusValMaps[offset]; auto stateSensorMatch = std::make_unique( pldm::utils::DBusHandler::getBus(), propertiesChanged(dbusMapping.objectPath.c_str(), dbusMapping.interface.c_str()), [this, sensorEventDataVec, dbusValueMapping, dbusMapping, sensorId, offset](auto& msg) mutable { DbusChangedProps props{}; std::string intf; uint8_t previousState = PLDM_SENSOR_UNKNOWN; msg.read(intf, props); if (!props.contains(dbusMapping.propertyName)) { return; } for (const auto& itr : dbusValueMapping) { bool findValue = false; if (dbusMapping.propertyType == "string") { std::string src = std::get(itr.second); std::string dst = std::get( props.at(dbusMapping.propertyName)); auto values = pldm::utils::split(src, "||", " "); for (const auto& value : values) { if (value == dst) { findValue = true; break; } } } else { findValue = itr.second == props.at(dbusMapping.propertyName) ? true : false; } if (findValue) { auto eventData = reinterpret_cast( sensorEventDataVec.data()); eventData->event_class[1] = itr.first; if (sensorCacheMap.contains(sensorId) && sensorCacheMap[sensorId][offset] != PLDM_SENSOR_UNKNOWN) { previousState = sensorCacheMap[sensorId][offset]; } else { previousState = itr.first; } eventData->event_class[2] = previousState; this->sendEventMsg(PLDM_SENSOR_EVENT, sensorEventDataVec); updateSensorCacheMaps(sensorId, offset, previousState); break; } } }); stateSensorMatchs.emplace_back(std::move(stateSensorMatch)); } } void DbusToPLDMEvent::listenSensorEvent(const pdr_utils::Repo& repo, const DbusObjMaps& dbusMaps) { const std::map sensorHandlers = { {PLDM_STATE_SENSOR_PDR, [this](SensorId sensorId, const DbusObjMaps& dbusMaps) { this->sendStateSensorEvent(sensorId, dbusMaps); }}}; pldm_state_sensor_pdr* pdr = nullptr; std::unique_ptr sensorPdrRepo( pldm_pdr_init(), pldm_pdr_destroy); if (!sensorPdrRepo) { throw std::runtime_error("Unable to instantiate sensor PDR repository"); } for (auto pdrType : pdrTypes) { Repo sensorPDRs(sensorPdrRepo.get()); getRepoByType(repo, sensorPDRs, pdrType); if (sensorPDRs.empty()) { return; } PdrEntry pdrEntry{}; auto pdrRecord = sensorPDRs.getFirstRecord(pdrEntry); while (pdrRecord) { pdr = reinterpret_cast(pdrEntry.data); SensorId sensorId = LE16TOH(pdr->sensor_id); if (sensorHandlers.contains(pdrType)) { sensorHandlers.at(pdrType)(sensorId, dbusMaps); } pdrRecord = sensorPDRs.getNextRecord(pdrRecord, pdrEntry); } } } } // namespace state_sensor } // namespace pldm