1 #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 11 namespace phosphor::modbus::rtu::port 12 { 13 14 using ModbusIntf = phosphor::modbus::rtu::Modbus; 15 16 namespace config 17 { 18 19 enum class PortMode 20 { 21 rs232, 22 rs485, 23 unknown 24 }; 25 26 static constexpr std::array<std::pair<std::string_view, PortMode>, 2> 27 validPortModes = {{{"RS232", PortMode::rs232}, {"RS485", PortMode::rs485}}}; 28 29 struct Config 30 { 31 std::string name = "unknown"; 32 PortMode portMode = PortMode::unknown; 33 uint32_t baudRate = 0; 34 uint16_t rtsDelay = 0; 35 }; 36 37 template <typename T> 38 concept 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 53 template <typename T> 54 concept 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 61 template <HasConfigMembers BaseConfig, HasPropertiesMembers BaseProperties> 62 auto 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 95 class 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 115