blob: 27c90715ed5453e70fc4fbd51cb0a876f6a70ba0 [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),
Jagpal Singh Gill71848052025-10-16 00:28:58 -070041 std::bind_front(&DeviceManager::processConfigRemoved, this)),
42 events(ctx)
Jagpal Singh Gillcad9ecf2025-10-22 19:53:16 -070043{
44 ctx.spawn(entityManager.handleInventoryGet());
45 info("DeviceManager created successfully");
46}
47
48auto DeviceManager::processConfigAdded(
49 const sdbusplus::message::object_path& objectPath,
50 const std::string& interfaceName) -> sdbusplus::async::task<>
51{
52 debug("Config added for {PATH} with {INTF}", "PATH", objectPath, "INTF",
53 interfaceName);
54 if (interfaceName == ModbusRTUDetectIntf::interface && ports.size() == 0)
55 {
56 warning(
57 "Skip processing ModbusRTUDetectIntf::interface as no serial ports detected yet");
58 co_return;
59 }
60
61 auto portInterfaces = PortIntf::PortFactory::getInterfaces();
62 if (std::find(portInterfaces.begin(), portInterfaces.end(),
63 interfaceName) != portInterfaces.end())
64 {
Jagpal Singh Gille92aba42025-10-16 00:00:13 -070065 co_return co_await processPortAdded(objectPath, interfaceName);
Jagpal Singh Gillcad9ecf2025-10-22 19:53:16 -070066 }
Jagpal Singh Gille92aba42025-10-16 00:00:13 -070067
68 if (interfaceName == ModbusRTUDetectIntf::interface)
Jagpal Singh Gillcad9ecf2025-10-22 19:53:16 -070069 {
Jagpal Singh Gille92aba42025-10-16 00:00:13 -070070 co_return co_await processInventoryAdded(objectPath);
71 }
72
73 auto deviceInterfaces = DeviceFactoryIntf::getInterfaces();
74 if (std::find(deviceInterfaces.begin(), deviceInterfaces.end(),
75 interfaceName) != deviceInterfaces.end())
76 {
77 co_return co_await processDeviceAdded(objectPath, interfaceName);
78 }
79}
80
81auto DeviceManager::processPortAdded(
82 const sdbusplus::message::object_path& objectPath,
83 const std::string& interfaceName) -> sdbusplus::async::task<>
84{
85 auto config = co_await PortIntf::PortFactory::getConfig(
86 ctx, objectPath, interfaceName);
87 if (!config)
88 {
89 error("Failed to get Port config for {PATH}", "PATH", objectPath);
90 co_return;
91 }
92
93 try
94 {
95 ports[config->name] = PortIntf::PortFactory::create(ctx, *config);
96 }
97 catch (const std::exception& e)
98 {
99 error("Failed to create Port for {PATH} with {ERROR}", "PATH",
100 objectPath, "ERROR", e);
101 co_return;
102 }
103}
104
105auto DeviceManager::processInventoryAdded(
106 const sdbusplus::message::object_path& objectPath)
107 -> sdbusplus::async::task<>
108{
109 auto res = co_await InventoryIntf::config::getConfig(ctx, objectPath);
110 if (!res)
111 {
112 error("Failed to get Inventory Device config for {PATH}", "PATH",
113 objectPath);
114 co_return;
115 }
116 auto config = res.value();
117 try
118 {
119 auto inventoryDevice =
120 std::make_unique<InventoryIntf::Device>(ctx, config, ports);
121 ctx.spawn(inventoryDevice->probePorts());
122 inventoryDevices[config.name] = std::move(inventoryDevice);
123 }
124 catch (const std::exception& e)
125 {
126 error("Failed to create Inventory Device for {PATH} with {ERROR}",
127 "PATH", objectPath, "ERROR", e);
128 co_return;
129 }
130}
131
132auto DeviceManager::processDeviceAdded(
133 const sdbusplus::message::object_path& objectPath,
134 const std::string& interfaceName) -> sdbusplus::async::task<>
135{
136 auto res =
137 co_await DeviceFactoryIntf::getConfig(ctx, objectPath, interfaceName);
138 if (!res)
139 {
140 error("Failed to get Device config for {PATH}", "PATH", objectPath);
141 co_return;
142 }
143 auto config = res.value();
144
145 try
146 {
147 auto serialPort = ports.find(config.portName);
148 if (serialPort == ports.end())
Jagpal Singh Gillcad9ecf2025-10-22 19:53:16 -0700149 {
150 error("Failed to get Inventory Device config for {PATH}", "PATH",
151 objectPath);
152 co_return;
153 }
Jagpal Singh Gille92aba42025-10-16 00:00:13 -0700154
Jagpal Singh Gill71848052025-10-16 00:28:58 -0700155 auto device = DeviceFactoryIntf::create(ctx, config,
156 *(serialPort->second), events);
Jagpal Singh Gille92aba42025-10-16 00:00:13 -0700157 ctx.spawn(device->readSensorRegisters());
158 devices[config.name] = std::move(device);
159 }
160 catch (const std::exception& e)
161 {
162 error("Failed to create Device for {PATH} with {ERROR}", "PATH",
163 objectPath, "ERROR", e);
164 co_return;
Jagpal Singh Gillcad9ecf2025-10-22 19:53:16 -0700165 }
166}
167
168auto DeviceManager::processConfigRemoved(
169 const sdbusplus::message::object_path& /*unused*/,
170 const std::string& /*unused*/) -> sdbusplus::async::task<>
171{
172 // TODO: Implement this
173 co_return;
174}
175
176} // namespace phosphor::modbus::rtu
177
178auto main() -> int
179{
180 constexpr auto path = "/xyz/openbmc_project";
181 constexpr auto serviceName = "xyz.openbmc_project.ModbusRTU";
182 sdbusplus::async::context ctx;
183 sdbusplus::server::manager_t manager{ctx, path};
184
185 info("Creating Modbus device manager at {PATH}", "PATH", path);
186 phosphor::modbus::rtu::DeviceManager deviceManager{ctx};
187
188 ctx.request_name(serviceName);
189
190 ctx.run();
191 return 0;
192}