Implement Liquid Leak Detector

Implement liquid leak detector based on design
https://gerrit.openbmc.org/c/openbmc/docs/+/73152.

Related PRs:
https://gerrit.openbmc.org/c/openbmc/phosphor-dbus-interfaces/+/73151
https://gerrit.openbmc.org/c/openbmc/phosphor-dbus-interfaces/+/73707
https://gerrit.openbmc.org/c/openbmc/sdbusplus/+/75461
https://gerrit.openbmc.org/c/openbmc/phosphor-dbus-interfaces/+/75999

Tested:
```
>> busctl tree xyz.openbmc_project.LeakDetector
└─ /xyz
  └─ /xyz/openbmc_project
    └─ /xyz/openbmc_project/state
      └─ /xyz/openbmc_project/state/leak
        └─ /xyz/openbmc_project/state/leak/detector
          ├─ /xyz/openbmc_project/state/leak/detector/TrayDetector1
          └─ /xyz/openbmc_project/state/leak/detector/TrayDetector2

>> echo pull-up > /sys/devices/platform/gpio-sim.0/gpiochip2/sim_gpio0/pull

>> curl -k -H "X-Auth-Token: $token" -X GET https://${bmc}/redfish/v1/Systems/system/LogServices/EventLog/Entries
{
  "@odata.id": "/redfish/v1/Systems/system/LogServices/EventLog/Entries",
  "@odata.type": "#LogEntryCollection.LogEntryCollection",
  "Description": "Collection of System Event Log Entries",
  "Members": [
  	...
    {
      "@odata.id": "/redfish/v1/Systems/system/LogServices/EventLog/Entries/2",
      "@odata.type": "#LogEntry.v1_9_0.LogEntry",
      "AdditionalDataURI": "/redfish/v1/Systems/system/LogServices/EventLog/Entries/2/attachment",
      "Created": "2024-05-10T06:40:30.423+00:00",
      "EntryType": "Event",
      "Id": "2",
      "Message": "xyz.openbmc_project.State.Leak.Detector.LeakDetectedWarning",
      "Modified": "2024-05-10T06:40:30.423+00:00",
      "Name": "System Event Log Entry",
      "Resolved": false,
      "Severity": "Warning"
    }
  ],
  "Members@odata.count": 2,
  "Name": "System Event Log Entries"
}

>> echo pull-down > /sys/devices/platform/gpio-sim.0/gpiochip2/sim_gpio0/pull

>> curl -k -H "X-Auth-Token: $token" -X GET https://${bmc}/redfish/v1/Systems/system/LogServices/EventLog/Entries
{
  "@odata.id": "/redfish/v1/Systems/system/LogServices/EventLog/Entries",
  "@odata.type": "#LogEntryCollection.LogEntryCollection",
  "Description": "Collection of System Event Log Entries",
  "Members": [
	...
    {
      "@odata.id": "/redfish/v1/Systems/system/LogServices/EventLog/Entries/2",
      "@odata.type": "#LogEntry.v1_9_0.LogEntry",
      "AdditionalDataURI": "/redfish/v1/Systems/system/LogServices/EventLog/Entries/2/attachment",
      "Created": "2024-05-10T06:40:30.423+00:00",
      "EntryType": "Event",
      "Id": "2",
      "Message": "xyz.openbmc_project.State.Leak.Detector.LeakDetectedWarning",
      "Modified": "2024-05-10T06:42:23.989+00:00",
      "Name": "System Event Log Entry",
      "Resolved": true,
      "Severity": "Warning"
    },
    {
      "@odata.id": "/redfish/v1/Systems/system/LogServices/EventLog/Entries/3",
      "@odata.type": "#LogEntry.v1_9_0.LogEntry",
      "AdditionalDataURI": "/redfish/v1/Systems/system/LogServices/EventLog/Entries/3/attachment",
      "Created": "2024-05-10T06:42:24.024+00:00",
      "EntryType": "Event",
      "Id": "3",
      "Message": "xyz.openbmc_project.State.Leak.Detector.LeakDetectedNormal",
      "Modified": "2024-05-10T06:42:24.024+00:00",
      "Name": "System Event Log Entry",
      "Resolved": false,
      "Severity": "OK"
    }
  ],
  "Members@odata.count": 3,
  "Name": "System Event Log Entries"
}
```

