pseq: Create class for finding devices
Create class for finding power sequencer devices in the system.
Tested:
* See test plan at
https://gist.github.com/smccarney/115a90a26a04e28c226d4e86eaf84cbf
Change-Id: I024eb6ccf82ea30c08c558194c19afcba8dcf5a2
Signed-off-by: Shawn McCarney <shawnmm@us.ibm.com>
diff --git a/phosphor-power-sequencer/src/device_finder.cpp b/phosphor-power-sequencer/src/device_finder.cpp
new file mode 100644
index 0000000..65d3651
--- /dev/null
+++ b/phosphor-power-sequencer/src/device_finder.cpp
@@ -0,0 +1,92 @@
+/**
+ * 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 "device_finder.hpp"
+
+#include <phosphor-logging/lg2.hpp>
+
+#include <exception>
+#include <format>
+#include <stdexcept>
+#include <utility>
+#include <variant>
+#include <vector>
+
+namespace phosphor::power::sequencer
+{
+
+const std::string deviceInterfacesService = "xyz.openbmc_project.EntityManager";
+
+const std::vector<std::string> deviceInterfaces{
+ "xyz.openbmc_project.Configuration.UCD90160",
+ "xyz.openbmc_project.Configuration.UCD90320"};
+
+const std::string typeProperty = "Type";
+const std::string nameProperty = "Name";
+const std::string busProperty = "Bus";
+const std::string addressProperty = "Address";
+
+DeviceFinder::DeviceFinder(sdbusplus::bus_t& bus, Callback callback) :
+ callback{std::move(callback)},
+ interfacesFinder{
+ bus, deviceInterfacesService, deviceInterfaces,
+ std::bind_front(&DeviceFinder::interfaceFoundCallback, this)}
+{}
+
+void DeviceFinder::interfaceFoundCallback(
+ [[maybe_unused]] const std::string& path, const std::string& interface,
+ const DbusPropertyMap& properties)
+{
+ try
+ {
+ DeviceProperties device{};
+
+ auto value = getPropertyValue(properties, typeProperty);
+ device.type = std::get<std::string>(value);
+
+ value = getPropertyValue(properties, nameProperty);
+ device.name = std::get<std::string>(value);
+
+ value = getPropertyValue(properties, busProperty);
+ device.bus = static_cast<uint8_t>(std::get<uint64_t>(value));
+
+ value = getPropertyValue(properties, addressProperty);
+ device.address = static_cast<uint16_t>(std::get<uint64_t>(value));
+
+ callback(device);
+ }
+ catch (const std::exception& e)
+ {
+ lg2::error(
+ "Unable to obtain properties of interface {INTERFACE}: {ERROR}",
+ "INTERFACE", interface, "ERROR", e);
+ }
+}
+
+const DbusVariant&
+ DeviceFinder::getPropertyValue(const DbusPropertyMap& properties,
+ const std::string& propertyName)
+{
+ auto it = properties.find(propertyName);
+ if (it == properties.end())
+ {
+ throw std::runtime_error{
+ std::format("{} property not found", propertyName)};
+ }
+ return it->second;
+}
+
+} // namespace phosphor::power::sequencer
diff --git a/phosphor-power-sequencer/src/device_finder.hpp b/phosphor-power-sequencer/src/device_finder.hpp
new file mode 100644
index 0000000..f09d164
--- /dev/null
+++ b/phosphor-power-sequencer/src/device_finder.hpp
@@ -0,0 +1,119 @@
+/**
+ * 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.
+ */
+#pragma once
+
+#include "dbus_interfaces_finder.hpp"
+#include "utility.hpp"
+
+#include <sdbusplus/bus.hpp>
+
+#include <cstdint>
+#include <functional>
+#include <string>
+
+namespace phosphor::power::sequencer
+{
+
+using DbusVariant = phosphor::power::util::DbusVariant;
+using DbusPropertyMap = phosphor::power::util::DbusPropertyMap;
+using DBusInterfacesFinder = phosphor::power::util::DBusInterfacesFinder;
+
+/**
+ * Power sequencer device properties.
+ */
+struct DeviceProperties
+{
+ std::string type;
+ std::string name;
+ uint8_t bus;
+ uint16_t address;
+};
+
+/**
+ * @class DeviceFinder
+ *
+ * Class that finds power sequencer devices in the system.
+ *
+ * When a device is found, the callback function specified in the constructor is
+ * called. This function will be called multiple times if multiple devices are
+ * found.
+ */
+class DeviceFinder
+{
+ public:
+ // Specify which compiler-generated methods we want
+ DeviceFinder() = delete;
+ DeviceFinder(const DeviceFinder&) = delete;
+ DeviceFinder(DeviceFinder&&) = delete;
+ DeviceFinder& operator=(const DeviceFinder&) = delete;
+ DeviceFinder& operator=(DeviceFinder&&) = delete;
+ ~DeviceFinder() = default;
+
+ /**
+ * Callback function that is called when a power sequencer device is found.
+ *
+ * @param device Device that was found
+ */
+ using Callback = std::function<void(const DeviceProperties& device)>;
+
+ /**
+ * Constructor.
+ *
+ * @param bus D-Bus bus object
+ * @param callback Callback function that is called each time a power
+ * sequencer device is found
+ */
+ explicit DeviceFinder(sdbusplus::bus_t& bus, Callback callback);
+
+ /**
+ * Callback function that is called when a D-Bus interface is found that
+ * contains power sequencer device properties.
+ *
+ * @param path D-Bus object path that implements the interface
+ * @param interface D-Bus interface that was found
+ * @param properties Properties of the D-Bus interface
+ */
+ void interfaceFoundCallback(const std::string& path,
+ const std::string& interface,
+ const DbusPropertyMap& properties);
+
+ private:
+ /**
+ * Returns the value of the D-Bus property with the specified name.
+ *
+ * Throws an exception if the property was not found.
+ *
+ * @param properties D-Bus interface properties
+ * @param propertyName D-Bus property name
+ * @return Property value
+ */
+ const DbusVariant& getPropertyValue(const DbusPropertyMap& properties,
+ const std::string& propertyName);
+
+ /**
+ * Callback function that is called each time a power sequencer device is
+ * found.
+ */
+ Callback callback;
+
+ /**
+ * Class used to find D-Bus interfaces that contain power sequencer device
+ * properties.
+ */
+ DBusInterfacesFinder interfacesFinder;
+};
+
+} // namespace phosphor::power::sequencer
diff --git a/phosphor-power-sequencer/src/meson.build b/phosphor-power-sequencer/src/meson.build
index eb641b9..f853c7a 100644
--- a/phosphor-power-sequencer/src/meson.build
+++ b/phosphor-power-sequencer/src/meson.build
@@ -6,6 +6,7 @@
phosphor_power_sequencer_library = static_library(
'phosphor-power-sequencer',
'config_file_parser.cpp',
+ 'device_finder.cpp',
'pmbus_driver_device.cpp',
'rail.cpp',
'services.cpp',
@@ -16,7 +17,9 @@
implicit_include_directories: false,
dependencies: [
nlohmann_json_dep,
- phosphor_logging
+ phosphor_dbus_interfaces,
+ phosphor_logging,
+ sdbusplus,
],
include_directories: [
phosphor_power_sequencer_include_directories