xref: /openbmc/dbus-sensors/src/cable-monitor/CableMonitor.cpp (revision ca8c7e98687da407fbab5dcd20cfe892928928ae)
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