1*cf77ef54SJagpal Singh Gill #include "device_firmware.hpp"
2*cf77ef54SJagpal Singh Gill
3*cf77ef54SJagpal Singh Gill #include "device/base_device.hpp"
4*cf77ef54SJagpal Singh Gill
5*cf77ef54SJagpal Singh Gill #include <phosphor-logging/lg2.hpp>
6*cf77ef54SJagpal Singh Gill
7*cf77ef54SJagpal Singh Gill namespace phosphor::modbus::rtu::device
8*cf77ef54SJagpal Singh Gill {
9*cf77ef54SJagpal Singh Gill
10*cf77ef54SJagpal Singh Gill PHOSPHOR_LOG2_USING;
11*cf77ef54SJagpal Singh Gill
getRandomId()12*cf77ef54SJagpal Singh Gill static auto getRandomId() -> long int
13*cf77ef54SJagpal Singh Gill {
14*cf77ef54SJagpal Singh Gill struct timespec ts;
15*cf77ef54SJagpal Singh Gill clock_gettime(CLOCK_REALTIME, &ts);
16*cf77ef54SJagpal Singh Gill unsigned int seed = ts.tv_nsec ^ getpid();
17*cf77ef54SJagpal Singh Gill srandom(seed);
18*cf77ef54SJagpal Singh Gill return random() % 10000;
19*cf77ef54SJagpal Singh Gill }
20*cf77ef54SJagpal Singh Gill
getObjectPath(const config_intf::Config & config)21*cf77ef54SJagpal Singh Gill static auto getObjectPath(const config_intf::Config& config)
22*cf77ef54SJagpal Singh Gill -> sdbusplus::message::object_path
23*cf77ef54SJagpal Singh Gill {
24*cf77ef54SJagpal Singh Gill for (const auto& firmwareRegister : config.firmwareRegisters)
25*cf77ef54SJagpal Singh Gill {
26*cf77ef54SJagpal Singh Gill if (firmwareRegister.type == config_intf::FirmwareRegisterType::version)
27*cf77ef54SJagpal Singh Gill {
28*cf77ef54SJagpal Singh Gill if (firmwareRegister.name.empty())
29*cf77ef54SJagpal Singh Gill {
30*cf77ef54SJagpal Singh Gill return sdbusplus::message::object_path(
31*cf77ef54SJagpal Singh Gill FirmwareIntf::namespace_path) /
32*cf77ef54SJagpal Singh Gill std::format("{}_{}", config.name, getRandomId());
33*cf77ef54SJagpal Singh Gill }
34*cf77ef54SJagpal Singh Gill else
35*cf77ef54SJagpal Singh Gill {
36*cf77ef54SJagpal Singh Gill return sdbusplus::message::object_path(
37*cf77ef54SJagpal Singh Gill FirmwareIntf::namespace_path) /
38*cf77ef54SJagpal Singh Gill std::format("{}_{}_{}", config.name,
39*cf77ef54SJagpal Singh Gill firmwareRegister.name, getRandomId());
40*cf77ef54SJagpal Singh Gill }
41*cf77ef54SJagpal Singh Gill }
42*cf77ef54SJagpal Singh Gill }
43*cf77ef54SJagpal Singh Gill
44*cf77ef54SJagpal Singh Gill throw std::runtime_error(
45*cf77ef54SJagpal Singh Gill "No firmware version register found for " + config.name);
46*cf77ef54SJagpal Singh Gill }
47*cf77ef54SJagpal Singh Gill
48*cf77ef54SJagpal Singh Gill constexpr FirmwareIntf::Version::properties_t initVersion{
49*cf77ef54SJagpal Singh Gill "Unknown", FirmwareIntf::VersionPurpose::Other};
50*cf77ef54SJagpal Singh Gill constexpr FirmwareIntf::Activation::properties_t initActivation{
51*cf77ef54SJagpal Singh Gill FirmwareIntf::Activations::NotReady,
52*cf77ef54SJagpal Singh Gill FirmwareIntf::RequestedActivations::None};
53*cf77ef54SJagpal Singh Gill constexpr FirmwareIntf::Definitions::properties_t initAssociations{};
54*cf77ef54SJagpal Singh Gill
DeviceFirmware(sdbusplus::async::context & ctx,const config_intf::Config & config,PortIntf & serialPort)55*cf77ef54SJagpal Singh Gill DeviceFirmware::DeviceFirmware(sdbusplus::async::context& ctx,
56*cf77ef54SJagpal Singh Gill const config_intf::Config& config,
57*cf77ef54SJagpal Singh Gill PortIntf& serialPort) :
58*cf77ef54SJagpal Singh Gill objectPath(getObjectPath(config)),
59*cf77ef54SJagpal Singh Gill currentFirmware(
60*cf77ef54SJagpal Singh Gill std::make_unique<FirmwareIntf>(ctx, objectPath.str.c_str(), initVersion,
61*cf77ef54SJagpal Singh Gill initActivation, initAssociations)),
62*cf77ef54SJagpal Singh Gill config(config), serialPort(serialPort)
63*cf77ef54SJagpal Singh Gill {
64*cf77ef54SJagpal Singh Gill currentFirmware->Version::emit_added();
65*cf77ef54SJagpal Singh Gill currentFirmware->Activation::emit_added();
66*cf77ef54SJagpal Singh Gill currentFirmware->Definitions::emit_added();
67*cf77ef54SJagpal Singh Gill
68*cf77ef54SJagpal Singh Gill info("Device firmware {NAME} created successfully", "NAME", config.name);
69*cf77ef54SJagpal Singh Gill }
70*cf77ef54SJagpal Singh Gill
readVersionRegister()71*cf77ef54SJagpal Singh Gill auto DeviceFirmware::readVersionRegister() -> sdbusplus::async::task<void>
72*cf77ef54SJagpal Singh Gill {
73*cf77ef54SJagpal Singh Gill const auto it = std::find_if(
74*cf77ef54SJagpal Singh Gill config.firmwareRegisters.begin(), config.firmwareRegisters.end(),
75*cf77ef54SJagpal Singh Gill [](const config_intf::FirmwareRegister& firmwareRegister) {
76*cf77ef54SJagpal Singh Gill return firmwareRegister.type ==
77*cf77ef54SJagpal Singh Gill config_intf::FirmwareRegisterType::version;
78*cf77ef54SJagpal Singh Gill });
79*cf77ef54SJagpal Singh Gill
80*cf77ef54SJagpal Singh Gill if (it == config.firmwareRegisters.end())
81*cf77ef54SJagpal Singh Gill {
82*cf77ef54SJagpal Singh Gill error("No firmware version register found for {NAME}", "NAME",
83*cf77ef54SJagpal Singh Gill config.name);
84*cf77ef54SJagpal Singh Gill co_return;
85*cf77ef54SJagpal Singh Gill }
86*cf77ef54SJagpal Singh Gill
87*cf77ef54SJagpal Singh Gill const config_intf::FirmwareRegister& versionRegister = *it;
88*cf77ef54SJagpal Singh Gill
89*cf77ef54SJagpal Singh Gill auto registers = std::vector<uint16_t>(versionRegister.size);
90*cf77ef54SJagpal Singh Gill auto ret = co_await serialPort.readHoldingRegisters(
91*cf77ef54SJagpal Singh Gill config.address, versionRegister.offset, config.baudRate, config.parity,
92*cf77ef54SJagpal Singh Gill registers);
93*cf77ef54SJagpal Singh Gill if (!ret)
94*cf77ef54SJagpal Singh Gill {
95*cf77ef54SJagpal Singh Gill error("Failed to read holding registers {NAME} for {DEVICE_ADDRESS}",
96*cf77ef54SJagpal Singh Gill "NAME", versionRegister.name, "DEVICE_ADDRESS", config.address);
97*cf77ef54SJagpal Singh Gill co_return;
98*cf77ef54SJagpal Singh Gill }
99*cf77ef54SJagpal Singh Gill
100*cf77ef54SJagpal Singh Gill std::string strValue = "";
101*cf77ef54SJagpal Singh Gill
102*cf77ef54SJagpal Singh Gill for (const auto& value : registers)
103*cf77ef54SJagpal Singh Gill {
104*cf77ef54SJagpal Singh Gill strValue += static_cast<char>((value >> 8) & 0xFF);
105*cf77ef54SJagpal Singh Gill strValue += static_cast<char>(value & 0xFF);
106*cf77ef54SJagpal Singh Gill }
107*cf77ef54SJagpal Singh Gill
108*cf77ef54SJagpal Singh Gill currentFirmware->version(strValue);
109*cf77ef54SJagpal Singh Gill currentFirmware->activation(FirmwareIntf::Activation::Activations::Active);
110*cf77ef54SJagpal Singh Gill auto associationList =
111*cf77ef54SJagpal Singh Gill std::vector<std::tuple<std::string, std::string, std::string>>{
112*cf77ef54SJagpal Singh Gill {"running", "ran_on", config.inventoryPath}};
113*cf77ef54SJagpal Singh Gill currentFirmware->associations(associationList);
114*cf77ef54SJagpal Singh Gill
115*cf77ef54SJagpal Singh Gill info("Firmware version {VERSION} for {NAME} at {DEVICE_ADDRESS}", "VERSION",
116*cf77ef54SJagpal Singh Gill strValue, "NAME", config.name, "DEVICE_ADDRESS", config.address);
117*cf77ef54SJagpal Singh Gill }
118*cf77ef54SJagpal Singh Gill
119*cf77ef54SJagpal Singh Gill } // namespace phosphor::modbus::rtu::device
120