1*ca8c7e98SJagpal Singh Gill #include "CableMonitor.hpp"
2*ca8c7e98SJagpal Singh Gill
3*ca8c7e98SJagpal Singh Gill #include "CableConfig.hpp"
4*ca8c7e98SJagpal Singh Gill
5*ca8c7e98SJagpal Singh Gill #include <phosphor-logging/lg2.hpp>
6*ca8c7e98SJagpal Singh Gill #include <sdbusplus/async.hpp>
7*ca8c7e98SJagpal Singh Gill #include <sdbusplus/async/stdexec/__detail/__then.hpp>
8*ca8c7e98SJagpal Singh Gill #include <sdbusplus/message/native_types.hpp>
9*ca8c7e98SJagpal Singh Gill #include <sdbusplus/server/manager.hpp>
10*ca8c7e98SJagpal Singh Gill
11*ca8c7e98SJagpal Singh Gill #include <chrono>
12*ca8c7e98SJagpal Singh Gill #include <cstring>
13*ca8c7e98SJagpal Singh Gill #include <filesystem>
14*ca8c7e98SJagpal Singh Gill #include <functional>
15*ca8c7e98SJagpal Singh Gill #include <string>
16*ca8c7e98SJagpal Singh Gill
17*ca8c7e98SJagpal Singh Gill PHOSPHOR_LOG2_USING;
18*ca8c7e98SJagpal Singh Gill
19*ca8c7e98SJagpal Singh Gill namespace cable
20*ca8c7e98SJagpal Singh Gill {
21*ca8c7e98SJagpal Singh Gill
Monitor(sdbusplus::async::context & ctx)22*ca8c7e98SJagpal Singh Gill Monitor::Monitor(sdbusplus::async::context& ctx) :
23*ca8c7e98SJagpal Singh Gill ctx(ctx), cableEvents(ctx),
24*ca8c7e98SJagpal Singh Gill entityManager(ctx, {CableInventoryIntf::interface},
25*ca8c7e98SJagpal Singh Gill std::bind_front(&Monitor::inventoryAddedHandler, this),
26*ca8c7e98SJagpal Singh Gill std::bind_front(&Monitor::inventoryRemovedHandler, this)),
27*ca8c7e98SJagpal Singh Gill notifyWatch(ctx, Config::configFileDir,
28*ca8c7e98SJagpal Singh Gill std::bind_front(&Monitor::configUpdateHandler, this))
29*ca8c7e98SJagpal Singh Gill {
30*ca8c7e98SJagpal Singh Gill ctx.spawn(start());
31*ca8c7e98SJagpal Singh Gill }
32*ca8c7e98SJagpal Singh Gill
inventoryAddedHandler(const sdbusplus::message::object_path & objectPath,const std::string &)33*ca8c7e98SJagpal Singh Gill auto Monitor::inventoryAddedHandler(
34*ca8c7e98SJagpal Singh Gill const sdbusplus::message::object_path& objectPath,
35*ca8c7e98SJagpal Singh Gill const std::string& /*unused*/) -> void
36*ca8c7e98SJagpal Singh Gill {
37*ca8c7e98SJagpal Singh Gill debug("Received cable added for {NAME}", "NAME", objectPath);
38*ca8c7e98SJagpal Singh Gill ctx.spawn(processCableAddedAsync(objectPath));
39*ca8c7e98SJagpal Singh Gill }
40*ca8c7e98SJagpal Singh Gill
inventoryRemovedHandler(const sdbusplus::message::object_path & objectPath,const std::string &)41*ca8c7e98SJagpal Singh Gill auto Monitor::inventoryRemovedHandler(
42*ca8c7e98SJagpal Singh Gill const sdbusplus::message::object_path& objectPath,
43*ca8c7e98SJagpal Singh Gill const std::string& /*unused*/) -> void
44*ca8c7e98SJagpal Singh Gill {
45*ca8c7e98SJagpal Singh Gill debug("Received cable removed for {NAME}", "NAME", objectPath);
46*ca8c7e98SJagpal Singh Gill ctx.spawn(processCableRemovedAsync(objectPath));
47*ca8c7e98SJagpal Singh Gill }
48*ca8c7e98SJagpal Singh Gill
configUpdateHandler(std::string configFileName)49*ca8c7e98SJagpal Singh Gill auto Monitor::configUpdateHandler(std::string configFileName)
50*ca8c7e98SJagpal Singh Gill -> sdbusplus::async::task<>
51*ca8c7e98SJagpal Singh Gill {
52*ca8c7e98SJagpal Singh Gill if (strcmp(Config::configFileName, configFileName.c_str()) != 0)
53*ca8c7e98SJagpal Singh Gill {
54*ca8c7e98SJagpal Singh Gill error("Update config file name {NAME} is not expected", "NAME",
55*ca8c7e98SJagpal Singh Gill configFileName);
56*ca8c7e98SJagpal Singh Gill co_return;
57*ca8c7e98SJagpal Singh Gill }
58*ca8c7e98SJagpal Singh Gill auto configFilePath =
59*ca8c7e98SJagpal Singh Gill std::string(Config::configFileDir) + "/" + configFileName;
60*ca8c7e98SJagpal Singh Gill if (!std::filesystem::exists(configFilePath))
61*ca8c7e98SJagpal Singh Gill {
62*ca8c7e98SJagpal Singh Gill error("Config file {NAME} does not exist", "NAME", configFilePath);
63*ca8c7e98SJagpal Singh Gill co_return;
64*ca8c7e98SJagpal Singh Gill }
65*ca8c7e98SJagpal Singh Gill expectedCables = co_await Config::processConfig(configFilePath);
66*ca8c7e98SJagpal Singh Gill if (expectedCables.empty())
67*ca8c7e98SJagpal Singh Gill {
68*ca8c7e98SJagpal Singh Gill error("No expected cables found in config file {NAME}", "NAME",
69*ca8c7e98SJagpal Singh Gill configFileName);
70*ca8c7e98SJagpal Singh Gill co_return;
71*ca8c7e98SJagpal Singh Gill }
72*ca8c7e98SJagpal Singh Gill co_await entityManager.handleInventoryGet();
73*ca8c7e98SJagpal Singh Gill ctx.spawn(sdbusplus::async::sleep_for(ctx, std::chrono::seconds(5)) |
74*ca8c7e98SJagpal Singh Gill stdexec::then([&]() { reconcileCableData(); }));
75*ca8c7e98SJagpal Singh Gill }
76*ca8c7e98SJagpal Singh Gill
start()77*ca8c7e98SJagpal Singh Gill auto Monitor::start() -> sdbusplus::async::task<>
78*ca8c7e98SJagpal Singh Gill {
79*ca8c7e98SJagpal Singh Gill info("Start cable monitor");
80*ca8c7e98SJagpal Singh Gill
81*ca8c7e98SJagpal Singh Gill // Start async handler for cable config update
82*ca8c7e98SJagpal Singh Gill ctx.spawn(notifyWatch.readNotifyAsync());
83*ca8c7e98SJagpal Singh Gill
84*ca8c7e98SJagpal Singh Gill // Process the cable config if it already exists
85*ca8c7e98SJagpal Singh Gill auto configFilePath =
86*ca8c7e98SJagpal Singh Gill std::string(Config::configFileDir) + "/" + Config::configFileName;
87*ca8c7e98SJagpal Singh Gill if (std::filesystem::exists(configFilePath))
88*ca8c7e98SJagpal Singh Gill {
89*ca8c7e98SJagpal Singh Gill co_await configUpdateHandler(Config::configFileName);
90*ca8c7e98SJagpal Singh Gill }
91*ca8c7e98SJagpal Singh Gill
92*ca8c7e98SJagpal Singh Gill co_return;
93*ca8c7e98SJagpal Singh Gill }
94*ca8c7e98SJagpal Singh Gill
processCableAddedAsync(sdbusplus::message::object_path objectPath)95*ca8c7e98SJagpal Singh Gill auto Monitor::processCableAddedAsync(sdbusplus::message::object_path objectPath)
96*ca8c7e98SJagpal Singh Gill -> sdbusplus::async::task<>
97*ca8c7e98SJagpal Singh Gill {
98*ca8c7e98SJagpal Singh Gill auto cableName = objectPath.filename();
99*ca8c7e98SJagpal Singh Gill
100*ca8c7e98SJagpal Singh Gill debug("Received cable added for {NAME}", "NAME", cableName);
101*ca8c7e98SJagpal Singh Gill
102*ca8c7e98SJagpal Singh Gill if (connectedCables.contains(cableName))
103*ca8c7e98SJagpal Singh Gill {
104*ca8c7e98SJagpal Singh Gill debug("Cable {NAME} is already connected, so skip it", "NAME",
105*ca8c7e98SJagpal Singh Gill cableName);
106*ca8c7e98SJagpal Singh Gill co_return;
107*ca8c7e98SJagpal Singh Gill }
108*ca8c7e98SJagpal Singh Gill else if (expectedCables.empty())
109*ca8c7e98SJagpal Singh Gill {
110*ca8c7e98SJagpal Singh Gill debug("No expected cables yet, so skip cable add for {NAME}", "NAME",
111*ca8c7e98SJagpal Singh Gill cableName);
112*ca8c7e98SJagpal Singh Gill co_return;
113*ca8c7e98SJagpal Singh Gill }
114*ca8c7e98SJagpal Singh Gill else if (!expectedCables.contains(cableName))
115*ca8c7e98SJagpal Singh Gill {
116*ca8c7e98SJagpal Singh Gill debug(
117*ca8c7e98SJagpal Singh Gill "Cable {NAME} is not in expected cables, skip connected event generation",
118*ca8c7e98SJagpal Singh Gill "NAME", cableName);
119*ca8c7e98SJagpal Singh Gill co_return;
120*ca8c7e98SJagpal Singh Gill }
121*ca8c7e98SJagpal Singh Gill
122*ca8c7e98SJagpal Singh Gill connectedCables.insert(cableName);
123*ca8c7e98SJagpal Singh Gill co_await cableEvents.generateCableEvent(Events::Type::connected, cableName);
124*ca8c7e98SJagpal Singh Gill debug("New cable {NAME} added", "NAME", cableName);
125*ca8c7e98SJagpal Singh Gill
126*ca8c7e98SJagpal Singh Gill co_return;
127*ca8c7e98SJagpal Singh Gill }
128*ca8c7e98SJagpal Singh Gill
processCableRemovedAsync(sdbusplus::message::object_path objectPath)129*ca8c7e98SJagpal Singh Gill auto Monitor::processCableRemovedAsync(
130*ca8c7e98SJagpal Singh Gill sdbusplus::message::object_path objectPath) -> sdbusplus::async::task<>
131*ca8c7e98SJagpal Singh Gill {
132*ca8c7e98SJagpal Singh Gill auto cableName = objectPath.filename();
133*ca8c7e98SJagpal Singh Gill
134*ca8c7e98SJagpal Singh Gill debug("Received cable removed for {NAME}", "NAME", cableName);
135*ca8c7e98SJagpal Singh Gill
136*ca8c7e98SJagpal Singh Gill if (expectedCables.empty())
137*ca8c7e98SJagpal Singh Gill {
138*ca8c7e98SJagpal Singh Gill debug("No expected cables yet, so skip cable add for {NAME}", "NAME",
139*ca8c7e98SJagpal Singh Gill cableName);
140*ca8c7e98SJagpal Singh Gill co_return;
141*ca8c7e98SJagpal Singh Gill }
142*ca8c7e98SJagpal Singh Gill else if (!expectedCables.contains(cableName))
143*ca8c7e98SJagpal Singh Gill {
144*ca8c7e98SJagpal Singh Gill debug(
145*ca8c7e98SJagpal Singh Gill "Cable {NAME} is not in expected cables, so skip disconnected event generation",
146*ca8c7e98SJagpal Singh Gill "NAME", cableName);
147*ca8c7e98SJagpal Singh Gill co_return;
148*ca8c7e98SJagpal Singh Gill }
149*ca8c7e98SJagpal Singh Gill else if (!connectedCables.contains(cableName))
150*ca8c7e98SJagpal Singh Gill {
151*ca8c7e98SJagpal Singh Gill debug(
152*ca8c7e98SJagpal Singh Gill "Cable {NAME} is not connected, so skip disconnected event generation",
153*ca8c7e98SJagpal Singh Gill "NAME", cableName);
154*ca8c7e98SJagpal Singh Gill co_return;
155*ca8c7e98SJagpal Singh Gill }
156*ca8c7e98SJagpal Singh Gill
157*ca8c7e98SJagpal Singh Gill connectedCables.erase(cableName);
158*ca8c7e98SJagpal Singh Gill co_await cableEvents.generateCableEvent(Events::Type::disconnected,
159*ca8c7e98SJagpal Singh Gill cableName);
160*ca8c7e98SJagpal Singh Gill debug("Removed cable {NAME}", "NAME", cableName);
161*ca8c7e98SJagpal Singh Gill
162*ca8c7e98SJagpal Singh Gill co_return;
163*ca8c7e98SJagpal Singh Gill }
164*ca8c7e98SJagpal Singh Gill
reconcileCableData()165*ca8c7e98SJagpal Singh Gill auto Monitor::reconcileCableData() -> void
166*ca8c7e98SJagpal Singh Gill {
167*ca8c7e98SJagpal Singh Gill for (const auto& cableName : expectedCables)
168*ca8c7e98SJagpal Singh Gill {
169*ca8c7e98SJagpal Singh Gill if (connectedCables.contains(cableName))
170*ca8c7e98SJagpal Singh Gill {
171*ca8c7e98SJagpal Singh Gill continue;
172*ca8c7e98SJagpal Singh Gill }
173*ca8c7e98SJagpal Singh Gill ctx.spawn(cableEvents.generateCableEvent(Events::Type::disconnected,
174*ca8c7e98SJagpal Singh Gill cableName));
175*ca8c7e98SJagpal Singh Gill }
176*ca8c7e98SJagpal Singh Gill }
177*ca8c7e98SJagpal Singh Gill
178*ca8c7e98SJagpal Singh Gill } // namespace cable
179*ca8c7e98SJagpal Singh Gill
main()180*ca8c7e98SJagpal Singh Gill int main()
181*ca8c7e98SJagpal Singh Gill {
182*ca8c7e98SJagpal Singh Gill constexpr auto path = "/xyz/openbmc_project/cable_monitor";
183*ca8c7e98SJagpal Singh Gill constexpr auto serviceName = "xyz.openbmc_project.cablemonitor";
184*ca8c7e98SJagpal Singh Gill sdbusplus::async::context ctx;
185*ca8c7e98SJagpal Singh Gill sdbusplus::server::manager_t manager{ctx, path};
186*ca8c7e98SJagpal Singh Gill
187*ca8c7e98SJagpal Singh Gill info("Creating cable monitor");
188*ca8c7e98SJagpal Singh Gill cable::Monitor cableMonitor{ctx};
189*ca8c7e98SJagpal Singh Gill ctx.request_name(serviceName);
190*ca8c7e98SJagpal Singh Gill
191*ca8c7e98SJagpal Singh Gill ctx.run();
192*ca8c7e98SJagpal Singh Gill return 0;
193*ca8c7e98SJagpal Singh Gill }
194