blob: 762607618282e20c2471fda0ee3db8e45d2864cc [file] [log] [blame]
#include "device_firmware.hpp"
#include "device/base_device.hpp"
#include <phosphor-logging/lg2.hpp>
namespace phosphor::modbus::rtu::device
{
PHOSPHOR_LOG2_USING;
static auto getRandomId() -> long int
{
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
unsigned int seed = ts.tv_nsec ^ getpid();
srandom(seed);
return random() % 10000;
}
static auto getObjectPath(const config_intf::Config& config)
-> sdbusplus::message::object_path
{
for (const auto& firmwareRegister : config.firmwareRegisters)
{
if (firmwareRegister.type == config_intf::FirmwareRegisterType::version)
{
if (firmwareRegister.name.empty())
{
return sdbusplus::message::object_path(
FirmwareIntf::namespace_path) /
std::format("{}_{}", config.name, getRandomId());
}
else
{
return sdbusplus::message::object_path(
FirmwareIntf::namespace_path) /
std::format("{}_{}_{}", config.name,
firmwareRegister.name, getRandomId());
}
}
}
throw std::runtime_error(
"No firmware version register found for " + config.name);
}
constexpr FirmwareIntf::Version::properties_t initVersion{
"Unknown", FirmwareIntf::VersionPurpose::Other};
constexpr FirmwareIntf::Activation::properties_t initActivation{
FirmwareIntf::Activations::NotReady,
FirmwareIntf::RequestedActivations::None};
constexpr FirmwareIntf::Definitions::properties_t initAssociations{};
DeviceFirmware::DeviceFirmware(sdbusplus::async::context& ctx,
const config_intf::Config& config,
PortIntf& serialPort) :
objectPath(getObjectPath(config)),
currentFirmware(
std::make_unique<FirmwareIntf>(ctx, objectPath.str.c_str(), initVersion,
initActivation, initAssociations)),
config(config), serialPort(serialPort)
{
currentFirmware->Version::emit_added();
currentFirmware->Activation::emit_added();
currentFirmware->Definitions::emit_added();
info("Device firmware {NAME} created successfully", "NAME", config.name);
}
auto DeviceFirmware::readVersionRegister() -> sdbusplus::async::task<void>
{
const auto it = std::find_if(
config.firmwareRegisters.begin(), config.firmwareRegisters.end(),
[](const config_intf::FirmwareRegister& firmwareRegister) {
return firmwareRegister.type ==
config_intf::FirmwareRegisterType::version;
});
if (it == config.firmwareRegisters.end())
{
error("No firmware version register found for {NAME}", "NAME",
config.name);
co_return;
}
const config_intf::FirmwareRegister& versionRegister = *it;
auto registers = std::vector<uint16_t>(versionRegister.size);
auto ret = co_await serialPort.readHoldingRegisters(
config.address, versionRegister.offset, config.baudRate, config.parity,
registers);
if (!ret)
{
error("Failed to read holding registers {NAME} for {DEVICE_ADDRESS}",
"NAME", versionRegister.name, "DEVICE_ADDRESS", config.address);
co_return;
}
std::string strValue = "";
for (const auto& value : registers)
{
strValue += static_cast<char>((value >> 8) & 0xFF);
strValue += static_cast<char>(value & 0xFF);
}
currentFirmware->version(strValue);
currentFirmware->activation(FirmwareIntf::Activation::Activations::Active);
auto associationList =
std::vector<std::tuple<std::string, std::string, std::string>>{
{"running", "ran_on", config.inventoryPath}};
currentFirmware->associations(associationList);
info("Firmware version {VERSION} for {NAME} at {DEVICE_ADDRESS}", "VERSION",
strValue, "NAME", config.name, "DEVICE_ADDRESS", config.address);
}
} // namespace phosphor::modbus::rtu::device