phosphor-buttons: Fix HostSelector mode logic

Task Description:
This task fixes a issue where power button handlers fail to register
in multi-power button systems when a HostSelector D-Bus object exists
for OCP debug card support. The problem occurs because the existing
logic incorrectly assumes that any HostSelector object presence
indicates host selector button mode, preventing proper power button
signal registration in multi-power button configurations.

Motivation:
The current power button handler has two modes:
- Host Selector Button Mode (e.g., Yosemite V2):
Single power button with host selector switch for target host
handling, where hostSelectButtonMode = true
- Multi Power Button Mode (e.g., Yosemite V4):
Each slot/sled has its own power button, where
hostSelectButtonMode = false
However, when HostSelector D-Bus object exists solely for OCP
debug card support (not for power button functionality), the system
incorrectly enters host selector button mode, causing multi-power
button systems to fail registering powerReleased signals.
This results in non-functional power buttons across the platform.

Design:
- Virtual Button Flag: Added virtualButton flag to distinguish
between HostSelector objects used for actual power button control
versus those used for OCP debug card support. The flag is read from
the virtual_button field in the HOST_SELECTOR GPIO configuration.
- Corrected Mode Logic: Modified hostSelectButtonMode calculation
to isHostSelectorExists && !virtualButton, ensuring that
HostSelector objects marked as virtual buttons don't trigger
host selector button mode.
- Unified Signal Registration: Replaced separate single/multi power
button registration logic with a unified approach that dynamically
discovers and registers powerReleased signal handlers for all available
power button interfaces using D-Bus ObjectMapper's GetSubTreePaths.

Test Log(Tested on Yosemite V4):
```
root@bmc:~# cat /etc/default/obmc/gpio/gpio_defs.json | grep -i -E "POWER_BUTTON|HOST_SELECTOR|virtual_button"
            "name": "POWER_BUTTON1",
            "name": "POWER_BUTTON2",
            "name": "POWER_BUTTON3",
            "name": "POWER_BUTTON4",
            "name": "POWER_BUTTON5",
            "name": "POWER_BUTTON6",
            "name": "POWER_BUTTON7",
            "name": "POWER_BUTTON8",
            "name": "HOST_SELECTOR",
            "virtual_button": true,

root@bmc:~# systemctl status phosphor-button-handler.service
● phosphor-button-handler.service - Phosphor Button Handler
     Loaded: loaded (/usr/lib/systemd/system/phosphor-button-handler.service; enabled; preset: enabled)
     Active: active (running) since Wed 2025-11-05 03:09:06 PST; 7s ago
 Invocation: 81fd455a960e4c6cb201712d71219cb2
   Main PID: 9319 (button-handler)
      Tasks: 1 (limit: 1961)
     Memory: 324K (peak: 1M)
        CPU: 65ms
     CGroup: /system.slice/phosphor-button-handler.service
             └─9319 /usr/bin/button-handler

Nov 05 03:09:06 bmc button-handler[9319]: hostSelectButtonMode: False
Nov 05 03:09:06 bmc button-handler[9319]: Starting power button handler
Nov 05 03:09:06 bmc button-handler[9319]: Registering power button handler for: /xyz/openbmc_project/Chassis/Buttons/Power01
Nov 05 03:09:06 bmc button-handler[9319]: Registering power button handler for: /xyz/openbmc_project/Chassis/Buttons/Power02
Nov 05 03:09:06 bmc button-handler[9319]: Registering power button handler for: /xyz/openbmc_project/Chassis/Buttons/Power03
Nov 05 03:09:06 bmc button-handler[9319]: Registering power button handler for: /xyz/openbmc_project/Chassis/Buttons/Power04
Nov 05 03:09:06 bmc button-handler[9319]: Registering power button handler for: /xyz/openbmc_project/Chassis/Buttons/Power05
Nov 05 03:09:06 bmc button-handler[9319]: Registering power button handler for: /xyz/openbmc_project/Chassis/Buttons/Power06
Nov 05 03:09:06 bmc button-handler[9319]: Registering power button handler for: /xyz/openbmc_project/Chassis/Buttons/Power07
Nov 05 03:09:06 bmc button-handler[9319]: Registering power button handler for: /xyz/openbmc_project/Chassis/Buttons/Power08

```
Change-Id: Iaf5a6a4fc93522633ac3caa31d63f86a32eb88f5
Signed-off-by: Liora Guo <liora.guo.wiwynn@gmail.com>
diff --git a/README.md b/README.md
index 8b63513..3428fa6 100644
--- a/README.md
+++ b/README.md
@@ -152,6 +152,13 @@
 - **polling_interval_ms** (optional): Polling interval in milliseconds. Defaults
   to `1000` ms if not specified.
 
