1 #pragma once 2 3 #include "common/utils.hpp" 4 #include "event_parser.hpp" 5 #include "fru.hpp" 6 #include "host-bmc/dbus_to_event_handler.hpp" 7 #include "host-bmc/host_pdr_handler.hpp" 8 #include "libpldmresponder/pdr.hpp" 9 #include "libpldmresponder/pdr_utils.hpp" 10 #include "libpldmresponder/platform_config.hpp" 11 #include "oem_handler.hpp" 12 #include "pldmd/handler.hpp" 13 14 #include <libpldm/pdr.h> 15 #include <libpldm/platform.h> 16 #include <libpldm/states.h> 17 18 #include <phosphor-logging/lg2.hpp> 19 20 #include <cstdint> 21 #include <map> 22 23 PHOSPHOR_LOG2_USING; 24 25 namespace pldm 26 { 27 namespace responder 28 { 29 namespace platform 30 { 31 using generatePDR = std::function<void( 32 const pldm::utils::DBusHandler& dBusIntf, const pldm::utils::Json& json, 33 pdr_utils::RepoInterface& repo)>; 34 35 using EffecterId = uint16_t; 36 using DbusObjMaps = 37 std::map<EffecterId, 38 std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps>>; 39 using DbusPath = std::string; 40 using EffecterObjs = std::vector<DbusPath>; 41 using EventType = uint8_t; 42 using EventHandler = std::function<int( 43 const pldm_msg* request, size_t payloadLength, uint8_t formatVersion, 44 uint8_t tid, size_t eventDataOffset)>; 45 using EventHandlers = std::vector<EventHandler>; 46 using EventMap = std::map<EventType, EventHandlers>; 47 using AssociatedEntityMap = std::map<DbusPath, pldm_entity>; 48 49 using ChangeEntry = uint32_t; 50 51 class Handler : public CmdHandler 52 { 53 public: Handler(const pldm::utils::DBusHandler * dBusIntf,uint8_t eid,pldm::InstanceIdDb * instanceIdDb,const fs::path & pdrJsonDir,pldm_pdr * repo,HostPDRHandler * hostPDRHandler,pldm::state_sensor::DbusToPLDMEvent * dbusToPLDMEventHandler,fru::Handler * fruHandler,pldm::responder::platform_config::Handler * platformConfigHandler,pldm::requester::Handler<pldm::requester::Request> * handler,sdeventplus::Event & event,bool buildPDRLazily=false,const std::optional<EventMap> & addOnHandlersMap=std::nullopt)54 Handler(const pldm::utils::DBusHandler* dBusIntf, uint8_t eid, 55 pldm::InstanceIdDb* instanceIdDb, const fs::path& pdrJsonDir, 56 pldm_pdr* repo, HostPDRHandler* hostPDRHandler, 57 pldm::state_sensor::DbusToPLDMEvent* dbusToPLDMEventHandler, 58 fru::Handler* fruHandler, 59 pldm::responder::platform_config::Handler* platformConfigHandler, 60 pldm::requester::Handler<pldm::requester::Request>* handler, 61 sdeventplus::Event& event, bool buildPDRLazily = false, 62 const std::optional<EventMap>& addOnHandlersMap = std::nullopt) : 63 eid(eid), instanceIdDb(instanceIdDb), pdrRepo(repo), 64 hostPDRHandler(hostPDRHandler), 65 dbusToPLDMEventHandler(dbusToPLDMEventHandler), fruHandler(fruHandler), 66 dBusIntf(dBusIntf), platformConfigHandler(platformConfigHandler), 67 handler(handler), event(event), pdrJsonDir(pdrJsonDir), 68 pdrCreated(false), pdrJsonsDir({pdrJsonDir}) 69 { 70 if (!buildPDRLazily) 71 { 72 generateTerminusLocatorPDR(pdrRepo); 73 generate(*dBusIntf, pdrJsonsDir, pdrRepo); 74 pdrCreated = true; 75 } 76 77 handlers.emplace( 78 PLDM_GET_PDR, __anon58b9ed2e0102(pldm_tid_t, const pldm_msg* request, size_t payloadLength) 79 [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) { 80 return this->getPDR(request, payloadLength); 81 }); 82 handlers.emplace( 83 PLDM_SET_NUMERIC_EFFECTER_VALUE, __anon58b9ed2e0202(pldm_tid_t, const pldm_msg* request, size_t payloadLength) 84 [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) { 85 return this->setNumericEffecterValue(request, payloadLength); 86 }); 87 handlers.emplace( 88 PLDM_GET_NUMERIC_EFFECTER_VALUE, __anon58b9ed2e0302(pldm_tid_t, const pldm_msg* request, size_t payloadLength) 89 [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) { 90 return this->getNumericEffecterValue(request, payloadLength); 91 }); 92 handlers.emplace( 93 PLDM_SET_STATE_EFFECTER_STATES, __anon58b9ed2e0402(pldm_tid_t, const pldm_msg* request, size_t payloadLength) 94 [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) { 95 return this->setStateEffecterStates(request, payloadLength); 96 }); 97 handlers.emplace( 98 PLDM_PLATFORM_EVENT_MESSAGE, __anon58b9ed2e0502(pldm_tid_t, const pldm_msg* request, size_t payloadLength) 99 [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) { 100 return this->platformEventMessage(request, payloadLength); 101 }); 102 handlers.emplace( 103 PLDM_GET_STATE_SENSOR_READINGS, __anon58b9ed2e0602(pldm_tid_t, const pldm_msg* request, size_t payloadLength) 104 [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) { 105 return this->getStateSensorReadings(request, payloadLength); 106 }); 107 108 // Default handler for PLDM Events 109 eventHandlers[PLDM_SENSOR_EVENT].emplace_back( 110 [this](const pldm_msg* request, size_t payloadLength, __anon58b9ed2e0702(const pldm_msg* request, size_t payloadLength, uint8_t formatVersion, uint8_t tid, size_t eventDataOffset) 111 uint8_t formatVersion, uint8_t tid, size_t eventDataOffset) { 112 return this->sensorEvent(request, payloadLength, formatVersion, 113 tid, eventDataOffset); 114 }); 115 eventHandlers[PLDM_PDR_REPOSITORY_CHG_EVENT].emplace_back( 116 [this](const pldm_msg* request, size_t payloadLength, __anon58b9ed2e0802(const pldm_msg* request, size_t payloadLength, uint8_t formatVersion, uint8_t tid, size_t eventDataOffset) 117 uint8_t formatVersion, uint8_t tid, size_t eventDataOffset) { 118 return this->pldmPDRRepositoryChgEvent( 119 request, payloadLength, formatVersion, tid, 120 eventDataOffset); 121 }); 122 123 // Additional OEM event handlers for PLDM events, append it to the 124 // standard handlers 125 if (addOnHandlersMap) 126 { 127 auto addOnHandlers = addOnHandlersMap.value(); 128 for (EventMap::iterator iter = addOnHandlers.begin(); 129 iter != addOnHandlers.end(); ++iter) 130 { 131 auto search = eventHandlers.find(iter->first); 132 if (search != eventHandlers.end()) 133 { 134 search->second.insert(std::end(search->second), 135 std::begin(iter->second), 136 std::end(iter->second)); 137 } 138 else 139 { 140 eventHandlers.emplace(iter->first, iter->second); 141 } 142 } 143 } 144 } 145 getRepo()146 pdr_utils::Repo& getRepo() 147 { 148 return this->pdrRepo; 149 } 150 151 /** @brief Add D-Bus mapping and value mapping(stateId to D-Bus) for the 152 * Id. If the same id is added, the previous dbusObjs will 153 * be "over-written". 154 * 155 * @param[in] Id - effecter/sensor id 156 * @param[in] dbusObj - list of D-Bus object structure and list of D-Bus 157 * property value to attribute value 158 * @param[in] typeId - the type id of enum 159 */ 160 void addDbusObjMaps( 161 uint16_t id, 162 std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps> dbusObj, 163 pldm::responder::pdr_utils::TypeId typeId = 164 pldm::responder::pdr_utils::TypeId::PLDM_EFFECTER_ID); 165 166 /** @brief Retrieve an id -> D-Bus objects mapping 167 * 168 * @param[in] Id - id 169 * @param[in] typeId - the type id of enum 170 * 171 * @return std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps> - 172 * list of D-Bus object structure and list of D-Bus property value 173 * to attribute value 174 */ 175 const std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps>& 176 getDbusObjMaps( 177 uint16_t id, 178 pldm::responder::pdr_utils::TypeId typeId = 179 pldm::responder::pdr_utils::TypeId::PLDM_EFFECTER_ID) const; 180 getNextEffecterId()181 uint16_t getNextEffecterId() 182 { 183 return ++nextEffecterId; 184 } 185 getNextSensorId()186 uint16_t getNextSensorId() 187 { 188 return ++nextSensorId; 189 } 190 191 /** @brief Parse PDR JSONs and build PDR repository 192 * 193 * @param[in] dBusIntf - The interface object 194 * @param[in] dir - directory housing platform specific PDR JSON files 195 * @param[in] repo - instance of concrete implementation of Repo 196 */ 197 void generate(const pldm::utils::DBusHandler& dBusIntf, 198 const std::vector<fs::path>& dir, 199 pldm::responder::pdr_utils::Repo& repo); 200 201 /** @brief Parse PDR JSONs and build state effecter PDR repository 202 * 203 * @param[in] json - platform specific PDR JSON files 204 * @param[in] repo - instance of state effecter implementation of Repo 205 */ 206 void generateStateEffecterRepo(const pldm::utils::Json& json, 207 pldm::responder::pdr_utils::Repo& repo); 208 209 /** @brief map of PLDM event type to EventHandlers 210 * 211 */ 212 EventMap eventHandlers; 213 214 /* @brief Method to set the oem platform handler in platform handler class 215 * 216 * @param[in] handler - oem platform handler 217 */ setOemPlatformHandler(pldm::responder::oem_platform::Handler * handler)218 inline void setOemPlatformHandler( 219 pldm::responder::oem_platform::Handler* handler) 220 { 221 oemPlatformHandler = handler; 222 } 223 224 /* @brief Method to register event handlers 225 * 226 * @param[in] handler - oem event handlers 227 */ registerEventHandlers(EventType eventId,EventHandlers handlers)228 inline void registerEventHandlers(EventType eventId, EventHandlers handlers) 229 { 230 // Try to emplace the eventId with an empty vector if it doesn't exist 231 auto [iter, 232 inserted] = eventHandlers.try_emplace(eventId, EventHandlers{}); 233 234 for (const auto& handler : handlers) 235 { 236 iter->second.emplace_back(handler); 237 } 238 } 239 240 /** @brief Handler for GetPDR 241 * 242 * @param[in] request - Request message payload 243 * @param[in] payloadLength - Request payload length 244 * @param[out] Response - Response message written here 245 */ 246 Response getPDR(const pldm_msg* request, size_t payloadLength); 247 248 /** @brief Handler for setNumericEffecterValue 249 * 250 * @param[in] request - Request message 251 * @param[in] payloadLength - Request payload length 252 * @return Response - PLDM Response message 253 */ 254 Response setNumericEffecterValue(const pldm_msg* request, 255 size_t payloadLength); 256 257 /** @brief Handler for getNumericEffecterValue 258 * 259 * @param[in] request - Request message 260 * @param[in] payloadLength - Request payload length 261 * @return Response - PLDM Response message 262 */ 263 Response getNumericEffecterValue(const pldm_msg* request, 264 size_t payloadLength); 265 266 /** @brief Handler for getStateSensorReadings 267 * 268 * @param[in] request - Request message 269 * @param[in] payloadLength - Request payload length 270 * @return Response - PLDM Response message 271 */ 272 Response getStateSensorReadings(const pldm_msg* request, 273 size_t payloadLength); 274 275 /** @brief Handler for setStateEffecterStates 276 * 277 * @param[in] request - Request message 278 * @param[in] payloadLength - Request payload length 279 * @return Response - PLDM Response message 280 */ 281 Response setStateEffecterStates(const pldm_msg* request, 282 size_t payloadLength); 283 284 /** @brief Handler for PlatformEventMessage 285 * 286 * @param[in] request - Request message 287 * @param[in] payloadLength - Request payload length 288 * @return Response - PLDM Response message 289 */ 290 Response platformEventMessage(const pldm_msg* request, 291 size_t payloadLength); 292 293 /** @brief Handler for event class Sensor event 294 * 295 * @param[in] request - Request message 296 * @param[in] payloadLength - Request payload length 297 * @param[in] formatVersion - Version of the event format 298 * @param[in] tid - Terminus ID of the event's originator 299 * @param[in] eventDataOffset - Offset of the event data in the request 300 * message 301 * @return PLDM completion code 302 */ 303 int sensorEvent(const pldm_msg* request, size_t payloadLength, 304 uint8_t formatVersion, uint8_t tid, size_t eventDataOffset); 305 306 /** @brief Handler for pldmPDRRepositoryChgEvent 307 * 308 * @param[in] request - Request message 309 * @param[in] payloadLength - Request payload length 310 * @param[in] formatVersion - Version of the event format 311 * @param[in] tid - Terminus ID of the event's originator 312 * @param[in] eventDataOffset - Offset of the event data in the request 313 * message 314 * @return PLDM completion code 315 */ 316 int pldmPDRRepositoryChgEvent(const pldm_msg* request, size_t payloadLength, 317 uint8_t formatVersion, uint8_t tid, 318 size_t eventDataOffset); 319 320 /** @brief Handler for extracting the PDR handles from changeEntries 321 * 322 * @param[in] changeEntryData - ChangeEntry data from changeRecord 323 * @param[in] changeEntryDataSize - total size of changeEntryData 324 * @param[in] numberOfChangeEntries - total number of changeEntries to 325 * extract 326 * @param[out] pdrRecordHandles - std::vector where the extracted PDR 327 * handles are placed 328 * @return PLDM completion code 329 */ 330 int getPDRRecordHandles(const ChangeEntry* changeEntryData, 331 size_t changeEntryDataSize, 332 size_t numberOfChangeEntries, 333 PDRRecordHandles& pdrRecordHandles); 334 335 /** @brief Function to set the effecter requested by pldm requester 336 * @param[in] dBusIntf - The interface object 337 * @param[in] effecterId - Effecter ID sent by the requester to act on 338 * @param[in] stateField - The state field data for each of the states, 339 * equal to composite effecter count in number 340 * @return - Success or failure in setting the states. Returns failure in 341 * terms of PLDM completion codes if at least one state fails to be set 342 */ 343 template <class DBusInterface> setStateEffecterStatesHandler(const DBusInterface & dBusIntf,uint16_t effecterId,const std::vector<set_effecter_state_field> & stateField)344 int setStateEffecterStatesHandler( 345 const DBusInterface& dBusIntf, uint16_t effecterId, 346 const std::vector<set_effecter_state_field>& stateField) 347 { 348 using namespace pldm::responder::pdr; 349 using namespace pldm::utils; 350 using StateSetNum = uint8_t; 351 352 state_effecter_possible_states* states = nullptr; 353 pldm_state_effecter_pdr* pdr = nullptr; 354 uint8_t compEffecterCnt = stateField.size(); 355 356 std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)> 357 stateEffecterPdrRepo(pldm_pdr_init(), pldm_pdr_destroy); 358 if (!stateEffecterPdrRepo) 359 { 360 throw std::runtime_error( 361 "Failed to instantiate state effecter PDR repository"); 362 } 363 pldm::responder::pdr_utils::Repo stateEffecterPDRs( 364 stateEffecterPdrRepo.get()); 365 getRepoByType(pdrRepo, stateEffecterPDRs, PLDM_STATE_EFFECTER_PDR); 366 if (stateEffecterPDRs.empty()) 367 { 368 error("Failed to get record by PDR type"); 369 return PLDM_PLATFORM_INVALID_EFFECTER_ID; 370 } 371 372 pldm::responder::pdr_utils::PdrEntry pdrEntry{}; 373 auto pdrRecord = stateEffecterPDRs.getFirstRecord(pdrEntry); 374 while (pdrRecord) 375 { 376 pdr = new (pdrEntry.data) pldm_state_effecter_pdr; 377 if (pdr->effecter_id != effecterId) 378 { 379 pdr = nullptr; 380 pdrRecord = 381 stateEffecterPDRs.getNextRecord(pdrRecord, pdrEntry); 382 continue; 383 } 384 385 states = reinterpret_cast<state_effecter_possible_states*>( 386 pdr->possible_states); 387 if (compEffecterCnt > pdr->composite_effecter_count) 388 { 389 error( 390 "The requester sent wrong composite effecter count '{COMPOSITE_EFFECTER_COUNT}' for the effecter ID '{EFFECTERID}'.", 391 "COMPOSITE_EFFECTER_COUNT", compEffecterCnt, "EFFECTERID", 392 effecterId); 393 return PLDM_ERROR_INVALID_DATA; 394 } 395 break; 396 } 397 398 if (!pdr) 399 { 400 return PLDM_PLATFORM_INVALID_EFFECTER_ID; 401 } 402 403 int rc = PLDM_SUCCESS; 404 try 405 { 406 const auto& [dbusMappings, dbusValMaps] = 407 effecterDbusObjMaps.at(effecterId); 408 for (uint8_t currState = 0; currState < compEffecterCnt; 409 ++currState) 410 { 411 std::vector<StateSetNum> allowed{}; 412 // computation is based on table 79 from DSP0248 v1.1.1 413 uint8_t bitfieldIndex = 414 stateField[currState].effecter_state / 8; 415 uint8_t bit = stateField[currState].effecter_state - 416 (8 * bitfieldIndex); 417 if (states->possible_states_size < bitfieldIndex || 418 !(states->states[bitfieldIndex].byte & (1 << bit))) 419 { 420 error( 421 "Invalid state set value for effecter ID '{EFFECTERID}', effecter state '{EFFECTER_STATE}', composite effecter ID '{COMPOSITE_EFFECTER_ID}' and path '{PATH}'.", 422 "EFFECTERID", effecterId, "EFFECTER_STATE", 423 stateField[currState].effecter_state, 424 "COMPOSITE_EFFECTER_COUNT", currState, "PATH", 425 dbusMappings[currState].objectPath); 426 rc = PLDM_PLATFORM_SET_EFFECTER_UNSUPPORTED_SENSORSTATE; 427 break; 428 } 429 const DBusMapping& dbusMapping = dbusMappings[currState]; 430 const pldm::responder::pdr_utils::StatestoDbusVal& 431 dbusValToMap = dbusValMaps[currState]; 432 433 if (stateField[currState].set_request == PLDM_REQUEST_SET) 434 { 435 try 436 { 437 dBusIntf.setDbusProperty( 438 dbusMapping, 439 dbusValToMap.at( 440 stateField[currState].effecter_state)); 441 } 442 catch (const std::exception& e) 443 { 444 error( 445 "Failed to set property '{PROPERTY}' of interface '{INTERFACE}' at path '{PATH}', error - {ERROR}", 446 "PROPERTY", dbusMapping.propertyName, "DBUS_INTF", 447 dbusMapping.interface, "DBUS_OBJ_PATH", 448 dbusMapping.objectPath, "ERROR", e); 449 return PLDM_ERROR; 450 } 451 } 452 uint8_t* nextState = 453 reinterpret_cast<uint8_t*>(states) + 454 sizeof(state_effecter_possible_states) - 455 sizeof(states->states) + 456 (states->possible_states_size * sizeof(states->states)); 457 states = reinterpret_cast<state_effecter_possible_states*>( 458 nextState); 459 } 460 } 461 catch (const std::out_of_range& e) 462 { 463 error( 464 "The effecter ID '{EFFECTERID}' does not exist, error - {ERROR}.", 465 "EFFECTERID", effecterId, "ERROR", e); 466 } 467 468 return rc; 469 } 470 471 /** @brief Build BMC Terminus Locator PDR 472 * 473 * @param[in] repo - instance of concrete implementation of Repo 474 */ 475 void generateTerminusLocatorPDR(pldm::responder::pdr_utils::Repo& repo); 476 477 /** @brief Get std::map associated with the entity 478 * key: object path 479 * value: pldm_entity 480 * 481 * @return std::map<ObjectPath, pldm_entity> 482 */ getAssociateEntityMap() const483 inline const AssociatedEntityMap& getAssociateEntityMap() const 484 { 485 if (fruHandler == nullptr) 486 { 487 throw InternalFailure(); 488 } 489 return fruHandler->getAssociateEntityMap(); 490 } 491 492 /** @brief update the sensor cache map 493 * @param[in] sensorId - sensor id that needs an update 494 * @param[in] sensorRearm - rearm value within the sensor 495 * @param[in] value - value that needs to be cached 496 */ 497 updateSensorCache(pldm::pdr::SensorID sensorId,size_t sensorRearm,uint8_t value)498 inline void updateSensorCache(pldm::pdr::SensorID sensorId, 499 size_t sensorRearm, uint8_t value) 500 { 501 if (dbusToPLDMEventHandler) 502 { 503 dbusToPLDMEventHandler->updateSensorCacheMaps(sensorId, sensorRearm, 504 value); 505 } 506 } 507 508 /** @brief process the actions that needs to be performed after a GetPDR 509 * call is received 510 * @param[in] source - sdeventplus event source 511 */ 512 void _processPostGetPDRActions(sdeventplus::source::EventBase& source); 513 514 /** @brief Method for setEventreceiver */ 515 void setEventReceiver(); 516 517 /* @brief Send a PLDM event to host firmware containing a list of record 518 * handles of PDRs that the host firmware has to fetch. 519 * 520 * @param[in] pdrRecordHandles - list of PDR record handles 521 * @param[in] eventDataOps - event data operation for PDRRepositoryChgEvent 522 * as in DSP0248 SPEC 523 */ 524 void sendPDRRepositoryChgEventbyPDRHandles( 525 const std::vector<uint32_t>& pdrRecordHandles, 526 const std::vector<uint8_t>& eventDataOps); 527 528 private: 529 uint8_t eid; 530 InstanceIdDb* instanceIdDb; 531 pdr_utils::Repo pdrRepo; 532 uint16_t nextEffecterId{}; 533 uint16_t nextSensorId{}; 534 DbusObjMaps effecterDbusObjMaps{}; 535 DbusObjMaps sensorDbusObjMaps{}; 536 HostPDRHandler* hostPDRHandler; 537 pldm::state_sensor::DbusToPLDMEvent* dbusToPLDMEventHandler; 538 fru::Handler* fruHandler; 539 const pldm::utils::DBusHandler* dBusIntf; 540 pldm::responder::oem_platform::Handler* oemPlatformHandler = nullptr; 541 pldm::responder::platform_config::Handler* platformConfigHandler; 542 pldm::requester::Handler<pldm::requester::Request>* handler; 543 sdeventplus::Event& event; 544 fs::path pdrJsonDir; 545 bool pdrCreated; 546 std::vector<fs::path> pdrJsonsDir; 547 std::unique_ptr<sdeventplus::source::Defer> deferredGetPDREvent; 548 }; 549 550 /** @brief Function to check if a sensor falls in OEM range 551 * A sensor is considered to be oem if either of entity 552 * type or state set or both falls in oem range 553 * 554 * @param[in] handler - the interface object 555 * @param[in] sensorId - sensor id 556 * @param[in] sensorRearmCount - sensor rearm count 557 * @param[out] compSensorCnt - composite sensor count 558 * @param[out] entityType - entity type 559 * @param[out] entityInstance - entity instance number 560 * @param[out] stateSetId - state set id 561 * @param[out] containerId - container id 562 * 563 * @return true if the sensor is OEM. All out parameters are invalid 564 * for a non OEM sensor 565 */ 566 bool isOemStateSensor(Handler& handler, uint16_t sensorId, 567 uint8_t sensorRearmCount, uint8_t& compSensorCnt, 568 uint16_t& entityType, uint16_t& entityInstance, 569 uint16_t& stateSetId, uint16_t& containerId); 570 571 /** @brief Function to check if an effecter falls in OEM range 572 * An effecter is considered to be oem if either of entity 573 * type or state set or both falls in oem range 574 * 575 * @param[in] handler - the interface object 576 * @param[in] effecterId - effecter id 577 * @param[in] compEffecterCnt - composite effecter count 578 * @param[out] entityType - entity type 579 * @param[out] entityInstance - entity instance number 580 * @param[out] stateSetId - state set id 581 * 582 * @return true if the effecter is OEM. All out parameters are invalid 583 * for a non OEM effecter 584 */ 585 bool isOemStateEffecter(Handler& handler, uint16_t effecterId, 586 uint8_t compEffecterCnt, uint16_t& entityType, 587 uint16_t& entityInstance, uint16_t& stateSetId); 588 589 } // namespace platform 590 } // namespace responder 591 } // namespace pldm 592