xref: /openbmc/openpower-occ-control/occ_device.hpp (revision 636577f44fe3fc951538c1119ed0da8ac9a40932)
1 #pragma once
2 
3 #include <fstream>
4 #include <experimental/filesystem>
5 #include "occ_events.hpp"
6 #include "occ_errors.hpp"
7 #include "occ_presence.hpp"
8 #include "config.h"
9 
10 namespace open_power
11 {
12 namespace occ
13 {
14 
15 class Manager;
16 namespace fs = std::experimental::filesystem;
17 
18 /** @class Device
19  *  @brief Binds and unbinds the OCC driver upon request
20  */
21 class Device
22 {
23     public:
24         Device() = delete;
25         ~Device() = default;
26         Device(const Device&) = delete;
27         Device& operator=(const Device&) = delete;
28         Device(Device&&) = default;
29         Device& operator=(Device&&) = default;
30 
31         /** @brief Constructs the Device object
32          *
33          *  @param[in] event    - Unique ptr reference to sd_event
34          *  @param[in] name     - OCC instance name
35          *  @param[in] manager  - OCC manager instance
36          *  @param[in] callback - Optional callback on errors
37          */
38         Device(EventPtr& event,
39                const std::string& name,
40                const Manager& manager,
41                std::function<void()> callBack = nullptr) :
42 #ifdef I2C_OCC
43             config(name),
44 #else
45             config(name + '-' + "dev0"),
46 #endif
47             errorFile(fs::path(config) / "occ_error"),
48             error(event, errorFile, callBack),
49             presence(event,
50                      fs::path(config) / "occs_present",
51                      manager,
52                      callBack)
53         {
54             // Nothing to do here
55         }
56 
57         /** @brief Binds device to the OCC driver */
58         inline void bind()
59         {
60             // Bind the device
61             return write(bindPath, config);
62         }
63 
64         /** @brief Un-binds device from the OCC driver */
65         inline void unBind()
66         {
67            // Unbind the device
68            return write(unBindPath, config);
69         }
70 
71         /** @brief Returns if device is already bound.
72          *
73          *  On device bind, a soft link by the name $config
74          *  gets created in OCC_HWMON_PATH and gets removed
75          *  on unbind
76          *
77          *  @return true if bound, else false
78          */
79         inline bool bound() const
80         {
81             return fs::exists(OCC_HWMON_PATH + config);
82         }
83 
84         /** @brief Starts to monitor for errors */
85         inline void addErrorWatch()
86         {
87             if (master())
88             {
89                 presence.addWatch();
90             }
91 
92             error.addWatch();
93         }
94 
95         /** @brief stops monitoring for errors */
96         inline void removeErrorWatch()
97         {
98             // we can always safely remove watch even if we don't add it
99             presence.removeWatch();
100             error.removeWatch();
101         }
102 
103     private:
104         /** @brief Config value to be used to do bind and unbind */
105         const std::string config;
106 
107         /** @brief This file contains 0 for success, non-zero for errors */
108         const fs::path errorFile;
109 
110         /**  @brief To bind the device to the OCC driver, do:
111          *
112          *    Write occ<#>-dev0 to: /sys/bus/platform/drivers/occ-hwmon/bind
113          */
114         static fs::path bindPath;
115 
116         /**  @brief To un-bind the device from the OCC driver, do:
117          *    Write occ<#>-dev0 to: /sys/bus/platform/drivers/occ-hwmon/unbind
118          */
119         static fs::path unBindPath;
120 
121         /** Abstraction of error monitoring */
122         Error error;
123 
124         /** Abstraction of OCC presence monitoring */
125         Presence presence;
126 
127         /** @brief file writer to achieve bind and unbind
128          *
129          *  @param[in] filename - Name of file to be written
130          *  @param[in] data     - Data to be written to
131          *  @return             - None
132          */
133         void write(const fs::path& fileName, const std::string& data)
134         {
135             // If there is an error, move the exception all the way up
136             std::ofstream file(fileName, std::ios::out);
137             file << data;
138             file.close();
139             return;
140         }
141 
142         /** @brief Returns if device represents the master OCC */
143         bool master() const;
144 };
145 
146 } // namespace occ
147 } // namespace open_power
148