blob: 6a30dabe803091a46e83fc75388b62fe9a9fe044 [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;
35};
36
37template <typename T>
38concept HasPropertiesMembers = requires(T properties) {
39 {
40 properties.name
41 } -> std::same_as<std::string&>;
42 {
43 properties.mode
44 } -> std::same_as<std::string&>;
45 {
46 properties.baud_rate
47 } -> std::same_as<uint64_t&>;
48 {
49 properties.rts_delay
50 } -> std::same_as<uint64_t&>;
51 };
52
53template <typename T>
54concept HasConfigMembers = requires(T config) {
55 { config.name } -> std::same_as<std::string&>;
56 { config.portMode } -> std::same_as<PortMode&>;
57 { config.baudRate } -> std::same_as<uint32_t&>;
58 { config.rtsDelay } -> std::same_as<uint16_t&>;
59 };
60
61template <HasConfigMembers BaseConfig, HasPropertiesMembers BaseProperties>
62auto updateBaseConfig(BaseConfig& config, const BaseProperties& properties)
63 -> bool
64{
65 PHOSPHOR_LOG2_USING;
66
67 config.name = properties.name;
68 config.baudRate = static_cast<uint32_t>(properties.baud_rate);
69 config.rtsDelay = static_cast<uint16_t>(properties.rts_delay);
70
71 for (const auto& [modeStr, portMode] : config::validPortModes)
72 {
73 if (modeStr == properties.mode)
74 {
75 config.portMode = portMode;
76 break;
77 }
78 }
79 if (config.portMode == PortMode::unknown)
80 {
81 error("Invalid port mode {PORT_MODE} for {NAME}", "PORT_MODE",
82 properties.mode, "NAME", properties.name);
83 return false;
84 }
85
86 debug("Base Port config: {NAME} {PORT_MODE} {BAUD_RATE} {RTS_DELAY}",
87 "NAME", config.name, "PORT_MODE", config.portMode, "BAUD_RATE",
88 config.baudRate, "RTS_DELAY", config.rtsDelay);
89
90 return true;
91}
92
93} // namespace config
94
95class BasePort
96{
97 public:
98 explicit BasePort(sdbusplus::async::context& ctx,
99 const config::Config& config,
100 const std::string& devicePath);
101
102 auto readHoldingRegisters(uint8_t deviceAddress, uint16_t registerOffset,
103 uint32_t baudRate, Parity parity,
104 std::vector<uint16_t>& registers)
105 -> sdbusplus::async::task<bool>;
106
107 private:
108 std::string name;
109 int fd = -1;
110 std::unique_ptr<ModbusIntf> modbus;
111 sdbusplus::async::mutex mutex;
112};
113
114} // namespace phosphor::modbus::rtu::port