diff --git a/src/modbus-private.h b/src/modbus-private.h index 198baeffd..6fdb72542 100644 --- a/src/modbus-private.h +++ b/src/modbus-private.h @@ -92,6 +92,8 @@ typedef struct _modbus_backend { struct _modbus { /* Slave address */ int slave; + /* used only in user-defined functions */ + int wanted_resp_data_length; /* Socket or file descriptor */ int s; int debug; diff --git a/src/modbus-rtu.c b/src/modbus-rtu.c index 56c812ca3..b9dbe3394 100644 --- a/src/modbus-rtu.c +++ b/src/modbus-rtu.c @@ -911,11 +911,11 @@ int modbus_rtu_set_serial_mode(modbus_t *ctx, int mode) struct serial_rs485 rs485conf; if (mode == MODBUS_RTU_RS485) { - // Get + /* Get */ if (ioctl(ctx->s, TIOCGRS485, &rs485conf) < 0) { return -1; } - // Set + /* Set */ rs485conf.flags |= SER_RS485_ENABLED; if (ioctl(ctx->s, TIOCSRS485, &rs485conf) < 0) { return -1; diff --git a/src/modbus.c b/src/modbus.c index 41a421359..38fe14f7e 100644 --- a/src/modbus.c +++ b/src/modbus.c @@ -207,7 +207,8 @@ static int send_msg(modbus_t *ctx, uint8_t *msg, int msg_length) return rc; } -int modbus_send_raw_request(modbus_t *ctx, const uint8_t *raw_req, int raw_req_length) +int modbus_send_generic_request(modbus_t *ctx, + const uint8_t *raw_req, int raw_req_length, int wanted_resp_data_length) { sft_t sft; uint8_t req[MAX_MESSAGE_LENGTH]; @@ -226,10 +227,14 @@ int modbus_send_raw_request(modbus_t *ctx, const uint8_t *raw_req, int raw_req_l return -1; } - sft.slave = raw_req[0]; + ctx->wanted_resp_data_length = wanted_resp_data_length; + + sft.slave = raw_req[0]; sft.function = raw_req[1]; + /* The t_id is left to zero */ sft.t_id = 0; + /* This response function only set the header so it's convenient here */ req_length = ctx->backend->build_response_basis(&sft, req); @@ -242,6 +247,18 @@ int modbus_send_raw_request(modbus_t *ctx, const uint8_t *raw_req, int raw_req_l return send_msg(ctx, req, req_length); } +int modbus_send_raw_request(modbus_t *ctx, const uint8_t *raw_req, int raw_req_length) +{ + /* The wanted_resp_data_length is set to zero (cause used only in user-defined functions) */ + return modbus_send_generic_request(ctx, raw_req, raw_req_length, 0); +} + +static uint_fast8_t is_users_function(int function) +{ + return ((function >= MODBUS_FC_USERS_RANGE1_LO && function <= MODBUS_FC_USERS_RANGE1_HI) || + (function >= MODBUS_FC_USERS_RANGE2_LO && function <= MODBUS_FC_USERS_RANGE2_HI)); +} + /* * ---------- Request Indication ---------- * | Client | ---------------------->| Server | @@ -270,19 +287,17 @@ static uint8_t compute_meta_length_after_function(int function, } } else { /* MSG_CONFIRMATION */ - switch (function) { - case MODBUS_FC_WRITE_SINGLE_COIL: - case MODBUS_FC_WRITE_SINGLE_REGISTER: - case MODBUS_FC_WRITE_MULTIPLE_COILS: - case MODBUS_FC_WRITE_MULTIPLE_REGISTERS: + if ((function == MODBUS_FC_WRITE_SINGLE_COIL) || + (function == MODBUS_FC_WRITE_SINGLE_REGISTER) || + (function == MODBUS_FC_WRITE_MULTIPLE_COILS) || + (function == MODBUS_FC_WRITE_MULTIPLE_REGISTERS)) length = 4; - break; - case MODBUS_FC_MASK_WRITE_REGISTER: + else if (function == MODBUS_FC_MASK_WRITE_REGISTER) length = 6; - break; - default: + else if (is_users_function(function)) + length = 0; + else length = 1; - } } return length; @@ -293,7 +308,7 @@ static int compute_data_length_after_meta(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) { int function = msg[ctx->backend->header_length]; - int length; + int length = 0; if (msg_type == MSG_INDICATION) { switch (function) { @@ -304,18 +319,15 @@ static int compute_data_length_after_meta(modbus_t *ctx, uint8_t *msg, case MODBUS_FC_WRITE_AND_READ_REGISTERS: length = msg[ctx->backend->header_length + 9]; break; - default: - length = 0; } } else { /* MSG_CONFIRMATION */ - if (function <= MODBUS_FC_READ_INPUT_REGISTERS || - function == MODBUS_FC_REPORT_SLAVE_ID || - function == MODBUS_FC_WRITE_AND_READ_REGISTERS) { + if ( function <= MODBUS_FC_READ_INPUT_REGISTERS || + function == MODBUS_FC_REPORT_SLAVE_ID || + function == MODBUS_FC_WRITE_AND_READ_REGISTERS ) length = msg[ctx->backend->header_length + 1]; - } else { - length = 0; - } + else if (is_users_function(function)) + length = ctx->wanted_resp_data_length; } length += ctx->backend->checksum_length; diff --git a/src/modbus.h b/src/modbus.h index c63f5ceb4..5a031bdb2 100644 --- a/src/modbus.h +++ b/src/modbus.h @@ -71,6 +71,11 @@ MODBUS_BEGIN_DECLS #define MODBUS_FC_MASK_WRITE_REGISTER 0x16 #define MODBUS_FC_WRITE_AND_READ_REGISTERS 0x17 +#define MODBUS_FC_USERS_RANGE1_LO 0x41 /* 65-72 */ +#define MODBUS_FC_USERS_RANGE1_HI 0x48 +#define MODBUS_FC_USERS_RANGE2_LO 0x64 /* 100-110 */ +#define MODBUS_FC_USERS_RANGE2_HI 0x6E + #define MODBUS_BROADCAST_ADDRESS 0 /* Modbus_Application_Protocol_V1_1b.pdf (chapter 6 section 1 page 12) @@ -227,6 +232,9 @@ MODBUS_API modbus_mapping_t* modbus_mapping_new(int nb_bits, int nb_input_bits, int nb_registers, int nb_input_registers); MODBUS_API void modbus_mapping_free(modbus_mapping_t *mb_mapping); +MODBUS_API int modbus_send_generic_request(modbus_t *ctx, + const uint8_t *raw_req, int raw_req_length, int wanted_resp_data_length); + MODBUS_API int modbus_send_raw_request(modbus_t *ctx, const uint8_t *raw_req, int raw_req_length); MODBUS_API int modbus_receive(modbus_t *ctx, uint8_t *req);