118c42b0fSMatt Spinler /** 218c42b0fSMatt Spinler * Copyright © 2020 IBM Corporation 318c42b0fSMatt Spinler * 418c42b0fSMatt Spinler * Licensed under the Apache License, Version 2.0 (the "License"); 518c42b0fSMatt Spinler * you may not use this file except in compliance with the License. 618c42b0fSMatt Spinler * You may obtain a copy of the License at 718c42b0fSMatt Spinler * 818c42b0fSMatt Spinler * http://www.apache.org/licenses/LICENSE-2.0 918c42b0fSMatt Spinler * 1018c42b0fSMatt Spinler * Unless required by applicable law or agreed to in writing, software 1118c42b0fSMatt Spinler * distributed under the License is distributed on an "AS IS" BASIS, 1218c42b0fSMatt Spinler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1318c42b0fSMatt Spinler * See the License for the specific language governing permissions and 1418c42b0fSMatt Spinler * limitations under the License. 1518c42b0fSMatt Spinler */ 1618c42b0fSMatt Spinler #include "device_callouts.hpp" 1718c42b0fSMatt Spinler 1818c42b0fSMatt Spinler #include "paths.hpp" 1918c42b0fSMatt Spinler 2018c42b0fSMatt Spinler #include <fstream> 2118c42b0fSMatt Spinler #include <phosphor-logging/log.hpp> 2218c42b0fSMatt Spinler #include <regex> 2318c42b0fSMatt Spinler 2418c42b0fSMatt Spinler namespace openpower::pels::device_callouts 2518c42b0fSMatt Spinler { 2618c42b0fSMatt Spinler 2718c42b0fSMatt Spinler constexpr auto debugFilePath = "/etc/phosphor-logging/"; 2818c42b0fSMatt Spinler constexpr auto calloutFileSuffix = "_dev_callouts.json"; 2918c42b0fSMatt Spinler 3018c42b0fSMatt Spinler namespace fs = std::filesystem; 3118c42b0fSMatt Spinler using namespace phosphor::logging; 3218c42b0fSMatt Spinler 3318c42b0fSMatt Spinler namespace util 3418c42b0fSMatt Spinler { 3518c42b0fSMatt Spinler 3618c42b0fSMatt Spinler fs::path getJSONFilename(const std::vector<std::string>& compatibleList) 3718c42b0fSMatt Spinler { 3818c42b0fSMatt Spinler auto basePath = getPELReadOnlyDataPath(); 3918c42b0fSMatt Spinler fs::path fullPath; 4018c42b0fSMatt Spinler 4118c42b0fSMatt Spinler // Find an entry in the list of compatible system names that 4218c42b0fSMatt Spinler // matches a filename we have. 4318c42b0fSMatt Spinler 4418c42b0fSMatt Spinler for (const auto& name : compatibleList) 4518c42b0fSMatt Spinler { 4618c42b0fSMatt Spinler fs::path filename = name + calloutFileSuffix; 4718c42b0fSMatt Spinler 4818c42b0fSMatt Spinler // Check the debug path first 4918c42b0fSMatt Spinler fs::path path{fs::path{debugFilePath} / filename}; 5018c42b0fSMatt Spinler 5118c42b0fSMatt Spinler if (fs::exists(path)) 5218c42b0fSMatt Spinler { 5318c42b0fSMatt Spinler log<level::INFO>("Found device callout debug file"); 5418c42b0fSMatt Spinler fullPath = path; 5518c42b0fSMatt Spinler break; 5618c42b0fSMatt Spinler } 5718c42b0fSMatt Spinler 5818c42b0fSMatt Spinler path = basePath / filename; 5918c42b0fSMatt Spinler 6018c42b0fSMatt Spinler if (fs::exists(path)) 6118c42b0fSMatt Spinler { 6218c42b0fSMatt Spinler fullPath = path; 6318c42b0fSMatt Spinler break; 6418c42b0fSMatt Spinler } 6518c42b0fSMatt Spinler } 6618c42b0fSMatt Spinler 6718c42b0fSMatt Spinler if (fullPath.empty()) 6818c42b0fSMatt Spinler { 6918c42b0fSMatt Spinler throw std::invalid_argument( 7018c42b0fSMatt Spinler "No JSON dev path callout file for this system"); 7118c42b0fSMatt Spinler } 7218c42b0fSMatt Spinler 7318c42b0fSMatt Spinler return fullPath; 7418c42b0fSMatt Spinler } 7518c42b0fSMatt Spinler 7618c42b0fSMatt Spinler /** 7718c42b0fSMatt Spinler * @brief Reads the callout JSON into an object based on the 7818c42b0fSMatt Spinler * compatible system names list. 7918c42b0fSMatt Spinler * 8018c42b0fSMatt Spinler * @param[in] compatibleList - The list of compatible names for this 8118c42b0fSMatt Spinler * system. 8218c42b0fSMatt Spinler * 8318c42b0fSMatt Spinler * @return nlohmann::json - The JSON object 8418c42b0fSMatt Spinler */ 8518c42b0fSMatt Spinler nlohmann::json loadJSON(const std::vector<std::string>& compatibleList) 8618c42b0fSMatt Spinler { 8718c42b0fSMatt Spinler auto filename = getJSONFilename(compatibleList); 8818c42b0fSMatt Spinler std::ifstream file{filename}; 8918c42b0fSMatt Spinler return nlohmann::json::parse(file); 9018c42b0fSMatt Spinler } 9118c42b0fSMatt Spinler 9218c42b0fSMatt Spinler std::vector<device_callouts::Callout> 9318c42b0fSMatt Spinler calloutI2C(size_t i2cBus, uint8_t i2cAddress, 9418c42b0fSMatt Spinler const nlohmann::json& calloutJSON) 9518c42b0fSMatt Spinler { 9618c42b0fSMatt Spinler // TODO 9718c42b0fSMatt Spinler return {}; 9818c42b0fSMatt Spinler } 9918c42b0fSMatt Spinler 10018c42b0fSMatt Spinler std::vector<device_callouts::Callout> findCallouts(const std::string& devPath, 10118c42b0fSMatt Spinler const nlohmann::json& json) 10218c42b0fSMatt Spinler { 10318c42b0fSMatt Spinler std::vector<Callout> callouts; 104*a307089cSMatt Spinler fs::path path; 10518c42b0fSMatt Spinler 106*a307089cSMatt Spinler // Gives the /sys/devices/platform/ path 107*a307089cSMatt Spinler try 108*a307089cSMatt Spinler { 109*a307089cSMatt Spinler path = fs::canonical(devPath); 110*a307089cSMatt Spinler } 111*a307089cSMatt Spinler catch (const fs::filesystem_error& e) 112*a307089cSMatt Spinler { 113*a307089cSMatt Spinler // Path not there, still try to do the callout 114*a307089cSMatt Spinler path = devPath; 115*a307089cSMatt Spinler } 116*a307089cSMatt Spinler 117*a307089cSMatt Spinler switch (util::getCalloutType(path)) 118*a307089cSMatt Spinler { 119*a307089cSMatt Spinler case util::CalloutType::i2c: 120*a307089cSMatt Spinler // callouts = calloutI2CUsingPath(errnoValue, path, json); 121*a307089cSMatt Spinler break; 122*a307089cSMatt Spinler case util::CalloutType::fsi: 123*a307089cSMatt Spinler // callouts = calloutFSI(errnoValue, path, json); 124*a307089cSMatt Spinler break; 125*a307089cSMatt Spinler case util::CalloutType::fsii2c: 126*a307089cSMatt Spinler // callouts = calloutFSII2C(errnoValue, path, json); 127*a307089cSMatt Spinler break; 128*a307089cSMatt Spinler case util::CalloutType::fsispi: 129*a307089cSMatt Spinler // callouts = calloutFSISPI(errnoValue, path, json); 130*a307089cSMatt Spinler break; 131*a307089cSMatt Spinler default: 132*a307089cSMatt Spinler std::string msg = 133*a307089cSMatt Spinler "Could not get callout type from device path: " + path.string(); 134*a307089cSMatt Spinler throw std::invalid_argument{msg.c_str()}; 135*a307089cSMatt Spinler break; 136*a307089cSMatt Spinler } 13718c42b0fSMatt Spinler 13818c42b0fSMatt Spinler return callouts; 13918c42b0fSMatt Spinler } 14018c42b0fSMatt Spinler 141*a307089cSMatt Spinler CalloutType getCalloutType(const std::string& devPath) 142*a307089cSMatt Spinler { 143*a307089cSMatt Spinler if ((devPath.find("fsi-master") != std::string::npos) && 144*a307089cSMatt Spinler (devPath.find("i2c-") != std::string::npos)) 145*a307089cSMatt Spinler { 146*a307089cSMatt Spinler return CalloutType::fsii2c; 147*a307089cSMatt Spinler } 148*a307089cSMatt Spinler 149*a307089cSMatt Spinler if ((devPath.find("fsi-master") != std::string::npos) && 150*a307089cSMatt Spinler (devPath.find("spi") != std::string::npos)) 151*a307089cSMatt Spinler { 152*a307089cSMatt Spinler return CalloutType::fsispi; 153*a307089cSMatt Spinler } 154*a307089cSMatt Spinler 155*a307089cSMatt Spinler // Treat anything else FSI related as plain FSI 156*a307089cSMatt Spinler if (devPath.find("fsi-master") != std::string::npos) 157*a307089cSMatt Spinler { 158*a307089cSMatt Spinler return CalloutType::fsi; 159*a307089cSMatt Spinler } 160*a307089cSMatt Spinler 161*a307089cSMatt Spinler if (devPath.find("i2c-bus/i2c-") != std::string::npos) 162*a307089cSMatt Spinler { 163*a307089cSMatt Spinler return CalloutType::i2c; 164*a307089cSMatt Spinler } 165*a307089cSMatt Spinler 166*a307089cSMatt Spinler return CalloutType::unknown; 167*a307089cSMatt Spinler } 168*a307089cSMatt Spinler 16918c42b0fSMatt Spinler } // namespace util 17018c42b0fSMatt Spinler 17118c42b0fSMatt Spinler std::vector<Callout> getCallouts(const std::string& devPath, 17218c42b0fSMatt Spinler const std::vector<std::string>& compatibleList) 17318c42b0fSMatt Spinler { 17418c42b0fSMatt Spinler auto json = util::loadJSON(compatibleList); 17518c42b0fSMatt Spinler return util::findCallouts(devPath, json); 17618c42b0fSMatt Spinler } 17718c42b0fSMatt Spinler 17818c42b0fSMatt Spinler std::vector<Callout> 17918c42b0fSMatt Spinler getI2CCallouts(size_t i2cBus, uint8_t i2cAddress, 18018c42b0fSMatt Spinler const std::vector<std::string>& compatibleList) 18118c42b0fSMatt Spinler { 18218c42b0fSMatt Spinler auto json = util::loadJSON(compatibleList); 18318c42b0fSMatt Spinler return util::calloutI2C(i2cBus, i2cAddress, json); 18418c42b0fSMatt Spinler } 18518c42b0fSMatt Spinler 18618c42b0fSMatt Spinler } // namespace openpower::pels::device_callouts 187