|
|
|
@ -40,15 +40,44 @@ ModbusError_t mb_handleRequest( |
|
|
|
|
size_t *resp_size |
|
|
|
|
) |
|
|
|
|
{ |
|
|
|
|
uint16_t txn_id, msglen, protocol_id, ref, count, ref2, count2, value, and_mask, or_mask; |
|
|
|
|
uint16_t txn_id, protocol_id, ref; |
|
|
|
|
|
|
|
|
|
#ifdef MB_SUPPORT_FC22 |
|
|
|
|
uint16_t and_mask, or_mask; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#ifdef MB_SUPPORT_FC23 |
|
|
|
|
uint16_t ref2, count2; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#if defined(MB_SUPPORT_FC01) || defined(MB_SUPPORT_FC02) |
|
|
|
|
bool bvalue; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#if defined(MB_SUPPORT_FC03) || defined(MB_SUPPORT_FC04) \ |
|
|
|
|
|| defined(MB_SUPPORT_FC16) || defined(MB_SUPPORT_FC22) || defined(MB_SUPPORT_FC23) \
|
|
|
|
|
|| defined(MB_SUPPORT_FC05) || defined(MB_SUPPORT_FC06) |
|
|
|
|
uint16_t value; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#if defined(MB_SUPPORT_FC01) || defined(MB_SUPPORT_FC02) || defined(MB_SUPPORT_FC15) |
|
|
|
|
uint8_t scratch, bytecount, bitcnt; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#if defined(MB_SUPPORT_FC01) || defined(MB_SUPPORT_FC02) || defined(MB_SUPPORT_FC03) \ |
|
|
|
|
|| defined(MB_SUPPORT_FC04) || defined(MB_SUPPORT_FC15) || defined(MB_SUPPORT_FC16) \
|
|
|
|
|
|| defined(MB_SUPPORT_FC23) |
|
|
|
|
uint16_t count; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
ModbusException_t exc = MB_EXCEPTION_OK; |
|
|
|
|
size_t numbytes; |
|
|
|
|
uint8_t fcx, bytecount, bitcnt, scratch; |
|
|
|
|
uint8_t fcx; |
|
|
|
|
|
|
|
|
|
const size_t TCP_RESP_OVERHEAD = 8; |
|
|
|
|
const size_t RTU_RESP_OVERHEAD = 4; |
|
|
|
|
const size_t overhead = ms->proto == MB_PROTO_TCP ? TCP_RESP_OVERHEAD : RTU_RESP_OVERHEAD; |
|
|
|
|
pb_mark_t resp_fc_mark, resp_len_mark, resp_pld_start_mark; |
|
|
|
|
pb_mark_t resp_fc_mark = NULL, resp_len_mark = NULL, resp_pld_start_mark = NULL; |
|
|
|
|
|
|
|
|
|
const bool tcp = ms->proto == MB_PROTO_TCP; |
|
|
|
|
PayloadParser pp = pp_start_be(req, req_size, NULL); |
|
|
|
@ -58,12 +87,11 @@ ModbusError_t mb_handleRequest( |
|
|
|
|
/* Parse header */ |
|
|
|
|
txn_id = pp_u16(&pp); |
|
|
|
|
protocol_id = pp_u16(&pp); |
|
|
|
|
msglen = pp_u16(&pp); |
|
|
|
|
pp_skip(&pp, 2); // msglen
|
|
|
|
|
if (protocol_id != 0) { |
|
|
|
|
return MB_ERR_BADPROTO; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
msglen = req_size; |
|
|
|
|
/* check CRC */ |
|
|
|
|
uint16_t crc = crc16_init(); |
|
|
|
|
for (int pos = 0; pos < req_size /* size of CRC */; pos++) { |
|
|
|
@ -108,6 +136,7 @@ ModbusError_t mb_handleRequest( |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
switch (fcx) { |
|
|
|
|
#ifdef MB_SUPPORT_FC05 |
|
|
|
|
case FC05_WRITE_SINGLE_COIL: |
|
|
|
|
if (!ms->writeCoil) { |
|
|
|
|
exc = MB_EXCEPTION_ILLEGAL_FUNCTION; |
|
|
|
@ -133,17 +162,24 @@ ModbusError_t mb_handleRequest( |
|
|
|
|
pb_u16(&pb, ref); |
|
|
|
|
pb_u16(&pb, value); |
|
|
|
|
break; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#if defined(MB_SUPPORT_FC01) || defined(MB_SUPPORT_FC02) |
|
|
|
|
case FC01_READ_COILS: |
|
|
|
|
case FC02_READ_DISCRETES: |
|
|
|
|
/* check we have the needed function */ |
|
|
|
|
#ifdef MB_SUPPORT_FC01 |
|
|
|
|
if (fcx == FC01_READ_COILS && !ms->readCoil) { |
|
|
|
|
exc = MB_EXCEPTION_ILLEGAL_FUNCTION; |
|
|
|
|
goto exception; |
|
|
|
|
} else if (!ms->readDiscrete) { |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
#ifdef MB_SUPPORT_FC02 |
|
|
|
|
if (fcx == FC02_READ_DISCRETES && !ms->readDiscrete) { |
|
|
|
|
exc = MB_EXCEPTION_ILLEGAL_FUNCTION; |
|
|
|
|
goto exception; |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
ref = pp_u16(&pp); |
|
|
|
|
count = pp_u16(&pp); |
|
|
|
|
if (!pp_ok(&pp)) { |
|
|
|
@ -158,11 +194,16 @@ ModbusError_t mb_handleRequest( |
|
|
|
|
bitcnt = 0; |
|
|
|
|
scratch = 0; |
|
|
|
|
while (count-- > 0) { |
|
|
|
|
#ifdef MB_SUPPORT_FC01 |
|
|
|
|
if (fcx == FC01_READ_COILS) { |
|
|
|
|
exc = ms->readCoil(ms, ref++, &bvalue); |
|
|
|
|
} else { |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
#ifdef MB_SUPPORT_FC02 |
|
|
|
|
if (fcx == FC02_READ_DISCRETES) { |
|
|
|
|
exc = ms->readDiscrete(ms, ref++, &bvalue); |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
if (exc != 0) { |
|
|
|
|
goto exception; |
|
|
|
|
} |
|
|
|
@ -178,18 +219,24 @@ ModbusError_t mb_handleRequest( |
|
|
|
|
pb_u8(&pb, scratch); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#if defined(MB_SUPPORT_FC03) || defined(MB_SUPPORT_FC04) |
|
|
|
|
case FC03_READ_HOLDING_REGISTERS: |
|
|
|
|
case FC04_READ_INPUT_REGISTERS: |
|
|
|
|
#ifdef MB_SUPPORT_FC03 |
|
|
|
|
/* check we have the needed function */ |
|
|
|
|
if (fcx == FC03_READ_HOLDING_REGISTERS && !ms->readHolding) { |
|
|
|
|
exc = MB_EXCEPTION_ILLEGAL_FUNCTION; |
|
|
|
|
goto exception; |
|
|
|
|
} else if (!ms->readInput) { |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
#ifdef MB_SUPPORT_FC04 |
|
|
|
|
if (fcx == FC04_READ_INPUT_REGISTERS && !ms->readInput) { |
|
|
|
|
exc = MB_EXCEPTION_ILLEGAL_FUNCTION; |
|
|
|
|
goto exception; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#endif |
|
|
|
|
ref = pp_u16(&pp); |
|
|
|
|
count = pp_u16(&pp); |
|
|
|
|
if (!pp_ok(&pp)) { |
|
|
|
@ -201,18 +248,25 @@ ModbusError_t mb_handleRequest( |
|
|
|
|
} |
|
|
|
|
pb_u8(&pb, count*2); |
|
|
|
|
while (count-- > 0) { |
|
|
|
|
#ifdef MB_SUPPORT_FC03 |
|
|
|
|
if (fcx == FC03_READ_HOLDING_REGISTERS) { |
|
|
|
|
exc = ms->readHolding(ms, ref++, &value); |
|
|
|
|
} else { |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
#ifdef MB_SUPPORT_FC04 |
|
|
|
|
if (fcx == FC04_READ_INPUT_REGISTERS) { |
|
|
|
|
exc = ms->readInput(ms, ref++, &value); |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
if (exc != 0) { |
|
|
|
|
goto exception; |
|
|
|
|
} |
|
|
|
|
pb_u16(&pb, value); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#ifdef MB_SUPPORT_FC06 |
|
|
|
|
case FC06_WRITE_SINGLE_REGISTER: |
|
|
|
|
if (!ms->writeHolding) { |
|
|
|
|
exc = MB_EXCEPTION_ILLEGAL_FUNCTION; |
|
|
|
@ -234,7 +288,9 @@ ModbusError_t mb_handleRequest( |
|
|
|
|
pb_u16(&pb, ref); |
|
|
|
|
pb_u16(&pb, value); |
|
|
|
|
break; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#ifdef MB_SUPPORT_FC16 |
|
|
|
|
case FC16_WRITE_MULTIPLE_REGISTERS: |
|
|
|
|
if (!ms->writeHolding) { |
|
|
|
|
exc = MB_EXCEPTION_ILLEGAL_FUNCTION; |
|
|
|
@ -263,7 +319,9 @@ ModbusError_t mb_handleRequest( |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#ifdef MB_SUPPORT_FC15 |
|
|
|
|
case FC15_WRITE_MULTIPLE_COILS: |
|
|
|
|
if (!ms->writeCoil) { |
|
|
|
|
exc = MB_EXCEPTION_ILLEGAL_FUNCTION; |
|
|
|
@ -298,7 +356,9 @@ ModbusError_t mb_handleRequest( |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#ifdef MB_SUPPORT_FC22 |
|
|
|
|
case FC22_MASK_WRITE_REGISTER: |
|
|
|
|
if (!ms->writeHolding || !ms->readHolding) { |
|
|
|
|
exc = MB_EXCEPTION_ILLEGAL_FUNCTION; |
|
|
|
@ -329,7 +389,9 @@ ModbusError_t mb_handleRequest( |
|
|
|
|
pb_u16(&pb, and_mask); |
|
|
|
|
pb_u16(&pb, or_mask); |
|
|
|
|
break; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#ifdef MB_SUPPORT_FC23 |
|
|
|
|
case FC23_READ_WRITE_MULTIPLE_REGISTERS: |
|
|
|
|
if (!ms->writeHolding || !ms->readHolding) { |
|
|
|
|
exc = MB_EXCEPTION_ILLEGAL_FUNCTION; |
|
|
|
@ -370,6 +432,7 @@ ModbusError_t mb_handleRequest( |
|
|
|
|
pb_u16(&pb, value); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
exc = MB_EXCEPTION_ILLEGAL_FUNCTION; |
|
|
|
@ -386,7 +449,6 @@ ModbusError_t mb_handleRequest( |
|
|
|
|
checksum: |
|
|
|
|
numbytes = pb_length(&pb); |
|
|
|
|
if (tcp) { |
|
|
|
|
pb_mark_t end = pb_save(&pb); |
|
|
|
|
pb_restore(&pb, resp_len_mark); |
|
|
|
|
pb_u16(&pb, numbytes - 6); |
|
|
|
|
*resp_size = numbytes; |
|
|
|
|