+**Optional: Virtual Button Configuration** Some platforms implement HostSelector
+objects without actual power button control functionality. To prevent
+interference with multi-power button mode detection:
+
+- **virtual_button** : Set to `true` when not used as power button, e.g., OCP
+  debug card. Defaults to false if not specified.
+
 ### Config Example
 
 #### A.Interrupt example
diff --git a/inc/button_handler.hpp b/inc/button_handler.hpp
index ff8850b..8706024 100644
--- a/inc/button_handler.hpp
+++ b/inc/button_handler.hpp
@@ -157,11 +157,6 @@
     sdbusplus::bus_t& bus;
 
     /**
-     * @brief Matches on the power button released signal
-     */
-    std::unique_ptr<sdbusplus::bus::match_t> powerButtonReleased;
-
-    /**
      * @brief Matches on the power button long press released signal
      */
     std::unique_ptr<sdbusplus::bus::match_t> powerButtonLongPressed;
@@ -199,9 +194,9 @@
     bool hostSelectButtonMode = false;
 
     /**
-     * @brief Flag to indicate if the button supports multi action
+     * @brief Flag to indicate if the button is a virtual button
      */
-    bool isButtonMultiActionSupport = true;
+    bool virtualButton = false;
 };
 
 } // namespace button
diff --git a/src/button_handler.cpp b/src/button_handler.cpp
index ab52c66..f18f1b5 100644
--- a/src/button_handler.cpp
+++ b/src/button_handler.cpp
@@ -21,6 +21,7 @@
 namespace sdbusRule = sdbusplus::bus::match::rules;
 using namespace sdbusplus::xyz::openbmc_project::State::server;
 using namespace sdbusplus::xyz::openbmc_project::Chassis::Buttons::server;
+using GetSubTreePathsType = std::vector<std::string>;
 
 const std::map<std::string, Chassis::Transition> chassisPwrCtls = {
     {"chassis-on", Chassis::Transition::On},
@@ -58,18 +59,14 @@
     - multi power button mode, e.g.: Greatlakes
     each slot/sled has its own power button,
     in the case, hostSelectButtonMode = false */
-    hostSelectButtonMode =
-        !getService(HS_DBUS_OBJECT_NAME, hostSelectorIface).empty();
-    size_t powerButtonCount = 1;
-    if (!hostSelectButtonMode)
-    {
-        powerButtonCount = phosphor::button::numberOfChassis();
-    }
 
     std::ifstream gpios{gpioDefFile};
     auto configDefJson = nlohmann::json::parse(gpios, nullptr, true);
     nlohmann::json gpioDefs = configDefJson["gpio_definitions"];
 
+    bool isHostSelectorExists =
+        !getService(HS_DBUS_OBJECT_NAME, hostSelectorIface).empty();
+
     for (const auto& gpioConfig : gpioDefs)
     {
         if (gpioConfig.contains("multi-action"))
@@ -91,16 +88,29 @@
             }
             multiPwrBtnActConf.emplace_back(mapEntry);
         }
