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