blob: 804f6eb5a7b9f9e3864cafc390778d898822f986 [file] [log] [blame]
Jagpal Singh Gillcad9ecf2025-10-22 19:53:16 -07001#include "device_manager.hpp"
2
Jagpal Singh Gille92aba42025-10-16 00:00:13 -07003#include "device/device_factory.hpp"
Jagpal Singh Gillcad9ecf2025-10-22 19:53:16 -07004#include "port/port_factory.hpp"
5
6#include <phosphor-logging/lg2.hpp>
7#include <sdbusplus/async.hpp>
8#include <sdbusplus/server/manager.hpp>
9#include <xyz/openbmc_project/Configuration/ModbusRTUDetect/client.hpp>
10
11PHOSPHOR_LOG2_USING;
12
13namespace phosphor::modbus::rtu
14{
15
16using ModbusRTUDetectIntf =
17 sdbusplus::client::xyz::openbmc_project::configuration::ModbusRTUDetect<>;
Jagpal Singh Gille92aba42025-10-16 00:00:13 -070018using DeviceFactoryIntf = phosphor::modbus::rtu::device::DeviceFactory;
Jagpal Singh Gillcad9ecf2025-10-22 19:53:16 -070019
20static entity_manager::interface_list_t getInterfaces()
21{
22 entity_manager::interface_list_t interfaces;
23
24 auto portInterfaces = PortIntf::PortFactory::getInterfaces();
25 interfaces.insert(interfaces.end(), portInterfaces.begin(),
26 portInterfaces.end());
Jagpal Singh Gille92aba42025-10-16 00:00:13 -070027
Jagpal Singh Gillcad9ecf2025-10-22 19:53:16 -070028 interfaces.emplace_back(ModbusRTUDetectIntf::interface);
29
Jagpal Singh Gille92aba42025-10-16 00:00:13 -070030 auto deviceInterfaces = DeviceFactoryIntf::getInterfaces();
31 interfaces.insert(interfaces.end(), deviceInterfaces.begin(),
32 deviceInterfaces.end());
33
Jagpal Singh Gillcad9ecf2025-10-22 19:53:16 -070034 return interfaces;
35}
36
37DeviceManager::DeviceManager(sdbusplus::async::context& ctx) :
38 ctx(ctx),
39 entityManager(ctx, getInterfaces(),
40 std::bind_front(&DeviceManager::processConfigAdded, this),
41 std::bind_front(&DeviceManager::processConfigRemoved, this))
42{
43 ctx.spawn(entityManager.handleInventoryGet());
44 info("DeviceManager created successfully");
45}
46
47auto DeviceManager::processConfigAdded(
48 const sdbusplus::message::object_path& objectPath,
49 const std::string& interfaceName) -> sdbusplus::async::task<>
50{
51 debug("Config added for {PATH} with {INTF}", "PATH", objectPath, "INTF",
52 interfaceName);
53 if (interfaceName == ModbusRTUDetectIntf::interface && ports.size() == 0)
54 {
55 warning(
56 "Skip processing ModbusRTUDetectIntf::interface as no serial ports detected yet");
57 co_return;
58 }
59
60 auto portInterfaces = PortIntf::PortFactory::getInterfaces();
61 if (std::find(portInterfaces.begin(), portInterfaces.end(),
62 interfaceName) != portInterfaces.end())
63 {
Jagpal Singh Gille92aba42025-10-16 00:00:13 -070064 co_return co_await processPortAdded(objectPath, interfaceName);
Jagpal Singh Gillcad9ecf2025-10-22 19:53:16 -070065 }
Jagpal Singh Gille92aba42025-10-16 00:00:13 -070066
67 if (interfaceName == ModbusRTUDetectIntf::interface)
Jagpal Singh Gillcad9ecf2025-10-22 19:53:16 -070068 {
Jagpal Singh Gille92aba42025-10-16 00:00:13 -070069 co_return co_await processInventoryAdded(objectPath);
70 }
71
72 auto deviceInterfaces = DeviceFactoryIntf::getInterfaces();
73 if (std::find(deviceInterfaces.begin(), deviceInterfaces.end(),
74 interfaceName) != deviceInterfaces.end())
75 {
76 co_return co_await processDeviceAdded(objectPath, interfaceName);
77 }
78}
79
80auto DeviceManager::processPortAdded(
81 const sdbusplus::message::object_path& objectPath,
82 const std::string& interfaceName) -> sdbusplus::async::task<>
83{
84 auto config = co_await PortIntf::PortFactory::getConfig(
85 ctx, objectPath, interfaceName);
86 if (!config)
87 {
88 error("Failed to get Port config for {PATH}", "PATH", objectPath);
89 co_return;
90 }
91
92 try
93 {
94 ports[config->name] = PortIntf::PortFactory::create(ctx, *config);
95 }
96 catch (const std::exception& e)
97 {
98 error("Failed to create Port for {PATH} with {ERROR}", "PATH",
99 objectPath, "ERROR", e);
100 co_return;
101 }
102}
103
104auto DeviceManager::processInventoryAdded(
105 const sdbusplus::message::object_path& objectPath)
106 -> sdbusplus::async::task<>
107{
108 auto res = co_await InventoryIntf::config::getConfig(ctx, objectPath);
109 if (!res)
110 {
111 error("Failed to get Inventory Device config for {PATH}", "PATH",
112 objectPath);
113 co_return;
114 }
115 auto config = res.value();
116 try
117 {
118 auto inventoryDevice =
119 std::make_unique<InventoryIntf::Device>(ctx, config, ports);
120 ctx.spawn(inventoryDevice->probePorts());
121 inventoryDevices[config.name] = std::move(inventoryDevice);
122 }
123 catch (const std::exception& e)
124 {
125 error("Failed to create Inventory Device for {PATH} with {ERROR}",
126 "PATH", objectPath, "ERROR", e);
127 co_return;
128 }
129}
130
131auto DeviceManager::processDeviceAdded(
132 const sdbusplus::message::object_path& objectPath,
133 const std::string& interfaceName) -> sdbusplus::async::task<>
134{
135 auto res =
136 co_await DeviceFactoryIntf::getConfig(ctx, objectPath, interfaceName);
137 if (!res)
138 {
139 error("Failed to get Device config for {PATH}", "PATH", objectPath);
140 co_return;
141 }
142 auto config = res.value();
143
144 try
145 {
146 auto serialPort = ports.find(config.portName);
147 if (serialPort == ports.end())
Jagpal Singh Gillcad9ecf2025-10-22 19:53:16 -0700148 {
149 error("Failed to get Inventory Device config for {PATH}", "PATH",
150 objectPath);
151 co_return;
152 }
Jagpal Singh Gille92aba42025-10-16 00:00:13 -0700153
154 auto device =
155 DeviceFactoryIntf::create(ctx, config, *(serialPort->second));
156 ctx.spawn(device->readSensorRegisters());
157 devices[config.name] = std::move(device);
158 }
159 catch (const std::exception& e)
160 {
161 error("Failed to create Device for {PATH} with {ERROR}", "PATH",
162 objectPath, "ERROR", e);
163 co_return;
Jagpal Singh Gillcad9ecf2025-10-22 19:53:16 -0700164 }
165}
166
167auto DeviceManager::processConfigRemoved(
168 const sdbusplus::message::object_path& /*unused*/,
169 const std::string& /*unused*/) -> sdbusplus::async::task<>
170{
171 // TODO: Implement this
172 co_return;
173}
174
175} // namespace phosphor::modbus::rtu
176
177auto main() -> int
178{
179 constexpr auto path = "/xyz/openbmc_project";
180 constexpr auto serviceName = "xyz.openbmc_project.ModbusRTU";
181 sdbusplus::async::context ctx;
182 sdbusplus::server::manager_t manager{ctx, path};
183
184 info("Creating Modbus device manager at {PATH}", "PATH", path);
185 phosphor::modbus::rtu::DeviceManager deviceManager{ctx};
186
187 ctx.request_name(serviceName);
188
189 ctx.run();
190 return 0;
191}