16714a25aSJames Feist /* 26714a25aSJames Feist // Copyright (c) 2017 Intel Corporation 36714a25aSJames Feist // 46714a25aSJames Feist // Licensed under the Apache License, Version 2.0 (the "License"); 56714a25aSJames Feist // you may not use this file except in compliance with the License. 66714a25aSJames Feist // You may obtain a copy of the License at 76714a25aSJames Feist // 86714a25aSJames Feist // http://www.apache.org/licenses/LICENSE-2.0 96714a25aSJames Feist // 106714a25aSJames Feist // Unless required by applicable law or agreed to in writing, software 116714a25aSJames Feist // distributed under the License is distributed on an "AS IS" BASIS, 126714a25aSJames Feist // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136714a25aSJames Feist // See the License for the specific language governing permissions and 146714a25aSJames Feist // limitations under the License. 156714a25aSJames Feist */ 166714a25aSJames Feist 178a57ec09SEd Tanous #include <PwmSensor.hpp> 188a57ec09SEd Tanous #include <TachSensor.hpp> 198a57ec09SEd Tanous #include <Utils.hpp> 208a57ec09SEd Tanous #include <VariantVisitors.hpp> 216714a25aSJames Feist #include <boost/algorithm/string/predicate.hpp> 226714a25aSJames Feist #include <boost/algorithm/string/replace.hpp> 2396e97db7SPatrick Venture #include <boost/container/flat_map.hpp> 246714a25aSJames Feist #include <boost/container/flat_set.hpp> 256714a25aSJames Feist #include <boost/lexical_cast.hpp> 2638fb5983SJames Feist #include <sdbusplus/asio/connection.hpp> 2738fb5983SJames Feist #include <sdbusplus/asio/object_server.hpp> 2838fb5983SJames Feist #include <sdbusplus/bus/match.hpp> 2938fb5983SJames Feist 3038fb5983SJames Feist #include <array> 3124f02f24SJames Feist #include <filesystem> 326714a25aSJames Feist #include <fstream> 3396e97db7SPatrick Venture #include <functional> 3496e97db7SPatrick Venture #include <memory> 3596e97db7SPatrick Venture #include <optional> 366714a25aSJames Feist #include <regex> 3796e97db7SPatrick Venture #include <string> 3896e97db7SPatrick Venture #include <utility> 3996e97db7SPatrick Venture #include <variant> 4096e97db7SPatrick Venture #include <vector> 416714a25aSJames Feist 428a57ec09SEd Tanous static constexpr bool debug = false; 436714a25aSJames Feist 44cf3bce6eSJames Feist namespace fs = std::filesystem; 453eb82629SJames Feist 46a3e8f2a3SYong Zhao // The following two structures need to be consistent 478843b627SPeter Lundgren static constexpr std::array<const char*, 3> sensorTypes = { 4895b079b7SJames Feist "xyz.openbmc_project.Configuration.AspeedFan", 498843b627SPeter Lundgren "xyz.openbmc_project.Configuration.I2CFan", 508843b627SPeter Lundgren "xyz.openbmc_project.Configuration.NuvotonFan"}; 51a3e8f2a3SYong Zhao 52a3e8f2a3SYong Zhao enum FanTypes 53a3e8f2a3SYong Zhao { 54a3e8f2a3SYong Zhao aspeed = 0, 55a3e8f2a3SYong Zhao i2c, 56a3e8f2a3SYong Zhao nuvoton, 57a3e8f2a3SYong Zhao max, 58a3e8f2a3SYong Zhao }; 59a3e8f2a3SYong Zhao 60a3e8f2a3SYong Zhao static_assert(std::tuple_size<decltype(sensorTypes)>::value == FanTypes::max, 61a3e8f2a3SYong Zhao "sensorTypes element number is not equal to FanTypes number"); 62a3e8f2a3SYong Zhao 63dc6c55f3SJames Feist constexpr const char* redundancyConfiguration = 64dc6c55f3SJames Feist "xyz.openbmc_project.Configuration.FanRedundancy"; 659ced0a38SJae Hyun Yoo static std::regex inputRegex(R"(fan(\d+)_input)"); 666714a25aSJames Feist 67dc6c55f3SJames Feist // todo: power supply fan redundancy 687b18b1e0SJames Feist std::optional<RedundancySensor> systemRedundancy; 6995b079b7SJames Feist 7095b079b7SJames Feist FanTypes getFanType(const fs::path& parentPath) 7195b079b7SJames Feist { 7295b079b7SJames Feist fs::path linkPath = parentPath / "device"; 7395b079b7SJames Feist std::string canonical = fs::read_symlink(linkPath); 74241356e3SJae Hyun Yoo if (boost::ends_with(canonical, "1e786000.pwm-tacho-controller") || 75241356e3SJae Hyun Yoo boost::ends_with(canonical, "1e610000.pwm-tacho-controller")) 7695b079b7SJames Feist { 7795b079b7SJames Feist return FanTypes::aspeed; 7895b079b7SJames Feist } 798a57ec09SEd Tanous if (boost::ends_with(canonical, "f0103000.pwm-fan-controller")) 808843b627SPeter Lundgren { 818843b627SPeter Lundgren return FanTypes::nuvoton; 828843b627SPeter Lundgren } 8395b079b7SJames Feist // todo: will we need to support other types? 8495b079b7SJames Feist return FanTypes::i2c; 8595b079b7SJames Feist } 86abf91de1SJeff Lin void enablePwm(const fs::path& filePath) 87abf91de1SJeff Lin { 88abf91de1SJeff Lin std::fstream enableFile(filePath, std::ios::in | std::ios::out); 89abf91de1SJeff Lin if (!enableFile.good()) 90abf91de1SJeff Lin { 91abf91de1SJeff Lin std::cerr << "Error read/write " << filePath << "\n"; 92abf91de1SJeff Lin return; 93abf91de1SJeff Lin } 94dc6c55f3SJames Feist 95abf91de1SJeff Lin std::string regulateMode; 96abf91de1SJeff Lin std::getline(enableFile, regulateMode); 97abf91de1SJeff Lin if (regulateMode == "0") 98abf91de1SJeff Lin { 99abf91de1SJeff Lin enableFile << 1; 100abf91de1SJeff Lin } 101abf91de1SJeff Lin } 102d540741eSKuiying Wang void createRedundancySensor( 103d540741eSKuiying Wang const boost::container::flat_map<std::string, std::unique_ptr<TachSensor>>& 104d540741eSKuiying Wang sensors, 1058a57ec09SEd Tanous const std::shared_ptr<sdbusplus::asio::connection>& conn, 106d540741eSKuiying Wang sdbusplus::asio::object_server& objectServer) 107d540741eSKuiying Wang { 108d540741eSKuiying Wang 109d540741eSKuiying Wang conn->async_method_call( 110d540741eSKuiying Wang [&objectServer, &sensors](boost::system::error_code& ec, 1118a57ec09SEd Tanous const ManagedObjectType& managedObj) { 112d540741eSKuiying Wang if (ec) 113d540741eSKuiying Wang { 114d540741eSKuiying Wang std::cerr << "Error calling entity manager \n"; 115d540741eSKuiying Wang return; 116d540741eSKuiying Wang } 117d540741eSKuiying Wang for (const auto& pathPair : managedObj) 118d540741eSKuiying Wang { 119d540741eSKuiying Wang for (const auto& interfacePair : pathPair.second) 120d540741eSKuiying Wang { 121d540741eSKuiying Wang if (interfacePair.first == redundancyConfiguration) 122d540741eSKuiying Wang { 123d540741eSKuiying Wang // currently only support one 124d540741eSKuiying Wang auto findCount = 125d540741eSKuiying Wang interfacePair.second.find("AllowedFailures"); 126d540741eSKuiying Wang if (findCount == interfacePair.second.end()) 127d540741eSKuiying Wang { 128d540741eSKuiying Wang std::cerr << "Malformed redundancy record \n"; 129d540741eSKuiying Wang return; 130d540741eSKuiying Wang } 131d540741eSKuiying Wang std::vector<std::string> sensorList; 132d540741eSKuiying Wang 133d540741eSKuiying Wang for (const auto& sensor : sensors) 134d540741eSKuiying Wang { 135d540741eSKuiying Wang sensorList.push_back( 136d540741eSKuiying Wang "/xyz/openbmc_project/sensors/fan_tach/" + 137d540741eSKuiying Wang sensor.second->name); 138d540741eSKuiying Wang } 139d540741eSKuiying Wang systemRedundancy.reset(); 140d540741eSKuiying Wang systemRedundancy.emplace(RedundancySensor( 141d540741eSKuiying Wang std::get<uint64_t>(findCount->second), sensorList, 142d540741eSKuiying Wang objectServer, pathPair.first)); 143d540741eSKuiying Wang 144d540741eSKuiying Wang return; 145d540741eSKuiying Wang } 146d540741eSKuiying Wang } 147d540741eSKuiying Wang } 148d540741eSKuiying Wang }, 149d540741eSKuiying Wang "xyz.openbmc_project.EntityManager", "/", 150d540741eSKuiying Wang "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 151d540741eSKuiying Wang } 152d540741eSKuiying Wang 1536714a25aSJames Feist void createSensors( 1546714a25aSJames Feist boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer, 1556714a25aSJames Feist boost::container::flat_map<std::string, std::unique_ptr<TachSensor>>& 1566714a25aSJames Feist tachSensors, 1576714a25aSJames Feist boost::container::flat_map<std::string, std::unique_ptr<PwmSensor>>& 1586714a25aSJames Feist pwmSensors, 1596714a25aSJames Feist std::shared_ptr<sdbusplus::asio::connection>& dbusConnection, 1605591cf08SJames Feist const std::shared_ptr<boost::container::flat_set<std::string>>& 161f27a55c7SJames Feist sensorsChanged, 162f27a55c7SJames Feist size_t retries = 0) 1636714a25aSJames Feist { 164de5e9705SJames Feist auto getter = std::make_shared<GetSensorConfiguration>( 165de5e9705SJames Feist dbusConnection, 166de5e9705SJames Feist std::move([&io, &objectServer, &tachSensors, &pwmSensors, 1675591cf08SJames Feist &dbusConnection, sensorsChanged]( 168de5e9705SJames Feist const ManagedObjectType& sensorConfigurations) { 1696714a25aSJames Feist bool firstScan = sensorsChanged == nullptr; 1706714a25aSJames Feist std::vector<fs::path> paths; 171de5e9705SJames Feist if (!findFiles(fs::path("/sys/class/hwmon"), R"(fan\d+_input)", 172de5e9705SJames Feist paths)) 1736714a25aSJames Feist { 17477b3add2SYong Zhao std::cerr << "No fan sensors in system\n"; 1756714a25aSJames Feist return; 1766714a25aSJames Feist } 1776714a25aSJames Feist 1786714a25aSJames Feist // iterate through all found fan sensors, and try to match them with 1796714a25aSJames Feist // configuration 18095b079b7SJames Feist for (const auto& path : paths) 1816714a25aSJames Feist { 1826714a25aSJames Feist std::smatch match; 1836714a25aSJames Feist std::string pathStr = path.string(); 1846714a25aSJames Feist 1859ced0a38SJae Hyun Yoo std::regex_search(pathStr, match, inputRegex); 1866714a25aSJames Feist std::string indexStr = *(match.begin() + 1); 1876714a25aSJames Feist 18877b3add2SYong Zhao fs::path directory = path.parent_path(); 18995b079b7SJames Feist FanTypes fanType = getFanType(directory); 19077b3add2SYong Zhao 1916714a25aSJames Feist // convert to 0 based 1926714a25aSJames Feist size_t index = std::stoul(indexStr) - 1; 1936714a25aSJames Feist 1946714a25aSJames Feist const char* baseType; 1956714a25aSJames Feist const SensorData* sensorData = nullptr; 1966714a25aSJames Feist const std::string* interfacePath = nullptr; 19787d713abSJames Feist const SensorBaseConfiguration* baseConfiguration = nullptr; 198de5e9705SJames Feist for (const std::pair<sdbusplus::message::object_path, 199de5e9705SJames Feist SensorData>& sensor : sensorConfigurations) 2006714a25aSJames Feist { 201de5e9705SJames Feist // find the base of the configuration to see if indexes 202de5e9705SJames Feist // match 203a3e8f2a3SYong Zhao auto sensorBaseFind = 204a3e8f2a3SYong Zhao sensor.second.find(sensorTypes[fanType]); 205a3e8f2a3SYong Zhao if (sensorBaseFind == sensor.second.end()) 2066714a25aSJames Feist { 2076714a25aSJames Feist continue; 2086714a25aSJames Feist } 209347dd4e7SZhikui Ren 210a3e8f2a3SYong Zhao baseConfiguration = &(*sensorBaseFind); 211a3e8f2a3SYong Zhao interfacePath = &(sensor.first.str); 212a3e8f2a3SYong Zhao baseType = sensorTypes[fanType]; 213a3e8f2a3SYong Zhao 2146714a25aSJames Feist auto findIndex = baseConfiguration->second.find("Index"); 2156714a25aSJames Feist if (findIndex == baseConfiguration->second.end()) 2166714a25aSJames Feist { 217de5e9705SJames Feist std::cerr << baseConfiguration->first 218de5e9705SJames Feist << " missing index\n"; 2196714a25aSJames Feist continue; 2206714a25aSJames Feist } 221de5e9705SJames Feist unsigned int configIndex = std::visit( 222de5e9705SJames Feist VariantToUnsignedIntVisitor(), findIndex->second); 2236714a25aSJames Feist if (configIndex != index) 2246714a25aSJames Feist { 2256714a25aSJames Feist continue; 2266714a25aSJames Feist } 227de5e9705SJames Feist if (fanType == FanTypes::aspeed || 228de5e9705SJames Feist fanType == FanTypes::nuvoton) 2296714a25aSJames Feist { 230de5e9705SJames Feist // there will be only 1 aspeed or nuvoton sensor object 231de5e9705SJames Feist // in sysfs, we found the fan 23295b079b7SJames Feist sensorData = &(sensor.second); 23395b079b7SJames Feist break; 23495b079b7SJames Feist } 2358a57ec09SEd Tanous if (fanType == FanTypes::i2c) 23695b079b7SJames Feist { 237add46820SYong Zhao size_t bus = 0; 238add46820SYong Zhao size_t address = 0; 239add46820SYong Zhao 240add46820SYong Zhao std::string link = 241add46820SYong Zhao fs::read_symlink(directory / "device").filename(); 242add46820SYong Zhao 243add46820SYong Zhao size_t findDash = link.find('-'); 244add46820SYong Zhao if (findDash == std::string::npos || 245add46820SYong Zhao link.size() <= findDash + 1) 246add46820SYong Zhao { 247add46820SYong Zhao std::cerr << "Error finding device from symlink"; 248add46820SYong Zhao } 249add46820SYong Zhao bus = std::stoi(link.substr(0, findDash)); 250add46820SYong Zhao address = 251add46820SYong Zhao std::stoi(link.substr(findDash + 1), nullptr, 16); 252add46820SYong Zhao 25395b079b7SJames Feist auto findBus = baseConfiguration->second.find("Bus"); 254de5e9705SJames Feist auto findAddress = 255de5e9705SJames Feist baseConfiguration->second.find("Address"); 25695b079b7SJames Feist if (findBus == baseConfiguration->second.end() || 25795b079b7SJames Feist findAddress == baseConfiguration->second.end()) 25895b079b7SJames Feist { 25995b079b7SJames Feist std::cerr << baseConfiguration->first 26095b079b7SJames Feist << " missing bus or address\n"; 2616714a25aSJames Feist continue; 2626714a25aSJames Feist } 263de5e9705SJames Feist unsigned int configBus = std::visit( 264de5e9705SJames Feist VariantToUnsignedIntVisitor(), findBus->second); 2653eb82629SJames Feist unsigned int configAddress = std::visit( 26695b079b7SJames Feist VariantToUnsignedIntVisitor(), findAddress->second); 26795b079b7SJames Feist 26884e9e662SJae Hyun Yoo if (configBus == bus && configAddress == address) 2696714a25aSJames Feist { 2706714a25aSJames Feist sensorData = &(sensor.second); 2716714a25aSJames Feist break; 2726714a25aSJames Feist } 2736714a25aSJames Feist } 27495b079b7SJames Feist } 2756714a25aSJames Feist if (sensorData == nullptr) 2766714a25aSJames Feist { 277de5e9705SJames Feist std::cerr << "failed to find match for " << path.string() 278de5e9705SJames Feist << "\n"; 2796714a25aSJames Feist continue; 2806714a25aSJames Feist } 2816714a25aSJames Feist 2826714a25aSJames Feist auto findSensorName = baseConfiguration->second.find("Name"); 283347dd4e7SZhikui Ren 2846714a25aSJames Feist if (findSensorName == baseConfiguration->second.end()) 2856714a25aSJames Feist { 2866714a25aSJames Feist std::cerr << "could not determine configuration name for " 2876714a25aSJames Feist << path.string() << "\n"; 2886714a25aSJames Feist continue; 2896714a25aSJames Feist } 290de5e9705SJames Feist std::string sensorName = 291de5e9705SJames Feist std::get<std::string>(findSensorName->second); 292347dd4e7SZhikui Ren 2936714a25aSJames Feist // on rescans, only update sensors we were signaled by 2946714a25aSJames Feist auto findSensor = tachSensors.find(sensorName); 2956714a25aSJames Feist if (!firstScan && findSensor != tachSensors.end()) 2966714a25aSJames Feist { 2976714a25aSJames Feist bool found = false; 298de5e9705SJames Feist for (auto it = sensorsChanged->begin(); 299de5e9705SJames Feist it != sensorsChanged->end(); it++) 3006714a25aSJames Feist { 3016714a25aSJames Feist if (boost::ends_with(*it, findSensor->second->name)) 3026714a25aSJames Feist { 3036714a25aSJames Feist sensorsChanged->erase(it); 3046714a25aSJames Feist findSensor->second = nullptr; 3056714a25aSJames Feist found = true; 3066714a25aSJames Feist break; 3076714a25aSJames Feist } 3086714a25aSJames Feist } 3096714a25aSJames Feist if (!found) 3106714a25aSJames Feist { 3116714a25aSJames Feist continue; 3126714a25aSJames Feist } 3136714a25aSJames Feist } 3146714a25aSJames Feist std::vector<thresholds::Threshold> sensorThresholds; 3159ced0a38SJae Hyun Yoo if (!parseThresholdsFromConfig(*sensorData, sensorThresholds)) 3166714a25aSJames Feist { 317de5e9705SJames Feist std::cerr << "error populating thresholds for " 318de5e9705SJames Feist << sensorName << "\n"; 3196714a25aSJames Feist } 3206714a25aSJames Feist 3217bc2bab2SJames Feist auto presenceConfig = 3227bc2bab2SJames Feist sensorData->find(baseType + std::string(".Presence")); 3237bc2bab2SJames Feist 3247bc2bab2SJames Feist std::unique_ptr<PresenceSensor> presenceSensor(nullptr); 3257bc2bab2SJames Feist 3267bc2bab2SJames Feist // presence sensors are optional 3277bc2bab2SJames Feist if (presenceConfig != sensorData->end()) 3287bc2bab2SJames Feist { 3297bc2bab2SJames Feist auto findPolarity = presenceConfig->second.find("Polarity"); 330347dd4e7SZhikui Ren auto findPinName = presenceConfig->second.find("PinName"); 3317bc2bab2SJames Feist 332347dd4e7SZhikui Ren if (findPinName == presenceConfig->second.end() || 3337bc2bab2SJames Feist findPolarity == presenceConfig->second.end()) 3347bc2bab2SJames Feist { 3357bc2bab2SJames Feist std::cerr << "Malformed Presence Configuration\n"; 3367bc2bab2SJames Feist } 3377bc2bab2SJames Feist else 3387bc2bab2SJames Feist { 339de5e9705SJames Feist bool inverted = std::get<std::string>( 340de5e9705SJames Feist findPolarity->second) == "Low"; 341347dd4e7SZhikui Ren if (auto pinName = 342347dd4e7SZhikui Ren std::get_if<std::string>(&findPinName->second)) 343347dd4e7SZhikui Ren { 3447b18b1e0SJames Feist presenceSensor = std::make_unique<PresenceSensor>( 345347dd4e7SZhikui Ren *pinName, inverted, io, sensorName); 346347dd4e7SZhikui Ren } 347347dd4e7SZhikui Ren else 348347dd4e7SZhikui Ren { 349347dd4e7SZhikui Ren std::cerr 350347dd4e7SZhikui Ren << "Malformed Presence pinName for sensor " 351347dd4e7SZhikui Ren << sensorName << " \n"; 352347dd4e7SZhikui Ren } 3537bc2bab2SJames Feist } 3547bc2bab2SJames Feist } 3557b18b1e0SJames Feist std::optional<RedundancySensor>* redundancy = nullptr; 35695b079b7SJames Feist if (fanType == FanTypes::aspeed) 35795b079b7SJames Feist { 3587b18b1e0SJames Feist redundancy = &systemRedundancy; 35995b079b7SJames Feist } 3607bc2bab2SJames Feist 361f920e09cSJosh Lehan PowerState powerState = PowerState::on; 362f920e09cSJosh Lehan auto findPower = baseConfiguration->second.find("PowerState"); 363f920e09cSJosh Lehan if (findPower != baseConfiguration->second.end()) 364f920e09cSJosh Lehan { 365f920e09cSJosh Lehan auto ptrPower = 366f920e09cSJosh Lehan std::get_if<std::string>(&(findPower->second)); 367f920e09cSJosh Lehan if (ptrPower) 368f920e09cSJosh Lehan { 369f920e09cSJosh Lehan setReadState(*ptrPower, powerState); 370f920e09cSJosh Lehan } 371f920e09cSJosh Lehan } 372f920e09cSJosh Lehan 37387d713abSJames Feist constexpr double defaultMaxReading = 25000; 37487d713abSJames Feist constexpr double defaultMinReading = 0; 375de5e9705SJames Feist auto limits = 376de5e9705SJames Feist std::make_pair(defaultMinReading, defaultMaxReading); 37787d713abSJames Feist 378de5e9705SJames Feist auto connector = 379de5e9705SJames Feist sensorData->find(baseType + std::string(".Connector")); 38049a8ccd6SJames Feist 38149a8ccd6SJames Feist std::optional<std::string> led; 38277b3add2SYong Zhao std::string pwmName; 383d05867c0SZhikui Ren fs::path pwmPath; 38449a8ccd6SJames Feist 3858e94c204SJames Feist if (connector != sensorData->end()) 3868e94c204SJames Feist { 3878e94c204SJames Feist auto findPwm = connector->second.find("Pwm"); 38849a8ccd6SJames Feist if (findPwm != connector->second.end()) 3898e94c204SJames Feist { 390abf91de1SJeff Lin fs::path pwmEnableFile = 391abf91de1SJeff Lin "pwm" + std::to_string(index + 1) + "_enable"; 392abf91de1SJeff Lin fs::path enablePath = 393abf91de1SJeff Lin path.parent_path() / pwmEnableFile; 394abf91de1SJeff Lin enablePwm(enablePath); 395de5e9705SJames Feist size_t pwm = std::visit(VariantToUnsignedIntVisitor(), 396de5e9705SJames Feist findPwm->second); 397d05867c0SZhikui Ren pwmPath = directory / ("pwm" + std::to_string(pwm + 1)); 39849a8ccd6SJames Feist /* use pwm name override if found in configuration else 39949a8ccd6SJames Feist * use default */ 400d320a2e1SJason Ling auto findOverride = connector->second.find("PwmName"); 401d320a2e1SJason Ling if (findOverride != connector->second.end()) 402d320a2e1SJason Ling { 403d320a2e1SJason Ling pwmName = std::visit(VariantToStringVisitor(), 404d320a2e1SJason Ling findOverride->second); 405d320a2e1SJason Ling } 406d320a2e1SJason Ling else 407d320a2e1SJason Ling { 408d320a2e1SJason Ling pwmName = "Pwm_" + std::to_string(pwm + 1); 409d320a2e1SJason Ling } 4108e94c204SJames Feist } 41149a8ccd6SJames Feist else 41249a8ccd6SJames Feist { 41349a8ccd6SJames Feist std::cerr << "Connector for " << sensorName 41449a8ccd6SJames Feist << " missing pwm!\n"; 41549a8ccd6SJames Feist } 41649a8ccd6SJames Feist 41749a8ccd6SJames Feist auto findLED = connector->second.find("LED"); 41849a8ccd6SJames Feist if (findLED != connector->second.end()) 41949a8ccd6SJames Feist { 42049a8ccd6SJames Feist auto ledName = 42149a8ccd6SJames Feist std::get_if<std::string>(&(findLED->second)); 42249a8ccd6SJames Feist if (ledName == nullptr) 42349a8ccd6SJames Feist { 42449a8ccd6SJames Feist std::cerr << "Wrong format for LED of " 42549a8ccd6SJames Feist << sensorName << "\n"; 42649a8ccd6SJames Feist } 42749a8ccd6SJames Feist else 42849a8ccd6SJames Feist { 42949a8ccd6SJames Feist led = *ledName; 43049a8ccd6SJames Feist } 43149a8ccd6SJames Feist } 43249a8ccd6SJames Feist } 43349a8ccd6SJames Feist 43449a8ccd6SJames Feist findLimits(limits, baseConfiguration); 43549a8ccd6SJames Feist tachSensors[sensorName] = std::make_unique<TachSensor>( 43649a8ccd6SJames Feist path.string(), baseType, objectServer, dbusConnection, 43749a8ccd6SJames Feist std::move(presenceSensor), redundancy, io, sensorName, 43849a8ccd6SJames Feist std::move(sensorThresholds), *interfacePath, limits, 43949a8ccd6SJames Feist powerState, led); 44077b3add2SYong Zhao 441d05867c0SZhikui Ren if (!pwmPath.empty() && fs::exists(pwmPath) && 442d05867c0SZhikui Ren !pwmSensors.count(pwmPath)) 44377b3add2SYong Zhao { 44477b3add2SYong Zhao pwmSensors[pwmPath] = std::make_unique<PwmSensor>( 44577b3add2SYong Zhao pwmName, pwmPath, dbusConnection, objectServer, 44677b3add2SYong Zhao *interfacePath, "Fan"); 4476714a25aSJames Feist } 44877b3add2SYong Zhao } 44977b3add2SYong Zhao 450d540741eSKuiying Wang createRedundancySensor(tachSensors, dbusConnection, objectServer); 451de5e9705SJames Feist })); 452de5e9705SJames Feist getter->getConfiguration( 453f27a55c7SJames Feist std::vector<std::string>{sensorTypes.begin(), sensorTypes.end()}, 454f27a55c7SJames Feist retries); 4556714a25aSJames Feist } 4566714a25aSJames Feist 457b6c0b914SJames Feist int main() 4586714a25aSJames Feist { 4596714a25aSJames Feist boost::asio::io_service io; 4606714a25aSJames Feist auto systemBus = std::make_shared<sdbusplus::asio::connection>(io); 4616714a25aSJames Feist systemBus->request_name("xyz.openbmc_project.FanSensor"); 4626714a25aSJames Feist sdbusplus::asio::object_server objectServer(systemBus); 4636714a25aSJames Feist boost::container::flat_map<std::string, std::unique_ptr<TachSensor>> 4646714a25aSJames Feist tachSensors; 4656714a25aSJames Feist boost::container::flat_map<std::string, std::unique_ptr<PwmSensor>> 4666714a25aSJames Feist pwmSensors; 4676714a25aSJames Feist std::vector<std::unique_ptr<sdbusplus::bus::match::match>> matches; 4685591cf08SJames Feist auto sensorsChanged = 4695591cf08SJames Feist std::make_shared<boost::container::flat_set<std::string>>(); 4706714a25aSJames Feist 4716714a25aSJames Feist io.post([&]() { 4726714a25aSJames Feist createSensors(io, objectServer, tachSensors, pwmSensors, systemBus, 4736714a25aSJames Feist nullptr); 4746714a25aSJames Feist }); 4756714a25aSJames Feist 4766714a25aSJames Feist boost::asio::deadline_timer filterTimer(io); 4776714a25aSJames Feist std::function<void(sdbusplus::message::message&)> eventHandler = 4786714a25aSJames Feist [&](sdbusplus::message::message& message) { 4796714a25aSJames Feist if (message.is_method_error()) 4806714a25aSJames Feist { 4816714a25aSJames Feist std::cerr << "callback method error\n"; 4826714a25aSJames Feist return; 4836714a25aSJames Feist } 4846714a25aSJames Feist sensorsChanged->insert(message.get_path()); 4856714a25aSJames Feist // this implicitly cancels the timer 4866714a25aSJames Feist filterTimer.expires_from_now(boost::posix_time::seconds(1)); 4876714a25aSJames Feist 4886714a25aSJames Feist filterTimer.async_wait([&](const boost::system::error_code& ec) { 4896714a25aSJames Feist if (ec == boost::asio::error::operation_aborted) 4906714a25aSJames Feist { 4916714a25aSJames Feist /* we were canceled*/ 4926714a25aSJames Feist return; 4936714a25aSJames Feist } 4948a57ec09SEd Tanous if (ec) 4956714a25aSJames Feist { 4966714a25aSJames Feist std::cerr << "timer error\n"; 4976714a25aSJames Feist return; 4986714a25aSJames Feist } 4996714a25aSJames Feist createSensors(io, objectServer, tachSensors, pwmSensors, 500f27a55c7SJames Feist systemBus, sensorsChanged, 5); 5016714a25aSJames Feist }); 5026714a25aSJames Feist }; 5036714a25aSJames Feist 5049ced0a38SJae Hyun Yoo for (const char* type : sensorTypes) 5056714a25aSJames Feist { 5066714a25aSJames Feist auto match = std::make_unique<sdbusplus::bus::match::match>( 5076714a25aSJames Feist static_cast<sdbusplus::bus::bus&>(*systemBus), 5086714a25aSJames Feist "type='signal',member='PropertiesChanged',path_namespace='" + 5099ced0a38SJae Hyun Yoo std::string(inventoryPath) + "',arg0namespace='" + type + "'", 5106714a25aSJames Feist eventHandler); 5116714a25aSJames Feist matches.emplace_back(std::move(match)); 5126714a25aSJames Feist } 5136714a25aSJames Feist 514dc6c55f3SJames Feist // redundancy sensor 515dc6c55f3SJames Feist std::function<void(sdbusplus::message::message&)> redundancyHandler = 516dc6c55f3SJames Feist [&tachSensors, &systemBus, 517b6c0b914SJames Feist &objectServer](sdbusplus::message::message&) { 518dc6c55f3SJames Feist createRedundancySensor(tachSensors, systemBus, objectServer); 519dc6c55f3SJames Feist }; 520dc6c55f3SJames Feist auto match = std::make_unique<sdbusplus::bus::match::match>( 521dc6c55f3SJames Feist static_cast<sdbusplus::bus::bus&>(*systemBus), 522dc6c55f3SJames Feist "type='signal',member='PropertiesChanged',path_namespace='" + 523dc6c55f3SJames Feist std::string(inventoryPath) + "',arg0namespace='" + 524dc6c55f3SJames Feist redundancyConfiguration + "'", 525b6c0b914SJames Feist std::move(redundancyHandler)); 526dc6c55f3SJames Feist matches.emplace_back(std::move(match)); 527dc6c55f3SJames Feist 5281263c3daSBruce Lee setupManufacturingModeMatch(*systemBus); 5296714a25aSJames Feist io.run(); 530*8685b17aSZhikui Ren return 0; 5316714a25aSJames Feist } 532