xref: /openbmc/phosphor-modbus/common/entity_manager_interface.cpp (revision 978c7809923b3ef62a39ab404f35093ea39fcdc7)
1 #include "entity_manager_interface.hpp"
2 
3 #include <phosphor-logging/lg2.hpp>
4 #include <sdbusplus/async.hpp>
5 #include <sdbusplus/message/native_types.hpp>
6 #include <xyz/openbmc_project/Inventory/Item/client.hpp>
7 
8 #include <algorithm>
9 #include <flat_map>
10 #include <utility>
11 
12 namespace entity_manager
13 {
14 
15 PHOSPHOR_LOG2_USING;
16 
17 namespace rules_intf = sdbusplus::bus::match::rules;
18 
19 using BasicVariantType =
20     std::variant<std::vector<std::string>, std::vector<uint8_t>, std::string,
21                  int64_t, uint64_t, double, int32_t, uint32_t, int16_t,
22                  uint16_t, uint8_t, bool>;
23 using BaseConfigMap = std::flat_map<std::string, BasicVariantType>;
24 using ConfigData = std::flat_map<std::string, BaseConfigMap>;
25 using ManagedObjectType =
26     std::flat_map<sdbusplus::message::object_path, ConfigData>;
27 
EntityManagerInterface(sdbusplus::async::context & ctx,const interface_list_t & interfaceNames,Callback_t addedCallback,Callback_t removedCallback)28 EntityManagerInterface::EntityManagerInterface(
29     sdbusplus::async::context& ctx, const interface_list_t& interfaceNames,
30     Callback_t addedCallback, Callback_t removedCallback) :
31     ctx(ctx), interfaceNames(interfaceNames),
32     addedCallback(std::move(addedCallback)),
33     removedCallback(std::move(removedCallback))
34 {
35     ctx.spawn(handleInventoryAdded());
36     ctx.spawn(handleInventoryRemoved());
37 }
38 
handleInventoryGet()39 auto EntityManagerInterface::handleInventoryGet() -> sdbusplus::async::task<>
40 {
41     if (!addedCallback)
42     {
43         error("addedCallback is not set");
44         co_return;
45     }
46 
47     using InventoryIntf =
48         sdbusplus::client::xyz::openbmc_project::inventory::Item<>;
49 
50     constexpr auto entityManager =
51         sdbusplus::async::proxy()
52             .service(serviceName)
53             .path(InventoryIntf::namespace_path)
54             .interface("org.freedesktop.DBus.ObjectManager");
55 
56     for (const auto& [objectPath, interfaceConfig] :
57          co_await entityManager.call<ManagedObjectType>(ctx,
58                                                         "GetManagedObjects"))
59     {
60         for (const auto& interfaceName : interfaceNames)
61         {
62             if (interfaceConfig.contains(interfaceName))
63             {
64                 co_await addedCallback(objectPath, interfaceName);
65             }
66         }
67     }
68 
69     co_return;
70 }
71 
handleInventoryAdded()72 auto EntityManagerInterface::handleInventoryAdded() -> sdbusplus::async::task<>
73 {
74     if (!addedCallback)
75     {
76         error("addedCallback is not set");
77         co_return;
78     }
79 
80     auto addedMatch = sdbusplus::async::match(
81         ctx, rules_intf::interfacesAdded() + rules_intf::sender(serviceName));
82 
83     while (!ctx.stop_requested())
84     {
85         auto result = co_await addedMatch
86                           .next<sdbusplus::message::object_path, ConfigData>();
87         auto& [objectPath, inventoryData] = result;
88 
89         for (const auto& interfaceName : interfaceNames)
90         {
91             if (inventoryData.contains(interfaceName))
92             {
93                 co_await addedCallback(objectPath, interfaceName);
94             }
95         }
96     }
97 
98     co_return;
99 }
100 
handleInventoryRemoved()101 auto EntityManagerInterface::handleInventoryRemoved()
102     -> sdbusplus::async::task<>
103 {
104     if (!removedCallback)
105     {
106         error("removedCallback is not set");
107         co_return;
108     }
109 
110     auto removedMatch = sdbusplus::async::match(
111         ctx, rules_intf::interfacesRemoved() + rules_intf::sender(serviceName));
112 
113     while (!ctx.stop_requested())
114     {
115         auto result =
116             co_await removedMatch
117                 .next<sdbusplus::message::object_path, interface_list_t>();
118         auto& [objectPath, interfaces] = result;
119 
120         for (const auto& interfaceName : interfaceNames)
121         {
122             if (std::ranges::find(interfaces, interfaceName) !=
123                 interfaces.end())
124             {
125                 co_await removedCallback(objectPath, interfaceName);
126             }
127         }
128     }
129 
130     co_return;
131 }
132 
133 } // namespace entity_manager
134