1 #pragma once 2 3 #include "config.h" 4 5 #include "occ_events.hpp" 6 7 #include <unistd.h> 8 9 #include <filesystem> 10 #include <functional> 11 namespace open_power 12 { 13 namespace occ 14 { 15 16 namespace fs = std::filesystem; 17 18 constexpr auto PRESENCE_ERROR_PATH = 19 "org.open_power.OCC.Firmware.PresenceMismatch"; 20 constexpr auto SAFE_ERROR_PATH = "org.open_power.OCC.Device.SafeState"; 21 22 /** @class Error 23 * @brief Monitors for OCC device error condition 24 */ 25 class Error 26 { 27 public: 28 Error() = delete; 29 Error(const Error&) = delete; 30 Error& operator=(const Error&) = delete; 31 Error(Error&&) = default; 32 Error& operator=(Error&&) = default; 33 34 /** @brief Constructs the Error object 35 * 36 * @param[in] event - reference to sd_event unique_ptr 37 * @param[in] file - File used by driver to communicate errors 38 * @param[in] callBack - Optional function callback on error condition 39 */ 40 Error(EventPtr& event, const fs::path& file, 41 std::function<void(int)> callBack = nullptr) : 42 event(event), 43 file(file), callBack(callBack) 44 { 45 // Nothing to do here. 46 } 47 48 virtual ~Error() 49 { 50 if (fd >= 0) 51 { 52 close(fd); 53 } 54 } 55 56 /** @class Descriptor 57 * @brief Contains data relevant to an error that occurred. 58 */ 59 class Descriptor 60 { 61 public: 62 Descriptor(const Descriptor&) = default; 63 Descriptor& operator=(const Descriptor&) = default; 64 Descriptor(Descriptor&&) = default; 65 Descriptor& operator=(Descriptor&&) = default; 66 67 Descriptor() : log(false), err(0), callout(nullptr), path(nullptr) 68 {} 69 70 /** @brief Constructs the Descriptor object 71 * 72 * @param[in] path - the DBus error path 73 * @param[in] err - Optional error return code 74 * @param[in] callout - Optional PEL callout path 75 */ 76 Descriptor(const char* path, int err = 0, 77 const char* callout = nullptr) : 78 log(true), 79 err(err), callout(callout), path(path) 80 {} 81 82 bool log; 83 int err; 84 const char* callout; 85 const char* path; 86 }; 87 88 /** @brief Starts to monitor for error conditions 89 * 90 * @param[in] poll - Indicates whether or not the error file should 91 * actually be polled for changes. Disabling polling is 92 * necessary for error files that don't support the poll 93 * file operation. 94 */ 95 void addWatch(bool poll = true); 96 97 /** @brief Removes error watch */ 98 void removeWatch(); 99 100 inline void setFile(const fs::path& f) 101 { 102 file = f; 103 } 104 105 private: 106 /** @brief sd_event wrapped in unique_ptr */ 107 EventPtr& event; 108 109 /** @brief event source wrapped in unique_ptr */ 110 EventSourcePtr eventSource; 111 112 /** @brief Current state of error watching */ 113 bool watching = false; 114 115 /** @brief attaches FD to events and sets up callback handler */ 116 void registerCallBack(); 117 118 /** @brief Opens the file and populates fd */ 119 void openFile(); 120 121 /** @brief Callback handler when the FD has some activity on it 122 * 123 * @param[in] es - Populated event source 124 * @param[in] fd - Associated File descriptor 125 * @param[in] revents - Type of event 126 * @param[in] userData - User data that was passed during registration 127 * 128 * @return - 0 or positive number on success and negative 129 * errno otherwise 130 */ 131 static int processEvents(sd_event_source* es, int fd, uint32_t revents, 132 void* userData); 133 134 /** @brief When the error event is received, analyzes it 135 * and makes a callback to error handler if the 136 * content denotes an error condition 137 */ 138 virtual void analyzeEvent(); 139 140 protected: 141 /** @brief File descriptor to watch for errors */ 142 int fd = -1; 143 144 /** Error file */ 145 fs::path file; 146 147 /** @brief Optional function to call on error scenario */ 148 std::function<void(int)> callBack; 149 150 /** @brief Reads file data 151 * 152 * @return data read. Since its a /sysfs entry, 153 * it would be a string 154 */ 155 std::string readFile(int) const; 156 }; 157 158 } // namespace occ 159 } // namespace open_power 160