/** * Copyright © 2024 IBM Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "dbus_interfaces_finder.hpp" #include #include #include #include namespace phosphor::power::util { DBusInterfacesFinder::DBusInterfacesFinder( sdbusplus::bus_t& bus, const std::string& service, const std::vector& interfaces, Callback callback) : bus{bus}, service{service}, interfaces{interfaces}, callback{std::move(callback)}, match{bus, sdbusplus::bus::match::rules::interfacesAdded() + sdbusplus::bus::match::rules::sender(service), std::bind(&DBusInterfacesFinder::interfacesAddedCallback, this, std::placeholders::_1)} { findInterfaces(); } void DBusInterfacesFinder::interfacesAddedCallback( sdbusplus::message_t& message) { // Exit if message is invalid if (!message) { return; } try { // Read the D-Bus message sdbusplus::message::object_path path; std::map> interfaces; message.read(path, interfaces); // Call callback for interfaces that we are looking for for (const auto& [interface, properties] : interfaces) { if (std::ranges::contains(this->interfaces, interface)) { callback(path, interface, properties); } } } catch (const std::exception&) { // Error trying to read InterfacesAdded message. One possible cause // could be a property whose value is an unexpected data type. } } void DBusInterfacesFinder::findInterfaces() { try { // Use ObjectMapper to find interface instances that already exist auto objects = util::getSubTree(bus, "/", interfaces, 0); // Search for matching interfaces in returned objects for (const auto& [path, services] : objects) { for (const auto& [service, interfaces] : services) { if (service == this->service) { for (const auto& interface : interfaces) { if (std::ranges::contains(this->interfaces, interface)) { auto properties = util::getAllProperties( bus, path, interface, service); callback(path, interface, properties); } } } } } } catch (const std::exception&) { // Interface instances might not be available yet } } } // namespace phosphor::power::util