1 /* 2 * SPDX-FileCopyrightText: Copyright (c) 2022-2024. All rights 3 * reserved. SPDX-License-Identifier: Apache-2.0 4 */ 5 #include "config_provider.hpp" 6 7 #include <boost/container/flat_map.hpp> 8 #include <phosphor-logging/lg2.hpp> 9 #include <sdbusplus/async/match.hpp> 10 #include <sdbusplus/bus/match.hpp> 11 #include <xyz/openbmc_project/ObjectMapper/client.hpp> 12 13 #include <ranges> 14 #include <string> 15 16 PHOSPHOR_LOG2_USING; 17 18 using VariantType = 19 std::variant<std::vector<std::string>, std::string, int64_t, uint64_t, 20 double, int32_t, uint32_t, int16_t, uint16_t, uint8_t, bool>; 21 using ConfigMap = boost::container::flat_map<std::string, VariantType>; 22 using ConfigData = boost::container::flat_map<std::string, ConfigMap>; 23 24 namespace gpio_presence 25 { 26 27 ConfigProvider::ConfigProvider(sdbusplus::async::context& ctx, 28 const std::string& interface) : 29 interface(interface), ctx(ctx) 30 {} 31 32 auto ConfigProvider::initialize(AddedCallback addConfig, 33 RemovedCallback removeConfig) 34 -> sdbusplus::async::task<void> 35 { 36 ctx.spawn(handleInterfacesAdded(addConfig)); 37 ctx.spawn(handleInterfacesRemoved(removeConfig)); 38 39 co_await getConfig(addConfig); 40 } 41 42 auto ConfigProvider::getConfig(AddedCallback addConfig) 43 -> sdbusplus::async::task<void> 44 { 45 auto client = sdbusplus::client::xyz::openbmc_project::ObjectMapper<>(ctx) 46 .service("xyz.openbmc_project.ObjectMapper") 47 .path("/xyz/openbmc_project/object_mapper"); 48 49 debug("calling 'GetSubTree' to find instances of {INTF}", "INTF", 50 interface); 51 52 using SubTreeType = 53 std::map<std::string, std::map<std::string, std::vector<std::string>>>; 54 SubTreeType res = {}; 55 56 try 57 { 58 std::vector<std::string> interfaces = {interface}; 59 res = co_await client.get_sub_tree("/xyz/openbmc_project/inventory", 0, 60 interfaces); 61 } 62 catch (std::exception& e) 63 { 64 error("Failed GetSubTree call for configuration interface: {ERR}", 65 "ERR", e); 66 } 67 68 if (res.empty()) 69 { 70 co_return; 71 } 72 73 // call the user callback for all the device that is already available 74 for (auto& [path, serviceInterfaceMap] : res) 75 { 76 for (const auto& service : 77 std::ranges::views::keys(serviceInterfaceMap)) 78 { 79 debug("found configuration interface at {SERVICE} {PATH} {INTF}", 80 "SERVICE", service, "PATH", path, "INTF", interface); 81 82 addConfig(path); 83 } 84 } 85 } 86 87 namespace rules_intf = sdbusplus::bus::match::rules; 88 89 const auto senderRule = rules_intf::sender("xyz.openbmc_project.EntityManager"); 90 91 auto ConfigProvider::handleInterfacesAdded(AddedCallback addConfig) 92 -> sdbusplus::async::task<void> 93 { 94 debug("setting up dbus match for interfaces added"); 95 96 sdbusplus::async::match addedMatch( 97 ctx, rules_intf::interfacesAdded() + senderRule); 98 99 while (!ctx.stop_requested()) 100 { 101 auto tmp = co_await addedMatch 102 .next<sdbusplus::message::object_path, ConfigData>(); 103 104 auto [objPath, intfMap] = std::move(tmp); 105 106 debug("Detected interface added on {OBJPATH}", "OBJPATH", objPath); 107 108 if (!std::ranges::contains(std::views::keys(intfMap), interface)) 109 { 110 continue; 111 } 112 113 try 114 { 115 addConfig(objPath); 116 } 117 catch (std::exception& e) 118 { 119 error("Incomplete or invalid config found: {ERR}", "ERR", e); 120 } 121 } 122 }; 123 124 auto ConfigProvider::handleInterfacesRemoved(RemovedCallback removeConfig) 125 -> sdbusplus::async::task<void> 126 { 127 debug("setting up dbus match for interfaces removed"); 128 129 sdbusplus::async::match removedMatch( 130 ctx, rules_intf::interfacesRemoved() + senderRule); 131 132 while (!ctx.stop_requested()) 133 { 134 auto tmp = co_await removedMatch.next<sdbusplus::message::object_path, 135 std::vector<std::string>>(); 136 auto [objectPath, interfaces] = std::move(tmp); 137 138 if (!std::ranges::contains(interfaces, interface)) 139 { 140 continue; 141 } 142 143 debug("Detected interface {INTF} removed on {OBJPATH}", "INTF", 144 interface, "OBJPATH", objectPath); 145 146 removeConfig(objectPath); 147 } 148 }; 149 150 } // namespace gpio_presence 151