1 /** 2 * Copyright © 2024 IBM Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "compatible_system_types_finder.hpp" 18 19 #include <phosphor-logging/lg2.hpp> 20 21 #include <algorithm> 22 #include <exception> 23 #include <format> 24 #include <ranges> 25 #include <regex> 26 #include <stdexcept> 27 #include <utility> 28 #include <variant> 29 30 namespace phosphor::power::util 31 { 32 33 const std::string compatibleInterfaceService = 34 "xyz.openbmc_project.EntityManager"; 35 36 const std::string compatibleInterface = 37 "xyz.openbmc_project.Inventory.Decorator.Compatible"; 38 39 const std::string namesProperty = "Names"; 40 41 CompatibleSystemTypesFinder::CompatibleSystemTypesFinder(sdbusplus::bus_t& bus, 42 Callback callback) : 43 callback{std::move(callback)} 44 { 45 interfaceFinder = std::make_unique<DBusInterfacesFinder>( 46 bus, compatibleInterfaceService, 47 std::vector<std::string>{compatibleInterface}, 48 std::bind_front(&CompatibleSystemTypesFinder::interfaceFoundCallback, 49 this)); 50 } 51 52 void CompatibleSystemTypesFinder::interfaceFoundCallback( 53 [[maybe_unused]] const std::string& path, 54 [[maybe_unused]] const std::string& interface, 55 const DbusPropertyMap& properties) 56 { 57 try 58 { 59 // Get the property containing the list of compatible names 60 auto it = properties.find(namesProperty); 61 if (it == properties.end()) 62 { 63 throw std::runtime_error{ 64 std::format("{} property not found", namesProperty)}; 65 } 66 auto names = std::get<std::vector<std::string>>(it->second); 67 if (!names.empty()) 68 { 69 // If all the compatible names are system or chassis types 70 std::regex pattern{"\\.(system|chassis)\\.", std::regex::icase}; 71 if (std::ranges::all_of(names, [&pattern](auto&& name) { 72 return std::regex_search(name, pattern); 73 })) 74 { 75 // Call callback with compatible system type names 76 callback(names); 77 } 78 } 79 } 80 catch (const std::exception& e) 81 { 82 lg2::error( 83 "Unable to obtain properties of Compatible interface: {ERROR}", 84 "ERROR", e); 85 } 86 } 87 88 } // namespace phosphor::power::util 89