blob: 8e99ee8c5ee70d0bdbf896924e702f48defea1a6 [file] [log] [blame]
Shawn McCarney98f42942024-05-24 17:24:32 -05001/**
2 * Copyright © 2024 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#pragma once
17
18#include "utility.hpp"
19
20#include <sdbusplus/bus.hpp>
21#include <sdbusplus/bus/match.hpp>
22
23#include <functional>
24#include <string>
25#include <vector>
26
27namespace phosphor::power::util
28{
29
30/**
31 * @class DBusInterfacesFinder
32 *
33 * Class that finds instances of one or more D-Bus interfaces.
34 *
35 * A D-Bus service name and one or more D-Bus interfaces are specified in the
36 * constructor. The class finds instances of those interfaces that are owned by
37 * the service.
38 *
39 * The class finds the instances using two different methods:
40 * - Registers an InterfacesAdded listener for the specified service. Class is
41 * notified when a new interface instance is created on D-Bus.
42 * - Queries the ObjectMapper to find interface instances that already exist.
43 *
44 * Utilizing both methods allows this class to be used before, during, or after
45 * the service has created the interface instances.
46 *
47 * When an interface instance is found, the callback function specified in the
48 * constructor is called. This function will be called multiple times if
49 * multiple instances are found.
50 */
51class DBusInterfacesFinder
52{
53 public:
54 // Specify which compiler-generated methods we want
55 DBusInterfacesFinder() = delete;
56 DBusInterfacesFinder(const DBusInterfacesFinder&) = delete;
57 DBusInterfacesFinder(DBusInterfacesFinder&&) = delete;
58 DBusInterfacesFinder& operator=(const DBusInterfacesFinder&) = delete;
59 DBusInterfacesFinder& operator=(DBusInterfacesFinder&&) = delete;
60 ~DBusInterfacesFinder() = default;
61
62 /**
63 * Callback function that is called when an interface instance is found.
64 *
65 * @param path D-Bus object path that implements the interface
66 * @param interface D-Bus interface that was found
67 * @param properties Properties of the D-Bus interface
68 */
69 using Callback = std::function<void(const std::string& path,
70 const std::string& interface,
71 const DbusPropertyMap& properties)>;
72
73 /**
74 * Constructor.
75 *
Shawn McCarney1838dbf2024-06-05 23:19:04 -050076 * Note: The callback function may be called immediately by this
77 * constructor. For this reason, do not use this constructor in the
78 * initialization list of constructors in other classes. Otherwise the
79 * callback may be called before the other class is fully initialized,
80 * leading to unpredictable behavior.
81 *
Shawn McCarney98f42942024-05-24 17:24:32 -050082 * @param bus D-Bus bus object
83 * @param service D-Bus service that owns the object paths implementing
84 * the specified interfaces
85 * @param interfaces D-Bus interfaces to find
86 * @param callback Callback function that is called each time an interface
87 * instance is found
88 */
Patrick Williamsf5402192024-08-16 15:20:53 -040089 explicit DBusInterfacesFinder(
90 sdbusplus::bus_t& bus, const std::string& service,
91 const std::vector<std::string>& interfaces, Callback callback);
Shawn McCarney98f42942024-05-24 17:24:32 -050092
93 /**
Shawn McCarney8b098b92024-08-05 14:17:34 -050094 * Refind all instances of the interfaces specified in the constructor.
95 *
96 * The callback specified in the constructor will be called for each
97 * instance found.
98 *
99 * This method normally does not need to be called. New instances are
100 * automatically detected using an InterfacesAdded listener. However, this
101 * method may be useful if the caller is not currently receiving D-Bus
102 * signals (such as within a loop).
103 */
104 void refind()
105 {
106 findInterfaces();
107 }
108
109 /**
Shawn McCarney98f42942024-05-24 17:24:32 -0500110 * Callback function to handle InterfacesAdded D-Bus signals
111 *
112 * @param message Expanded sdbusplus message data
113 */
114 void interfacesAddedCallback(sdbusplus::message_t& message);
115
116 private:
117 /**
118 * Finds any interface instances that already exist on D-Bus.
119 */
120 void findInterfaces();
121
122 /**
123 * D-Bus bus object.
124 */
125 sdbusplus::bus_t& bus;
126
127 /**
128 * D-Bus service that owns the object paths implementing the interfaces.
129 */
130 std::string service;
131
132 /**
133 * D-Bus interfaces to find.
134 */
135 std::vector<std::string> interfaces;
136
137 /**
138 * Callback function that is called each time an interface instance is
139 * found.
140 */
141 Callback callback;
142
143 /**
144 * Match object for InterfacesAdded signals.
145 */
146 sdbusplus::bus::match_t match;
147};
148
149} // namespace phosphor::power::util