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