From 8941a84ceeca75e25e393986f5b6633daaef6057 Mon Sep 17 00:00:00 2001 From: Stéphane Raimbault Date: Wed, 23 Oct 2013 23:33:36 +0200 Subject: [PATCH] Export Modbus function codes supported by libmodbus --- doc/modbus_send_raw_request.txt | 6 +++++- src/modbus-private.h | 14 -------------- src/modbus.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------------------------------- src/modbus.h | 16 +++++++++++++++- tests/unit-test-client.c | 13 +++++++++---- 5 files changed, 91 insertions(+), 78 deletions(-) diff --git a/doc/modbus_send_raw_request.txt b/doc/modbus_send_raw_request.txt index 0b884ed..0485533 100644 --- a/doc/modbus_send_raw_request.txt +++ b/doc/modbus_send_raw_request.txt @@ -21,6 +21,10 @@ message, the header or CRC of the selected backend, so 'raw_req' must start and contain at least a slave/unit identifier and a function code. This function can be used to send request not handled by the library. +The public header of libmodbus provides a list of supported Modbus functions +codes, prefixed by `MODBUS_FC_` (eg. MODBUS_FC_READ_HOLDING_REGISTERS), to help +build of raw requests. + RETURN VALUE ------------ @@ -35,7 +39,7 @@ EXAMPLE ------------------- modbus_t *ctx; /* Read 5 holding registers from address 1 */ -uint8_t raw_req[] = { 0xFF, 0x03, 0x00, 0x01, 0x0, 0x05 }; +uint8_t raw_req[] = { 0xFF, MODBUS_FC_READ_HOLDING_REGISTERS, 0x00, 0x01, 0x0, 0x05 }; int req_length; uint8_t rsp[MODBUS_TCP_MAX_ADU_LENGTH]; diff --git a/src/modbus-private.h b/src/modbus-private.h index 4f84745..9f986da 100644 --- a/src/modbus-private.h +++ b/src/modbus-private.h @@ -51,20 +51,6 @@ MODBUS_BEGIN_DECLS #define _RESPONSE_TIMEOUT 500000 #define _BYTE_TIMEOUT 500000 -/* Function codes */ -#define _FC_READ_COILS 0x01 -#define _FC_READ_DISCRETE_INPUTS 0x02 -#define _FC_READ_HOLDING_REGISTERS 0x03 -#define _FC_READ_INPUT_REGISTERS 0x04 -#define _FC_WRITE_SINGLE_COIL 0x05 -#define _FC_WRITE_SINGLE_REGISTER 0x06 -#define _FC_READ_EXCEPTION_STATUS 0x07 -#define _FC_WRITE_MULTIPLE_COILS 0x0F -#define _FC_WRITE_MULTIPLE_REGISTERS 0x10 -#define _FC_REPORT_SLAVE_ID 0x11 -#define _FC_MASK_WRITE_REGISTER 0x16 -#define _FC_WRITE_AND_READ_REGISTERS 0x17 - typedef enum { _MODBUS_BACKEND_TYPE_RTU=0, _MODBUS_BACKEND_TYPE_TCP diff --git a/src/modbus.c b/src/modbus.c index 88be932..d2f2a96 100644 --- a/src/modbus.c +++ b/src/modbus.c @@ -141,27 +141,27 @@ static unsigned int compute_response_length_from_request(modbus_t *ctx, uint8_t const int offset = ctx->backend->header_length; switch (req[offset]) { - case _FC_READ_COILS: - case _FC_READ_DISCRETE_INPUTS: { + case MODBUS_FC_READ_COILS: + case MODBUS_FC_READ_DISCRETE_INPUTS: { /* Header + nb values (code from write_bits) */ int nb = (req[offset + 3] << 8) | req[offset + 4]; length = 2 + (nb / 8) + ((nb % 8) ? 1 : 0); } break; - case _FC_WRITE_AND_READ_REGISTERS: - case _FC_READ_HOLDING_REGISTERS: - case _FC_READ_INPUT_REGISTERS: + case MODBUS_FC_WRITE_AND_READ_REGISTERS: + case MODBUS_FC_READ_HOLDING_REGISTERS: + case MODBUS_FC_READ_INPUT_REGISTERS: /* Header + 2 * nb values */ length = 2 + 2 * (req[offset + 3] << 8 | req[offset + 4]); break; - case _FC_READ_EXCEPTION_STATUS: + case MODBUS_FC_READ_EXCEPTION_STATUS: length = 3; break; - case _FC_REPORT_SLAVE_ID: + case MODBUS_FC_REPORT_SLAVE_ID: /* The response is device specific (the header provides the length) */ return MSG_LENGTH_UNDEFINED; - case _FC_MASK_WRITE_REGISTER: + case MODBUS_FC_MASK_WRITE_REGISTER: length = 7; break; default: @@ -262,29 +262,29 @@ static uint8_t compute_meta_length_after_function(int function, int length; if (msg_type == MSG_INDICATION) { - if (function <= _FC_WRITE_SINGLE_REGISTER) { + if (function <= MODBUS_FC_WRITE_SINGLE_REGISTER) { length = 4; - } else if (function == _FC_WRITE_MULTIPLE_COILS || - function == _FC_WRITE_MULTIPLE_REGISTERS) { + } else if (function == MODBUS_FC_WRITE_MULTIPLE_COILS || + function == MODBUS_FC_WRITE_MULTIPLE_REGISTERS) { length = 5; - } else if (function == _FC_MASK_WRITE_REGISTER) { + } else if (function == MODBUS_FC_MASK_WRITE_REGISTER) { length = 6; - } else if (function == _FC_WRITE_AND_READ_REGISTERS) { + } else if (function == MODBUS_FC_WRITE_AND_READ_REGISTERS) { length = 9; } else { - /* _FC_READ_EXCEPTION_STATUS, _FC_REPORT_SLAVE_ID */ + /* MODBUS_FC_READ_EXCEPTION_STATUS, MODBUS_FC_REPORT_SLAVE_ID */ length = 0; } } else { /* MSG_CONFIRMATION */ switch (function) { - case _FC_WRITE_SINGLE_COIL: - case _FC_WRITE_SINGLE_REGISTER: - case _FC_WRITE_MULTIPLE_COILS: - case _FC_WRITE_MULTIPLE_REGISTERS: + case MODBUS_FC_WRITE_SINGLE_COIL: + case MODBUS_FC_WRITE_SINGLE_REGISTER: + case MODBUS_FC_WRITE_MULTIPLE_COILS: + case MODBUS_FC_WRITE_MULTIPLE_REGISTERS: length = 4; break; - case _FC_MASK_WRITE_REGISTER: + case MODBUS_FC_MASK_WRITE_REGISTER: length = 6; break; default: @@ -304,11 +304,11 @@ static int compute_data_length_after_meta(modbus_t *ctx, uint8_t *msg, if (msg_type == MSG_INDICATION) { switch (function) { - case _FC_WRITE_MULTIPLE_COILS: - case _FC_WRITE_MULTIPLE_REGISTERS: + case MODBUS_FC_WRITE_MULTIPLE_COILS: + case MODBUS_FC_WRITE_MULTIPLE_REGISTERS: length = msg[ctx->backend->header_length + 5]; break; - case _FC_WRITE_AND_READ_REGISTERS: + case MODBUS_FC_WRITE_AND_READ_REGISTERS: length = msg[ctx->backend->header_length + 9]; break; default: @@ -316,9 +316,9 @@ static int compute_data_length_after_meta(modbus_t *ctx, uint8_t *msg, } } else { /* MSG_CONFIRMATION */ - if (function <= _FC_READ_INPUT_REGISTERS || - function == _FC_REPORT_SLAVE_ID || - function == _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; @@ -570,8 +570,8 @@ static int check_confirmation(modbus_t *ctx, uint8_t *req, /* Check the number of values is corresponding to the request */ switch (function) { - case _FC_READ_COILS: - case _FC_READ_DISCRETE_INPUTS: + case MODBUS_FC_READ_COILS: + case MODBUS_FC_READ_DISCRETE_INPUTS: /* Read functions, 8 values in a byte (nb * of values in the request and byte count in * the response. */ @@ -579,20 +579,20 @@ static int check_confirmation(modbus_t *ctx, uint8_t *req, req_nb_value = (req_nb_value / 8) + ((req_nb_value % 8) ? 1 : 0); rsp_nb_value = rsp[offset + 1]; break; - case _FC_WRITE_AND_READ_REGISTERS: - case _FC_READ_HOLDING_REGISTERS: - case _FC_READ_INPUT_REGISTERS: + case MODBUS_FC_WRITE_AND_READ_REGISTERS: + case MODBUS_FC_READ_HOLDING_REGISTERS: + case MODBUS_FC_READ_INPUT_REGISTERS: /* Read functions 1 value = 2 bytes */ req_nb_value = (req[offset + 3] << 8) + req[offset + 4]; rsp_nb_value = (rsp[offset + 1] / 2); break; - case _FC_WRITE_MULTIPLE_COILS: - case _FC_WRITE_MULTIPLE_REGISTERS: + case MODBUS_FC_WRITE_MULTIPLE_COILS: + case MODBUS_FC_WRITE_MULTIPLE_REGISTERS: /* N Write functions */ req_nb_value = (req[offset + 3] << 8) + req[offset + 4]; rsp_nb_value = (rsp[offset + 3] << 8) | rsp[offset + 4]; break; - case _FC_REPORT_SLAVE_ID: + case MODBUS_FC_REPORT_SLAVE_ID: /* Report slave ID (bytes received) */ req_nb_value = rsp_nb_value = rsp[offset + 1]; break; @@ -703,7 +703,7 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, sft.t_id = ctx->backend->prepare_response_tid(req, &req_length); switch (function) { - case _FC_READ_COILS: { + case MODBUS_FC_READ_COILS: { int nb = (req[offset + 3] << 8) + req[offset + 4]; if (nb < 1 || MODBUS_MAX_READ_BITS < nb) { @@ -732,7 +732,7 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, } } break; - case _FC_READ_DISCRETE_INPUTS: { + case MODBUS_FC_READ_DISCRETE_INPUTS: { /* Similar to coil status (but too many arguments to use a * function) */ int nb = (req[offset + 3] << 8) + req[offset + 4]; @@ -763,7 +763,7 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, } } break; - case _FC_READ_HOLDING_REGISTERS: { + case MODBUS_FC_READ_HOLDING_REGISTERS: { int nb = (req[offset + 3] << 8) + req[offset + 4]; if (nb < 1 || MODBUS_MAX_READ_REGISTERS < nb) { @@ -795,7 +795,7 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, } } break; - case _FC_READ_INPUT_REGISTERS: { + case MODBUS_FC_READ_INPUT_REGISTERS: { /* Similar to holding registers (but too many arguments to use a * function) */ int nb = (req[offset + 3] << 8) + req[offset + 4]; @@ -829,7 +829,7 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, } } break; - case _FC_WRITE_SINGLE_COIL: + case MODBUS_FC_WRITE_SINGLE_COIL: if (address >= mb_mapping->nb_bits) { if (ctx->debug) { fprintf(stderr, @@ -858,7 +858,7 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, } } break; - case _FC_WRITE_SINGLE_REGISTER: + case MODBUS_FC_WRITE_SINGLE_REGISTER: if (address >= mb_mapping->nb_registers) { if (ctx->debug) { fprintf(stderr, "Illegal data address %0X in write_register\n", @@ -875,7 +875,7 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, rsp_length = req_length; } break; - case _FC_WRITE_MULTIPLE_COILS: { + case MODBUS_FC_WRITE_MULTIPLE_COILS: { int nb = (req[offset + 3] << 8) + req[offset + 4]; if ((address + nb) > mb_mapping->nb_bits) { @@ -897,7 +897,7 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, } } break; - case _FC_WRITE_MULTIPLE_REGISTERS: { + case MODBUS_FC_WRITE_MULTIPLE_REGISTERS: { int nb = (req[offset + 3] << 8) + req[offset + 4]; if ((address + nb) > mb_mapping->nb_registers) { @@ -923,7 +923,7 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, } } break; - case _FC_REPORT_SLAVE_ID: { + case MODBUS_FC_REPORT_SLAVE_ID: { int str_len; int byte_count_pos; @@ -940,14 +940,14 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, rsp[byte_count_pos] = rsp_length - byte_count_pos - 1; } break; - case _FC_READ_EXCEPTION_STATUS: + case MODBUS_FC_READ_EXCEPTION_STATUS: if (ctx->debug) { fprintf(stderr, "FIXME Not implemented\n"); } errno = ENOPROTOOPT; return -1; break; - case _FC_MASK_WRITE_REGISTER: + case MODBUS_FC_MASK_WRITE_REGISTER: if (address >= mb_mapping->nb_registers) { if (ctx->debug) { fprintf(stderr, "Illegal data address %0X in write_register\n", @@ -967,7 +967,7 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, rsp_length = req_length; } break; - case _FC_WRITE_AND_READ_REGISTERS: { + case MODBUS_FC_WRITE_AND_READ_REGISTERS: { int nb = (req[offset + 3] << 8) + req[offset + 4]; uint16_t address_write = (req[offset + 5] << 8) + req[offset + 6]; int nb_write = (req[offset + 7] << 8) + req[offset + 8]; @@ -1121,7 +1121,7 @@ int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest) return -1; } - rc = read_io_status(ctx, _FC_READ_COILS, addr, nb, dest); + rc = read_io_status(ctx, MODBUS_FC_READ_COILS, addr, nb, dest); if (rc == -1) return -1; @@ -1150,7 +1150,7 @@ int modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest) return -1; } - rc = read_io_status(ctx, _FC_READ_DISCRETE_INPUTS, addr, nb, dest); + rc = read_io_status(ctx, MODBUS_FC_READ_DISCRETE_INPUTS, addr, nb, dest); if (rc == -1) return -1; @@ -1225,7 +1225,7 @@ int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest) return -1; } - status = read_registers(ctx, _FC_READ_HOLDING_REGISTERS, + status = read_registers(ctx, MODBUS_FC_READ_HOLDING_REGISTERS, addr, nb, dest); return status; } @@ -1249,7 +1249,7 @@ int modbus_read_input_registers(modbus_t *ctx, int addr, int nb, return -1; } - status = read_registers(ctx, _FC_READ_INPUT_REGISTERS, + status = read_registers(ctx, MODBUS_FC_READ_INPUT_REGISTERS, addr, nb, dest); return status; @@ -1293,7 +1293,7 @@ int modbus_write_bit(modbus_t *ctx, int addr, int status) return -1; } - return write_single(ctx, _FC_WRITE_SINGLE_COIL, addr, + return write_single(ctx, MODBUS_FC_WRITE_SINGLE_COIL, addr, status ? 0xFF00 : 0); } @@ -1305,7 +1305,7 @@ int modbus_write_register(modbus_t *ctx, int addr, int value) return -1; } - return write_single(ctx, _FC_WRITE_SINGLE_REGISTER, addr, value); + return write_single(ctx, MODBUS_FC_WRITE_SINGLE_REGISTER, addr, value); } /* Write the bits of the array in the remote device */ @@ -1334,7 +1334,7 @@ int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *src) } req_length = ctx->backend->build_request_basis(ctx, - _FC_WRITE_MULTIPLE_COILS, + MODBUS_FC_WRITE_MULTIPLE_COILS, addr, nb, req); byte_count = (nb / 8) + ((nb % 8) ? 1 : 0); req[req_length++] = byte_count; @@ -1396,7 +1396,7 @@ int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *src) } req_length = ctx->backend->build_request_basis(ctx, - _FC_WRITE_MULTIPLE_REGISTERS, + MODBUS_FC_WRITE_MULTIPLE_REGISTERS, addr, nb, req); byte_count = nb * 2; req[req_length++] = byte_count; @@ -1426,7 +1426,9 @@ int modbus_mask_write_register(modbus_t *ctx, int addr, uint16_t and_mask, uint1 int req_length; uint8_t req[_MIN_REQ_LENGTH]; - req_length = ctx->backend->build_request_basis(ctx, _FC_MASK_WRITE_REGISTER, addr, 0, req); + req_length = ctx->backend->build_request_basis(ctx, + MODBUS_FC_MASK_WRITE_REGISTER, + addr, 0, req); /* HACKISH, count is not used */ req_length -=2; @@ -1454,8 +1456,10 @@ int modbus_mask_write_register(modbus_t *ctx, int addr, uint16_t and_mask, uint1 /* Write multiple registers from src array to remote device and read multiple registers from remote device to dest array. */ int modbus_write_and_read_registers(modbus_t *ctx, - int write_addr, int write_nb, const uint16_t *src, - int read_addr, int read_nb, uint16_t *dest) + int write_addr, int write_nb, + const uint16_t *src, + int read_addr, int read_nb, + uint16_t *dest) { int rc; @@ -1490,7 +1494,7 @@ int modbus_write_and_read_registers(modbus_t *ctx, return -1; } req_length = ctx->backend->build_request_basis(ctx, - _FC_WRITE_AND_READ_REGISTERS, + MODBUS_FC_WRITE_AND_READ_REGISTERS, read_addr, read_nb, req); req[req_length++] = write_addr >> 8; @@ -1541,7 +1545,7 @@ int modbus_report_slave_id(modbus_t *ctx, uint8_t *dest) return -1; } - req_length = ctx->backend->build_request_basis(ctx, _FC_REPORT_SLAVE_ID, + req_length = ctx->backend->build_request_basis(ctx, MODBUS_FC_REPORT_SLAVE_ID, 0, 0, req); /* HACKISH, addr and count are not used */ diff --git a/src/modbus.h b/src/modbus.h index 1fb3591..6fc705c 100644 --- a/src/modbus.h +++ b/src/modbus.h @@ -1,5 +1,5 @@ /* - * Copyright © 2001-2011 Stéphane Raimbault + * Copyright © 2001-2013 Stéphane Raimbault * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -71,6 +71,20 @@ MODBUS_BEGIN_DECLS #define ON 1 #endif +/* Modbus function codes */ +#define MODBUS_FC_READ_COILS 0x01 +#define MODBUS_FC_READ_DISCRETE_INPUTS 0x02 +#define MODBUS_FC_READ_HOLDING_REGISTERS 0x03 +#define MODBUS_FC_READ_INPUT_REGISTERS 0x04 +#define MODBUS_FC_WRITE_SINGLE_COIL 0x05 +#define MODBUS_FC_WRITE_SINGLE_REGISTER 0x06 +#define MODBUS_FC_READ_EXCEPTION_STATUS 0x07 +#define MODBUS_FC_WRITE_MULTIPLE_COILS 0x0F +#define MODBUS_FC_WRITE_MULTIPLE_REGISTERS 0x10 +#define MODBUS_FC_REPORT_SLAVE_ID 0x11 +#define MODBUS_FC_MASK_WRITE_REGISTER 0x16 +#define MODBUS_FC_WRITE_AND_READ_REGISTERS 0x17 + #define MODBUS_BROADCAST_ADDRESS 0 /* Modbus_Application_Protocol_V1_1b.pdf (chapter 6 section 1 page 12) diff --git a/tests/unit-test-client.c b/tests/unit-test-client.c index f80e7b0..efa5901 100644 --- a/tests/unit-test-client.c +++ b/tests/unit-test-client.c @@ -728,14 +728,14 @@ int test_raw_request(modbus_t *ctx, int use_backend) /* slave */ (use_backend == RTU) ? SERVER_ID : 0xFF, /* function, addr 1, 5 values */ - 0x03, 0x00, 0x01, 0x0, 0x05, + MODBUS_FC_READ_HOLDING_REGISTERS, 0x00, 0x01, 0x0, 0x05, }; /* Write and read registers request */ uint8_t raw_rw_req[] = { /* slave */ (use_backend == RTU) ? SERVER_ID : 0xFF, /* function, addr to read, nb to read */ - 0x17, + MODBUS_FC_WRITE_AND_READ_REGISTERS, /* Read */ 0, 0, (MODBUS_MAX_WR_READ_REGISTERS + 1) >> 8, @@ -751,7 +751,12 @@ int test_raw_request(modbus_t *ctx, int use_backend) /* See issue #143, test with MAX_WR_WRITE_REGISTERS */ int req_length; uint8_t rsp[MODBUS_TCP_MAX_ADU_LENGTH]; - int tab_function[] = {0x01, 0x02, 0x03, 0x04}; + int tab_function[] = { + MODBUS_FC_READ_COILS, + MODBUS_FC_READ_DISCRETE_INPUTS, + MODBUS_FC_READ_HOLDING_REGISTERS, + MODBUS_FC_READ_INPUT_REGISTERS + }; int tab_nb_max[] = { MODBUS_MAX_READ_BITS + 1, MODBUS_MAX_READ_BITS + 1, @@ -835,7 +840,7 @@ int test_raw_request(modbus_t *ctx, int use_backend) /* Modbus write and read multiple registers */ i = 0; - tab_function[i] = 0x17; + tab_function[i] = MODBUS_FC_WRITE_AND_READ_REGISTERS; for (j=0; j<2; j++) { if (j == 0) { /* Try to read zero values on first iteration */ -- libgit2 0.21.4