modbus_rtu_lib: implement library APIs

Implement modbus-rtu library APIs which will be used by
phosphor-modbus-rtu service based on [1].

[1]: https://gerrit.openbmc.org/c/openbmc/docs/+/77318

Tested:
Added a Mock Modbus RTU server using socat which intercepts and replies
to modbus messages for testing.
```
> meson test -C builddir
ninja: Entering directory `/host/repos/Modbus/phosphor-modbus/builddir'
ninja: no work to do.
1/2 test_modbus_commands        OK              0.01s
2/2 test_modbus                 OK              6.02s

Ok:                2
Fail:              0
```

Change-Id: I66cdc8fd930dd6f7ad6888116d1419ad8f8b8ed8
Signed-off-by: Jagpal Singh Gill <paligill@gmail.com>
diff --git a/rtu/modbus/modbus.hpp b/rtu/modbus/modbus.hpp
new file mode 100644
index 0000000..d26bed9
--- /dev/null
+++ b/rtu/modbus/modbus.hpp
@@ -0,0 +1,46 @@
+#pragma once
+
+#include <sdbusplus/async.hpp>
+
+namespace phosphor::modbus::rtu
+{
+
+class Message;
+
+enum class Parity
+{
+    odd,
+    even,
+    none,
+    unknown
+};
+
+class Modbus
+{
+  public:
+    explicit Modbus(sdbusplus::async::context& ctx, int fd, uint32_t baudRate,
+                    uint16_t rtsDelay);
+
+    auto setProperties(uint32_t inBaudRate, Parity inParity) -> bool;
+
+    auto readHoldingRegisters(uint8_t deviceAddress, uint16_t registerOffset,
+                              std::vector<uint16_t>& registers)
+        -> sdbusplus::async::task<bool>;
+
+  private:
+    auto writeRequest(uint8_t deviceAddress, Message& request)
+        -> sdbusplus::async::task<bool>;
+
+    auto readResponse(uint8_t deviceAddress, Message& response,
+                      uint8_t expectedResponseCode)
+        -> sdbusplus::async::task<bool>;
+
+    sdbusplus::async::context& ctx;
+    int fd;
+    uint16_t rtsDelay;
+    uint32_t baudRate = 0;
+    Parity parity = Parity::odd;
+    sdbusplus::async::fdio fdioInstance;
+};
+
+} // namespace phosphor::modbus::rtu