-        else
+
+        if (gpioConfig.value("name", "") == "HOST_SELECTOR")
         {
-            isButtonMultiActionSupport = false;
-            break;
+            virtualButton = gpioConfig.value("virtual_button", false);
+            lg2::debug("Change virtualButton flag to: {VIRTUAL}", "VIRTUAL",
+                       virtualButton);
         }
     }
 
+    hostSelectButtonMode = isHostSelectorExists && !virtualButton;
+    lg2::debug("hostSelectButtonMode: {MODE}", "MODE", hostSelectButtonMode);
+
     try
     {
-        if (!getService(POWER_DBUS_OBJECT_NAME, powerButtonIface).empty())
+        static const int depth = 1;
+        GetSubTreePathsType powerButtonSubTreePaths;
+        auto method = bus.new_method_call(mapperService, mapperObjPath,
+                                          mapperIface, "GetSubTreePaths");
+        method.append("/xyz/openbmc_project/Chassis/Buttons", depth,
+                      GetSubTreePathsType({powerButtonIface}));
+        auto reply = bus.call(method);
+        reply.read(powerButtonSubTreePaths);
+        if (!powerButtonSubTreePaths.empty())
         {
             lg2::info("Starting power button handler");
 
@@ -108,45 +118,33 @@
             powerButtonProfile =
                 PowerButtonProfileFactory::instance().createProfile(bus);
 
+            // Fallback: register for all power buttons found
             if (!powerButtonProfile)
             {
-                powerButtonReleased = std::make_unique<sdbusplus::bus::match_t>(
-                    bus,
-                    sdbusRule::type::signal() + sdbusRule::member("Released") +
-                        sdbusRule::path(POWER_DBUS_OBJECT_NAME) +
-                        sdbusRule::interface(powerButtonIface),
-                    std::bind(std::mem_fn(&Handler::powerReleased), this,
-                              std::placeholders::_1));
-            }
-        }
-
-        if (!hostSelectButtonMode && isButtonMultiActionSupport)
-        {
-            lg2::info("Starting multi power button handler");
-            // The index, 'countIter', starts at 1 and increments,
-            // representing slot_1 through slot_N.
-            for (size_t countIter = 1; countIter <= powerButtonCount;
-                 countIter++)
-            {
-                std::unique_ptr<sdbusplus::bus::match_t>
-                    multiPowerReleaseMatch =
-                        std::make_unique<sdbusplus::bus::match_t>(
-                            bus,
-                            sdbusRule::type::signal() +
-                                sdbusRule::member("Released") +
-                                sdbusRule::path(POWER_DBUS_OBJECT_NAME +
-                                                std::to_string(countIter)) +
-                                sdbusRule::interface(powerButtonIface),
-                            std::bind(std::mem_fn(&Handler::powerReleased),
-                                      this, std::placeholders::_1));
-                multiPowerButtonReleased.emplace_back(
-                    std::move(multiPowerReleaseMatch));
+                for (const auto& path : powerButtonSubTreePaths)
+                {
+                    lg2::debug("Registering power button handler for: {PATH}",
+                               "PATH", path);
+                    std::unique_ptr<sdbusplus::bus::match_t>
+                        multiPowerReleaseMatch =
+                            std::make_unique<sdbusplus::bus::match_t>(
+                                bus,
+                                sdbusRule::type::signal() +
+                                    sdbusRule::member("Released") +
+                                    sdbusRule::path(path) +
+                                    sdbusRule::interface(powerButtonIface),
+                                std::bind(std::mem_fn(&Handler::powerReleased),
+                                          this, std::placeholders::_1));
+                    multiPowerButtonReleased.emplace_back(
+                        std::move(multiPowerReleaseMatch));
+                }
             }
         }
     }
     catch (const sdbusplus::exception_t& e)
     {
-        lg2::error("Error creating power button handler: {ERROR}", "ERROR", e);
+        lg2::error("Error creating power button handlers: '{ERROR_MESSAGE}'",
+                   "ERROR_MESSAGE", e.what());
     }
 
     try