1 #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>
13 #include <tuple>
14
15 namespace leak
16 {
17
18 namespace config
19 {
20
21 /** @brief Leak level to systemd target service map */
22 static 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@"}}};
33 } // namespace config
34
getObjectPath(const std::string & detectorName)35 static 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
GPIODetector(sdbusplus::async::context & ctx,Events & leakEvents,const config::DetectorConfig & config)43 GPIODetector::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
updateGPIOStateAsync(bool gpioState)59 auto 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);
74 std::string action = (state_ == DetectorIntf::DetectorState::Normal)
75 ? "deassert"
76 : "assert";
77
78 for (const auto& [level, action_str, serviceSuffix] :
79 config::leakActionTargets)
80 {
81 if (config.level == level && action_str == action)
82 {
83 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;
88 }
89 }
90 }
91
92 co_return;
93 }
94
95 } // namespace leak
96