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 42cf3bce6eSJames Feist namespace fs = std::filesystem; 433eb82629SJames Feist 44a3e8f2a3SYong Zhao // The following two structures need to be consistent 458843b627SPeter Lundgren static constexpr std::array<const char*, 3> sensorTypes = { 4695b079b7SJames Feist "xyz.openbmc_project.Configuration.AspeedFan", 478843b627SPeter Lundgren "xyz.openbmc_project.Configuration.I2CFan", 488843b627SPeter Lundgren "xyz.openbmc_project.Configuration.NuvotonFan"}; 49a3e8f2a3SYong Zhao 50a3e8f2a3SYong Zhao enum FanTypes 51a3e8f2a3SYong Zhao { 52a3e8f2a3SYong Zhao aspeed = 0, 53a3e8f2a3SYong Zhao i2c, 54a3e8f2a3SYong Zhao nuvoton, 55a3e8f2a3SYong Zhao max, 56a3e8f2a3SYong Zhao }; 57a3e8f2a3SYong Zhao 58a3e8f2a3SYong Zhao static_assert(std::tuple_size<decltype(sensorTypes)>::value == FanTypes::max, 59a3e8f2a3SYong Zhao "sensorTypes element number is not equal to FanTypes number"); 60a3e8f2a3SYong Zhao 61dc6c55f3SJames Feist constexpr const char* redundancyConfiguration = 62dc6c55f3SJames Feist "xyz.openbmc_project.Configuration.FanRedundancy"; 639ced0a38SJae Hyun Yoo static std::regex inputRegex(R"(fan(\d+)_input)"); 646714a25aSJames Feist 65dc6c55f3SJames Feist // todo: power supply fan redundancy 667b18b1e0SJames Feist std::optional<RedundancySensor> systemRedundancy; 6795b079b7SJames Feist 6895b079b7SJames Feist FanTypes getFanType(const fs::path& parentPath) 6995b079b7SJames Feist { 7095b079b7SJames Feist fs::path linkPath = parentPath / "device"; 7195b079b7SJames Feist std::string canonical = fs::read_symlink(linkPath); 72241356e3SJae Hyun Yoo if (boost::ends_with(canonical, "1e786000.pwm-tacho-controller") || 73241356e3SJae Hyun Yoo boost::ends_with(canonical, "1e610000.pwm-tacho-controller")) 7495b079b7SJames Feist { 7595b079b7SJames Feist return FanTypes::aspeed; 7695b079b7SJames Feist } 778a57ec09SEd Tanous if (boost::ends_with(canonical, "f0103000.pwm-fan-controller")) 788843b627SPeter Lundgren { 798843b627SPeter Lundgren return FanTypes::nuvoton; 808843b627SPeter Lundgren } 8195b079b7SJames Feist // todo: will we need to support other types? 8295b079b7SJames Feist return FanTypes::i2c; 8395b079b7SJames Feist } 84abf91de1SJeff Lin void enablePwm(const fs::path& filePath) 85abf91de1SJeff Lin { 86abf91de1SJeff Lin std::fstream enableFile(filePath, std::ios::in | std::ios::out); 87abf91de1SJeff Lin if (!enableFile.good()) 88abf91de1SJeff Lin { 89abf91de1SJeff Lin std::cerr << "Error read/write " << filePath << "\n"; 90abf91de1SJeff Lin return; 91abf91de1SJeff Lin } 92dc6c55f3SJames Feist 93abf91de1SJeff Lin std::string regulateMode; 94abf91de1SJeff Lin std::getline(enableFile, regulateMode); 95abf91de1SJeff Lin if (regulateMode == "0") 96abf91de1SJeff Lin { 97abf91de1SJeff Lin enableFile << 1; 98abf91de1SJeff Lin } 99abf91de1SJeff Lin } 100d540741eSKuiying Wang void createRedundancySensor( 101d540741eSKuiying Wang const boost::container::flat_map<std::string, std::unique_ptr<TachSensor>>& 102d540741eSKuiying Wang sensors, 1038a57ec09SEd Tanous const std::shared_ptr<sdbusplus::asio::connection>& conn, 104d540741eSKuiying Wang sdbusplus::asio::object_server& objectServer) 105d540741eSKuiying Wang { 106d540741eSKuiying Wang 107d540741eSKuiying Wang conn->async_method_call( 108d540741eSKuiying Wang [&objectServer, &sensors](boost::system::error_code& ec, 1098a57ec09SEd Tanous const ManagedObjectType& managedObj) { 110d540741eSKuiying Wang if (ec) 111d540741eSKuiying Wang { 112d540741eSKuiying Wang std::cerr << "Error calling entity manager \n"; 113d540741eSKuiying Wang return; 114d540741eSKuiying Wang } 115d540741eSKuiying Wang for (const auto& pathPair : managedObj) 116d540741eSKuiying Wang { 117d540741eSKuiying Wang for (const auto& interfacePair : pathPair.second) 118d540741eSKuiying Wang { 119d540741eSKuiying Wang if (interfacePair.first == redundancyConfiguration) 120d540741eSKuiying Wang { 121d540741eSKuiying Wang // currently only support one 122d540741eSKuiying Wang auto findCount = 123d540741eSKuiying Wang interfacePair.second.find("AllowedFailures"); 124d540741eSKuiying Wang if (findCount == interfacePair.second.end()) 125d540741eSKuiying Wang { 126d540741eSKuiying Wang std::cerr << "Malformed redundancy record \n"; 127d540741eSKuiying Wang return; 128d540741eSKuiying Wang } 129d540741eSKuiying Wang std::vector<std::string> sensorList; 130d540741eSKuiying Wang 131d540741eSKuiying Wang for (const auto& sensor : sensors) 132d540741eSKuiying Wang { 133d540741eSKuiying Wang sensorList.push_back( 134d540741eSKuiying Wang "/xyz/openbmc_project/sensors/fan_tach/" + 135d540741eSKuiying Wang sensor.second->name); 136d540741eSKuiying Wang } 137d540741eSKuiying Wang systemRedundancy.reset(); 138d540741eSKuiying Wang systemRedundancy.emplace(RedundancySensor( 139d540741eSKuiying Wang std::get<uint64_t>(findCount->second), sensorList, 140d540741eSKuiying Wang objectServer, pathPair.first)); 141d540741eSKuiying Wang 142d540741eSKuiying Wang return; 143d540741eSKuiying Wang } 144d540741eSKuiying Wang } 145d540741eSKuiying Wang } 146d540741eSKuiying Wang }, 147d540741eSKuiying Wang "xyz.openbmc_project.EntityManager", "/", 148d540741eSKuiying Wang "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 149d540741eSKuiying Wang } 150d540741eSKuiying Wang 1516714a25aSJames Feist void createSensors( 1526714a25aSJames Feist boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer, 1536714a25aSJames Feist boost::container::flat_map<std::string, std::unique_ptr<TachSensor>>& 1546714a25aSJames Feist tachSensors, 1556714a25aSJames Feist boost::container::flat_map<std::string, std::unique_ptr<PwmSensor>>& 1566714a25aSJames Feist pwmSensors, 1576714a25aSJames Feist std::shared_ptr<sdbusplus::asio::connection>& dbusConnection, 1585591cf08SJames Feist const std::shared_ptr<boost::container::flat_set<std::string>>& 159f27a55c7SJames Feist sensorsChanged, 160f27a55c7SJames Feist size_t retries = 0) 1616714a25aSJames Feist { 162de5e9705SJames Feist auto getter = std::make_shared<GetSensorConfiguration>( 163de5e9705SJames Feist dbusConnection, 1648a17c303SEd Tanous [&io, &objectServer, &tachSensors, &pwmSensors, &dbusConnection, 1658a17c303SEd Tanous sensorsChanged](const ManagedObjectType& sensorConfigurations) { 1666714a25aSJames Feist bool firstScan = sensorsChanged == nullptr; 1676714a25aSJames Feist std::vector<fs::path> paths; 168de5e9705SJames Feist if (!findFiles(fs::path("/sys/class/hwmon"), R"(fan\d+_input)", 169de5e9705SJames Feist paths)) 1706714a25aSJames Feist { 17177b3add2SYong Zhao std::cerr << "No fan sensors in system\n"; 1726714a25aSJames Feist return; 1736714a25aSJames Feist } 1746714a25aSJames Feist 1756714a25aSJames Feist // iterate through all found fan sensors, and try to match them with 1766714a25aSJames Feist // configuration 17795b079b7SJames Feist for (const auto& path : paths) 1786714a25aSJames Feist { 1796714a25aSJames Feist std::smatch match; 1806714a25aSJames Feist std::string pathStr = path.string(); 1816714a25aSJames Feist 1829ced0a38SJae Hyun Yoo std::regex_search(pathStr, match, inputRegex); 1836714a25aSJames Feist std::string indexStr = *(match.begin() + 1); 1846714a25aSJames Feist 18577b3add2SYong Zhao fs::path directory = path.parent_path(); 18695b079b7SJames Feist FanTypes fanType = getFanType(directory); 18777b3add2SYong Zhao 1886714a25aSJames Feist // convert to 0 based 1896714a25aSJames Feist size_t index = std::stoul(indexStr) - 1; 1906714a25aSJames Feist 1916714a25aSJames Feist const char* baseType; 1926714a25aSJames Feist const SensorData* sensorData = nullptr; 1936714a25aSJames Feist const std::string* interfacePath = nullptr; 19487d713abSJames Feist const SensorBaseConfiguration* baseConfiguration = nullptr; 195de5e9705SJames Feist for (const std::pair<sdbusplus::message::object_path, 196de5e9705SJames Feist SensorData>& sensor : sensorConfigurations) 1976714a25aSJames Feist { 198de5e9705SJames Feist // find the base of the configuration to see if indexes 199de5e9705SJames Feist // match 200a3e8f2a3SYong Zhao auto sensorBaseFind = 201a3e8f2a3SYong Zhao sensor.second.find(sensorTypes[fanType]); 202a3e8f2a3SYong Zhao if (sensorBaseFind == sensor.second.end()) 2036714a25aSJames Feist { 2046714a25aSJames Feist continue; 2056714a25aSJames Feist } 206347dd4e7SZhikui Ren 207a3e8f2a3SYong Zhao baseConfiguration = &(*sensorBaseFind); 208a3e8f2a3SYong Zhao interfacePath = &(sensor.first.str); 209a3e8f2a3SYong Zhao baseType = sensorTypes[fanType]; 210a3e8f2a3SYong Zhao 2116714a25aSJames Feist auto findIndex = baseConfiguration->second.find("Index"); 2126714a25aSJames Feist if (findIndex == baseConfiguration->second.end()) 2136714a25aSJames Feist { 214de5e9705SJames Feist std::cerr << baseConfiguration->first 215de5e9705SJames Feist << " missing index\n"; 2166714a25aSJames Feist continue; 2176714a25aSJames Feist } 218de5e9705SJames Feist unsigned int configIndex = std::visit( 219de5e9705SJames Feist VariantToUnsignedIntVisitor(), findIndex->second); 2206714a25aSJames Feist if (configIndex != index) 2216714a25aSJames Feist { 2226714a25aSJames Feist continue; 2236714a25aSJames Feist } 224de5e9705SJames Feist if (fanType == FanTypes::aspeed || 225de5e9705SJames Feist fanType == FanTypes::nuvoton) 2266714a25aSJames Feist { 227de5e9705SJames Feist // there will be only 1 aspeed or nuvoton sensor object 228de5e9705SJames Feist // in sysfs, we found the fan 22995b079b7SJames Feist sensorData = &(sensor.second); 23095b079b7SJames Feist break; 23195b079b7SJames Feist } 2328a57ec09SEd Tanous if (fanType == FanTypes::i2c) 23395b079b7SJames Feist { 234add46820SYong Zhao size_t bus = 0; 235add46820SYong Zhao size_t address = 0; 236add46820SYong Zhao 237add46820SYong Zhao std::string link = 238add46820SYong Zhao fs::read_symlink(directory / "device").filename(); 239add46820SYong Zhao 240add46820SYong Zhao size_t findDash = link.find('-'); 241add46820SYong Zhao if (findDash == std::string::npos || 242add46820SYong Zhao link.size() <= findDash + 1) 243add46820SYong Zhao { 244add46820SYong Zhao std::cerr << "Error finding device from symlink"; 245add46820SYong Zhao } 246add46820SYong Zhao bus = std::stoi(link.substr(0, findDash)); 247add46820SYong Zhao address = 248add46820SYong Zhao std::stoi(link.substr(findDash + 1), nullptr, 16); 249add46820SYong Zhao 25095b079b7SJames Feist auto findBus = baseConfiguration->second.find("Bus"); 251de5e9705SJames Feist auto findAddress = 252de5e9705SJames Feist baseConfiguration->second.find("Address"); 25395b079b7SJames Feist if (findBus == baseConfiguration->second.end() || 25495b079b7SJames Feist findAddress == baseConfiguration->second.end()) 25595b079b7SJames Feist { 25695b079b7SJames Feist std::cerr << baseConfiguration->first 25795b079b7SJames Feist << " missing bus or address\n"; 2586714a25aSJames Feist continue; 2596714a25aSJames Feist } 260de5e9705SJames Feist unsigned int configBus = std::visit( 261de5e9705SJames Feist VariantToUnsignedIntVisitor(), findBus->second); 2623eb82629SJames Feist unsigned int configAddress = std::visit( 26395b079b7SJames Feist VariantToUnsignedIntVisitor(), findAddress->second); 26495b079b7SJames Feist 26584e9e662SJae Hyun Yoo if (configBus == bus && configAddress == address) 2666714a25aSJames Feist { 2676714a25aSJames Feist sensorData = &(sensor.second); 2686714a25aSJames Feist break; 2696714a25aSJames Feist } 2706714a25aSJames Feist } 27195b079b7SJames Feist } 2726714a25aSJames Feist if (sensorData == nullptr) 2736714a25aSJames Feist { 274de5e9705SJames Feist std::cerr << "failed to find match for " << path.string() 275de5e9705SJames Feist << "\n"; 2766714a25aSJames Feist continue; 2776714a25aSJames Feist } 2786714a25aSJames Feist 2796714a25aSJames Feist auto findSensorName = baseConfiguration->second.find("Name"); 280347dd4e7SZhikui Ren 2816714a25aSJames Feist if (findSensorName == baseConfiguration->second.end()) 2826714a25aSJames Feist { 2836714a25aSJames Feist std::cerr << "could not determine configuration name for " 2846714a25aSJames Feist << path.string() << "\n"; 2856714a25aSJames Feist continue; 2866714a25aSJames Feist } 287de5e9705SJames Feist std::string sensorName = 288de5e9705SJames Feist std::get<std::string>(findSensorName->second); 289347dd4e7SZhikui Ren 2906714a25aSJames Feist // on rescans, only update sensors we were signaled by 2916714a25aSJames Feist auto findSensor = tachSensors.find(sensorName); 2926714a25aSJames Feist if (!firstScan && findSensor != tachSensors.end()) 2936714a25aSJames Feist { 2946714a25aSJames Feist bool found = false; 295de5e9705SJames Feist for (auto it = sensorsChanged->begin(); 296de5e9705SJames Feist it != sensorsChanged->end(); it++) 2976714a25aSJames Feist { 2986714a25aSJames Feist if (boost::ends_with(*it, findSensor->second->name)) 2996714a25aSJames Feist { 3006714a25aSJames Feist sensorsChanged->erase(it); 3016714a25aSJames Feist findSensor->second = nullptr; 3026714a25aSJames Feist found = true; 3036714a25aSJames Feist break; 3046714a25aSJames Feist } 3056714a25aSJames Feist } 3066714a25aSJames Feist if (!found) 3076714a25aSJames Feist { 3086714a25aSJames Feist continue; 3096714a25aSJames Feist } 3106714a25aSJames Feist } 3116714a25aSJames Feist std::vector<thresholds::Threshold> sensorThresholds; 3129ced0a38SJae Hyun Yoo if (!parseThresholdsFromConfig(*sensorData, sensorThresholds)) 3136714a25aSJames Feist { 314de5e9705SJames Feist std::cerr << "error populating thresholds for " 315de5e9705SJames Feist << sensorName << "\n"; 3166714a25aSJames Feist } 3176714a25aSJames Feist 3187bc2bab2SJames Feist auto presenceConfig = 3197bc2bab2SJames Feist sensorData->find(baseType + std::string(".Presence")); 3207bc2bab2SJames Feist 3217bc2bab2SJames Feist std::unique_ptr<PresenceSensor> presenceSensor(nullptr); 3227bc2bab2SJames Feist 3237bc2bab2SJames Feist // presence sensors are optional 3247bc2bab2SJames Feist if (presenceConfig != sensorData->end()) 3257bc2bab2SJames Feist { 3267bc2bab2SJames Feist auto findPolarity = presenceConfig->second.find("Polarity"); 327347dd4e7SZhikui Ren auto findPinName = presenceConfig->second.find("PinName"); 3287bc2bab2SJames Feist 329347dd4e7SZhikui Ren if (findPinName == presenceConfig->second.end() || 3307bc2bab2SJames Feist findPolarity == presenceConfig->second.end()) 3317bc2bab2SJames Feist { 3327bc2bab2SJames Feist std::cerr << "Malformed Presence Configuration\n"; 3337bc2bab2SJames Feist } 3347bc2bab2SJames Feist else 3357bc2bab2SJames Feist { 336de5e9705SJames Feist bool inverted = std::get<std::string>( 337de5e9705SJames Feist findPolarity->second) == "Low"; 338347dd4e7SZhikui Ren if (auto pinName = 339347dd4e7SZhikui Ren std::get_if<std::string>(&findPinName->second)) 340347dd4e7SZhikui Ren { 3417b18b1e0SJames Feist presenceSensor = std::make_unique<PresenceSensor>( 342347dd4e7SZhikui Ren *pinName, inverted, io, sensorName); 343347dd4e7SZhikui Ren } 344347dd4e7SZhikui Ren else 345347dd4e7SZhikui Ren { 346347dd4e7SZhikui Ren std::cerr 347347dd4e7SZhikui Ren << "Malformed Presence pinName for sensor " 348347dd4e7SZhikui Ren << sensorName << " \n"; 349347dd4e7SZhikui Ren } 3507bc2bab2SJames Feist } 3517bc2bab2SJames Feist } 3527b18b1e0SJames Feist std::optional<RedundancySensor>* redundancy = nullptr; 35395b079b7SJames Feist if (fanType == FanTypes::aspeed) 35495b079b7SJames Feist { 3557b18b1e0SJames Feist redundancy = &systemRedundancy; 35695b079b7SJames Feist } 3577bc2bab2SJames Feist 358f920e09cSJosh Lehan PowerState powerState = PowerState::on; 359f920e09cSJosh Lehan auto findPower = baseConfiguration->second.find("PowerState"); 360f920e09cSJosh Lehan if (findPower != baseConfiguration->second.end()) 361f920e09cSJosh Lehan { 362f920e09cSJosh Lehan auto ptrPower = 363f920e09cSJosh Lehan std::get_if<std::string>(&(findPower->second)); 364f920e09cSJosh Lehan if (ptrPower) 365f920e09cSJosh Lehan { 366f920e09cSJosh Lehan setReadState(*ptrPower, powerState); 367f920e09cSJosh Lehan } 368f920e09cSJosh Lehan } 369f920e09cSJosh Lehan 37087d713abSJames Feist constexpr double defaultMaxReading = 25000; 37187d713abSJames Feist constexpr double defaultMinReading = 0; 372de5e9705SJames Feist auto limits = 373de5e9705SJames Feist std::make_pair(defaultMinReading, defaultMaxReading); 37487d713abSJames Feist 375de5e9705SJames Feist auto connector = 376de5e9705SJames Feist sensorData->find(baseType + std::string(".Connector")); 37749a8ccd6SJames Feist 37849a8ccd6SJames Feist std::optional<std::string> led; 37977b3add2SYong Zhao std::string pwmName; 380d05867c0SZhikui Ren fs::path pwmPath; 38149a8ccd6SJames Feist 382*3291b9c7SJie Yang // The Mutable parameter is optional, defaulting to false 383*3291b9c7SJie Yang bool isValueMutable = false; 3848e94c204SJames Feist if (connector != sensorData->end()) 3858e94c204SJames Feist { 3868e94c204SJames Feist auto findPwm = connector->second.find("Pwm"); 38749a8ccd6SJames Feist if (findPwm != connector->second.end()) 3888e94c204SJames Feist { 389abf91de1SJeff Lin fs::path pwmEnableFile = 390abf91de1SJeff Lin "pwm" + std::to_string(index + 1) + "_enable"; 391abf91de1SJeff Lin fs::path enablePath = 392abf91de1SJeff Lin path.parent_path() / pwmEnableFile; 393abf91de1SJeff Lin enablePwm(enablePath); 394de5e9705SJames Feist size_t pwm = std::visit(VariantToUnsignedIntVisitor(), 395de5e9705SJames Feist findPwm->second); 396d05867c0SZhikui Ren pwmPath = directory / ("pwm" + std::to_string(pwm + 1)); 39749a8ccd6SJames Feist /* use pwm name override if found in configuration else 39849a8ccd6SJames Feist * use default */ 399d320a2e1SJason Ling auto findOverride = connector->second.find("PwmName"); 400d320a2e1SJason Ling if (findOverride != connector->second.end()) 401d320a2e1SJason Ling { 402d320a2e1SJason Ling pwmName = std::visit(VariantToStringVisitor(), 403d320a2e1SJason Ling findOverride->second); 404d320a2e1SJason Ling } 405d320a2e1SJason Ling else 406d320a2e1SJason Ling { 407d320a2e1SJason Ling pwmName = "Pwm_" + std::to_string(pwm + 1); 408d320a2e1SJason Ling } 409*3291b9c7SJie Yang 410*3291b9c7SJie Yang // Check PWM sensor mutability 411*3291b9c7SJie Yang auto findMutable = connector->second.find("Mutable"); 412*3291b9c7SJie Yang if (findMutable != connector->second.end()) 413*3291b9c7SJie Yang { 414*3291b9c7SJie Yang auto ptrMutable = 415*3291b9c7SJie Yang std::get_if<bool>(&(findMutable->second)); 416*3291b9c7SJie Yang if (ptrMutable) 417*3291b9c7SJie Yang { 418*3291b9c7SJie Yang isValueMutable = *ptrMutable; 419*3291b9c7SJie Yang } 420*3291b9c7SJie Yang } 4218e94c204SJames Feist } 42249a8ccd6SJames Feist else 42349a8ccd6SJames Feist { 42449a8ccd6SJames Feist std::cerr << "Connector for " << sensorName 42549a8ccd6SJames Feist << " missing pwm!\n"; 42649a8ccd6SJames Feist } 42749a8ccd6SJames Feist 42849a8ccd6SJames Feist auto findLED = connector->second.find("LED"); 42949a8ccd6SJames Feist if (findLED != connector->second.end()) 43049a8ccd6SJames Feist { 43149a8ccd6SJames Feist auto ledName = 43249a8ccd6SJames Feist std::get_if<std::string>(&(findLED->second)); 43349a8ccd6SJames Feist if (ledName == nullptr) 43449a8ccd6SJames Feist { 43549a8ccd6SJames Feist std::cerr << "Wrong format for LED of " 43649a8ccd6SJames Feist << sensorName << "\n"; 43749a8ccd6SJames Feist } 43849a8ccd6SJames Feist else 43949a8ccd6SJames Feist { 44049a8ccd6SJames Feist led = *ledName; 44149a8ccd6SJames Feist } 44249a8ccd6SJames Feist } 44349a8ccd6SJames Feist } 44449a8ccd6SJames Feist 44549a8ccd6SJames Feist findLimits(limits, baseConfiguration); 44649a8ccd6SJames Feist tachSensors[sensorName] = std::make_unique<TachSensor>( 44749a8ccd6SJames Feist path.string(), baseType, objectServer, dbusConnection, 44849a8ccd6SJames Feist std::move(presenceSensor), redundancy, io, sensorName, 44949a8ccd6SJames Feist std::move(sensorThresholds), *interfacePath, limits, 45049a8ccd6SJames Feist powerState, led); 45177b3add2SYong Zhao 452d05867c0SZhikui Ren if (!pwmPath.empty() && fs::exists(pwmPath) && 453d05867c0SZhikui Ren !pwmSensors.count(pwmPath)) 45477b3add2SYong Zhao { 45577b3add2SYong Zhao pwmSensors[pwmPath] = std::make_unique<PwmSensor>( 45677b3add2SYong Zhao pwmName, pwmPath, dbusConnection, objectServer, 457*3291b9c7SJie Yang *interfacePath, "Fan", isValueMutable); 4586714a25aSJames Feist } 45977b3add2SYong Zhao } 46077b3add2SYong Zhao 461d540741eSKuiying Wang createRedundancySensor(tachSensors, dbusConnection, objectServer); 4628a17c303SEd Tanous }); 463de5e9705SJames Feist getter->getConfiguration( 464f27a55c7SJames Feist std::vector<std::string>{sensorTypes.begin(), sensorTypes.end()}, 465f27a55c7SJames Feist retries); 4666714a25aSJames Feist } 4676714a25aSJames Feist 468b6c0b914SJames Feist int main() 4696714a25aSJames Feist { 4706714a25aSJames Feist boost::asio::io_service io; 4716714a25aSJames Feist auto systemBus = std::make_shared<sdbusplus::asio::connection>(io); 4726714a25aSJames Feist systemBus->request_name("xyz.openbmc_project.FanSensor"); 4736714a25aSJames Feist sdbusplus::asio::object_server objectServer(systemBus); 4746714a25aSJames Feist boost::container::flat_map<std::string, std::unique_ptr<TachSensor>> 4756714a25aSJames Feist tachSensors; 4766714a25aSJames Feist boost::container::flat_map<std::string, std::unique_ptr<PwmSensor>> 4776714a25aSJames Feist pwmSensors; 4786714a25aSJames Feist std::vector<std::unique_ptr<sdbusplus::bus::match::match>> matches; 4795591cf08SJames Feist auto sensorsChanged = 4805591cf08SJames Feist std::make_shared<boost::container::flat_set<std::string>>(); 4816714a25aSJames Feist 4826714a25aSJames Feist io.post([&]() { 4836714a25aSJames Feist createSensors(io, objectServer, tachSensors, pwmSensors, systemBus, 4846714a25aSJames Feist nullptr); 4856714a25aSJames Feist }); 4866714a25aSJames Feist 4876714a25aSJames Feist boost::asio::deadline_timer filterTimer(io); 4886714a25aSJames Feist std::function<void(sdbusplus::message::message&)> eventHandler = 4896714a25aSJames Feist [&](sdbusplus::message::message& message) { 4906714a25aSJames Feist if (message.is_method_error()) 4916714a25aSJames Feist { 4926714a25aSJames Feist std::cerr << "callback method error\n"; 4936714a25aSJames Feist return; 4946714a25aSJames Feist } 4956714a25aSJames Feist sensorsChanged->insert(message.get_path()); 4966714a25aSJames Feist // this implicitly cancels the timer 4976714a25aSJames Feist filterTimer.expires_from_now(boost::posix_time::seconds(1)); 4986714a25aSJames Feist 4996714a25aSJames Feist filterTimer.async_wait([&](const boost::system::error_code& ec) { 5006714a25aSJames Feist if (ec == boost::asio::error::operation_aborted) 5016714a25aSJames Feist { 5026714a25aSJames Feist /* we were canceled*/ 5036714a25aSJames Feist return; 5046714a25aSJames Feist } 5058a57ec09SEd Tanous if (ec) 5066714a25aSJames Feist { 5076714a25aSJames Feist std::cerr << "timer error\n"; 5086714a25aSJames Feist return; 5096714a25aSJames Feist } 5106714a25aSJames Feist createSensors(io, objectServer, tachSensors, pwmSensors, 511f27a55c7SJames Feist systemBus, sensorsChanged, 5); 5126714a25aSJames Feist }); 5136714a25aSJames Feist }; 5146714a25aSJames Feist 5159ced0a38SJae Hyun Yoo for (const char* type : sensorTypes) 5166714a25aSJames Feist { 5176714a25aSJames Feist auto match = std::make_unique<sdbusplus::bus::match::match>( 5186714a25aSJames Feist static_cast<sdbusplus::bus::bus&>(*systemBus), 5196714a25aSJames Feist "type='signal',member='PropertiesChanged',path_namespace='" + 5209ced0a38SJae Hyun Yoo std::string(inventoryPath) + "',arg0namespace='" + type + "'", 5216714a25aSJames Feist eventHandler); 5226714a25aSJames Feist matches.emplace_back(std::move(match)); 5236714a25aSJames Feist } 5246714a25aSJames Feist 525dc6c55f3SJames Feist // redundancy sensor 526dc6c55f3SJames Feist std::function<void(sdbusplus::message::message&)> redundancyHandler = 527dc6c55f3SJames Feist [&tachSensors, &systemBus, 528b6c0b914SJames Feist &objectServer](sdbusplus::message::message&) { 529dc6c55f3SJames Feist createRedundancySensor(tachSensors, systemBus, objectServer); 530dc6c55f3SJames Feist }; 531dc6c55f3SJames Feist auto match = std::make_unique<sdbusplus::bus::match::match>( 532dc6c55f3SJames Feist static_cast<sdbusplus::bus::bus&>(*systemBus), 533dc6c55f3SJames Feist "type='signal',member='PropertiesChanged',path_namespace='" + 534dc6c55f3SJames Feist std::string(inventoryPath) + "',arg0namespace='" + 535dc6c55f3SJames Feist redundancyConfiguration + "'", 536b6c0b914SJames Feist std::move(redundancyHandler)); 537dc6c55f3SJames Feist matches.emplace_back(std::move(match)); 538dc6c55f3SJames Feist 5391263c3daSBruce Lee setupManufacturingModeMatch(*systemBus); 5406714a25aSJames Feist io.run(); 5418685b17aSZhikui Ren return 0; 5426714a25aSJames Feist } 543