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