modbus_rtu_lib: define read holding register

Add the modbus rtu library commands with initial support for read
holding register. Define a base Message classes which all subsequent and
specific request & response messages can inherit from. Also add the
relevant unit testing for the added command set.

Tested:
```
> meson test -C builddir
ninja: Entering directory `/host/repos/Modbus/phosphor-modbus/builddir'
ninja: no work to do.
1/1 test_modbus_commands        OK              0.01s

Ok:                1
Fail:              0

```

Change-Id: I331b0dee66a0829e9352ae0eac8ac82a9150904c
Signed-off-by: Jagpal Singh Gill <paligill@gmail.com>
diff --git a/rtu/modbus/modbus_commands.hpp b/rtu/modbus/modbus_commands.hpp
new file mode 100644
index 0000000..117408b
--- /dev/null
+++ b/rtu/modbus/modbus_commands.hpp
@@ -0,0 +1,65 @@
+#pragma once
+
+#include "modbus_message.hpp"
+
+#include <vector>
+
+namespace phosphor::modbus::rtu
+{
+
+static constexpr uint8_t ReadHoldingRegistersFunctionCode = 0x03;
+
+class ReadHoldingRegistersRequest : public Message
+{
+  public:
+    ReadHoldingRegistersRequest() = delete;
+    ReadHoldingRegistersRequest(const ReadHoldingRegistersRequest&) = delete;
+    ReadHoldingRegistersRequest& operator=(const ReadHoldingRegistersRequest&) =
+        delete;
+    ReadHoldingRegistersRequest(ReadHoldingRegistersRequest&&) = delete;
+    ReadHoldingRegistersRequest& operator=(ReadHoldingRegistersRequest&&) =
+        delete;
+
+    explicit ReadHoldingRegistersRequest(
+        uint8_t deviceAddress, uint16_t registerOffset, uint16_t registerCount);
+
+    auto encode() -> void;
+
+  private:
+    static constexpr uint8_t commandCode = ReadHoldingRegistersFunctionCode;
+    const uint8_t deviceAddress;
+    const uint16_t registerOffset;
+    const uint16_t registerCount;
+};
+
+class Response : public Message
+{
+  public:
+    auto decode() -> void;
+};
+
+class ReadHoldingRegistersResponse : public Response
+{
+  public:
+    ReadHoldingRegistersResponse() = delete;
+    ReadHoldingRegistersResponse(const ReadHoldingRegistersResponse&) = delete;
+    ReadHoldingRegistersResponse& operator=(
+        const ReadHoldingRegistersResponse&) = delete;
+    ReadHoldingRegistersResponse(ReadHoldingRegistersResponse&&) = delete;
+    ReadHoldingRegistersResponse& operator=(ReadHoldingRegistersResponse&&) =
+        delete;
+
+    explicit ReadHoldingRegistersResponse(uint8_t deviceAddress,
+                                          std::vector<uint16_t>& registers);
+
+    auto decode() -> void;
+
+  private:
+    static constexpr uint8_t expectedCommandCode =
+        ReadHoldingRegistersFunctionCode;
+    const uint8_t expectedDeviceAddress;
+    // The returned response is stored in the registers vector
+    std::vector<uint16_t>& registers;
+};
+
+} // namespace phosphor::modbus::rtu