xref: /openbmc/openpower-occ-control/i2c_occ.cpp (revision bcef3b4870bd93e6350f952706861bfac79982f4)
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::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  
isMasterOcc(const fs::directory_entry & p)27  static bool isMasterOcc(const fs::directory_entry& p)
28  {
29      auto f = p / fs::path{OCC_MASTER_FILE};
30      auto str = getFileContent(f);
31      return (!str.empty()) && (str[0] == '1');
32  }
33  
getFileContent(const fs::path & f)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  
getOccHwmonDevices(const char * path)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 / fs::path{"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  
i2cToDbus(std::string & path)79  void i2cToDbus(std::string& path)
80  {
81      std::replace(path.begin(), path.end(), '-', '_');
82  }
83  
dbusToI2c(std::string & path)84  void dbusToI2c(std::string& path)
85  {
86      std::replace(path.begin(), path.end(), '_', '-');
87  }
88  
getI2cDeviceName(const std::string & dbusPath)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