Add beep support for PSU

Spec requires that system will beep with pattern 1-5-1-4
if there is any PSU failure or config error.

Tested:
With two PSUs, disconnect one AC cable, or unplug one PSU,
to trigger the psu failure/config error, there is a beep.

Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
Change-Id: I8664400164298fa4a35f82b79e4bf417481aabb0
diff --git a/include/PSUEvent.hpp b/include/PSUEvent.hpp
index 623806b..f5bc155 100644
--- a/include/PSUEvent.hpp
+++ b/include/PSUEvent.hpp
@@ -27,8 +27,10 @@
 {
   public:
     PSUSubEvent(std::shared_ptr<sdbusplus::asio::dbus_interface> eventInterface,
-                const std::string& path, boost::asio::io_service& io,
-                const std::string& groupEventName, const std::string& eventName,
+                const std::string& path,
+                std::shared_ptr<sdbusplus::asio::connection>& conn,
+                boost::asio::io_service& io, const std::string& groupEventName,
+                const std::string& eventName,
                 std::shared_ptr<std::set<std::string>> asserts,
                 std::shared_ptr<std::set<std::string>> combineEvent,
                 std::shared_ptr<bool> state, const std::string& psuName);
@@ -51,6 +53,8 @@
     void setupRead(void);
     void handleResponse(const boost::system::error_code& err);
     void updateValue(const int& newValue);
+    void beep(const uint8_t& beepPriority);
+    static constexpr uint8_t beepPSUFailure = 2;
     boost::asio::posix::stream_descriptor inputDev;
     static constexpr unsigned int eventPollMs = 1000;
     static constexpr size_t warnAfterErrorCount = 10;
@@ -58,6 +62,7 @@
     std::string fanName;
     std::string assertMessage;
     std::string deassertMessage;
+    std::shared_ptr<sdbusplus::asio::connection> systemBus;
 };
 
 class PSUCombineEvent
@@ -65,6 +70,7 @@
   public:
     PSUCombineEvent(
         sdbusplus::asio::object_server& objectSever,
+        std::shared_ptr<sdbusplus::asio::connection>& conn,
         boost::asio::io_service& io, const std::string& psuName,
         boost::container::flat_map<std::string, std::vector<std::string>>&
             eventPathList,
diff --git a/src/PSUEvent.cpp b/src/PSUEvent.cpp
index 0849500..1e228fe 100644
--- a/src/PSUEvent.cpp
+++ b/src/PSUEvent.cpp
@@ -30,8 +30,9 @@
 #include <vector>
 
 PSUCombineEvent::PSUCombineEvent(
-    sdbusplus::asio::object_server& objectServer, boost::asio::io_service& io,
-    const std::string& psuName,
+    sdbusplus::asio::object_server& objectServer,
+    std::shared_ptr<sdbusplus::asio::connection>& conn,
+    boost::asio::io_service& io, const std::string& psuName,
     boost::container::flat_map<std::string, std::vector<std::string>>&
         eventPathList,
     boost::container::flat_map<
@@ -65,7 +66,7 @@
         for (const auto& path : pathList.second)
         {
             events[eventPSUName].emplace_back(std::make_unique<PSUSubEvent>(
-                eventInterface, path, io, eventName, eventName, assert,
+                eventInterface, path, conn, io, eventName, eventName, assert,
                 combineEvent, state, psuName));
             asserts.emplace_back(assert);
             states.emplace_back(state);
@@ -85,7 +86,7 @@
             for (const auto& path : pathList.second)
             {
                 events[eventPSUName].emplace_back(std::make_unique<PSUSubEvent>(
-                    eventInterface, path, io, groupEventName,
+                    eventInterface, path, conn, io, groupEventName,
                     groupPathList.first, assert, combineEvent, state, psuName));
                 asserts.emplace_back(assert);
                 states.emplace_back(state);
@@ -128,15 +129,16 @@
 
 PSUSubEvent::PSUSubEvent(
     std::shared_ptr<sdbusplus::asio::dbus_interface> eventInterface,
-    const std::string& path, boost::asio::io_service& io,
-    const std::string& groupEventName, const std::string& eventName,
+    const std::string& path, std::shared_ptr<sdbusplus::asio::connection>& conn,
+    boost::asio::io_service& io, const std::string& groupEventName,
+    const std::string& eventName,
     std::shared_ptr<std::set<std::string>> asserts,
     std::shared_ptr<std::set<std::string>> combineEvent,
     std::shared_ptr<bool> state, const std::string& psuName) :
     eventInterface(eventInterface),
     asserts(asserts), combineEvent(combineEvent), assertState(state),
     errCount(0), path(path), eventName(eventName), waitTimer(io), inputDev(io),
-    psuName(psuName), groupEventName(groupEventName)
+    psuName(psuName), groupEventName(groupEventName), systemBus(conn)
 {
     fd = open(path.c_str(), O_RDONLY);
     if (fd < 0)
@@ -303,6 +305,15 @@
             *assertState = true;
             if (!assertMessage.empty())
             {
+                // For failure and configure error, spec requires a beep
+                if ((assertMessage == "OpenBMC.0.1.PowerSupplyFailed") ||
+                    (assertMessage ==
+                     "OpenBMC.0.1.PowerSupplyConfigurationError"))
+                {
+                    std::cout << " beep for " << assertMessage << "\n";
+                    beep(beepPSUFailure);
+                }
+
                 // Fan Failed has two args
                 std::string sendMessage = eventName + " assert";
                 if (assertMessage == "OpenBMC.0.1.PowerSupplyFanFailed")
@@ -332,3 +343,17 @@
     }
     value = newValue;
 }
+
+void PSUSubEvent::beep(const uint8_t& beepPriority)
+{
+    systemBus->async_method_call(
+        [](boost::system::error_code ec) {
+            if (ec)
+            {
+                std::cerr << "beep error (ec = " << ec << ")\n";
+                return;
+            }
+        },
+        "xyz.openbmc_project.BeepCode", "/xyz/openbmc_project/BeepCode",
+        "xyz.openbmc_project.BeepCode", "Beep", uint8_t(beepPriority));
+}
diff --git a/src/PSUSensorMain.cpp b/src/PSUSensorMain.cpp
index 19286f6..90c7950 100644
--- a/src/PSUSensorMain.cpp
+++ b/src/PSUSensorMain.cpp
@@ -748,9 +748,9 @@
         // OperationalStatus event
         combineEvents[*psuName + "OperationalStatus"] = nullptr;
         combineEvents[*psuName + "OperationalStatus"] =
-            std::make_unique<PSUCombineEvent>(objectServer, io, *psuName,
-                                              eventPathList, groupEventPathList,
-                                              "OperationalStatus");
+            std::make_unique<PSUCombineEvent>(
+                objectServer, dbusConnection, io, *psuName, eventPathList,
+                groupEventPathList, "OperationalStatus");
     }
 
     if constexpr (DEBUG)