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