Gunnar Mills | 94df8c9 | 2018-09-14 14:50:03 -0500 | [diff] [blame] | 1 | #include "config.h" |
| 2 | |
| 3 | #include "i2c_occ.hpp" |
| 4 | |
Lei YU | 0ab90ca | 2017-07-13 17:02:23 +0800 | [diff] [blame] | 5 | #include <algorithm> |
Lei YU | b5259a1 | 2017-09-01 16:22:40 +0800 | [diff] [blame] | 6 | #include <cassert> |
Lei YU | 0ab90ca | 2017-07-13 17:02:23 +0800 | [diff] [blame] | 7 | #include <fstream> |
| 8 | |
Lei YU | 0ab90ca | 2017-07-13 17:02:23 +0800 | [diff] [blame] | 9 | #ifdef I2C_OCC |
| 10 | |
| 11 | namespace i2c_occ |
| 12 | { |
| 13 | |
George Liu | bcef3b4 | 2021-09-10 12:39:02 +0800 | [diff] [blame] | 14 | namespace fs = std::filesystem; |
Lei YU | 0ab90ca | 2017-07-13 17:02:23 +0800 | [diff] [blame] | 15 | |
Lei YU | 41470e5 | 2017-11-30 16:03:50 +0800 | [diff] [blame] | 16 | // The occ_master sysfs file |
| 17 | constexpr auto OCC_MASTER_FILE = "occ_master"; |
Lei YU | 0ab90ca | 2017-07-13 17:02:23 +0800 | [diff] [blame] | 18 | // The device name's length, e.g. "p8-occ-hwmon" |
| 19 | constexpr auto DEVICE_NAME_LENGTH = 12; |
Lei YU | b5259a1 | 2017-09-01 16:22:40 +0800 | [diff] [blame] | 20 | // The occ name's length, e.g. "occ" |
| 21 | constexpr auto OCC_NAME_LENGTH = 3; |
Lei YU | 0ab90ca | 2017-07-13 17:02:23 +0800 | [diff] [blame] | 22 | |
| 23 | // static assert to make sure the i2c occ device name is expected |
Gunnar Mills | 94df8c9 | 2018-09-14 14:50:03 -0500 | [diff] [blame] | 24 | static_assert(sizeof(I2C_OCC_DEVICE_NAME) - 1 == DEVICE_NAME_LENGTH); |
| 25 | static_assert(sizeof(OCC_NAME) - 1 == OCC_NAME_LENGTH); |
Lei YU | 0ab90ca | 2017-07-13 17:02:23 +0800 | [diff] [blame] | 26 | |
Lei YU | 41470e5 | 2017-11-30 16:03:50 +0800 | [diff] [blame] | 27 | static bool isMasterOcc(const fs::directory_entry& p) |
| 28 | { |
George Liu | bcef3b4 | 2021-09-10 12:39:02 +0800 | [diff] [blame] | 29 | auto f = p / fs::path{OCC_MASTER_FILE}; |
Lei YU | 41470e5 | 2017-11-30 16:03:50 +0800 | [diff] [blame] | 30 | auto str = getFileContent(f); |
| 31 | return (!str.empty()) && (str[0] == '1'); |
| 32 | } |
| 33 | |
Lei YU | 0ab90ca | 2017-07-13 17:02:23 +0800 | [diff] [blame] | 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 | { |
Gunnar Mills | 94df8c9 | 2018-09-14 14:50:03 -0500 | [diff] [blame] | 52 | for (auto& p : fs::directory_iterator(path)) |
Lei YU | 0ab90ca | 2017-07-13 17:02:23 +0800 | [diff] [blame] | 53 | { |
| 54 | // Check if a device's name is "p8-occ-hwmon" |
George Liu | bcef3b4 | 2021-09-10 12:39:02 +0800 | [diff] [blame] | 55 | auto f = p / fs::path{"name"}; |
Lei YU | 0ab90ca | 2017-07-13 17:02:23 +0800 | [diff] [blame] | 56 | auto str = getFileContent(f); |
| 57 | if (str == I2C_OCC_DEVICE_NAME) |
| 58 | { |
Lei YU | 41470e5 | 2017-11-30 16:03:50 +0800 | [diff] [blame] | 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 | } |
Lei YU | 0ab90ca | 2017-07-13 17:02:23 +0800 | [diff] [blame] | 68 | } |
| 69 | } |
Lei YU | 41470e5 | 2017-11-30 16:03:50 +0800 | [diff] [blame] | 70 | } |
| 71 | if (!result.empty()) |
| 72 | { |
| 73 | // Sort the occ devices except for master |
| 74 | std::sort(result.begin() + 1, result.end()); |
Lei YU | 0ab90ca | 2017-07-13 17:02:23 +0800 | [diff] [blame] | 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(); |
Lei YU | b5259a1 | 2017-09-01 16:22:40 +0800 | [diff] [blame] | 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 | |
Lei YU | 0ab90ca | 2017-07-13 17:02:23 +0800 | [diff] [blame] | 99 | dbusToI2c(name); |
| 100 | return name; |
| 101 | } |
| 102 | |
| 103 | } // namespace i2c_occ |
| 104 | |
| 105 | #endif |