xref: /openbmc/dbus-sensors/src/FanMain.cpp (revision 3291b9c7)
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