Change-Id: Id6981deb314ca6852c5e31b932b28e601c2f3976
Signed-off-by: Jagpal Singh Gill <paligill@gmail.com>
diff --git a/src/leakdetector/LeakGPIODetector.hpp b/src/leakdetector/LeakGPIODetector.hpp
new file mode 100644
index 0000000..074e758
--- /dev/null
+++ b/src/leakdetector/LeakGPIODetector.hpp
@@ -0,0 +1,102 @@
+#pragma once
+
+#include "GPIOInterface.hpp"
+#include "LeakEvents.hpp"
+
+#include <phosphor-logging/lg2.hpp>
+#include <sdbusplus/async.hpp>
+#include <sdbusplus/async/server.hpp>
+#include <xyz/openbmc_project/Association/Definitions/aserver.hpp>
+#include <xyz/openbmc_project/Configuration/GPIOLeakDetector/client.hpp>
+#include <xyz/openbmc_project/State/Leak/Detector/aserver.hpp>
+
+#include <array>
+#include <string>
+#include <string_view>
+#include <utility>
+
+PHOSPHOR_LOG2_USING;
+
+namespace leak
+{
+
+class GPIODetector;
+
+using DetectorConfigIntf =
+    sdbusplus::client::xyz::openbmc_project::configuration::GPIOLeakDetector<>;
+
+using DetectorIntf = sdbusplus::async::server_t<
+    GPIODetector,
+    sdbusplus::aserver::xyz::openbmc_project::association::Definitions,
+    sdbusplus::aserver::xyz::openbmc_project::state::leak::Detector>;
+
+namespace config
+{
+
+/** @brief Detector type to enum map */
+static constexpr std::array<
+    std::pair<std::string_view, DetectorIntf::DetectorType>, 2>
+    validDetectorTypes = {
+        {{"LeakSensingCable", DetectorIntf::DetectorType::LeakSensingCable},
+         {"Unknown", DetectorIntf::DetectorType::Unknown}}};
+
+/** @brief GPIO polarity */
+enum class PinPolarity
+{
+    activeLow,
+    activeHigh,
+    unknown
+};
+
+/** @brief Polarity name to enum map */
+static constexpr std::array<std::pair<std::string_view, PinPolarity>, 2>
+    validPinPolarity = {
+        {{"Low", PinPolarity::activeLow}, {"High", PinPolarity::activeHigh}}};
+
+/** @brief Detector level */
+enum class DetectorLevel
+{
+    critical,
+    warning,
+    unknown
+};
+
+/** @brief Leak detector level name to enum map */
+static constexpr std::array<std::pair<std::string_view, DetectorLevel>, 2>
+    validDetectorLevel = {{{"Warning", DetectorLevel::warning},
+                           {"Critical", DetectorLevel::critical}}};
+
+/** @brief Leak detector configuration */
+struct DetectorConfig
+{
+    std::string name = Defaults::name;
+    DetectorIntf::DetectorType type = DetectorIntf::DetectorType::Unknown;
+    std::string pinName = Defaults::pinName;
+    PinPolarity polarity = PinPolarity::unknown;
+    DetectorLevel level = DetectorLevel::unknown;
+
+    struct Defaults
+    {
+        static constexpr auto name = "unknown";
+        static constexpr auto pinName = "unknown";
+    };
+};
+
+}; // namespace config
+
+class GPIODetector : public DetectorIntf
+{
+  public:
+    explicit GPIODetector(sdbusplus::async::context& ctx, Events& leakEvents,
+                          const config::DetectorConfig& config);
+
+    auto updateGPIOStateAsync(bool gpioState) -> sdbusplus::async::task<>;
+
+  private:
+    sdbusplus::async::context& ctx;
+    Events& leakEvents;
+    config::DetectorConfig config;
+    gpio::GPIOInterface gpioInterface;
+};
+
+} // namespace leak