xref: /openbmc/phosphor-modbus/rtu/modbus/modbus_commands.cpp (revision 9695bd284570b51677c11529103929c8e51da6b6)
1 #include "modbus_commands.hpp"
2 
3 #include "modbus_exception.hpp"
4 
5 #include <phosphor-logging/lg2.hpp>
6 
7 namespace phosphor::modbus::rtu
8 {
9 
ReadHoldingRegistersRequest(uint8_t deviceAddress,uint16_t registerOffset,uint16_t registerCount)10 ReadHoldingRegistersRequest::ReadHoldingRegistersRequest(
11     uint8_t deviceAddress, uint16_t registerOffset, uint16_t registerCount) :
12     deviceAddress(deviceAddress), registerOffset(registerOffset),
13     registerCount(registerCount)
14 {}
15 
encode()16 auto ReadHoldingRegistersRequest::encode() -> void
17 {
18     *this << deviceAddress << commandCode << registerOffset << registerCount;
19     appendCRC();
20 }
21 
ReadHoldingRegistersResponse(uint8_t deviceAddress,std::vector<uint16_t> & registers)22 ReadHoldingRegistersResponse::ReadHoldingRegistersResponse(
23     uint8_t deviceAddress, std::vector<uint16_t>& registers) :
24     expectedDeviceAddress(deviceAddress), registers(registers)
25 {
26     if (registers.empty())
27     {
28         throw std::underflow_error("Response registers are empty");
29     }
30     // addr(1), func(1), bytecount(1), <2 * count regs>, crc(2)
31     len = 5 + (2 * registers.size());
32 }
33 
decode()34 auto Response::decode() -> void
35 {
36     validate();
37 
38     // Error response is structured as:
39     // addr(1), errorFunctionCode(1), exceptionCode(1)
40     // Where errorFunctionCode is the response function with
41     // MSB set to 1, hence mask of 0x80.
42     bool isError = (len == 3 && (functionCode & 0x80) != 0);
43     if (isError)
44     {
45         throw ModbusException(raw[2]);
46     }
47 }
48 
decode()49 auto ReadHoldingRegistersResponse::decode() -> void
50 {
51     Response::decode();
52     uint8_t byteCount, responseCode, deviceAddress;
53     *this >> registers >> byteCount >> responseCode >> deviceAddress;
54     verifyValue("Device Address", deviceAddress, expectedDeviceAddress);
55     verifyValue("Response Function Code", responseCode, expectedCommandCode);
56     verifyValue("Byte Count", byteCount, registers.size() * 2);
57 }
58 
59 } // namespace phosphor::modbus::rtu
60