| #include <algorithm> |
| #include <cassert> |
| #include <fstream> |
| |
| #include "config.h" |
| #include "i2c_occ.hpp" |
| |
| #ifdef I2C_OCC |
| |
| namespace i2c_occ |
| { |
| |
| namespace fs = std::experimental::filesystem; |
| |
| // The occ_master sysfs file |
| constexpr auto OCC_MASTER_FILE = "occ_master"; |
| // The device name's length, e.g. "p8-occ-hwmon" |
| constexpr auto DEVICE_NAME_LENGTH = 12; |
| // The occ name's length, e.g. "occ" |
| constexpr auto OCC_NAME_LENGTH = 3; |
| |
| // static assert to make sure the i2c occ device name is expected |
| static_assert(sizeof(I2C_OCC_DEVICE_NAME) -1 == DEVICE_NAME_LENGTH); |
| static_assert(sizeof(OCC_NAME) -1 == OCC_NAME_LENGTH); |
| |
| static bool isMasterOcc(const fs::directory_entry& p) |
| { |
| auto f = p / OCC_MASTER_FILE; |
| auto str = getFileContent(f); |
| return (!str.empty()) && (str[0] == '1'); |
| } |
| |
| std::string getFileContent(const fs::path& f) |
| { |
| std::string ret(DEVICE_NAME_LENGTH, 0); |
| std::ifstream ifs(f.c_str(), std::ios::binary); |
| if (ifs.is_open()) |
| { |
| ifs.read(&ret[0], DEVICE_NAME_LENGTH); |
| ret.resize(ifs.gcount()); |
| } |
| return ret; |
| } |
| |
| std::vector<std::string> getOccHwmonDevices(const char* path) |
| { |
| std::vector<std::string> result{}; |
| |
| if (fs::is_directory(path)) |
| { |
| for (auto & p : fs::directory_iterator(path)) |
| { |
| // Check if a device's name is "p8-occ-hwmon" |
| auto f = p / "name"; |
| auto str = getFileContent(f); |
| if (str == I2C_OCC_DEVICE_NAME) |
| { |
| if (isMasterOcc(p)) |
| { |
| // Insert master occ at the beginning |
| result.emplace(result.begin(), p.path().filename()); |
| } |
| else |
| { |
| result.emplace_back(p.path().filename()); |
| } |
| } |
| } |
| } |
| if (!result.empty()) |
| { |
| // Sort the occ devices except for master |
| std::sort(result.begin() + 1, result.end()); |
| } |
| return result; |
| } |
| |
| void i2cToDbus(std::string& path) |
| { |
| std::replace(path.begin(), path.end(), '-', '_'); |
| } |
| |
| void dbusToI2c(std::string& path) |
| { |
| std::replace(path.begin(), path.end(), '_', '-'); |
| } |
| |
| std::string getI2cDeviceName(const std::string& dbusPath) |
| { |
| auto name = fs::path(dbusPath).filename().string(); |
| |
| // Need to make sure the name starts with "occ" |
| assert(name.compare(0, OCC_NAME_LENGTH, OCC_NAME) == 0); |
| |
| // Change name like occ_3_0050 to 3_0050 |
| name.erase(0, OCC_NAME_LENGTH + 1); |
| |
| dbusToI2c(name); |
| return name; |
| } |
| |
| } // namespace i2c_occ |
| |
| #endif |
| |