psu-ng: Dynamically assign the device driver name

Replaced hardcoded device driver name with a method to build the device
driver name dynamically and assign it to a private data member.

The dynamically built device driver name used during bind/unbind.

Tested the changes in simulation and actual system, compared journalctl
entries of phosphor-psu-monitor with modified phosphor-psu-monitor. The
following test were conducted and verified same journal output:
- Verified driver name assigned correcty to PSU
- Good Machine Path
- Removed Power Supply
- Inserted Power Supply
- Missing Power Supply

Change-Id: Ic376d4ff058e9a2df1887468932faaa28d998960
Signed-off-by: Faisal Awada <faisal@us.ibm.com>
diff --git a/phosphor-power-supply/power_supply.cpp b/phosphor-power-supply/power_supply.cpp
index 3fd72e8..a6e4fae 100644
--- a/phosphor-power-supply/power_supply.cpp
+++ b/phosphor-power-supply/power_supply.cpp
@@ -38,7 +38,7 @@
                          std::function<bool()>&& callback) :
     bus(bus),
     inventoryPath(invpath), bindPath("/sys/bus/i2c/drivers/" + driver),
-    isPowerOn(std::move(callback))
+    isPowerOn(std::move(callback)), driverName(driver)
 {
     if (inventoryPath.empty())
     {
@@ -427,7 +427,7 @@
 
 void PowerSupply::determineMFRFault()
 {
-    if (bindPath.string().find("ibm-cffps") != std::string::npos)
+    if (bindPath.string().find(IBMCFFPS_DD_NAME) != std::string::npos)
     {
         // IBM MFR_SPECIFIC[4] is PS_Kill fault
         if (statusMFR & 0x10)
@@ -555,7 +555,11 @@
             if (statusWord)
             {
                 statusInput = pmbusIntf->read(STATUS_INPUT, Type::Debug);
-                statusMFR = pmbusIntf->read(STATUS_MFR, Type::Debug);
+                if (bindPath.string().find(IBMCFFPS_DD_NAME) !=
+                    std::string::npos)
+                {
+                    statusMFR = pmbusIntf->read(STATUS_MFR, Type::Debug);
+                }
                 statusCML = pmbusIntf->read(STATUS_CML, Type::Debug);
                 auto status0Vout = pmbusIntf->insertPageNum(STATUS_VOUT, 0);
                 statusVout = pmbusIntf->read(status0Vout, Type::Debug);
@@ -1025,7 +1029,7 @@
 
 void PowerSupply::setupInputHistory()
 {
-    if (bindPath.string().find("ibm-cffps") != std::string::npos)
+    if (bindPath.string().find(IBMCFFPS_DD_NAME) != std::string::npos)
     {
         auto maxPowerOut = getMaxPowerOut();
 
diff --git a/phosphor-power-supply/power_supply.hpp b/phosphor-power-supply/power_supply.hpp
index c28c11e..5db6714 100644
--- a/phosphor-power-supply/power_supply.hpp
+++ b/phosphor-power-supply/power_supply.hpp
@@ -50,6 +50,8 @@
 // than PGOOD_DEGLITCH_LIMIT.
 constexpr auto AC_FAULT_LIMIT = 6;
 
+constexpr auto IBMCFFPS_DD_NAME = "ibm-cffps";
+
 using SensorInterface = sdbusplus::xyz::openbmc_project::Sensor::server::Value;
 using SensorObject = sdbusplus::server::object_t<SensorInterface>;
 
@@ -1038,6 +1040,11 @@
      * again (though that could be done as a future improvement).
      */
     std::unique_ptr<SensorObject> inputVoltageRatingIface;
+
+    /**
+     * @brief The device driver name
+     */
+    std::string driverName;
 };
 
 } // namespace phosphor::power::psu
diff --git a/phosphor-power-supply/psu_manager.cpp b/phosphor-power-supply/psu_manager.cpp
index 62501e9..597a164 100644
--- a/phosphor-power-supply/psu_manager.cpp
+++ b/phosphor-power-supply/psu_manager.cpp
@@ -34,6 +34,9 @@
 constexpr auto supportedConfIntf =
     "xyz.openbmc_project.Configuration.SupportedConfiguration";
 
+const auto deviceDirPath = "/sys/bus/i2c/devices/";
+const auto driverDirName = "/driver";
+
 constexpr auto INPUT_HISTORY_SYNC_DELAY = 5;
 
 PSUManager::PSUManager(sdbusplus::bus_t& bus, const sdeventplus::Event& e) :
@@ -245,14 +248,13 @@
             return;
         }
 
-        constexpr auto driver = "ibm-cffps";
+        buildDriverName(*i2cbus, *i2caddr);
         log<level::DEBUG>(
-            fmt::format(
-                "make PowerSupply bus: {} addr: {} driver: {} presline: {}",
-                *i2cbus, *i2caddr, driver, presline)
+            fmt::format("make PowerSupply bus: {} addr: {} presline: {}",
+                        *i2cbus, *i2caddr, presline)
                 .c_str());
         auto psu = std::make_unique<PowerSupply>(
-            bus, invpath, *i2cbus, *i2caddr, driver, presline,
+            bus, invpath, *i2cbus, *i2caddr, driverName, presline,
             std::bind(
                 std::mem_fn(&phosphor::power::manager::PSUManager::isPowerOn),
                 this));
@@ -1264,4 +1266,23 @@
     }
 }
 
+void PSUManager::buildDriverName(uint64_t i2cbus, uint64_t i2caddr)
+{
+    namespace fs = std::filesystem;
+    std::stringstream ss;
+    ss << std::hex << std::setw(4) << std::setfill('0') << i2caddr;
+    std::string symLinkPath =
+        deviceDirPath + std::to_string(i2cbus) + "-" + ss.str() + driverDirName;
+    try
+    {
+        fs::path linkStrPath = fs::read_symlink(symLinkPath);
+        driverName = linkStrPath.filename();
+    }
+    catch (const std::exception& e)
+    {
+        log<level::ERR>(fmt::format("Failed to find device driver {}, error {}",
+                                    symLinkPath, e.what())
+                            .c_str());
+    }
+}
 } // namespace phosphor::power::manager
diff --git a/phosphor-power-supply/psu_manager.hpp b/phosphor-power-supply/psu_manager.hpp
index 8acb416..7bee9f7 100644
--- a/phosphor-power-supply/psu_manager.hpp
+++ b/phosphor-power-supply/psu_manager.hpp
@@ -408,6 +408,19 @@
             psu->setInputVoltageRating();
         }
     }
+
+    /**
+     * @brief Build the device driver name for the power supply.
+     *
+     * @param[in] i2cbus - i2c bus
+     * @param[in] i2caddr - i2c bus address
+     */
+    void buildDriverName(uint64_t i2cbus, uint64_t i2caddr);
+
+    /**
+     * @brief The device driver name for all power supplies.
+     */
+    std::string driverName;
 };
 
 } // namespace phosphor::power::manager