hostSelector_switch: add support polling mode

Task Description:
Add support for polling mode to periodically sample the group GPIO
selector inputs and update the HostSelector interface’s Position
property on D-Bus.

Motivation:
-Some platforms expose the host-selector via a CPLD as GPIO inputs
without edge interrupts.
-Polling ensures all position changes are detected reliably.

Design:
- Enabled polling through the 'polling_mode' and 'polling_interval_ms'
  options in JSON configuration.
- Introduced pollTimerHandler to periodically check GPIO states
  and update the internal host selector position.

Tested:
journalctl -xeu xyz.openbmc_project.Chassis.Buttons.service -f
Jul 31 00:06:47 bmc buttons[629]: Start Phosphor buttons service...
Jul 31 00:06:47 bmc buttons[629]: Started polling mode: 2000ms
Jul 31 00:06:49 bmc buttons[629]: Host selector position updated to 0
Jul 31 00:06:53 bmc systemd[1]: Started Phosphor Buttons.

Jul 31 00:13:50 bmc buttons[629]: Host selector position updated to 1
Jul 31 00:13:52 bmc buttons[629]: Host selector position updated to 2
Jul 31 00:13:54 bmc buttons[629]: Host selector position updated to 3
Jul 31 00:14:00 bmc buttons[629]: Host selector position updated to 4
Jul 31 00:14:04 bmc buttons[629]: Host selector position updated to 5
Jul 31 00:14:10 bmc buttons[629]: Host selector position updated to 6
Jul 31 00:14:14 bmc buttons[629]: Host selector position updated to 7
Jul 31 00:14:16 bmc buttons[629]: Host selector position updated to 8
Jul 31 00:14:20 bmc buttons[629]: Host selector position updated to 0

Change-Id: I8b95d773191f1af03b747f9eeb33494da9878bc8
Signed-off-by: Liora Guo <liora.guo.wiwynn@gmail.com>
diff --git a/src/hostSelector_switch.cpp b/src/hostSelector_switch.cpp
index c398e35..567f338 100644
--- a/src/hostSelector_switch.cpp
+++ b/src/hostSelector_switch.cpp
@@ -1,6 +1,8 @@
 
 #include "hostSelector_switch.hpp"
 
+#include "gpio.hpp"
+
 #include <error.h>
 
 #include <phosphor-logging/lg2.hpp>
@@ -87,6 +89,19 @@
                    getFormFactorType(), "ERROR", e.what());
     }
 
+    if (config.extraJsonInfo.value("polling_mode", false))
+    {
+        // If polling mode is enabled, set up a timer to poll the GPIO state
+        int intervalMs =
+            config.extraJsonInfo.value("polling_interval_ms", 1000);
+        auto event = Event::get_default();
+        pollTimer.emplace(
+            event, [this](Timer&) { pollGpioState(); },
+            std::chrono::milliseconds(intervalMs));
+        pollTimer->setEnabled(true);
+        lg2::info("Started polling mode: {MS}ms", "MS", intervalMs);
+    }
+
     if (hsPosMapped != INVALID_INDEX)
     {
         position(hsPosMapped, true);
@@ -152,3 +167,23 @@
         position(hsPosMapped);
     }
 }
+
+void HostSelector::pollGpioState()
+{
+    for (const auto& gpioInfo : config.gpios)
+    {
+        GpioState state = getGpioState(gpioInfo.fd, gpioInfo.polarity);
+        setHostSelectorValue(gpioInfo.fd, state);
+        lg2::debug("GPIO {NUM} state is {STATE}", "NUM", gpioInfo.number,
+                   "STATE", state);
+    }
+
+    size_t currentPos = getMappedHSConfig(hostSelectorPosition);
+
+    if (currentPos != INVALID_INDEX && currentPos != previousPos)
+    {
+        position(currentPos);
+        previousPos = currentPos;
+        lg2::info("Host selector position updated to {POS}", "POS", currentPos);
+    }
+}