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