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