| Ed Tanous | 828c5a6 | 2024-02-09 16:59:22 -0800 | [diff] [blame] | 1 | #include "IpmbSDRSensor.hpp" | 
|  | 2 | #include "IpmbSensor.hpp" | 
|  | 3 | #include "Utils.hpp" | 
|  | 4 |  | 
|  | 5 | #include <boost/asio/error.hpp> | 
|  | 6 | #include <boost/asio/io_context.hpp> | 
|  | 7 | #include <boost/asio/post.hpp> | 
|  | 8 | #include <boost/asio/steady_timer.hpp> | 
|  | 9 | #include <boost/container/flat_map.hpp> | 
| George Liu | 73f6cdc | 2025-02-20 15:15:19 +0800 | [diff] [blame] | 10 | #include <phosphor-logging/lg2.hpp> | 
| Ed Tanous | 828c5a6 | 2024-02-09 16:59:22 -0800 | [diff] [blame] | 11 | #include <sdbusplus/asio/connection.hpp> | 
|  | 12 | #include <sdbusplus/asio/object_server.hpp> | 
|  | 13 | #include <sdbusplus/bus.hpp> | 
|  | 14 | #include <sdbusplus/bus/match.hpp> | 
|  | 15 | #include <sdbusplus/message.hpp> | 
|  | 16 |  | 
|  | 17 | #include <array> | 
|  | 18 | #include <chrono> | 
|  | 19 | #include <cstddef> | 
|  | 20 | #include <cstdint> | 
|  | 21 | #include <functional> | 
| Ed Tanous | 828c5a6 | 2024-02-09 16:59:22 -0800 | [diff] [blame] | 22 | #include <memory> | 
|  | 23 | #include <string> | 
|  | 24 | #include <variant> | 
|  | 25 | #include <vector> | 
|  | 26 |  | 
|  | 27 | std::unique_ptr<boost::asio::steady_timer> initCmdTimer; | 
|  | 28 | boost::container::flat_map<std::string, std::shared_ptr<IpmbSensor>> sensors; | 
|  | 29 | boost::container::flat_map<uint8_t, std::shared_ptr<IpmbSDRDevice>> sdrsensor; | 
|  | 30 |  | 
|  | 31 | void sdrHandler( | 
|  | 32 | boost::container::flat_map<uint8_t, std::shared_ptr<IpmbSDRDevice>> | 
|  | 33 | sdrsensor, | 
|  | 34 | sdbusplus::message_t& message, | 
|  | 35 | std::shared_ptr<sdbusplus::asio::connection>& dbusConnection) | 
|  | 36 | { | 
|  | 37 | std::string objectName; | 
|  | 38 | SensorBaseConfigMap values; | 
|  | 39 | message.read(objectName, values); | 
|  | 40 |  | 
|  | 41 | auto findBus = values.find("Bus"); | 
|  | 42 | if (findBus == values.end()) | 
|  | 43 | { | 
|  | 44 | return; | 
|  | 45 | } | 
|  | 46 |  | 
|  | 47 | uint8_t busIndex = loadVariant<uint8_t>(values, "Bus"); | 
|  | 48 |  | 
|  | 49 | auto& sdrsen = sdrsensor[busIndex]; | 
|  | 50 | sdrsen = nullptr; | 
|  | 51 | sdrsen = std::make_shared<IpmbSDRDevice>(dbusConnection, busIndex); | 
|  | 52 | sdrsen->getSDRRepositoryInfo(); | 
|  | 53 | } | 
|  | 54 |  | 
|  | 55 | void reinitSensors(sdbusplus::message_t& message) | 
|  | 56 | { | 
|  | 57 | constexpr const size_t reinitWaitSeconds = 2; | 
|  | 58 | std::string objectName; | 
|  | 59 | boost::container::flat_map<std::string, std::variant<std::string>> values; | 
|  | 60 | message.read(objectName, values); | 
|  | 61 |  | 
|  | 62 | auto findStatus = values.find(power::property); | 
|  | 63 | if (findStatus != values.end()) | 
|  | 64 | { | 
|  | 65 | bool powerStatus = | 
|  | 66 | std::get<std::string>(findStatus->second).ends_with(".Running"); | 
|  | 67 | if (powerStatus) | 
|  | 68 | { | 
|  | 69 | if (!initCmdTimer) | 
|  | 70 | { | 
|  | 71 | // this should be impossible | 
|  | 72 | return; | 
|  | 73 | } | 
|  | 74 | // we seem to send this command too fast sometimes, wait before | 
|  | 75 | // sending | 
|  | 76 | initCmdTimer->expires_after( | 
|  | 77 | std::chrono::seconds(reinitWaitSeconds)); | 
|  | 78 |  | 
|  | 79 | initCmdTimer->async_wait([](const boost::system::error_code ec) { | 
|  | 80 | if (ec == boost::asio::error::operation_aborted) | 
|  | 81 | { | 
|  | 82 | return; // we're being canceled | 
|  | 83 | } | 
|  | 84 |  | 
|  | 85 | for (const auto& [name, sensor] : sensors) | 
|  | 86 | { | 
|  | 87 | if (sensor) | 
|  | 88 | { | 
|  | 89 | sensor->runInitCmd(); | 
|  | 90 | } | 
|  | 91 | } | 
|  | 92 | }); | 
|  | 93 | } | 
|  | 94 | } | 
|  | 95 | } | 
|  | 96 |  | 
|  | 97 | int main() | 
|  | 98 | { | 
|  | 99 | boost::asio::io_context io; | 
|  | 100 | auto systemBus = std::make_shared<sdbusplus::asio::connection>(io); | 
|  | 101 | sdbusplus::asio::object_server objectServer(systemBus, true); | 
|  | 102 | objectServer.add_manager("/xyz/openbmc_project/sensors"); | 
|  | 103 | systemBus->request_name("xyz.openbmc_project.IpmbSensor"); | 
|  | 104 |  | 
|  | 105 | initCmdTimer = std::make_unique<boost::asio::steady_timer>(io); | 
|  | 106 |  | 
| Patrick Williams | 2aaf717 | 2024-08-16 15:20:40 -0400 | [diff] [blame] | 107 | boost::asio::post(io, [&]() { | 
|  | 108 | createSensors(io, objectServer, sensors, systemBus); | 
|  | 109 | }); | 
| Ed Tanous | 828c5a6 | 2024-02-09 16:59:22 -0800 | [diff] [blame] | 110 |  | 
|  | 111 | boost::asio::steady_timer configTimer(io); | 
|  | 112 |  | 
|  | 113 | std::function<void(sdbusplus::message_t&)> eventHandler = | 
|  | 114 | [&](sdbusplus::message_t&) { | 
| Patrick Williams | 2aaf717 | 2024-08-16 15:20:40 -0400 | [diff] [blame] | 115 | configTimer.expires_after(std::chrono::seconds(1)); | 
|  | 116 | // create a timer because normally multiple properties change | 
|  | 117 | configTimer.async_wait([&](const boost::system::error_code& ec) { | 
|  | 118 | if (ec == boost::asio::error::operation_aborted) | 
|  | 119 | { | 
|  | 120 | return; // we're being canceled | 
|  | 121 | } | 
|  | 122 | createSensors(io, objectServer, sensors, systemBus); | 
|  | 123 | if (sensors.empty()) | 
|  | 124 | { | 
| George Liu | 73f6cdc | 2025-02-20 15:15:19 +0800 | [diff] [blame] | 125 | lg2::info("Configuration not detected"); | 
| Patrick Williams | 2aaf717 | 2024-08-16 15:20:40 -0400 | [diff] [blame] | 126 | } | 
|  | 127 | }); | 
|  | 128 | }; | 
| Ed Tanous | 828c5a6 | 2024-02-09 16:59:22 -0800 | [diff] [blame] | 129 |  | 
|  | 130 | std::vector<std::unique_ptr<sdbusplus::bus::match_t>> matches = | 
|  | 131 | setupPropertiesChangedMatches( | 
|  | 132 | *systemBus, std::to_array<const char*>({sensorType}), eventHandler); | 
|  | 133 |  | 
|  | 134 | sdbusplus::bus::match_t powerChangeMatch( | 
|  | 135 | static_cast<sdbusplus::bus_t&>(*systemBus), | 
|  | 136 | "type='signal',interface='" + std::string(properties::interface) + | 
|  | 137 | "',path='" + std::string(power::path) + "',arg0='" + | 
|  | 138 | std::string(power::interface) + "'", | 
|  | 139 | reinitSensors); | 
|  | 140 |  | 
|  | 141 | auto matchSignal = std::make_shared<sdbusplus::bus::match_t>( | 
|  | 142 | static_cast<sdbusplus::bus_t&>(*systemBus), | 
|  | 143 | "type='signal',member='PropertiesChanged',path_namespace='" + | 
|  | 144 | std::string(inventoryPath) + "',arg0namespace='" + | 
|  | 145 | configInterfaceName(sdrInterface) + "'", | 
|  | 146 | [&systemBus](sdbusplus::message_t& msg) { | 
| Patrick Williams | 2aaf717 | 2024-08-16 15:20:40 -0400 | [diff] [blame] | 147 | sdrHandler(sdrsensor, msg, systemBus); | 
|  | 148 | }); | 
| Ed Tanous | 828c5a6 | 2024-02-09 16:59:22 -0800 | [diff] [blame] | 149 |  | 
|  | 150 | // Watch for entity-manager to remove configuration interfaces | 
|  | 151 | // so the corresponding sensors can be removed. | 
|  | 152 | auto ifaceRemovedMatch = std::make_shared<sdbusplus::bus::match_t>( | 
|  | 153 | static_cast<sdbusplus::bus_t&>(*systemBus), | 
|  | 154 | "type='signal',member='InterfacesRemoved',arg0path='" + | 
|  | 155 | std::string(inventoryPath) + "/'", | 
|  | 156 | [](sdbusplus::message_t& msg) { interfaceRemoved(msg, sensors); }); | 
|  | 157 |  | 
|  | 158 | setupManufacturingModeMatch(*systemBus); | 
|  | 159 | io.run(); | 
|  | 160 | return 0; | 
|  | 161 | } |