blob: a9d55fe3b141a1f53592423814b08f837adf43c3 [file] [log] [blame]
Gunnar Mills94df8c92018-09-14 14:50:03 -05001#include "config.h"
2
3#include "i2c_occ.hpp"
4
Lei YU0ab90ca2017-07-13 17:02:23 +08005#include <algorithm>
Lei YUb5259a12017-09-01 16:22:40 +08006#include <cassert>
Lei YU0ab90ca2017-07-13 17:02:23 +08007#include <fstream>
8
Lei YU0ab90ca2017-07-13 17:02:23 +08009#ifdef I2C_OCC
10
11namespace i2c_occ
12{
13
George Liubcef3b42021-09-10 12:39:02 +080014namespace fs = std::filesystem;
Lei YU0ab90ca2017-07-13 17:02:23 +080015
Lei YU41470e52017-11-30 16:03:50 +080016// The occ_master sysfs file
17constexpr auto OCC_MASTER_FILE = "occ_master";
Lei YU0ab90ca2017-07-13 17:02:23 +080018// The device name's length, e.g. "p8-occ-hwmon"
19constexpr auto DEVICE_NAME_LENGTH = 12;
Lei YUb5259a12017-09-01 16:22:40 +080020// The occ name's length, e.g. "occ"
21constexpr auto OCC_NAME_LENGTH = 3;
Lei YU0ab90ca2017-07-13 17:02:23 +080022
23// static assert to make sure the i2c occ device name is expected
Gunnar Mills94df8c92018-09-14 14:50:03 -050024static_assert(sizeof(I2C_OCC_DEVICE_NAME) - 1 == DEVICE_NAME_LENGTH);
25static_assert(sizeof(OCC_NAME) - 1 == OCC_NAME_LENGTH);
Lei YU0ab90ca2017-07-13 17:02:23 +080026
Lei YU41470e52017-11-30 16:03:50 +080027static bool isMasterOcc(const fs::directory_entry& p)
28{
George Liubcef3b42021-09-10 12:39:02 +080029 auto f = p / fs::path{OCC_MASTER_FILE};
Lei YU41470e52017-11-30 16:03:50 +080030 auto str = getFileContent(f);
31 return (!str.empty()) && (str[0] == '1');
32}
33
Lei YU0ab90ca2017-07-13 17:02:23 +080034std::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
46std::vector<std::string> getOccHwmonDevices(const char* path)
47{
48 std::vector<std::string> result{};
49
50 if (fs::is_directory(path))
51 {
Gunnar Mills94df8c92018-09-14 14:50:03 -050052 for (auto& p : fs::directory_iterator(path))
Lei YU0ab90ca2017-07-13 17:02:23 +080053 {
54 // Check if a device's name is "p8-occ-hwmon"
George Liubcef3b42021-09-10 12:39:02 +080055 auto f = p / fs::path{"name"};
Lei YU0ab90ca2017-07-13 17:02:23 +080056 auto str = getFileContent(f);
57 if (str == I2C_OCC_DEVICE_NAME)
58 {
Lei YU41470e52017-11-30 16:03:50 +080059 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 YU0ab90ca2017-07-13 17:02:23 +080068 }
69 }
Lei YU41470e52017-11-30 16:03:50 +080070 }
71 if (!result.empty())
72 {
73 // Sort the occ devices except for master
74 std::sort(result.begin() + 1, result.end());
Lei YU0ab90ca2017-07-13 17:02:23 +080075 }
76 return result;
77}
78
79void i2cToDbus(std::string& path)
80{
81 std::replace(path.begin(), path.end(), '-', '_');
82}
83
84void dbusToI2c(std::string& path)
85{
86 std::replace(path.begin(), path.end(), '_', '-');
87}
88
89std::string getI2cDeviceName(const std::string& dbusPath)
90{
91 auto name = fs::path(dbusPath).filename().string();
Lei YUb5259a12017-09-01 16:22:40 +080092
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 YU0ab90ca2017-07-13 17:02:23 +080099 dbusToI2c(name);
100 return name;
101}
102
103} // namespace i2c_occ
104
105#endif