blob: b4ca052f497bc5ccc72ebd51d1ae538fece60c06 [file] [log] [blame]
#pragma once
#include "modbus/modbus.hpp"
#include <phosphor-logging/lg2.hpp>
#include <sdbusplus/async.hpp>
#include <xyz/openbmc_project/Configuration/USBPort/client.hpp>
#include <concepts>
namespace phosphor::modbus::rtu::port
{
using ModbusIntf = phosphor::modbus::rtu::Modbus;
namespace config
{
enum class PortMode
{
rs232,
rs485,
unknown
};
static constexpr std::array<std::pair<std::string_view, PortMode>, 2>
validPortModes = {{{"RS232", PortMode::rs232}, {"RS485", PortMode::rs485}}};
struct Config
{
std::string name = "unknown";
PortMode portMode = PortMode::unknown;
uint32_t baudRate = 0;
uint16_t rtsDelay = 0;
virtual ~Config() = default;
};
template <typename T>
concept HasPropertiesMembers = requires(T properties) {
{
properties.name
} -> std::same_as<std::string&>;
{
properties.mode
} -> std::same_as<std::string&>;
{
properties.baud_rate
} -> std::same_as<uint64_t&>;
{
properties.rts_delay
} -> std::same_as<uint64_t&>;
};
template <typename T>
concept HasConfigMembers = requires(T config) {
{ config.name } -> std::same_as<std::string&>;
{ config.portMode } -> std::same_as<PortMode&>;
{ config.baudRate } -> std::same_as<uint32_t&>;
{ config.rtsDelay } -> std::same_as<uint16_t&>;
};
template <HasConfigMembers BaseConfig, HasPropertiesMembers BaseProperties>
auto updateBaseConfig(BaseConfig& config, const BaseProperties& properties)
-> bool
{
PHOSPHOR_LOG2_USING;
config.name = properties.name;
config.baudRate = static_cast<uint32_t>(properties.baud_rate);
config.rtsDelay = static_cast<uint16_t>(properties.rts_delay);
for (const auto& [modeStr, portMode] : config::validPortModes)
{
if (modeStr == properties.mode)
{
config.portMode = portMode;
break;
}
}
if (config.portMode == PortMode::unknown)
{
error("Invalid port mode {PORT_MODE} for {NAME}", "PORT_MODE",
properties.mode, "NAME", properties.name);
return false;
}
debug("Base Port config: {NAME} {PORT_MODE} {BAUD_RATE} {RTS_DELAY}",
"NAME", config.name, "PORT_MODE", config.portMode, "BAUD_RATE",
config.baudRate, "RTS_DELAY", config.rtsDelay);
return true;
}
} // namespace config
class BasePort
{
public:
explicit BasePort(sdbusplus::async::context& ctx,
const config::Config& config,
const std::string& devicePath);
auto readHoldingRegisters(uint8_t deviceAddress, uint16_t registerOffset,
uint32_t baudRate, Parity parity,
std::vector<uint16_t>& registers)
-> sdbusplus::async::task<bool>;
private:
std::string name;
int fd = -1;
std::unique_ptr<ModbusIntf> modbus;
sdbusplus::async::mutex mutex;
};
} // namespace phosphor::modbus::rtu::port