blob: c0a474984bb02346447fe131223b33c43642f0f1 [file] [log] [blame]
Matt Spinler18c42b02020-06-02 15:59:50 -05001/**
2 * Copyright © 2020 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include "device_callouts.hpp"
17
18#include "paths.hpp"
19
20#include <fstream>
21#include <phosphor-logging/log.hpp>
22#include <regex>
23
24namespace openpower::pels::device_callouts
25{
26
27constexpr auto debugFilePath = "/etc/phosphor-logging/";
28constexpr auto calloutFileSuffix = "_dev_callouts.json";
29
30namespace fs = std::filesystem;
31using namespace phosphor::logging;
32
33namespace util
34{
35
36fs::path getJSONFilename(const std::vector<std::string>& compatibleList)
37{
38 auto basePath = getPELReadOnlyDataPath();
39 fs::path fullPath;
40
41 // Find an entry in the list of compatible system names that
42 // matches a filename we have.
43
44 for (const auto& name : compatibleList)
45 {
46 fs::path filename = name + calloutFileSuffix;
47
48 // Check the debug path first
49 fs::path path{fs::path{debugFilePath} / filename};
50
51 if (fs::exists(path))
52 {
53 log<level::INFO>("Found device callout debug file");
54 fullPath = path;
55 break;
56 }
57
58 path = basePath / filename;
59
60 if (fs::exists(path))
61 {
62 fullPath = path;
63 break;
64 }
65 }
66
67 if (fullPath.empty())
68 {
69 throw std::invalid_argument(
70 "No JSON dev path callout file for this system");
71 }
72
73 return fullPath;
74}
75
76/**
77 * @brief Reads the callout JSON into an object based on the
78 * compatible system names list.
79 *
80 * @param[in] compatibleList - The list of compatible names for this
81 * system.
82 *
83 * @return nlohmann::json - The JSON object
84 */
85nlohmann::json loadJSON(const std::vector<std::string>& compatibleList)
86{
87 auto filename = getJSONFilename(compatibleList);
88 std::ifstream file{filename};
89 return nlohmann::json::parse(file);
90}
91
92std::vector<device_callouts::Callout>
93 calloutI2C(size_t i2cBus, uint8_t i2cAddress,
94 const nlohmann::json& calloutJSON)
95{
96 // TODO
97 return {};
98}
99
100std::vector<device_callouts::Callout> findCallouts(const std::string& devPath,
101 const nlohmann::json& json)
102{
103 std::vector<Callout> callouts;
Matt Spinlera3070892020-06-03 10:52:32 -0500104 fs::path path;
Matt Spinler18c42b02020-06-02 15:59:50 -0500105
Matt Spinlera3070892020-06-03 10:52:32 -0500106 // Gives the /sys/devices/platform/ path
107 try
108 {
109 path = fs::canonical(devPath);
110 }
111 catch (const fs::filesystem_error& e)
112 {
113 // Path not there, still try to do the callout
114 path = devPath;
115 }
116
117 switch (util::getCalloutType(path))
118 {
119 case util::CalloutType::i2c:
120 // callouts = calloutI2CUsingPath(errnoValue, path, json);
121 break;
122 case util::CalloutType::fsi:
123 // callouts = calloutFSI(errnoValue, path, json);
124 break;
125 case util::CalloutType::fsii2c:
126 // callouts = calloutFSII2C(errnoValue, path, json);
127 break;
128 case util::CalloutType::fsispi:
129 // callouts = calloutFSISPI(errnoValue, path, json);
130 break;
131 default:
132 std::string msg =
133 "Could not get callout type from device path: " + path.string();
134 throw std::invalid_argument{msg.c_str()};
135 break;
136 }
Matt Spinler18c42b02020-06-02 15:59:50 -0500137
138 return callouts;
139}
140
Matt Spinlera3070892020-06-03 10:52:32 -0500141CalloutType getCalloutType(const std::string& devPath)
142{
143 if ((devPath.find("fsi-master") != std::string::npos) &&
144 (devPath.find("i2c-") != std::string::npos))
145 {
146 return CalloutType::fsii2c;
147 }
148
149 if ((devPath.find("fsi-master") != std::string::npos) &&
150 (devPath.find("spi") != std::string::npos))
151 {
152 return CalloutType::fsispi;
153 }
154
155 // Treat anything else FSI related as plain FSI
156 if (devPath.find("fsi-master") != std::string::npos)
157 {
158 return CalloutType::fsi;
159 }
160
161 if (devPath.find("i2c-bus/i2c-") != std::string::npos)
162 {
163 return CalloutType::i2c;
164 }
165
166 return CalloutType::unknown;
167}
168
Matt Spinler18c42b02020-06-02 15:59:50 -0500169} // namespace util
170
171std::vector<Callout> getCallouts(const std::string& devPath,
172 const std::vector<std::string>& compatibleList)
173{
174 auto json = util::loadJSON(compatibleList);
175 return util::findCallouts(devPath, json);
176}
177
178std::vector<Callout>
179 getI2CCallouts(size_t i2cBus, uint8_t i2cAddress,
180 const std::vector<std::string>& compatibleList)
181{
182 auto json = util::loadJSON(compatibleList);
183 return util::calloutI2C(i2cBus, i2cAddress, json);
184}
185
186} // namespace openpower::pels::device_callouts