blob: aedffa1b9a84ae479220a3b6f8006e33d7d629c9 [file] [log] [blame]
Jagpal Singh Gill15dde862024-10-16 09:42:54 -07001#include "LeakGPIODetector.hpp"
2
3#include "LeakEvents.hpp"
4#include "SystemdInterface.hpp"
5
6#include <sdbusplus/async.hpp>
7#include <sdbusplus/message/native_types.hpp>
8
9#include <array>
10#include <functional>
11#include <string>
12#include <string_view>
Yang Chene6b17312025-06-13 21:58:19 +080013#include <tuple>
Jagpal Singh Gill15dde862024-10-16 09:42:54 -070014
15namespace leak
16{
17
18namespace config
19{
20
21/** @brief Leak level to systemd target service map */
Yang Chene6b17312025-06-13 21:58:19 +080022static constexpr std::array<
23 std::tuple<config::DetectorLevel, std::string_view, std::string_view>, 4>
24 leakActionTargets = {
25 {{config::DetectorLevel::warning, "assert",
26 "xyz.openbmc_project.leakdetector.warning.assert@"},
27 {config::DetectorLevel::warning, "deassert",
28 "xyz.openbmc_project.leakdetector.warning.deassert@"},
29 {config::DetectorLevel::critical, "assert",
30 "xyz.openbmc_project.leakdetector.critical.assert@"},
31 {config::DetectorLevel::critical, "deassert",
32 "xyz.openbmc_project.leakdetector.critical.deassert@"}}};
Jagpal Singh Gill15dde862024-10-16 09:42:54 -070033} // namespace config
34
35static auto getObjectPath(const std::string& detectorName)
36 -> sdbusplus::message::object_path
37{
38 return (
39 sdbusplus::message::object_path(DetectorIntf::namespace_path::value) /
40 DetectorIntf::namespace_path::detector / detectorName);
41}
42
43GPIODetector::GPIODetector(sdbusplus::async::context& ctx, Events& leakEvents,
44 const config::DetectorConfig& config) :
45 DetectorIntf(ctx, getObjectPath(config.name).str.c_str()), ctx(ctx),
46 leakEvents(leakEvents), config(config),
47 gpioInterface(ctx, config.name, config.pinName,
48 (config.polarity == config::PinPolarity::activeLow),
49 std::bind_front(&GPIODetector::updateGPIOStateAsync, this))
50{
51 pretty_name<false>(config.name);
52 type<false>(config.type);
53
54 ctx.spawn(gpioInterface.start());
55
56 debug("Created leak detector {NAME}", "NAME", config.name);
57}
58
59auto GPIODetector::updateGPIOStateAsync(bool gpioState)
60 -> sdbusplus::async::task<>
61{
62 auto newState = gpioState ? DetectorIntf::DetectorState::Abnormal
63 : DetectorIntf::DetectorState::Normal;
64
65 debug("Updating detector {DETECTOR} state to {STATE}", "DETECTOR",
66 config.name, "STATE", newState);
67
68 if (newState != state_)
69 {
70 state(newState);
71
72 co_await leakEvents.generateLeakEvent(getObjectPath(config.name),
73 state_, config.level);
Yang Chene6b17312025-06-13 21:58:19 +080074 std::string action = (state_ == DetectorIntf::DetectorState::Normal)
75 ? "deassert"
76 : "assert";
77
78 for (const auto& [level, action_str, serviceSuffix] :
79 config::leakActionTargets)
Jagpal Singh Gill15dde862024-10-16 09:42:54 -070080 {
Yang Chene6b17312025-06-13 21:58:19 +080081 if (config.level == level && action_str == action)
Jagpal Singh Gill15dde862024-10-16 09:42:54 -070082 {
Yang Chene6b17312025-06-13 21:58:19 +080083 auto target = std::string(serviceSuffix) + config.name +
84 ".service";
85 debug("Starting systemd target {TARGET}", "TARGET", target);
86 co_await systemd::SystemdInterface::startUnit(ctx, target);
87 break;
Jagpal Singh Gill15dde862024-10-16 09:42:54 -070088 }
89 }
90 }
91
92 co_return;
93}
94
95} // namespace leak