Add support to watch for OCC errors

Change-Id: I98d95020a2d01e281e5c8efa825d6b4bd4c6c160
Signed-off-by: Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com>
diff --git a/occ_errors.hpp b/occ_errors.hpp
new file mode 100644
index 0000000..1e66ffc
--- /dev/null
+++ b/occ_errors.hpp
@@ -0,0 +1,107 @@
+#pragma once
+
+#include <unistd.h>
+#include <functional>
+#include <experimental/filesystem>
+#include "occ_events.hpp"
+#include "config.h"
+namespace open_power
+{
+namespace occ
+{
+
+namespace fs = std::experimental::filesystem;
+
+/** @class Error
+ *  @brief Monitors for OCC device error condition
+ */
+class Error
+{
+    public:
+        Error() = delete;
+        Error(const Error&) = delete;
+        Error& operator=(const Error&) = delete;
+        Error(Error&&) = default;
+        Error& operator=(Error&&) = default;
+
+        /** @brief Constructs the Error object
+         *
+         *  @param[in] event    - reference to sd_event unique_ptr
+         *  @param[in] file     - File used by driver to communicate errors
+         *  @param[in] callBack - Optional function callback on error condition
+         */
+        Error(EventPtr& event,
+              const fs::path& file,
+              std::function<void()> callBack = nullptr) :
+            event(event),
+            file(fs::path(DEV_PATH) / file),
+            callBack(callBack)
+        {
+            // Nothing to do here.
+        }
+
+        ~Error()
+        {
+            if (fd>= 0)
+            {
+                close(fd);
+            }
+        }
+
+        /** @brief Starts to monitor for error conditions */
+        void addWatch();
+
+        /** @brief Removes error watch */
+        void removeWatch();
+
+    private:
+        /** @brief sd_event wrapped in unique_ptr */
+        EventPtr& event;
+
+        /** @brief event source wrapped in unique_ptr */
+        EventSourcePtr eventSource;
+
+        /** Error file */
+        const fs::path file;
+
+        /** @brief Optional function to call on error scenario */
+        std::function<void()> callBack;
+
+        /** @brief File descriptor to watch for errors */
+        int fd = -1;
+
+        /** @brief attaches FD to events and sets up callback handler */
+        void registerCallBack();
+
+        /** @brief Opens the file and populates fd */
+        void openFile();
+
+        /** @brief Reads file data
+         *
+         *  @return data read. Since its a /sysfs entry,
+         *          it would be a string
+         */
+        std::string readFile(int) const;
+
+        /** @brief Callback handler when the FD has some activity on it
+         *
+         *  @param[in] es       - Populated event source
+         *  @param[in] fd       - Associated File descriptor
+         *  @param[in] revents  - Type of event
+         *  @param[in] userData - User data that was passed during registration
+         *
+         *  @return             - 0 or positive number on success and negative
+         *                        errno otherwise
+         */
+        static int processEvents(sd_event_source* es, int fd,
+                                 uint32_t revents, void* userData);
+
+        /** @brief When the error event is received, analyzes it
+         *         and makes a callback to error handler if the
+         *         content denotes an error condition
+         */
+        void analyzeEvent();
+};
+
+} // namespace occ
+} // namespace open_power