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