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