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 constexpr auto OCC_COMM_ERROR_PATH =
24     "org.open_power.OCC.Device.Error.OpenFailure";
25 
26 /** @class Error
27  *  @brief Monitors for OCC device error condition
28  */
29 class Error
30 {
31   public:
32     Error() = delete;
33     Error(const Error&) = delete;
34     Error& operator=(const Error&) = delete;
35     Error(Error&&) = default;
36     Error& operator=(Error&&) = default;
37 
38     /** @brief Constructs the Error object
39      *
40      *  @param[in] event    - reference to sd_event unique_ptr
41      *  @param[in] file     - File used by driver to communicate errors
42      *  @param[in] callBack - Optional function callback on error condition
43      */
Error(EventPtr & event,const fs::path & file,std::function<void (int)> callBack=nullptr)44     Error(EventPtr& event, const fs::path& file,
45           std::function<void(int)> callBack = nullptr) :
46         event(event), file(file), callBack(callBack)
47     {
48         // Nothing to do here.
49     }
50 
~Error()51     virtual ~Error()
52     {
53         if (fd >= 0)
54         {
55             close(fd);
56         }
57     }
58 
59     /** @class Descriptor
60      *  @brief Contains data relevant to an error that occurred.
61      */
62     class Descriptor
63     {
64       public:
65         Descriptor(const Descriptor&) = default;
66         Descriptor& operator=(const Descriptor&) = default;
67         Descriptor(Descriptor&&) = default;
68         Descriptor& operator=(Descriptor&&) = default;
69 
Descriptor()70         Descriptor() : log(false), err(0), callout(nullptr), path(nullptr) {}
71 
72         /** @brief Constructs the Descriptor object
73          *
74          *  @param[in] path - the DBus error path
75          *  @param[in] err - Optional error return code
76          *  @param[in] callout - Optional PEL callout path
77          */
Descriptor(const char * path,int err=0,const char * callout=nullptr)78         Descriptor(const char* path, int err = 0,
79                    const char* callout = nullptr) :
80             log(true), 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