13cc348ceSShawn McCarney /**
23cc348ceSShawn McCarney  * Copyright © 2024 IBM Corporation
33cc348ceSShawn McCarney  *
43cc348ceSShawn McCarney  * Licensed under the Apache License, Version 2.0 (the "License");
53cc348ceSShawn McCarney  * you may not use this file except in compliance with the License.
63cc348ceSShawn McCarney  * You may obtain a copy of the License at
73cc348ceSShawn McCarney  *
83cc348ceSShawn McCarney  *     http://www.apache.org/licenses/LICENSE-2.0
93cc348ceSShawn McCarney  *
103cc348ceSShawn McCarney  * Unless required by applicable law or agreed to in writing, software
113cc348ceSShawn McCarney  * distributed under the License is distributed on an "AS IS" BASIS,
123cc348ceSShawn McCarney  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133cc348ceSShawn McCarney  * See the License for the specific language governing permissions and
143cc348ceSShawn McCarney  * limitations under the License.
153cc348ceSShawn McCarney  */
163cc348ceSShawn McCarney 
173cc348ceSShawn McCarney #include "compatible_system_types_finder.hpp"
183cc348ceSShawn McCarney 
193cc348ceSShawn McCarney #include <phosphor-logging/lg2.hpp>
203cc348ceSShawn McCarney 
213cc348ceSShawn McCarney #include <algorithm>
223cc348ceSShawn McCarney #include <exception>
233cc348ceSShawn McCarney #include <format>
243cc348ceSShawn McCarney #include <ranges>
253cc348ceSShawn McCarney #include <regex>
263cc348ceSShawn McCarney #include <stdexcept>
273cc348ceSShawn McCarney #include <utility>
283cc348ceSShawn McCarney #include <variant>
293cc348ceSShawn McCarney 
303cc348ceSShawn McCarney namespace phosphor::power::util
313cc348ceSShawn McCarney {
323cc348ceSShawn McCarney 
333cc348ceSShawn McCarney const std::string compatibleInterfaceService =
343cc348ceSShawn McCarney     "xyz.openbmc_project.EntityManager";
353cc348ceSShawn McCarney 
363cc348ceSShawn McCarney const std::string compatibleInterface =
373cc348ceSShawn McCarney     "xyz.openbmc_project.Inventory.Decorator.Compatible";
383cc348ceSShawn McCarney 
393cc348ceSShawn McCarney const std::string namesProperty = "Names";
403cc348ceSShawn McCarney 
CompatibleSystemTypesFinder(sdbusplus::bus_t & bus,Callback callback)413cc348ceSShawn McCarney CompatibleSystemTypesFinder::CompatibleSystemTypesFinder(sdbusplus::bus_t& bus,
423cc348ceSShawn McCarney                                                          Callback callback) :
43*1838dbf9SShawn McCarney     callback{std::move(callback)}
44*1838dbf9SShawn McCarney {
45*1838dbf9SShawn McCarney     interfaceFinder = std::make_unique<DBusInterfacesFinder>(
463cc348ceSShawn McCarney         bus, compatibleInterfaceService,
473cc348ceSShawn McCarney         std::vector<std::string>{compatibleInterface},
483cc348ceSShawn McCarney         std::bind_front(&CompatibleSystemTypesFinder::interfaceFoundCallback,
49*1838dbf9SShawn McCarney                         this));
50*1838dbf9SShawn McCarney }
513cc348ceSShawn McCarney 
interfaceFoundCallback(const std::string & path,const std::string & interface,const DbusPropertyMap & properties)523cc348ceSShawn McCarney void CompatibleSystemTypesFinder::interfaceFoundCallback(
533cc348ceSShawn McCarney     [[maybe_unused]] const std::string& path,
543cc348ceSShawn McCarney     [[maybe_unused]] const std::string& interface,
553cc348ceSShawn McCarney     const DbusPropertyMap& properties)
563cc348ceSShawn McCarney {
573cc348ceSShawn McCarney     try
583cc348ceSShawn McCarney     {
593cc348ceSShawn McCarney         // Get the property containing the list of compatible names
603cc348ceSShawn McCarney         auto it = properties.find(namesProperty);
613cc348ceSShawn McCarney         if (it == properties.end())
623cc348ceSShawn McCarney         {
633cc348ceSShawn McCarney             throw std::runtime_error{
643cc348ceSShawn McCarney                 std::format("{} property not found", namesProperty)};
653cc348ceSShawn McCarney         }
663cc348ceSShawn McCarney         auto names = std::get<std::vector<std::string>>(it->second);
673cc348ceSShawn McCarney         if (!names.empty())
683cc348ceSShawn McCarney         {
693cc348ceSShawn McCarney             // If all the compatible names are system or chassis types
703cc348ceSShawn McCarney             std::regex pattern{"\\.(system|chassis)\\.", std::regex::icase};
713cc348ceSShawn McCarney             if (std::ranges::all_of(names, [&pattern](auto&& name) {
723cc348ceSShawn McCarney                 return std::regex_search(name, pattern);
733cc348ceSShawn McCarney             }))
743cc348ceSShawn McCarney             {
753cc348ceSShawn McCarney                 // Call callback with compatible system type names
763cc348ceSShawn McCarney                 callback(names);
773cc348ceSShawn McCarney             }
783cc348ceSShawn McCarney         }
793cc348ceSShawn McCarney     }
803cc348ceSShawn McCarney     catch (const std::exception& e)
813cc348ceSShawn McCarney     {
823cc348ceSShawn McCarney         lg2::error(
833cc348ceSShawn McCarney             "Unable to obtain properties of Compatible interface: {ERROR}",
843cc348ceSShawn McCarney             "ERROR", e);
853cc348ceSShawn McCarney     }
863cc348ceSShawn McCarney }
873cc348ceSShawn McCarney 
883cc348ceSShawn McCarney } // namespace phosphor::power::util
89