blob: b4ca052f497bc5ccc72ebd51d1ae538fece60c06 [file] [log] [blame]
Jagpal Singh Gill7f9d41d2025-10-16 09:42:18 -07001#pragma once
2
3#include "modbus/modbus.hpp"
4
5#include <phosphor-logging/lg2.hpp>
6#include <sdbusplus/async.hpp>
7#include <xyz/openbmc_project/Configuration/USBPort/client.hpp>
8
9#include <concepts>
10
11namespace phosphor::modbus::rtu::port
12{
13
14using ModbusIntf = phosphor::modbus::rtu::Modbus;
15
16namespace config
17{
18
19enum class PortMode
20{
21 rs232,
22 rs485,
23 unknown
24};
25
26static constexpr std::array<std::pair<std::string_view, PortMode>, 2>
27 validPortModes = {{{"RS232", PortMode::rs232}, {"RS485", PortMode::rs485}}};
28
29struct Config
30{
31 std::string name = "unknown";
32 PortMode portMode = PortMode::unknown;
33 uint32_t baudRate = 0;
34 uint16_t rtsDelay = 0;
Jagpal Singh Gillb62e3df2025-10-22 18:10:40 -070035
36 virtual ~Config() = default;
Jagpal Singh Gill7f9d41d2025-10-16 09:42:18 -070037};
38
39template <typename T>
40concept HasPropertiesMembers = requires(T properties) {
41 {
42 properties.name
43 } -> std::same_as<std::string&>;
44 {
45 properties.mode
46 } -> std::same_as<std::string&>;
47 {
48 properties.baud_rate
49 } -> std::same_as<uint64_t&>;
50 {
51 properties.rts_delay
52 } -> std::same_as<uint64_t&>;
53 };
54
55template <typename T>
56concept HasConfigMembers = requires(T config) {
57 { config.name } -> std::same_as<std::string&>;
58 { config.portMode } -> std::same_as<PortMode&>;
59 { config.baudRate } -> std::same_as<uint32_t&>;
60 { config.rtsDelay } -> std::same_as<uint16_t&>;
61 };
62
63template <HasConfigMembers BaseConfig, HasPropertiesMembers BaseProperties>
64auto updateBaseConfig(BaseConfig& config, const BaseProperties& properties)
65 -> bool
66{
67 PHOSPHOR_LOG2_USING;
68
69 config.name = properties.name;
70 config.baudRate = static_cast<uint32_t>(properties.baud_rate);
71 config.rtsDelay = static_cast<uint16_t>(properties.rts_delay);
72
73 for (const auto& [modeStr, portMode] : config::validPortModes)
74 {
75 if (modeStr == properties.mode)
76 {
77 config.portMode = portMode;
78 break;
79 }
80 }
81 if (config.portMode == PortMode::unknown)
82 {
83 error("Invalid port mode {PORT_MODE} for {NAME}", "PORT_MODE",
84 properties.mode, "NAME", properties.name);
85 return false;
86 }
87
88 debug("Base Port config: {NAME} {PORT_MODE} {BAUD_RATE} {RTS_DELAY}",
89 "NAME", config.name, "PORT_MODE", config.portMode, "BAUD_RATE",
90 config.baudRate, "RTS_DELAY", config.rtsDelay);
91
92 return true;
93}
94
95} // namespace config
96
97class BasePort
98{
99 public:
100 explicit BasePort(sdbusplus::async::context& ctx,
101 const config::Config& config,
102 const std::string& devicePath);
103
104 auto readHoldingRegisters(uint8_t deviceAddress, uint16_t registerOffset,
105 uint32_t baudRate, Parity parity,
106 std::vector<uint16_t>& registers)
107 -> sdbusplus::async::task<bool>;
108
109 private:
110 std::string name;
111 int fd = -1;
112 std::unique_ptr<ModbusIntf> modbus;
113 sdbusplus::async::mutex mutex;
114};
115
116} // namespace phosphor::modbus::rtu::port