1 #include "config.h" 2 3 #include "i2c_occ.hpp" 4 5 #include <algorithm> 6 #include <cassert> 7 #include <fstream> 8 9 #ifdef I2C_OCC 10 11 namespace i2c_occ 12 { 13 14 namespace fs = std::experimental::filesystem; 15 16 // The occ_master sysfs file 17 constexpr auto OCC_MASTER_FILE = "occ_master"; 18 // The device name's length, e.g. "p8-occ-hwmon" 19 constexpr auto DEVICE_NAME_LENGTH = 12; 20 // The occ name's length, e.g. "occ" 21 constexpr auto OCC_NAME_LENGTH = 3; 22 23 // static assert to make sure the i2c occ device name is expected 24 static_assert(sizeof(I2C_OCC_DEVICE_NAME) - 1 == DEVICE_NAME_LENGTH); 25 static_assert(sizeof(OCC_NAME) - 1 == OCC_NAME_LENGTH); 26 27 static bool isMasterOcc(const fs::directory_entry& p) 28 { 29 auto f = p / OCC_MASTER_FILE; 30 auto str = getFileContent(f); 31 return (!str.empty()) && (str[0] == '1'); 32 } 33 34 std::string getFileContent(const fs::path& f) 35 { 36 std::string ret(DEVICE_NAME_LENGTH, 0); 37 std::ifstream ifs(f.c_str(), std::ios::binary); 38 if (ifs.is_open()) 39 { 40 ifs.read(&ret[0], DEVICE_NAME_LENGTH); 41 ret.resize(ifs.gcount()); 42 } 43 return ret; 44 } 45 46 std::vector<std::string> getOccHwmonDevices(const char* path) 47 { 48 std::vector<std::string> result{}; 49 50 if (fs::is_directory(path)) 51 { 52 for (auto& p : fs::directory_iterator(path)) 53 { 54 // Check if a device's name is "p8-occ-hwmon" 55 auto f = p / "name"; 56 auto str = getFileContent(f); 57 if (str == I2C_OCC_DEVICE_NAME) 58 { 59 if (isMasterOcc(p)) 60 { 61 // Insert master occ at the beginning 62 result.emplace(result.begin(), p.path().filename()); 63 } 64 else 65 { 66 result.emplace_back(p.path().filename()); 67 } 68 } 69 } 70 } 71 if (!result.empty()) 72 { 73 // Sort the occ devices except for master 74 std::sort(result.begin() + 1, result.end()); 75 } 76 return result; 77 } 78 79 void i2cToDbus(std::string& path) 80 { 81 std::replace(path.begin(), path.end(), '-', '_'); 82 } 83 84 void dbusToI2c(std::string& path) 85 { 86 std::replace(path.begin(), path.end(), '_', '-'); 87 } 88 89 std::string getI2cDeviceName(const std::string& dbusPath) 90 { 91 auto name = fs::path(dbusPath).filename().string(); 92 93 // Need to make sure the name starts with "occ" 94 assert(name.compare(0, OCC_NAME_LENGTH, OCC_NAME) == 0); 95 96 // Change name like occ_3_0050 to 3_0050 97 name.erase(0, OCC_NAME_LENGTH + 1); 98 99 dbusToI2c(name); 100 return name; 101 } 102 103 } // namespace i2c_occ 104 105 #endif 106