| From febe200fdf9115bd327a86ad621e963def1b5f09 Mon Sep 17 00:00:00 2001 |
| From: Cody Smith <scody@google.com> |
| Date: Fri, 18 Feb 2022 13:20:45 +0000 |
| Subject: [PATCH] Feature: Add association interfaces to a target EM |
| |
| This change gives the `gpiopresence` daemon in `dbus-sensors` |
| the ability to, upon request via configuration EM, generate am |
| `xyz.openbmc_project.Association.Definitions` object, which is |
| used by the Object Mapper to generate associations between two |
| dbus interfaces. |
| |
| As `gpiopresence` is unaware of what dbus interfaces may or may |
| not be probing for the interface it generates, it is left to |
| the user configuring `gpiopresence` to specify the association |
| via the `AssociationPath`, `AssociationForward`, and the |
| `AssociationReverse` fields in `GPIOStatus`. |
| |
| Once set these will equate to the three string values in |
| `xyz.openbmc_project.Association.Definitions`. |
| |
| Tested: |
| Add EM fields to an existing `GPIOStatus` object. |
| Check that an association is created by `gpiopresence` |
| as specified. |
| |
| Patch Tracking Bug: b/232034841 |
| Upstream info / review: https://gerrit.openbmc.org/c/openbmc/dbus-sensors/+/51360 |
| Upstream-Status: Submitted |
| Justification: In review |
| |
| Signed-off-by: Cody Smith <scody@google.com> |
| In-Review: https://gerrit.openbmc-project.xyz/c/openbmc/dbus-sensors/+/51360/12 |
| Change-Id: I0572d124a8e9b9fedbdfb30d41fe399e005f5c03 |
| --- |
| include/GPIOPresenceSensor.hpp | 17 +++++- |
| src/GPIOPresenceSensor.cpp | 4 +- |
| src/GPIOPresenceSensorMain.cpp | 94 +++++++++++++++++++++++++++++----- |
| 3 files changed, 101 insertions(+), 14 deletions(-) |
| |
| diff --git a/include/GPIOPresenceSensor.hpp b/include/GPIOPresenceSensor.hpp |
| index a9f49a0..fa32a20 100644 |
| --- a/include/GPIOPresenceSensor.hpp |
| +++ b/include/GPIOPresenceSensor.hpp |
| @@ -31,6 +31,11 @@ static constexpr inline const char* propertyGpioLine = "GpioLine"; |
| static constexpr inline const char* propertyPolarity = "Polarity"; |
| static constexpr inline const char* propertyPresent = "Present"; |
| static constexpr inline const char* propertyPollRate = "PollRate"; |
| +static constexpr inline const char* propertyAssociationPath = "AssociationPath"; |
| +static constexpr inline const char* propertyAssociationForward = |
| + "AssociationForward"; |
| +static constexpr inline const char* propertyAssociationReverse = |
| + "AssociationReverse"; |
| } // namespace Properties |
| |
| namespace interfaces |
| @@ -50,8 +55,15 @@ struct Config |
| bool activeLow; |
| // Presence signal. |
| bool present; |
| - // Update loop polling rate. |
| + // (Optional) Update loop polling rate. |
| int pollRate; |
| + // (Optional) Association |
| + bool generateAssociation; |
| + std::string associationPath; |
| + std::string associationForward; |
| + std::string associationReverse; |
| + // (Internal) Parent path |
| + std::string parentPath; |
| }; |
| |
| // Actively listen to the config information from EntityManager and calls the |
| @@ -65,9 +77,11 @@ class GPIOPresence |
| |
| // Add a dbus object to the reference list. |
| // @params statusIfc: pointer to object status interface. |
| + // @params associationIfc: Optional pointer to object association interface |
| // @params objPath: the dbus object path. |
| // @params config: EM config |
| void addObj(std::unique_ptr<sdbusplus::asio::dbus_interface> statusIfc, |
| + std::unique_ptr<sdbusplus::asio::dbus_interface> associationIfc, |
| std::string_view objPath, const Config& config); |
| |
| // Remove a object from the object reference list. |
| @@ -89,6 +103,7 @@ class GPIOPresence |
| struct ObjIfaces |
| { |
| std::unique_ptr<sdbusplus::asio::dbus_interface> statusIfc; |
| + std::unique_ptr<sdbusplus::asio::dbus_interface> associationIfc; |
| Config config; |
| }; |
| |
| diff --git a/src/GPIOPresenceSensor.cpp b/src/GPIOPresenceSensor.cpp |
| index 870b4b4..2d48491 100644 |
| --- a/src/GPIOPresenceSensor.cpp |
| +++ b/src/GPIOPresenceSensor.cpp |
| @@ -26,10 +26,12 @@ int GPIOPresence::readLine(std::string_view lineLabel) |
| |
| void GPIOPresence::addObj( |
| std::unique_ptr<sdbusplus::asio::dbus_interface> statusIfc, |
| + std::unique_ptr<sdbusplus::asio::dbus_interface> associationIfc, |
| std::string_view objPath, const Config& config) |
| { |
| std::cerr << "New objPath added " << objPath << std::endl; |
| - objIfaces[std::string(objPath)] = {std::move(statusIfc), config}; |
| + objIfaces[std::string(objPath)] = {std::move(statusIfc), |
| + std::move(associationIfc), config}; |
| } |
| |
| void GPIOPresence::removeObj(std::string_view objPath) |
| diff --git a/src/GPIOPresenceSensorMain.cpp b/src/GPIOPresenceSensorMain.cpp |
| index 8b22d25..f556900 100644 |
| --- a/src/GPIOPresenceSensorMain.cpp |
| +++ b/src/GPIOPresenceSensorMain.cpp |
| @@ -1,8 +1,10 @@ |
| #include "Utils.hpp" |
| |
| #include <GPIOPresenceSensor.hpp> |
| +#include <sdbusplus/bus/match.hpp> |
| |
| #include <iostream> |
| +#include <utility> |
| |
| namespace gpiopresencesensing |
| { |
| @@ -15,7 +17,7 @@ using OnInterfaceRemovedCallback = std::function<void(std::string_view)>; |
| |
| // Helper function to convert dbus property to struct |
| // @param[in] properties: dbus properties |
| -Config getConfig(const SensorBaseConfigMap& properties) |
| +Config getConfig(const SensorBaseConfigMap& properties, std::string parentPath) |
| { |
| auto name = loadVariant<std::string>(properties, Properties::propertyName); |
| auto gpioLine = |
| @@ -31,8 +33,48 @@ Config getConfig(const SensorBaseConfigMap& properties) |
| pollRate = |
| loadVariant<uint32_t>(properties, Properties::propertyPollRate); |
| } |
| - return {name, gpioLine, polarity == "active_low", |
| - /*present*/ false, pollRate}; |
| + |
| + // Optional Association |
| + bool generateAssociation = false; |
| + std::string associationForward = ""; |
| + std::string associationReverse = ""; |
| + std::string associationPath = ""; |
| + |
| + auto propertyAssociationPath = |
| + properties.find(Properties::propertyAssociationPath); |
| + if (propertyAssociationPath != properties.end()) |
| + { |
| + associationPath = loadVariant<std::string>( |
| + properties, Properties::propertyAssociationPath); |
| + |
| + auto propertyAssociationForward = |
| + properties.find(Properties::propertyAssociationForward); |
| + if (propertyAssociationForward != properties.end()) |
| + { |
| + associationForward = loadVariant<std::string>( |
| + properties, Properties::propertyAssociationForward); |
| + |
| + auto propertyAssociationReverse = |
| + properties.find(Properties::propertyAssociationReverse); |
| + if (propertyAssociationReverse != properties.end()) |
| + { |
| + associationReverse = loadVariant<std::string>( |
| + properties, Properties::propertyAssociationReverse); |
| + generateAssociation = true; |
| + } |
| + } |
| + } |
| + |
| + return {name, |
| + gpioLine, |
| + polarity == "active_low", |
| + /*present*/ false, |
| + pollRate, |
| + generateAssociation, |
| + associationPath, |
| + associationForward, |
| + associationReverse, |
| + std::move(parentPath)}; |
| } |
| |
| void setupInterfaceAdded(sdbusplus::asio::connection* conn, |
| @@ -49,7 +91,7 @@ void setupInterfaceAdded(sdbusplus::asio::connection* conn, |
| Config config; |
| try |
| { |
| - config = getConfig(found->second); |
| + config = getConfig(found->second, objPath.parent_path()); |
| callback(objPath.str, found->first, config); |
| } |
| catch (std::exception& e) |
| @@ -62,23 +104,24 @@ void setupInterfaceAdded(sdbusplus::asio::connection* conn, |
| |
| // call the user callback for all the device that is already available |
| conn->async_method_call( |
| - [cb](const boost::system::error_code ec, |
| - ManagedObjectType managedObjs) { |
| + [callback = cb](const boost::system::error_code ec, |
| + ManagedObjectType managedObjs) { |
| if (ec) |
| { |
| return; |
| } |
| for (auto& obj : managedObjs) |
| { |
| - auto& item = obj.second; |
| + SensorData& item = obj.second; |
| + |
| auto found = item.find(interfaces::emGPIOCableSensingIfc); |
| if (found != item.end()) |
| { |
| Config config; |
| try |
| { |
| - config = getConfig(found->second); |
| - cb(obj.first.str, found->first, config); |
| + config = getConfig(found->second, obj.first.parent_path()); |
| + callback(obj.first.str, found->first, config); |
| } |
| catch (std::exception& e) |
| { |
| @@ -103,7 +146,7 @@ void setupInterfaceRemoved(sdbusplus::asio::connection* conn, |
| OnInterfaceRemovedCallback&& cb) |
| { |
| // Listen to the interface removed event. |
| - std::function<void(sdbusplus::message::message & msg)> handler = |
| + std::function<void(sdbusplus::message::message&)> handler = |
| [callback = std::move(cb)](sdbusplus::message::message msg) { |
| sdbusplus::message::object_path objPath; |
| msg.read(objPath); |
| @@ -162,14 +205,41 @@ int main() |
| { |
| controller->removeObj(objPath.str); |
| } |
| - // Status |
| + // Add Status |
| auto statusIfc = objectServer.add_unique_interface( |
| objPath, gpiopresencesensing::interfaces::statusIfc); |
| + std::cout << "Adding status interface: " << config.name |
| + << " at path: " << objPath.str << std::endl; |
| statusIfc->register_property( |
| gpiopresencesensing::Properties::propertyPresent, false); |
| statusIfc->register_property("Name", config.name); |
| statusIfc->initialize(); |
| - controller->addObj(std::move(statusIfc), objPath.str, config); |
| + // Add Inventory Association |
| + if (config.generateAssociation) |
| + { |
| + sdbusplus::message::object_path associationPath( |
| + config.associationPath); |
| + |
| + std::cout << "Adding association interface: " |
| + << config.associationPath |
| + << " at path: " << associationPath.str << std::endl; |
| + |
| + auto assocIfc = objectServer.add_unique_interface( |
| + associationPath, association::interface); |
| + assocIfc->register_property( |
| + "Associations", |
| + std::vector<Association>{{config.associationForward, |
| + config.associationReverse, |
| + config.parentPath}}); |
| + assocIfc->initialize(); |
| + controller->addObj(std::move(statusIfc), std::move(assocIfc), |
| + objPath.str, config); |
| + } |
| + else |
| + { |
| + controller->addObj(std::move(statusIfc), nullptr, objPath.str, |
| + config); |
| + } |
| controller->setMinPollRate(config.pollRate); |
| // It is possible there are more EM config in the pipeline. |
| // Therefore, delay the main loop by 10 seconds to wait for more |
| -- |
| 2.40.1.521.gf1e218fcd8-goog |
| |