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