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 <HwmonTempSensor.hpp> 188a57ec09SEd Tanous #include <Utils.hpp> 196714a25aSJames Feist #include <boost/algorithm/string/predicate.hpp> 206714a25aSJames Feist #include <boost/algorithm/string/replace.hpp> 2196e97db7SPatrick Venture #include <boost/container/flat_map.hpp> 226714a25aSJames Feist #include <boost/container/flat_set.hpp> 2338fb5983SJames Feist #include <sdbusplus/asio/connection.hpp> 2438fb5983SJames Feist #include <sdbusplus/asio/object_server.hpp> 2538fb5983SJames Feist #include <sdbusplus/bus/match.hpp> 2638fb5983SJames Feist 2738fb5983SJames Feist #include <array> 2824f02f24SJames Feist #include <filesystem> 296714a25aSJames Feist #include <fstream> 3096e97db7SPatrick Venture #include <functional> 3196e97db7SPatrick Venture #include <memory> 326714a25aSJames Feist #include <regex> 3396e97db7SPatrick Venture #include <stdexcept> 3496e97db7SPatrick Venture #include <string> 3596e97db7SPatrick Venture #include <utility> 3696e97db7SPatrick Venture #include <variant> 3796e97db7SPatrick Venture #include <vector> 386714a25aSJames Feist 3987bc67f7SJeff Lin static constexpr float pollRateDefault = 0.5; 406714a25aSJames Feist 41544e7dc5SBruce Mitchell static constexpr double maxValuePressure = 120000; // Pascals 42544e7dc5SBruce Mitchell static constexpr double minValuePressure = 30000; // Pascals 43544e7dc5SBruce Mitchell 44544e7dc5SBruce Mitchell static constexpr double maxValueTemperature = 127; // DegreesC 45544e7dc5SBruce Mitchell static constexpr double minValueTemperature = -128; // DegreesC 46544e7dc5SBruce Mitchell 47cf3bce6eSJames Feist namespace fs = std::filesystem; 4866558235SBrandon Kim static auto sensorTypes{ 49*4786334fSPotin Lai std::to_array<const char*>({"xyz.openbmc_project.Configuration.DPS310", 50*4786334fSPotin Lai "xyz.openbmc_project.Configuration.EMC1412", 518b3f7d40SAlex Qiu "xyz.openbmc_project.Configuration.EMC1413", 52381636e2SGilbert Chen "xyz.openbmc_project.Configuration.EMC1414", 53*4786334fSPotin Lai "xyz.openbmc_project.Configuration.HDC1080", 54*4786334fSPotin Lai "xyz.openbmc_project.Configuration.JC42", 55*4786334fSPotin Lai "xyz.openbmc_project.Configuration.LM75A", 56*4786334fSPotin Lai "xyz.openbmc_project.Configuration.LM95234", 578b3f7d40SAlex Qiu "xyz.openbmc_project.Configuration.MAX31725", 588b3f7d40SAlex Qiu "xyz.openbmc_project.Configuration.MAX31730", 5916e7af1dSJason Ling "xyz.openbmc_project.Configuration.MAX6581", 603840d0adSJosh Lehan "xyz.openbmc_project.Configuration.MAX6654", 615770a6fdSOskar Senft "xyz.openbmc_project.Configuration.NCT7802", 628fb0a013SJosh Lehan "xyz.openbmc_project.Configuration.SBTSI", 63*4786334fSPotin Lai "xyz.openbmc_project.Configuration.SI7020", 6455ab2afbSJohn Wang "xyz.openbmc_project.Configuration.TMP112", 653546adb9SPatrick Venture "xyz.openbmc_project.Configuration.TMP175", 668b3f7d40SAlex Qiu "xyz.openbmc_project.Configuration.TMP421", 678b3f7d40SAlex Qiu "xyz.openbmc_project.Configuration.TMP441", 687ea918f2SZev Weiss "xyz.openbmc_project.Configuration.TMP75", 69*4786334fSPotin Lai "xyz.openbmc_project.Configuration.W83773G"})}; 706714a25aSJames Feist 71544e7dc5SBruce Mitchell static struct SensorParams 72544e7dc5SBruce Mitchell getSensorParameters(const std::filesystem::path& path) 73544e7dc5SBruce Mitchell { 74544e7dc5SBruce Mitchell // offset is to default to 0 and scale to 1, see lore 75544e7dc5SBruce Mitchell // https://lore.kernel.org/linux-iio/5c79425f-6e88-36b6-cdfe-4080738d039f@metafoo.de/ 76544e7dc5SBruce Mitchell struct SensorParams tmpSensorParameters = {.minValue = minValueTemperature, 77544e7dc5SBruce Mitchell .maxValue = maxValueTemperature, 78544e7dc5SBruce Mitchell .offsetValue = 0.0, 79544e7dc5SBruce Mitchell .scaleValue = 1.0, 805a86e562SBruce Mitchell .units = 815a86e562SBruce Mitchell sensor_paths::unitDegreesC, 82544e7dc5SBruce Mitchell .typeName = "temperature"}; 83544e7dc5SBruce Mitchell 84544e7dc5SBruce Mitchell // For IIO RAW sensors we get a raw_value, an offset, and scale 85544e7dc5SBruce Mitchell // to compute the value = (raw_value + offset) * scale 86544e7dc5SBruce Mitchell // with a _raw IIO device we need to get the 87544e7dc5SBruce Mitchell // offsetValue and scaleValue from the driver 88544e7dc5SBruce Mitchell // these are used to compute the reading in 89544e7dc5SBruce Mitchell // units that have yet to be scaled for D-Bus. 90544e7dc5SBruce Mitchell const std::string pathStr = path.string(); 91544e7dc5SBruce Mitchell if (pathStr.ends_with("_raw")) 92544e7dc5SBruce Mitchell { 93544e7dc5SBruce Mitchell std::string pathOffsetStr = 94544e7dc5SBruce Mitchell pathStr.substr(0, pathStr.size() - 4) + "_offset"; 95544e7dc5SBruce Mitchell std::optional<double> tmpOffsetValue = readFile(pathOffsetStr, 1.0); 96544e7dc5SBruce Mitchell // In case there is nothing to read skip this device 97544e7dc5SBruce Mitchell // This is not an error condition see lore 98544e7dc5SBruce Mitchell // https://lore.kernel.org/linux-iio/5c79425f-6e88-36b6-cdfe-4080738d039f@metafoo.de/ 99544e7dc5SBruce Mitchell if (tmpOffsetValue) 100544e7dc5SBruce Mitchell { 101544e7dc5SBruce Mitchell tmpSensorParameters.offsetValue = *tmpOffsetValue; 102544e7dc5SBruce Mitchell } 103544e7dc5SBruce Mitchell 104544e7dc5SBruce Mitchell std::string pathScaleStr = 105544e7dc5SBruce Mitchell pathStr.substr(0, pathStr.size() - 4) + "_scale"; 106544e7dc5SBruce Mitchell std::optional<double> tmpScaleValue = readFile(pathScaleStr, 1.0); 107544e7dc5SBruce Mitchell // In case there is nothing to read skip this device 108544e7dc5SBruce Mitchell // This is not an error condition see lore 109544e7dc5SBruce Mitchell // https://lore.kernel.org/linux-iio/5c79425f-6e88-36b6-cdfe-4080738d039f@metafoo.de/ 110544e7dc5SBruce Mitchell if (tmpScaleValue) 111544e7dc5SBruce Mitchell { 112544e7dc5SBruce Mitchell tmpSensorParameters.scaleValue = *tmpScaleValue; 113544e7dc5SBruce Mitchell } 114544e7dc5SBruce Mitchell } 115544e7dc5SBruce Mitchell 116544e7dc5SBruce Mitchell // Temperatures are read in milli degrees Celsius, we need 117544e7dc5SBruce Mitchell // degrees Celsius. Pressures are read in kilopascal, we need 118544e7dc5SBruce Mitchell // Pascals. On D-Bus for Open BMC we use the International 119544e7dc5SBruce Mitchell // System of Units without prefixes. Links to the kernel 120544e7dc5SBruce Mitchell // documentation: 121544e7dc5SBruce Mitchell // https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface 122544e7dc5SBruce Mitchell // https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-bus-iio 123544e7dc5SBruce Mitchell if (path.filename() == "in_pressure_input" || 124544e7dc5SBruce Mitchell path.filename() == "in_pressure_raw") 125544e7dc5SBruce Mitchell { 126544e7dc5SBruce Mitchell tmpSensorParameters.minValue = minValuePressure; 127544e7dc5SBruce Mitchell tmpSensorParameters.maxValue = maxValuePressure; 128544e7dc5SBruce Mitchell // Pressures are read in kilopascal, we need Pascals. 129544e7dc5SBruce Mitchell tmpSensorParameters.scaleValue *= 1000.0; 130544e7dc5SBruce Mitchell tmpSensorParameters.typeName = "pressure"; 1315a86e562SBruce Mitchell tmpSensorParameters.units = sensor_paths::unitPascals; 132544e7dc5SBruce Mitchell } 133544e7dc5SBruce Mitchell else 134544e7dc5SBruce Mitchell { 135544e7dc5SBruce Mitchell // Temperatures are read in milli degrees Celsius, 136544e7dc5SBruce Mitchell // we need degrees Celsius. 137544e7dc5SBruce Mitchell tmpSensorParameters.scaleValue *= 0.001; 138544e7dc5SBruce Mitchell } 139544e7dc5SBruce Mitchell 140544e7dc5SBruce Mitchell return tmpSensorParameters; 141544e7dc5SBruce Mitchell } 142544e7dc5SBruce Mitchell 1436714a25aSJames Feist void createSensors( 1446714a25aSJames Feist boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer, 145f3fd1915SYong Li boost::container::flat_map<std::string, std::shared_ptr<HwmonTempSensor>>& 1466714a25aSJames Feist sensors, 1476714a25aSJames Feist std::shared_ptr<sdbusplus::asio::connection>& dbusConnection, 1485591cf08SJames Feist const std::shared_ptr<boost::container::flat_set<std::string>>& 1496714a25aSJames Feist sensorsChanged) 1506714a25aSJames Feist { 151df515159SJames Feist auto getter = std::make_shared<GetSensorConfiguration>( 152df515159SJames Feist dbusConnection, 1538a17c303SEd Tanous [&io, &objectServer, &sensors, &dbusConnection, 1548a17c303SEd Tanous sensorsChanged](const ManagedObjectType& sensorConfigurations) { 1556714a25aSJames Feist bool firstScan = sensorsChanged == nullptr; 156df515159SJames Feist 157544e7dc5SBruce Mitchell // IIO _raw devices look like this on sysfs: 158544e7dc5SBruce Mitchell // /sys/bus/iio/devices/iio:device0/in_temp_raw 159544e7dc5SBruce Mitchell // /sys/bus/iio/devices/iio:device0/in_temp_offset 160544e7dc5SBruce Mitchell // /sys/bus/iio/devices/iio:device0/in_temp_scale 161544e7dc5SBruce Mitchell // 162544e7dc5SBruce Mitchell // Other IIO devices look like this on sysfs: 163544e7dc5SBruce Mitchell // /sys/bus/iio/devices/iio:device1/in_temp_input 164544e7dc5SBruce Mitchell // /sys/bus/iio/devices/iio:device1/in_pressure_input 1656714a25aSJames Feist std::vector<fs::path> paths; 166544e7dc5SBruce Mitchell fs::path root("/sys/bus/iio/devices"); 167544e7dc5SBruce Mitchell findFiles(root, R"(in_temp\d*_(input|raw))", paths); 168544e7dc5SBruce Mitchell findFiles(root, R"(in_pressure\d*_(input|raw))", paths); 169544e7dc5SBruce Mitchell findFiles(fs::path("/sys/class/hwmon"), R"(temp\d+_input)", paths); 170544e7dc5SBruce Mitchell 171544e7dc5SBruce Mitchell if (paths.empty()) 1726714a25aSJames Feist { 1736714a25aSJames Feist return; 1746714a25aSJames Feist } 1756714a25aSJames Feist 176544e7dc5SBruce Mitchell // iterate through all found temp and pressure sensors, 177544e7dc5SBruce Mitchell // and try to match them with configuration 1786714a25aSJames Feist for (auto& path : paths) 1796714a25aSJames Feist { 1806714a25aSJames Feist std::smatch match; 181544e7dc5SBruce Mitchell const std::string pathStr = path.string(); 1826714a25aSJames Feist auto directory = path.parent_path(); 183544e7dc5SBruce Mitchell fs::path device; 1846714a25aSJames Feist 185544e7dc5SBruce Mitchell std::string deviceName; 186544e7dc5SBruce Mitchell if (pathStr.starts_with("/sys/bus/iio/devices")) 1876714a25aSJames Feist { 188544e7dc5SBruce Mitchell device = fs::canonical(directory); 189544e7dc5SBruce Mitchell deviceName = device.parent_path().stem(); 19037266ca9SJames Feist } 191544e7dc5SBruce Mitchell else 192544e7dc5SBruce Mitchell { 193544e7dc5SBruce Mitchell device = directory / "device"; 194544e7dc5SBruce Mitchell deviceName = fs::canonical(device).stem(); 195544e7dc5SBruce Mitchell } 1968a57ec09SEd Tanous auto findHyphen = deviceName.find('-'); 19737266ca9SJames Feist if (findHyphen == std::string::npos) 19837266ca9SJames Feist { 19937266ca9SJames Feist std::cerr << "found bad device " << deviceName << "\n"; 2006714a25aSJames Feist continue; 2016714a25aSJames Feist } 20237266ca9SJames Feist std::string busStr = deviceName.substr(0, findHyphen); 20337266ca9SJames Feist std::string addrStr = deviceName.substr(findHyphen + 1); 20437266ca9SJames Feist 20537266ca9SJames Feist size_t bus = 0; 20637266ca9SJames Feist size_t addr = 0; 20737266ca9SJames Feist try 2086714a25aSJames Feist { 20937266ca9SJames Feist bus = std::stoi(busStr); 2108a57ec09SEd Tanous addr = std::stoi(addrStr, nullptr, 16); 21137266ca9SJames Feist } 21226601e89SPatrick Williams catch (const std::invalid_argument&) 21337266ca9SJames Feist { 2146714a25aSJames Feist continue; 2156714a25aSJames Feist } 2166714a25aSJames Feist const SensorData* sensorData = nullptr; 2176714a25aSJames Feist const std::string* interfacePath = nullptr; 21837266ca9SJames Feist const char* sensorType = nullptr; 2198b3f7d40SAlex Qiu const SensorBaseConfiguration* baseConfiguration = nullptr; 2208b3f7d40SAlex Qiu const SensorBaseConfigMap* baseConfigMap = nullptr; 22137266ca9SJames Feist 222544e7dc5SBruce Mitchell auto thisSensorParameters = getSensorParameters(path); 223544e7dc5SBruce Mitchell 224df515159SJames Feist for (const std::pair<sdbusplus::message::object_path, 225df515159SJames Feist SensorData>& sensor : sensorConfigurations) 22637266ca9SJames Feist { 22737266ca9SJames Feist sensorData = &(sensor.second); 2289ced0a38SJae Hyun Yoo for (const char* type : sensorTypes) 2296714a25aSJames Feist { 2306714a25aSJames Feist auto sensorBase = sensorData->find(type); 2316714a25aSJames Feist if (sensorBase != sensorData->end()) 2326714a25aSJames Feist { 2336714a25aSJames Feist baseConfiguration = &(*sensorBase); 2346714a25aSJames Feist sensorType = type; 2356714a25aSJames Feist break; 2366714a25aSJames Feist } 2376714a25aSJames Feist } 2386714a25aSJames Feist if (baseConfiguration == nullptr) 2396714a25aSJames Feist { 24037266ca9SJames Feist std::cerr << "error finding base configuration for " 24137266ca9SJames Feist << deviceName << "\n"; 24237266ca9SJames Feist continue; 24337266ca9SJames Feist } 2448b3f7d40SAlex Qiu baseConfigMap = &baseConfiguration->second; 2458b3f7d40SAlex Qiu auto configurationBus = baseConfigMap->find("Bus"); 2468b3f7d40SAlex Qiu auto configurationAddress = baseConfigMap->find("Address"); 24737266ca9SJames Feist 2488b3f7d40SAlex Qiu if (configurationBus == baseConfigMap->end() || 2498b3f7d40SAlex Qiu configurationAddress == baseConfigMap->end()) 25037266ca9SJames Feist { 2518b3f7d40SAlex Qiu std::cerr << "error finding bus or address in " 2528b3f7d40SAlex Qiu "configuration\n"; 25337266ca9SJames Feist continue; 25437266ca9SJames Feist } 25537266ca9SJames Feist 2563eb82629SJames Feist if (std::get<uint64_t>(configurationBus->second) != bus || 257df515159SJames Feist std::get<uint64_t>(configurationAddress->second) != 258df515159SJames Feist addr) 25937266ca9SJames Feist { 26037266ca9SJames Feist continue; 26137266ca9SJames Feist } 26237266ca9SJames Feist 26337266ca9SJames Feist interfacePath = &(sensor.first.str); 26437266ca9SJames Feist break; 26537266ca9SJames Feist } 26637266ca9SJames Feist if (interfacePath == nullptr) 26737266ca9SJames Feist { 2686714a25aSJames Feist continue; 2696714a25aSJames Feist } 2706714a25aSJames Feist 271544e7dc5SBruce Mitchell // Temperature has "Name", pressure has "Name1" 2728b3f7d40SAlex Qiu auto findSensorName = baseConfigMap->find("Name"); 273544e7dc5SBruce Mitchell if (thisSensorParameters.typeName == "pressure") 274544e7dc5SBruce Mitchell { 275544e7dc5SBruce Mitchell findSensorName = baseConfigMap->find("Name1"); 276544e7dc5SBruce Mitchell } 277544e7dc5SBruce Mitchell 2788b3f7d40SAlex Qiu if (findSensorName == baseConfigMap->end()) 2796714a25aSJames Feist { 2806714a25aSJames Feist std::cerr << "could not determine configuration name for " 28137266ca9SJames Feist << deviceName << "\n"; 2826714a25aSJames Feist continue; 2836714a25aSJames Feist } 284df515159SJames Feist std::string sensorName = 285df515159SJames Feist std::get<std::string>(findSensorName->second); 2866714a25aSJames Feist // on rescans, only update sensors we were signaled by 2876714a25aSJames Feist auto findSensor = sensors.find(sensorName); 2886714a25aSJames Feist if (!firstScan && findSensor != sensors.end()) 2896714a25aSJames Feist { 2906714a25aSJames Feist bool found = false; 291d653b75cSBruce Mitchell auto it = sensorsChanged->begin(); 292d653b75cSBruce Mitchell while (it != sensorsChanged->end()) 2936714a25aSJames Feist { 2946714a25aSJames Feist if (boost::ends_with(*it, findSensor->second->name)) 2956714a25aSJames Feist { 296d653b75cSBruce Mitchell it = sensorsChanged->erase(it); 2976714a25aSJames Feist findSensor->second = nullptr; 2986714a25aSJames Feist found = true; 2996714a25aSJames Feist break; 3006714a25aSJames Feist } 301d653b75cSBruce Mitchell ++it; 3026714a25aSJames Feist } 3036714a25aSJames Feist if (!found) 3046714a25aSJames Feist { 3056714a25aSJames Feist continue; 3066714a25aSJames Feist } 3076714a25aSJames Feist } 3085636d52bSMatt Spinler 3096714a25aSJames Feist std::vector<thresholds::Threshold> sensorThresholds; 3105636d52bSMatt Spinler int index = 1; 3115636d52bSMatt Spinler 3125636d52bSMatt Spinler if (!parseThresholdsFromConfig(*sensorData, sensorThresholds, 3135636d52bSMatt Spinler nullptr, &index)) 3146714a25aSJames Feist { 315df515159SJames Feist std::cerr << "error populating thresholds for " 3165636d52bSMatt Spinler << sensorName << " index 1\n"; 3176714a25aSJames Feist } 31887bc67f7SJeff Lin 31987bc67f7SJeff Lin auto findPollRate = baseConfiguration->second.find("PollRate"); 32087bc67f7SJeff Lin float pollRate = pollRateDefault; 32187bc67f7SJeff Lin if (findPollRate != baseConfiguration->second.end()) 32287bc67f7SJeff Lin { 32387bc67f7SJeff Lin pollRate = std::visit(VariantToFloatVisitor(), 32487bc67f7SJeff Lin findPollRate->second); 32587bc67f7SJeff Lin if (pollRate <= 0.0f) 32687bc67f7SJeff Lin { 32787bc67f7SJeff Lin pollRate = pollRateDefault; // polling time too short 32887bc67f7SJeff Lin } 32987bc67f7SJeff Lin } 33087bc67f7SJeff Lin 331f9b01b6dSJames Feist auto findPowerOn = baseConfiguration->second.find("PowerState"); 332f9b01b6dSJames Feist PowerState readState = PowerState::always; 333f9b01b6dSJames Feist if (findPowerOn != baseConfiguration->second.end()) 334f9b01b6dSJames Feist { 335f9b01b6dSJames Feist std::string powerState = std::visit( 336f9b01b6dSJames Feist VariantToStringVisitor(), findPowerOn->second); 337f9b01b6dSJames Feist setReadState(powerState, readState); 338f9b01b6dSJames Feist } 339100c20bfSJason Ling 340100c20bfSJason Ling auto permitSet = getPermitSet(*baseConfigMap); 3418b3f7d40SAlex Qiu auto& sensor = sensors[sensorName]; 3428b3f7d40SAlex Qiu sensor = nullptr; 343100c20bfSJason Ling auto hwmonFile = getFullHwmonFilePath(directory.string(), 344100c20bfSJason Ling "temp1", permitSet); 345544e7dc5SBruce Mitchell if (pathStr.starts_with("/sys/bus/iio/devices")) 346544e7dc5SBruce Mitchell { 347544e7dc5SBruce Mitchell hwmonFile = pathStr; 348544e7dc5SBruce Mitchell } 349100c20bfSJason Ling if (hwmonFile) 350100c20bfSJason Ling { 351f3fd1915SYong Li sensor = std::make_shared<HwmonTempSensor>( 352100c20bfSJason Ling *hwmonFile, sensorType, objectServer, dbusConnection, 353544e7dc5SBruce Mitchell io, sensorName, std::move(sensorThresholds), 354544e7dc5SBruce Mitchell thisSensorParameters, pollRate, *interfacePath, 355544e7dc5SBruce Mitchell readState); 356f3fd1915SYong Li sensor->setupRead(); 357100c20bfSJason Ling } 3588b3f7d40SAlex Qiu // Looking for keys like "Name1" for temp2_input, 3598b3f7d40SAlex Qiu // "Name2" for temp3_input, etc. 3608b3f7d40SAlex Qiu int i = 0; 3618b3f7d40SAlex Qiu while (true) 36237266ca9SJames Feist { 3638b3f7d40SAlex Qiu ++i; 3648b3f7d40SAlex Qiu auto findKey = 3658b8bcc87SJason Ling baseConfigMap->find("Name" + std::to_string(i)); 3668b3f7d40SAlex Qiu if (findKey == baseConfigMap->end()) 3678b3f7d40SAlex Qiu { 3688b3f7d40SAlex Qiu break; 36937266ca9SJames Feist } 3708b3f7d40SAlex Qiu std::string sensorName = 3718b3f7d40SAlex Qiu std::get<std::string>(findKey->second); 372100c20bfSJason Ling hwmonFile = getFullHwmonFilePath( 373100c20bfSJason Ling directory.string(), "temp" + std::to_string(i + 1), 374100c20bfSJason Ling permitSet); 375544e7dc5SBruce Mitchell if (pathStr.starts_with("/sys/bus/iio/devices")) 376544e7dc5SBruce Mitchell { 377544e7dc5SBruce Mitchell continue; 378544e7dc5SBruce Mitchell } 379100c20bfSJason Ling if (hwmonFile) 380100c20bfSJason Ling { 3815636d52bSMatt Spinler // To look up thresholds for these additional sensors, 3825636d52bSMatt Spinler // match on the Index property in the threshold data 3835636d52bSMatt Spinler // where the index comes from the sysfs file we're on, 3845636d52bSMatt Spinler // i.e. index = 2 for temp2_input. 3855636d52bSMatt Spinler int index = i + 1; 3865636d52bSMatt Spinler std::vector<thresholds::Threshold> thresholds; 3875636d52bSMatt Spinler 3885636d52bSMatt Spinler if (!parseThresholdsFromConfig(*sensorData, thresholds, 3895636d52bSMatt Spinler nullptr, &index)) 3905636d52bSMatt Spinler { 3915636d52bSMatt Spinler std::cerr << "error populating thresholds for " 3925636d52bSMatt Spinler << sensorName << " index " << index 3935636d52bSMatt Spinler << "\n"; 3945636d52bSMatt Spinler } 3955636d52bSMatt Spinler 3968b3f7d40SAlex Qiu auto& sensor = sensors[sensorName]; 3978b3f7d40SAlex Qiu sensor = nullptr; 398f3fd1915SYong Li sensor = std::make_shared<HwmonTempSensor>( 399100c20bfSJason Ling *hwmonFile, sensorType, objectServer, 400100c20bfSJason Ling dbusConnection, io, sensorName, 401544e7dc5SBruce Mitchell std::move(thresholds), thisSensorParameters, 402544e7dc5SBruce Mitchell pollRate, *interfacePath, readState); 403f3fd1915SYong Li sensor->setupRead(); 4048b3f7d40SAlex Qiu } 4056714a25aSJames Feist } 406100c20bfSJason Ling } 4078a17c303SEd Tanous }); 408df515159SJames Feist getter->getConfiguration( 409df515159SJames Feist std::vector<std::string>(sensorTypes.begin(), sensorTypes.end())); 4106714a25aSJames Feist } 4116714a25aSJames Feist 41220bf2c1cSMatt Spinler void interfaceRemoved( 41320bf2c1cSMatt Spinler sdbusplus::message::message& message, 41420bf2c1cSMatt Spinler boost::container::flat_map<std::string, std::shared_ptr<HwmonTempSensor>>& 41520bf2c1cSMatt Spinler sensors) 41620bf2c1cSMatt Spinler { 41720bf2c1cSMatt Spinler if (message.is_method_error()) 41820bf2c1cSMatt Spinler { 41920bf2c1cSMatt Spinler std::cerr << "interfacesRemoved callback method error\n"; 42020bf2c1cSMatt Spinler return; 42120bf2c1cSMatt Spinler } 42220bf2c1cSMatt Spinler 42320bf2c1cSMatt Spinler sdbusplus::message::object_path path; 42420bf2c1cSMatt Spinler std::vector<std::string> interfaces; 42520bf2c1cSMatt Spinler 42620bf2c1cSMatt Spinler message.read(path, interfaces); 42720bf2c1cSMatt Spinler 42820bf2c1cSMatt Spinler // If the xyz.openbmc_project.Confguration.X interface was removed 42920bf2c1cSMatt Spinler // for one or more sensors, delete those sensor objects. 43020bf2c1cSMatt Spinler auto sensorIt = sensors.begin(); 43120bf2c1cSMatt Spinler while (sensorIt != sensors.end()) 43220bf2c1cSMatt Spinler { 43320bf2c1cSMatt Spinler if ((sensorIt->second->configurationPath == path) && 43420bf2c1cSMatt Spinler (std::find(interfaces.begin(), interfaces.end(), 43520bf2c1cSMatt Spinler sensorIt->second->objectType) != interfaces.end())) 43620bf2c1cSMatt Spinler { 43720bf2c1cSMatt Spinler sensorIt = sensors.erase(sensorIt); 43820bf2c1cSMatt Spinler } 43920bf2c1cSMatt Spinler else 44020bf2c1cSMatt Spinler { 44120bf2c1cSMatt Spinler sensorIt++; 44220bf2c1cSMatt Spinler } 44320bf2c1cSMatt Spinler } 44420bf2c1cSMatt Spinler } 44520bf2c1cSMatt Spinler 446b6c0b914SJames Feist int main() 4476714a25aSJames Feist { 4486714a25aSJames Feist boost::asio::io_service io; 4496714a25aSJames Feist auto systemBus = std::make_shared<sdbusplus::asio::connection>(io); 4506714a25aSJames Feist systemBus->request_name("xyz.openbmc_project.HwmonTempSensor"); 4516714a25aSJames Feist sdbusplus::asio::object_server objectServer(systemBus); 452f3fd1915SYong Li boost::container::flat_map<std::string, std::shared_ptr<HwmonTempSensor>> 4536714a25aSJames Feist sensors; 4546714a25aSJames Feist std::vector<std::unique_ptr<sdbusplus::bus::match::match>> matches; 4555591cf08SJames Feist auto sensorsChanged = 4565591cf08SJames Feist std::make_shared<boost::container::flat_set<std::string>>(); 4576714a25aSJames Feist 4586714a25aSJames Feist io.post([&]() { 4596714a25aSJames Feist createSensors(io, objectServer, sensors, systemBus, nullptr); 4606714a25aSJames Feist }); 4616714a25aSJames Feist 4626714a25aSJames Feist boost::asio::deadline_timer filterTimer(io); 4636714a25aSJames Feist std::function<void(sdbusplus::message::message&)> eventHandler = 4646714a25aSJames Feist [&](sdbusplus::message::message& message) { 4656714a25aSJames Feist if (message.is_method_error()) 4666714a25aSJames Feist { 4676714a25aSJames Feist std::cerr << "callback method error\n"; 4686714a25aSJames Feist return; 4696714a25aSJames Feist } 4706714a25aSJames Feist sensorsChanged->insert(message.get_path()); 4716714a25aSJames Feist // this implicitly cancels the timer 4726714a25aSJames Feist filterTimer.expires_from_now(boost::posix_time::seconds(1)); 4736714a25aSJames Feist 4746714a25aSJames Feist filterTimer.async_wait([&](const boost::system::error_code& ec) { 4756714a25aSJames Feist if (ec == boost::asio::error::operation_aborted) 4766714a25aSJames Feist { 4776714a25aSJames Feist /* we were canceled*/ 4786714a25aSJames Feist return; 4796714a25aSJames Feist } 4808a57ec09SEd Tanous if (ec) 4816714a25aSJames Feist { 4826714a25aSJames Feist std::cerr << "timer error\n"; 4836714a25aSJames Feist return; 4846714a25aSJames Feist } 4856714a25aSJames Feist createSensors(io, objectServer, sensors, systemBus, 4866714a25aSJames Feist sensorsChanged); 4876714a25aSJames Feist }); 4886714a25aSJames Feist }; 4896714a25aSJames Feist 4909ced0a38SJae Hyun Yoo for (const char* type : sensorTypes) 4916714a25aSJames Feist { 4926714a25aSJames Feist auto match = std::make_unique<sdbusplus::bus::match::match>( 4936714a25aSJames Feist static_cast<sdbusplus::bus::bus&>(*systemBus), 4946714a25aSJames Feist "type='signal',member='PropertiesChanged',path_namespace='" + 4959ced0a38SJae Hyun Yoo std::string(inventoryPath) + "',arg0namespace='" + type + "'", 4966714a25aSJames Feist eventHandler); 4976714a25aSJames Feist matches.emplace_back(std::move(match)); 4986714a25aSJames Feist } 4996714a25aSJames Feist 5001263c3daSBruce Lee setupManufacturingModeMatch(*systemBus); 50120bf2c1cSMatt Spinler 50220bf2c1cSMatt Spinler // Watch for entity-manager to remove configuration interfaces 50320bf2c1cSMatt Spinler // so the corresponding sensors can be removed. 50420bf2c1cSMatt Spinler auto ifaceRemovedMatch = std::make_unique<sdbusplus::bus::match::match>( 50520bf2c1cSMatt Spinler static_cast<sdbusplus::bus::bus&>(*systemBus), 50620bf2c1cSMatt Spinler "type='signal',member='InterfacesRemoved',arg0path='" + 50720bf2c1cSMatt Spinler std::string(inventoryPath) + "/'", 50820bf2c1cSMatt Spinler [&sensors](sdbusplus::message::message& msg) { 50920bf2c1cSMatt Spinler interfaceRemoved(msg, sensors); 51020bf2c1cSMatt Spinler }); 51120bf2c1cSMatt Spinler 51220bf2c1cSMatt Spinler matches.emplace_back(std::move(ifaceRemovedMatch)); 51320bf2c1cSMatt Spinler 5146714a25aSJames Feist io.run(); 5156714a25aSJames Feist } 516