From 1a0c8f993015bb589a8c9853b2a87dfb03c76f60 Mon Sep 17 00:00:00 2001 From: oliver Date: Mon, 30 Oct 2017 21:32:39 +0100 Subject: [PATCH 1/2] Added 0x14 and 0x15 for File-access. Extended interface with two new functions, to make them useable Added documentation for new functions. Cleaned up indention --- doc/modbus_mapping_new_extend.txt | 63 +++ ...odbus_mapping_new_start_address_extend.txt | 81 ++++ doc/modbus_read_general_reference.txt | 84 ++++ doc/modbus_write_general_reference.txt | 80 ++++ src/modbus-private.h | 3 + src/modbus.c | 375 +++++++++++++++++- src/modbus.h | 18 + tests/unit-test-client.c | 121 +++++- tests/unit-test-server.c | 25 +- tests/unit-test.h.in | 6 + 10 files changed, 846 insertions(+), 10 deletions(-) create mode 100644 doc/modbus_mapping_new_extend.txt create mode 100644 doc/modbus_mapping_new_start_address_extend.txt create mode 100644 doc/modbus_read_general_reference.txt create mode 100644 doc/modbus_write_general_reference.txt diff --git a/doc/modbus_mapping_new_extend.txt b/doc/modbus_mapping_new_extend.txt new file mode 100644 index 000000000..c10cb6b64 --- /dev/null +++ b/doc/modbus_mapping_new_extend.txt @@ -0,0 +1,63 @@ +modbus_mapping_new_extend(3) +===================== + + +NAME +---- +modbus_mapping_new_extend - allocate four arrays of bits and registers and file registers + + +SYNOPSIS +-------- +*modbus_mapping_t* modbus_mapping_new_extend(int 'nb_bits', int 'nb_input_bits', int 'nb_registers', int 'nb_input_registers', uint16_t nb_file_register[MODBUS_MAX_REFERENCE_FILES]);* + + +DESCRIPTION +----------- +The *modbus_mapping_new_extend()* calls linkmb:modbus_mapping_new[3] and additionally allocates up to +MODBUS_MAX_REFERENCE_FILES (current specification limit it to 10) arrays for file registers. + +Each _value_ in the array, which is not 0 allocates _value_ registers in the file of _index_ -1 . +( The file registers start with "1" for the first file ) + +RETURN VALUE +------------ +The function shall return the new allocated structure if successful. Otherwise +it shall return NULL and set errno. + + +ERRORS +------ +*ENOMEM*:: +Not enough memory + + +EXAMPLE +------- +[source,c] +------------------- +/* The first value of each array is accessible from the 0 address. */ +mb_mapping = modbus_mapping_new_extend(BITS_ADDRESS + BITS_NB, + INPUT_BITS_ADDRESS + INPUT_BITS_NB, + REGISTERS_ADDRESS + REGISTERS_NB, + INPUT_REGISTERS_ADDRESS + INPUT_REGISTERS_NB, + FILE_REGISTERS_NB[MODBUS_MAX_REFERENCE_FILES]); +if (mb_mapping == NULL) { + fprintf(stderr, "Failed to allocate the mapping: %s\n", + modbus_strerror(errno)); + modbus_free(ctx); + return -1; +} +------------------- + +SEE ALSO +-------- +linkmb:modbus_mapping_new[3] +linkmb:modbus_mapping_free[3] +linkmb:modbus_mapping_new_start_address[3] + + +AUTHORS +------- +The libmodbus documentation was written by Stéphane Raimbault + diff --git a/doc/modbus_mapping_new_start_address_extend.txt b/doc/modbus_mapping_new_start_address_extend.txt new file mode 100644 index 000000000..d63b31966 --- /dev/null +++ b/doc/modbus_mapping_new_start_address_extend.txt @@ -0,0 +1,81 @@ +modbus_mapping_new_start_address_extend(3) +=================================== + + +NAME +---- +modbus_mapping_new_start_address_extend - allocate four arrays of bits and registers accessible from their starting addresses and file registers + + +SYNOPSIS +-------- +*modbus_mapping_t* modbus_mapping_new_start_address(int 'start_bits', int 'nb_bits', + int 'start_input_bits', int 'nb_input_bits', + int 'start_registers', int 'nb_registers', + int 'start_input_registers', int 'nb_input_registers', + 'uint16_t nb_file_register[MODBUS_MAX_REFERENCE_FILES]');* + + +DESCRIPTION +----------- +The *modbus_mapping_new_extend()* calls linkmb:modbus_mapping_new_start_address[3] and additionally allocates up to +MODBUS_MAX_REFERENCE_FILES (current specification limit it to 10) arrays for file registers. + +Each _value_ in the array, which is not 0 allocates _value_ registers in the file of _index_ -1 . +( The file registers start with "1" for the first file ) + +[source,c] +------------------- +mb_mapping = modbus_mapping_new_start_address_extend(0, 0, 0, 0, 10000, 10, 0, 0,{0,100,0,20,0,0,10000,0,0,0,0}); +------------------- + +With this code, 3 file registers ( 2, 4 and 7 ) with the size of 100 , 20 and 10000 registers are allocated. + +If it isn't necessary to allocate an array for a specific type of data, you can +pass the zero value in argument, the associated pointer will be NULL. + +This function is convenient to handle requests in a Modbus server/slave. + + +RETURN VALUE +------------ +The _modbus_mapping_new_start_address_extend()_ function shall return the new allocated structure if +successful. Otherwise it shall return NULL and set errno. + + +ERRORS +------ +ENOMEM:: +Not enough memory + + +EXAMPLE +------- +[source,c] +------------------- +/* The first value of each array is accessible at the defined address. + The end address is ADDRESS + NB - 1. */ +mb_mapping = modbus_mapping_new_start_address_extend(BITS_ADDRESS, BITS_NB, + INPUT_BITS_ADDRESS, INPUT_BITS_NB, + REGISTERS_ADDRESS, REGISTERS_NB, + INPUT_REGISTERS_ADDRESS, INPUT_REGISTERS_NB, + FILE_REGISTERS_NB[MODBUS_MAX_REFERENCE_FILES]); +if (mb_mapping == NULL) { + fprintf(stderr, "Failed to allocate the mapping: %s\n", + modbus_strerror(errno)); + modbus_free(ctx); + return -1; +} +------------------- + +SEE ALSO +-------- +linkmb:modbus_mapping_new_start_address[3] +linkmb:modbus_mapping_new[3] +linkmb:modbus_mapping_free[3] + + +AUTHORS +------- +The libmodbus documentation was written by Stéphane Raimbault + diff --git a/doc/modbus_read_general_reference.txt b/doc/modbus_read_general_reference.txt new file mode 100644 index 000000000..c1ad58e6f --- /dev/null +++ b/doc/modbus_read_general_reference.txt @@ -0,0 +1,84 @@ +modbus_read_general_reference(3) +======================== + + +NAME +---- +modbus_read_general_reference - read from file registers + + +SYNOPSIS +-------- +*int modbus_read_general_reference(modbus_t *ctx, int file_no, int read_addr, int read_nb, uint16_t *dest);* + + +DESCRIPTION +----------- +The *modbus_read_general_reference()* function shall read the number of _read_nb_ registers of the _file_no_ +reference file at the address _read_addr_ of the remote device. The result of +reading is stored in _dest_ array as word values (16 bits). + +_file_no_ has to be >= 1 and <= 10 . + +You must take care to allocate enough memory to store the results in _dest_ +(at least (_read_nb_ + 1 ) * sizeof(uint16_t)). + +The function uses the Modbus function code 0x14 (read file record). + + +RETURN VALUE +------------ +The function shall return the number of read registers + 1 +if successful. Otherwise it shall return -1 and set errno. + + +ERRORS +------ +*EMBMDATA*:: +Too many registers requested +*EMBXILVAL*:: +_file_no_ out of range , or file is not found. + + +EXAMPLE +------- +[source,c] +------------------- +modbus_t *ctx; +uint16_t tab_reg[64+1]; // one additional reg for filesize and reftype +int rc; +int i; + +ctx = modbus_new_tcp("127.0.0.1", 1502); +if (modbus_connect(ctx) == -1) { + fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno)); + modbus_free(ctx); + return -1; +} + + rc = modbus_read_general_reference(ctx, 1, 10 , 64, tab_reg ); + if (rc == -1) { + fprintf(stderr, "%s\n", modbus_strerror(errno)); + return -1; +} + +printf("size=%d subtype_ref=%d\n", i, tab_reg[0]>>8, tab_reg[0] &0xff); +for (i=1; i < rc; i++) { + printf("reg[%d]=%d (0x%X)\n", i, tab_reg[i], tab_reg[i]); +} + +modbus_close(ctx); +modbus_free(ctx); +------------------- + + +SEE ALSO +-------- +linkmb:modbus_write_general_reference[3] +linkmb:modbus_mapping_new_start_address_extend[3] +linkmb:modbus_mapping_new_extend[3] + +AUTHORS +------- +The libmodbus documentation was written by Stéphane Raimbault + diff --git a/doc/modbus_write_general_reference.txt b/doc/modbus_write_general_reference.txt new file mode 100644 index 000000000..9d1fd28bc --- /dev/null +++ b/doc/modbus_write_general_reference.txt @@ -0,0 +1,80 @@ +modbus_write_general_reference(3) +======================== + + +NAME +---- +modbus_write_general_reference - write to file registers + + +SYNOPSIS +-------- +*int modbus_write_general_reference(modbus_t *ctx, int file_no, int write_addr, int write_nb, const uint16_t *src);* + + +DESCRIPTION +----------- +The *modbus_read_general_reference()* function shall write the number of _write_nb_ registers of the _file_no_ +reference file at the address _write_addr_ of the remote device. The content for +writing is delivered in _src_ array as word values (16 bits). + +_file_no_ has to be >= 1 and <= 10 . + + +The function uses the Modbus function code 0x15 (write file record). + + +RETURN VALUE +------------ +The function shall return the number of written registers + 1 +if successful. Otherwise it shall return -1 and set errno. + + +ERRORS +------ +*EMBMDATA*:: +Too many registers requested +*EMBXILVAL*:: +_file_no_ out of range , or file is not found. + + +EXAMPLE +------- +[source,c] +------------------- +modbus_t *ctx; +uint16_t tab_reg[64]; +int rc; +int i; + +ctx = modbus_new_tcp("127.0.0.1", 1502); +if (modbus_connect(ctx) == -1) { + fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno)); + modbus_free(ctx); + return -1; +} + +for (i=0; i < 64; i++){ + tab_reg[i]=i+i*0x100; +} + rc = modbus_write_general_reference(ctx, 1, 10 , 64, tab_reg ); + if (rc == -1) { + fprintf(stderr, "%s\n", modbus_strerror(errno)); + return -1; +} + +modbus_close(ctx); +modbus_free(ctx); +------------------- + + +SEE ALSO +-------- +linkmb:modbus_read_general_reference[3] +linkmb:modbus_mapping_new_start_address_extend[3] +linkmb:modbus_mapping_new_extend[3] + +AUTHORS +------- +The libmodbus documentation was written by Stéphane Raimbault + diff --git a/src/modbus-private.h b/src/modbus-private.h index 2c601c495..a945d38fa 100644 --- a/src/modbus-private.h +++ b/src/modbus-private.h @@ -39,6 +39,9 @@ MODBUS_BEGIN_DECLS #define _RESPONSE_TIMEOUT 500000 #define _BYTE_TIMEOUT 500000 +#define SUB_REQUEST_LENGHT 0x07 +#define SUB_REQUEST_REF_TYPE 0x06 // Reference-Type for General Reference Read + Write + typedef enum { _MODBUS_BACKEND_TYPE_RTU=0, _MODBUS_BACKEND_TYPE_TCP diff --git a/src/modbus.c b/src/modbus.c index 03d8da248..cca346ae6 100644 --- a/src/modbus.c +++ b/src/modbus.c @@ -152,6 +152,11 @@ static unsigned int compute_response_length_from_request(modbus_t *ctx, uint8_t /* The response is device specific (the header provides the length) */ return MSG_LENGTH_UNDEFINED; + case MODBUS_FC_WRITE_GENERAL_REFERENCE: + length= 2 + req[offset + 1]; + break; + case MODBUS_FC_READ_GENERAL_REFERENCE: + return MSG_LENGTH_UNDEFINED; // Lenght is dedepnding of the subrequests case MODBUS_FC_MASK_WRITE_REGISTER: length = 7; break; @@ -264,6 +269,9 @@ static uint8_t compute_meta_length_after_function(int function, length = 6; } else if (function == MODBUS_FC_WRITE_AND_READ_REGISTERS) { length = 9; + } else if (function == MODBUS_FC_READ_GENERAL_REFERENCE || + function == MODBUS_FC_WRITE_GENERAL_REFERENCE) { + length = 1; // After the function, the number of bytes is transmitted } else { /* MODBUS_FC_READ_EXCEPTION_STATUS, MODBUS_FC_REPORT_SLAVE_ID */ length = 0; @@ -280,7 +288,11 @@ static uint8_t compute_meta_length_after_function(int function, case MODBUS_FC_MASK_WRITE_REGISTER: length = 6; break; - default: + case MODBUS_FC_WRITE_GENERAL_REFERENCE: + case MODBUS_FC_READ_GENERAL_REFERENCE: + length = 1; // After the function, the number of bytes is transmitted and at least one SUB_REQUEST + break; + default: length = 1; } } @@ -304,6 +316,10 @@ 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; + case MODBUS_FC_WRITE_GENERAL_REFERENCE: + case MODBUS_FC_READ_GENERAL_REFERENCE: + length = msg[ctx->backend->header_length + 1]; + break; default: length = 0; } @@ -313,6 +329,9 @@ static int compute_data_length_after_meta(modbus_t *ctx, uint8_t *msg, function == MODBUS_FC_REPORT_SLAVE_ID || function == MODBUS_FC_WRITE_AND_READ_REGISTERS) { length = msg[ctx->backend->header_length + 1]; + } else if (function == MODBUS_FC_READ_GENERAL_REFERENCE || + function == MODBUS_FC_WRITE_GENERAL_REFERENCE) { + length = msg[ctx->backend->header_length + 1]; } else { length = 0; } @@ -596,6 +615,15 @@ static int check_confirmation(modbus_t *ctx, uint8_t *req, req_nb_value = (req[offset + 3] << 8) + req[offset + 4]; rsp_nb_value = (rsp[offset + 3] << 8) | rsp[offset + 4]; break; + case MODBUS_FC_WRITE_GENERAL_REFERENCE: + /* Check for Bytes recevied, response is copy of the request */ + req_nb_value = req[offset + 1]; + rsp_nb_value = rsp[offset + 1]; + break; + case MODBUS_FC_READ_GENERAL_REFERENCE: + /* Check for Bytes recevied */ + req_nb_value = rsp_nb_value = rsp[offset + 1]; + break; case MODBUS_FC_REPORT_SLAVE_ID: /* Report slave ID (bytes received) */ req_nb_value = rsp_nb_value = rsp[offset + 1]; @@ -986,7 +1014,148 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, } } } - break; + break; + case MODBUS_FC_WRITE_GENERAL_REFERENCE: { + // Each "Read_General_Reference", aka as "Read_File", can consists of several Subrequests + uint8_t nb = req[offset + 1]; + uint16_t i; + int nsr = 0; + uint8_t ref_type=0; + + /* Each Subrequest has at least 7 Bytes */ + if (nb < SUB_REQUEST_LENGHT ) { + rsp_length = response_exception( + ctx, &sft, + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp,TRUE, + "Illegal nb of subrequests %d in write_general_reference \n", nb); + break; + } + + + rsp_length = ctx->backend->build_response_basis(&sft, rsp); + if (rsp_length+nb >=MODBUS_MAX_READ_REGISTERS){ + rsp_length = response_exception( + ctx, &sft, + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp,TRUE, + "Responselenght exceeds telegram-size %d in subrequests %d in write_general_reference \n", + rsp_length+nb,nsr); + + }else { + /* Response is a simple copy of the request */ + memcpy(rsp + rsp_length, req + offset + 1 , 1 + nb ); // number of bytes + the place for the nb itself + rsp_length += nb + 1; + + do{ + offset +=2; + ref_type=req[offset]; + if (ref_type!=SUB_REQUEST_REF_TYPE){ + rsp_length = response_exception( + ctx, &sft, + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp, TRUE, + "Illegal reference Type %d in subrequests %d in write_general_reference \n", + ref_type,nsr); + }else{ + uint16_t file_no = (req[offset + 1] << 8) + req[offset + 2]; + uint16_t f_address = (req[offset + 3] << 8) + req[offset + 4]; + uint16_t nb_write = (req[offset + 5] << 8) + req[offset + 6]; + + offset+=SUB_REQUEST_LENGHT; + nb-=SUB_REQUEST_LENGHT; + + if ((file_no==0)||(file_no > MODBUS_MAX_REFERENCE_FILES)||(mb_mapping->file_registers[file_no-1]==NULL)){ + rsp_length = response_exception( + ctx, &sft, + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp,TRUE, + "Illegal parameter file %d in subrequests %d in write_general_reference \n", + file_no,nsr); + break; + }else { + /* Write Registers to file at position adress */ + for (i = f_address; i < f_address + nb_write; i++) { + mb_mapping->file_registers[file_no-1][i]=(req[offset] <<8) + req[offset+1]; + offset+=2; + nb-=2; + } + } + } + nsr++; + }while (nb>0); + } + } + break; + case MODBUS_FC_READ_GENERAL_REFERENCE: { + // Each "Read_General_Reference", aka as "Read_File", can consists of several Subrequests + uint8_t nb = req[offset + 1]; + uint16_t i; + int nsr = 0; + uint8_t ref_type=0; + int rsp_length_byte_count=0; + + /* Each Subrequest has 7 Bytes */ + if (nb % SUB_REQUEST_LENGHT != 0 ) { + rsp_length = response_exception( + ctx, &sft, + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp,TRUE, + "Illegal nb of subrequests %d in read_general_reference \n",nb); + break; + } + + + rsp_length = ctx->backend->build_response_basis(&sft, rsp); + + rsp_length_byte_count=rsp_length; // Place-holder of overall message-size. + rsp[rsp_length++]=0; + + do{ + offset +=2; + ref_type=req[offset]; + + if (ref_type!=SUB_REQUEST_REF_TYPE){ + rsp_length = response_exception( + ctx, &sft, + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp,TRUE, + "Illegal reference Type %d in subrequests %d in read_general_reference \n", + ref_type,nsr); + }else{ + uint16_t file_no = (req[offset + 1] << 8) + req[offset + 2]; + uint16_t f_address = (req[offset + 3] << 8) + req[offset + 4]; + uint16_t nb_read = (req[offset + 5] << 8) + req[offset + 6]; + + if ((file_no==0)||(file_no > MODBUS_MAX_REFERENCE_FILES)||(mb_mapping->file_registers[file_no-1]==NULL)){ + rsp_length = response_exception( + ctx, &sft, + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp,TRUE, + "Illegal parameter file %d in subrequests %d in read_general_reference \n", + file_no,nsr); + + }else if (rsp_length+nb_read>=MODBUS_MAX_READ_REGISTERS){ + rsp_length = response_exception( + ctx, &sft, + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp,TRUE, + "Responselenght exceeds telegram-size %d in subrequests %d in read_general_reference \n", + rsp_length+nb_read,nsr); + + }else{ + rsp[rsp_length++]=nb_read; + rsp[rsp_length++]=SUB_REQUEST_REF_TYPE; + /* and read the data for the response */ + for (i = f_address; i < f_address + nb_read; i++) { + rsp[rsp_length++] = mb_mapping->file_registers[file_no-1][i] >> 8; + rsp[rsp_length++] = mb_mapping->file_registers[file_no-1][i] & 0xFF; + } + + + } + + } + offset+=SUB_REQUEST_LENGHT; + nsr++; + }while (nsr < (nb/ SUB_REQUEST_LENGHT)); + // put overall lenght of message at the reserved space in the beginning. + rsp[rsp_length_byte_count]=(rsp_length-rsp_length_byte_count)-1; + + } + break; default: rsp_length = response_exception( @@ -1559,6 +1728,140 @@ int modbus_report_slave_id(modbus_t *ctx, int max_dest, uint8_t *dest) return rc; } +/* Read General Reference ( aka as Read File ) reads nb registers (16-bit) from an offset ( also 16-bit stepping ) of a given filenumber*/ +/* This implements only the simple case with one subrequest. More complex can be created with raw-message. */ +/* !!! Take care, that dest must have the size of at least read_nb +1 !!! */ + +int modbus_read_general_reference(modbus_t *ctx, int file_no, int read_addr, int read_nb, uint16_t *dest) + +{ + int rc; + int req_length; + int i; + int byte_count; + uint8_t req[MAX_MESSAGE_LENGTH]; + uint8_t rsp[MAX_MESSAGE_LENGTH]; + + + if (read_nb > MODBUS_MAX_READ_REGISTERS) { + if (ctx->debug) { + fprintf(stderr, + "ERROR Too many registers requested (%d > %d)\n", + read_nb, MODBUS_MAX_READ_REGISTERS); + } + errno = EMBMDATA; + return -1; + } + byte_count=SUB_REQUEST_LENGHT; + req_length = ctx->backend->build_request_basis(ctx, + MODBUS_FC_READ_GENERAL_REFERENCE, + ((byte_count<<8)|0x06), file_no, req); + + req[req_length++] = read_addr >> 8; + req[req_length++] = read_addr & 0x00ff; + req[req_length++] = read_nb >> 8; + req[req_length++] = read_nb & 0x00ff; + + rc = send_msg(ctx, req, req_length); + if (rc > 0) { + int offset; + + rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION); + if (rc == -1) + return -1; + + rc = check_confirmation(ctx, req, rsp, rc); + if (rc == -1) + return -1; + + rc/=2; /* rc is in byte, we count in uint16-steps */ + offset = ctx->backend->header_length; + if (rc>(read_nb+1)){ /* One register is extra for size and ref-type */ + if (ctx->debug) { + fprintf(stderr, + "ERROR Too many data for destination (%d > %d)\n", + rc ,read_nb); + } + rc=read_nb; + + } + + /* If rc is negative, the loop is jumped ! */ + for (i = 0; i < rc; i++) { + /* shift reg hi_byte to temp OR with lo_byte */ + dest[i] = (rsp[offset + 2 + (i << 1)] << 8) | + rsp[offset + 3 + (i << 1)]; + } + } + + return rc; +} + +/* Write General Reference ( aka as Write File ) writes nb registers (16-bit) from an offset ( also 16-bit stepping ) of a given filenumber*/ +/* This implements only the simple case with one subrequest. More complex can be created with raw-message. */ +int modbus_write_general_reference(modbus_t *ctx, int file_no, int write_addr, int write_nb, const uint16_t *src) + +{ + int rc; + int req_length; + int i; + int byte_count; + uint8_t req[MAX_MESSAGE_LENGTH]; + uint8_t rsp[MAX_MESSAGE_LENGTH]; + + + if (write_nb > MODBUS_MAX_READ_REGISTERS) { + if (ctx->debug) { + fprintf(stderr, + "ERROR Too many registers requested (%d > %d)\n", + write_nb, MODBUS_MAX_READ_REGISTERS); + } + errno = EMBMDATA; + return -1; + } + byte_count=SUB_REQUEST_LENGHT + (write_nb * 2); + req_length = ctx->backend->build_request_basis(ctx, + MODBUS_FC_WRITE_GENERAL_REFERENCE, + ((byte_count<<8)|0x06), file_no, req); + + req[req_length++] = write_addr >> 8; + req[req_length++] = write_addr & 0x00ff; + req[req_length++] = write_nb >> 8; + req[req_length++] = write_nb & 0x00ff; + + for (i=0;i>8; + req[req_length++]=src[i]&0xff; + } + + rc = send_msg(ctx, req, req_length); + if (rc > 0) { + + rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION); + if (rc == -1) + return -1; + + rc = check_confirmation(ctx, req, rsp, rc); + + if (rc == -1) + return -1; + + rc/=2; /* rc is in byte, we count in uint16-steps */ + +#if 0 // Does it make sense to copy back the response to the caller ? It's a copy of the request + offset = ctx->backend->header_length; + + /* If rc is negative, the loop is jumped ! */ + for (i = 0; i < rc; i++) { + /* shift reg hi_byte to temp OR with lo_byte */ + src[i] = (rsp[offset + 2 + (i << 1)] << 8) | + rsp[offset + 3 + (i << 1)]; + } + +#endif + } + return rc; +} void _modbus_init_common(modbus_t *ctx) { /* Slave and socket are initialized to -1 */ @@ -1771,6 +2074,7 @@ modbus_mapping_t* modbus_mapping_new_start_address( unsigned int start_input_registers, unsigned int nb_input_registers) { modbus_mapping_t *mb_mapping; + int i; mb_mapping = (modbus_mapping_t *)malloc(sizeof(modbus_mapping_t)); if (mb_mapping == NULL) { @@ -1845,6 +2149,10 @@ modbus_mapping_t* modbus_mapping_new_start_address( nb_input_registers * sizeof(uint16_t)); } + for (i=0; i < MODBUS_MAX_REFERENCE_FILES ; i ++){ + mb_mapping->file_registers[i]=NULL; + } + return mb_mapping; } @@ -1855,13 +2163,76 @@ modbus_mapping_t* modbus_mapping_new(int nb_bits, int nb_input_bits, 0, nb_bits, 0, nb_input_bits, 0, nb_registers, 0, nb_input_registers); } +/* Allocates 4 arrays to store bits, input bits, registers and inputs + registers. The pointers are stored in modbus_mapping structure. + Aditionally the array for the file-reference acces are allocated, where the size for the files is >0 + + The modbus_mapping_new() function shall return the new allocated structure if + successful. Otherwise it shall return NULL and set errno to ENOMEM. */ +modbus_mapping_t* modbus_mapping_new_extend(int nb_bits, int nb_input_bits, + int nb_registers, int nb_input_registers , uint16_t nb_file_register[MODBUS_MAX_REFERENCE_FILES] ) +{ + int i; + + modbus_mapping_t *mb_mapping = modbus_mapping_new( nb_bits, nb_input_bits, nb_registers, nb_input_registers); + + if (mb_mapping) { + for (i=0; i < MODBUS_MAX_REFERENCE_FILES ; i ++){ + if (nb_file_register[i]){ + mb_mapping->file_registers[i]=(uint16_t *) malloc(nb_file_register[i] * sizeof(uint16_t)); + memset(mb_mapping->file_registers[i],0,nb_file_register[i] * sizeof(uint16_t)); + } + } + } + + return mb_mapping; + +} + +/* Allocates 4 arrays to store bits, input bits, registers and inputs + registers. The pointers are stored in modbus_mapping structure. + Aditionally the array for the file-reference acces are allocated, where the size for the files is >0 + + The modbus_mapping_new() function shall return the new allocated structure if + successful. Otherwise it shall return NULL and set errno to ENOMEM. */ +MODBUS_API modbus_mapping_t* modbus_mapping_new_start_address_extend( + unsigned int start_bits, unsigned int nb_bits, + unsigned int start_input_bits, unsigned int nb_input_bits, + unsigned int start_registers, unsigned int nb_registers, + unsigned int start_input_registers, unsigned int nb_input_registers, + uint16_t nb_file_registers[MODBUS_MAX_REFERENCE_FILES]) +{ + + int i; + + modbus_mapping_t *mb_mapping = modbus_mapping_new_start_address( start_bits, nb_bits, start_input_bits, nb_input_bits, start_registers, nb_registers, start_input_registers, nb_input_registers); + + + if (mb_mapping) { + for (i=0; i < MODBUS_MAX_REFERENCE_FILES ; i ++){ + if (nb_file_registers[i]){ + mb_mapping->file_registers[i]=(uint16_t *) malloc(nb_file_registers[i] * sizeof(uint16_t)); + memset(mb_mapping->file_registers[i],0,nb_file_registers[i] * sizeof(uint16_t)); + } + } + } + return mb_mapping; + +} /* Frees the 4 arrays */ void modbus_mapping_free(modbus_mapping_t *mb_mapping) { + int i; + if (mb_mapping == NULL) { return; } + for (i=0; i < MODBUS_MAX_REFERENCE_FILES ; i ++){ + if (mb_mapping->file_registers[i]){ + free(mb_mapping->file_registers[i]); + } + } free(mb_mapping->tab_input_registers); free(mb_mapping->tab_registers); free(mb_mapping->tab_input_bits); diff --git a/src/modbus.h b/src/modbus.h index fda3f02b7..0cd9d31d1 100644 --- a/src/modbus.h +++ b/src/modbus.h @@ -68,6 +68,8 @@ MODBUS_BEGIN_DECLS #define MODBUS_FC_WRITE_MULTIPLE_COILS 0x0F #define MODBUS_FC_WRITE_MULTIPLE_REGISTERS 0x10 #define MODBUS_FC_REPORT_SLAVE_ID 0x11 +#define MODBUS_FC_READ_GENERAL_REFERENCE 0x14 +#define MODBUS_FC_WRITE_GENERAL_REFERENCE 0x15 #define MODBUS_FC_MASK_WRITE_REGISTER 0x16 #define MODBUS_FC_WRITE_AND_READ_REGISTERS 0x17 @@ -92,6 +94,7 @@ MODBUS_BEGIN_DECLS #define MODBUS_MAX_WRITE_REGISTERS 123 #define MODBUS_MAX_WR_WRITE_REGISTERS 121 #define MODBUS_MAX_WR_READ_REGISTERS 125 +#define MODBUS_MAX_REFERENCE_FILES 10 /* The size of the MODBUS PDU is limited by the size constraint inherited from * the first MODBUS implementation on Serial Line network (max. RS485 ADU = 256 @@ -167,6 +170,7 @@ typedef struct { uint8_t *tab_input_bits; uint16_t *tab_input_registers; uint16_t *tab_registers; + uint16_t *file_registers[MODBUS_MAX_REFERENCE_FILES]; } modbus_mapping_t; typedef enum @@ -215,6 +219,9 @@ MODBUS_API int modbus_mask_write_register(modbus_t *ctx, int addr, uint16_t and_ MODBUS_API 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); +MODBUS_API int modbus_read_general_reference(modbus_t *ctx, int file_no, int read_addr, int read_nb, uint16_t *dest); +MODBUS_API int modbus_write_general_reference(modbus_t *ctx, int file_no, int write_addr, int write_nb, const uint16_t *src); + MODBUS_API int modbus_report_slave_id(modbus_t *ctx, int max_dest, uint8_t *dest); MODBUS_API modbus_mapping_t* modbus_mapping_new_start_address( @@ -223,8 +230,19 @@ MODBUS_API modbus_mapping_t* modbus_mapping_new_start_address( unsigned int start_registers, unsigned int nb_registers, unsigned int start_input_registers, unsigned int nb_input_registers); +MODBUS_API modbus_mapping_t* modbus_mapping_new_start_address_extend( + unsigned int start_bits, unsigned int nb_bits, + unsigned int start_input_bits, unsigned int nb_input_bits, + unsigned int start_registers, unsigned int nb_registers, + unsigned int start_input_registers, unsigned int nb_input_registers, + uint16_t nb_file_registers[MODBUS_MAX_REFERENCE_FILES] ); + MODBUS_API modbus_mapping_t* modbus_mapping_new(int nb_bits, int nb_input_bits, int nb_registers, int nb_input_registers); +MODBUS_API modbus_mapping_t* modbus_mapping_new_extend(int nb_bits, int nb_input_bits, + int nb_registers, int nb_input_registers + , uint16_t nb_file_registers[MODBUS_MAX_REFERENCE_FILES] ); + MODBUS_API void modbus_mapping_free(modbus_mapping_t *mb_mapping); MODBUS_API int modbus_send_raw_request(modbus_t *ctx, uint8_t *raw_req, int raw_req_length); diff --git a/tests/unit-test-client.c b/tests/unit-test-client.c index fdf5c26ed..b521b9b10 100644 --- a/tests/unit-test-client.c +++ b/tests/unit-test-client.c @@ -49,9 +49,10 @@ int main(int argc, char *argv[]) const int NB_REPORT_SLAVE_ID = 10; uint8_t *tab_rp_bits = NULL; uint16_t *tab_rp_registers = NULL; + uint16_t *tab_rp_file = NULL; uint16_t *tab_rp_registers_bad = NULL; modbus_t *ctx = NULL; - int i; + int i,j; uint8_t value; int nb_points; int rc; @@ -65,7 +66,8 @@ int main(int argc, char *argv[]) int use_backend; int success = FALSE; int old_slave; - + char devicename[MAX_DEVICENAME_LENGHT]={0,}; + int baudrate=115200; if (argc > 1) { if (strcmp(argv[1], "tcp") == 0) { use_backend = TCP; @@ -74,7 +76,7 @@ int main(int argc, char *argv[]) } else if (strcmp(argv[1], "rtu") == 0) { use_backend = RTU; } else { - printf("Usage:\n %s [tcp|tcppi|rtu] - Modbus client for unit testing\n\n", argv[0]); + printf("Usage:\n %s [tcp|tcppi|rtu] ('device-name for rtu') (baudrate for rtu) - Modbus client for unit testing\n\n", argv[0]); exit(1); } } else { @@ -82,12 +84,23 @@ int main(int argc, char *argv[]) use_backend = TCP; } + if (argc>2) + { + strncpy(devicename,argv[2],MAX_DEVICENAME_LENGHT); + }else{ + strncpy(devicename,"/dev/ttyUSB1",MAX_DEVICENAME_LENGHT); + } + if (argc>3) + { + baudrate=atoi(argv[3]); + } + if (use_backend == TCP) { ctx = modbus_new_tcp("127.0.0.1", 1502); } else if (use_backend == TCP_PI) { ctx = modbus_new_tcp_pi("::1", "1502"); } else { - ctx = modbus_new_rtu("/dev/ttyUSB1", 115200, 'N', 8, 1); + ctx = modbus_new_rtu(devicename, baudrate, 'N', 8, 1); } if (ctx == NULL) { fprintf(stderr, "Unable to allocate libmodbus context\n"); @@ -127,6 +140,10 @@ int main(int argc, char *argv[]) tab_rp_registers = (uint16_t *) malloc(nb_points * sizeof(uint16_t)); memset(tab_rp_registers, 0, nb_points * sizeof(uint16_t)); + tab_rp_file = (uint16_t *) malloc((MAX_REGISTER_PER_QUERY+2) * sizeof(uint16_t)); + memset(tab_rp_file, 0, (MAX_REGISTER_PER_QUERY+2) * sizeof(uint16_t)); + + printf("\nTEST WRITE/READ:\n"); /** COIL BITS **/ @@ -658,6 +675,101 @@ int main(int argc, char *argv[]) printf("* modbus_read_registers at special address: "); ASSERT_TRUE(rc == -1 && errno == EMBXSBUSY, ""); + + /** Read File*/ + printf("\nTEST READ GENERAL REFERENCE\n"); + { + + rc = modbus_read_general_reference(ctx, 1, 10 , MAX_REGISTER_PER_QUERY, tab_rp_file ); + printf("modbus_read_general_reference: "); + + if (rc < (MAX_REGISTER_PER_QUERY+1)) { // 2 bytes per register + 2 bytes header + printf("FAILED (nb points %d)\n", rc); + goto close; + } + + if (((tab_rp_file[0])>>8) != MAX_REGISTER_PER_QUERY) { + printf("FAILED Received size wrong(%0X != %0X)\n", + (tab_rp_file[0])>>8, + MAX_REGISTER_PER_QUERY); + goto close; + } + + if ((tab_rp_file[0]&0xff) != 0x06 ) { + printf("FAILED Received Subrequest Reference(%0X != %0X)\n", + tab_rp_file[0]&0xff, + 0x06); + goto close; + } + + for (i=0; i < MAX_REGISTER_PER_QUERY; i++) { + if (tab_rp_file[i+1] != 0) { + printf("FAILED (%0X != %0X)\n", + tab_rp_file[i+1], + 0); + goto close; + } + } + printf("OK\n"); + } + + + + printf("\nTEST WRITE GENERAL REFERENCE\n"); + { + + for (i=1; i < 5 ; i++){ + rc = modbus_write_general_reference(ctx, i, i*7 , UT_FILE_REGISTER_NB-i, &UT_FILE_REGISTER_TAB[i] ); + + printf("modbus_write_general_reference File_no %d: ",i); + + if (rc < (UT_FILE_REGISTER_NB+1-i)) { // 2 bytes per register + 2 bytes header + printf("FAILED (nb points %d)\n", rc); + goto close; + } + printf("OK\n"); + + } + + for (i=1; i < 5 ; i++){ + rc = modbus_read_general_reference(ctx, i, i*7 , UT_FILE_REGISTER_NB-1, tab_rp_file ); + + printf("modbus_read_general_reference File_no %d: ",i); + + if (rc < (UT_FILE_REGISTER_NB+1-i)) { // 2 bytes per register + 2 bytes header + printf("FAILED (nb points %d)\n", rc); + goto close; + } + + printf("OK , Verify : "); + + for (j=0; j < (UT_FILE_REGISTER_NB-i); j++) { + if (tab_rp_file[j+1] != UT_FILE_REGISTER_TAB[j+i]) { + printf("FAILED (%0X != %0X) at %d \n", + tab_rp_file[j+1], + UT_FILE_REGISTER_TAB[j+i], j); + goto close; + } + } + printf("OK\n"); + } + } + + /* Writing to a non existing file */ + rc = modbus_write_general_reference(ctx, 6, 0 , UT_FILE_REGISTER_NB, UT_FILE_REGISTER_TAB ); + + printf("modbus_write_general_reference File_no 6 "); + + if (rc == -1 && errno ==EMBXILVAL) { // This should fail + printf("OK\n"); + }else{ + printf("FAILED (nb points %d) errno %d \n", rc, errno ); + goto close; + } + + + + /** Run a few tests to challenge the server code **/ if (test_server(ctx, use_backend) == -1) { goto close; @@ -685,6 +797,7 @@ int main(int argc, char *argv[]) /* Free the memory */ free(tab_rp_bits); free(tab_rp_registers); + free(tab_rp_file); /* Close the connection */ modbus_close(ctx); diff --git a/tests/unit-test-server.c b/tests/unit-test-server.c index 7002b10c6..f77692489 100644 --- a/tests/unit-test-server.c +++ b/tests/unit-test-server.c @@ -39,6 +39,8 @@ int main(int argc, char*argv[]) int use_backend; uint8_t *query; int header_length; + char devicename[MAX_DEVICENAME_LENGHT]={0,}; + int baudrate=115200; if (argc > 1) { if (strcmp(argv[1], "tcp") == 0) { @@ -48,7 +50,7 @@ int main(int argc, char*argv[]) } else if (strcmp(argv[1], "rtu") == 0) { use_backend = RTU; } else { - printf("Usage:\n %s [tcp|tcppi|rtu] - Modbus server for unit testing\n\n", argv[0]); + printf("Usage:\n %s [tcp|tcppi|rtu] ('device-name for rtu') (baudrate for rtu) - Modbus server for unit testing\n\n", argv[0]); return -1; } } else { @@ -56,6 +58,17 @@ int main(int argc, char*argv[]) use_backend = TCP; } + if (argc>2) + { + strncpy(devicename,argv[2],MAX_DEVICENAME_LENGHT); + }else{ + strncpy(devicename,"/dev/ttyUSB0",MAX_DEVICENAME_LENGHT); + } + if (argc>3) + { + baudrate=atoi(argv[3]); + } + if (use_backend == TCP) { ctx = modbus_new_tcp("127.0.0.1", 1502); query = malloc(MODBUS_TCP_MAX_ADU_LENGTH); @@ -63,7 +76,7 @@ int main(int argc, char*argv[]) ctx = modbus_new_tcp_pi("::0", "1502"); query = malloc(MODBUS_TCP_MAX_ADU_LENGTH); } else { - ctx = modbus_new_rtu("/dev/ttyUSB0", 115200, 'N', 8, 1); + ctx = modbus_new_rtu(devicename, baudrate, 'N', 8, 1); modbus_set_slave(ctx, SERVER_ID); query = malloc(MODBUS_RTU_MAX_ADU_LENGTH); } @@ -71,11 +84,15 @@ int main(int argc, char*argv[]) modbus_set_debug(ctx, TRUE); - mb_mapping = modbus_mapping_new_start_address( + + + mb_mapping = modbus_mapping_new_start_address_extend ( UT_BITS_ADDRESS, UT_BITS_NB, UT_INPUT_BITS_ADDRESS, UT_INPUT_BITS_NB, UT_REGISTERS_ADDRESS, UT_REGISTERS_NB_MAX, - UT_INPUT_REGISTERS_ADDRESS, UT_INPUT_REGISTERS_NB); + UT_INPUT_REGISTERS_ADDRESS, UT_INPUT_REGISTERS_NB, + UT_FILE_REGISTERS_NB); + if (mb_mapping == NULL) { fprintf(stderr, "Failed to allocate the mapping: %s\n", modbus_strerror(errno)); diff --git a/tests/unit-test.h.in b/tests/unit-test.h.in index dca826f46..1e1ddc072 100644 --- a/tests/unit-test.h.in +++ b/tests/unit-test.h.in @@ -25,6 +25,9 @@ #define SERVER_ID 17 #define INVALID_SERVER_ID 18 +#define MAX_DEVICENAME_LENGHT 256 +#define MAX_REGISTER_PER_QUERY 100 + const uint16_t UT_BITS_ADDRESS = 0x130; const uint16_t UT_BITS_NB = 0x25; const uint8_t UT_BITS_TAB[] = { 0xCD, 0x6B, 0xB2, 0x0E, 0x1B }; @@ -55,6 +58,9 @@ const uint16_t UT_REGISTERS_NB_SPECIAL = 0x2; const uint16_t UT_INPUT_REGISTERS_ADDRESS = 0x108; const uint16_t UT_INPUT_REGISTERS_NB = 0x1; const uint16_t UT_INPUT_REGISTERS_TAB[] = { 0x000A }; +#define UT_FILE_REGISTER_NB 20 +const uint16_t UT_FILE_REGISTER_TAB[UT_FILE_REGISTER_NB] = { 0x0001,0x0101,0xFF55,0x1234,0x6789,0xABCD,0xDEFF,0x2222,0x3333,0x4444,0x5555,0x0505,0x6060,0xcafe, }; +uint16_t UT_FILE_REGISTERS_NB[MODBUS_MAX_REFERENCE_FILES] = { 200,500,100,700,50 }; const float UT_REAL = 123456.00; From 81017e176dc755fe014080b69234a09a4a0e3326 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Wed, 1 Nov 2017 09:09:30 +0100 Subject: [PATCH 2/2] fix coding-style as per clang-format --- src/modbus.c | 367 +++++++++++++++++++-------------------- src/modbus.h | 13 +- tests/unit-test-client.c | 148 ++++++++-------- tests/unit-test-server.c | 26 ++- 4 files changed, 265 insertions(+), 289 deletions(-) diff --git a/src/modbus.c b/src/modbus.c index cca346ae6..8786a4d2f 100644 --- a/src/modbus.c +++ b/src/modbus.c @@ -153,10 +153,10 @@ static unsigned int compute_response_length_from_request(modbus_t *ctx, uint8_t length) */ return MSG_LENGTH_UNDEFINED; case MODBUS_FC_WRITE_GENERAL_REFERENCE: - length= 2 + req[offset + 1]; + length = 2 + req[offset + 1]; break; case MODBUS_FC_READ_GENERAL_REFERENCE: - return MSG_LENGTH_UNDEFINED; // Lenght is dedepnding of the subrequests + return MSG_LENGTH_UNDEFINED; // Lenght is dedepnding of the subrequests case MODBUS_FC_MASK_WRITE_REGISTER: length = 7; break; @@ -270,8 +270,8 @@ static uint8_t compute_meta_length_after_function(int function, } else if (function == MODBUS_FC_WRITE_AND_READ_REGISTERS) { length = 9; } else if (function == MODBUS_FC_READ_GENERAL_REFERENCE || - function == MODBUS_FC_WRITE_GENERAL_REFERENCE) { - length = 1; // After the function, the number of bytes is transmitted + function == MODBUS_FC_WRITE_GENERAL_REFERENCE) { + length = 1; // After the function, the number of bytes is transmitted } else { /* MODBUS_FC_READ_EXCEPTION_STATUS, MODBUS_FC_REPORT_SLAVE_ID */ length = 0; @@ -290,9 +290,9 @@ static uint8_t compute_meta_length_after_function(int function, break; case MODBUS_FC_WRITE_GENERAL_REFERENCE: case MODBUS_FC_READ_GENERAL_REFERENCE: - length = 1; // After the function, the number of bytes is transmitted and at least one SUB_REQUEST + length = 1; // After the function, the number of bytes is transmitted and at least one SUB_REQUEST break; - default: + default: length = 1; } } @@ -318,7 +318,7 @@ static int compute_data_length_after_meta(modbus_t *ctx, uint8_t *msg, break; case MODBUS_FC_WRITE_GENERAL_REFERENCE: case MODBUS_FC_READ_GENERAL_REFERENCE: - length = msg[ctx->backend->header_length + 1]; + length = msg[ctx->backend->header_length + 1]; break; default: length = 0; @@ -330,7 +330,7 @@ static int compute_data_length_after_meta(modbus_t *ctx, uint8_t *msg, function == MODBUS_FC_WRITE_AND_READ_REGISTERS) { length = msg[ctx->backend->header_length + 1]; } else if (function == MODBUS_FC_READ_GENERAL_REFERENCE || - function == MODBUS_FC_WRITE_GENERAL_REFERENCE) { + function == MODBUS_FC_WRITE_GENERAL_REFERENCE) { length = msg[ctx->backend->header_length + 1]; } else { length = 0; @@ -1016,146 +1016,139 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, } break; case MODBUS_FC_WRITE_GENERAL_REFERENCE: { - // Each "Read_General_Reference", aka as "Read_File", can consists of several Subrequests - uint8_t nb = req[offset + 1]; - uint16_t i; - int nsr = 0; - uint8_t ref_type=0; - - /* Each Subrequest has at least 7 Bytes */ - if (nb < SUB_REQUEST_LENGHT ) { - rsp_length = response_exception( - ctx, &sft, - MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp,TRUE, - "Illegal nb of subrequests %d in write_general_reference \n", nb); - break; - } + // Each "Read_General_Reference", aka as "Read_File", can consists of several Subrequests + uint8_t nb = req[offset + 1]; + uint16_t i; + int nsr = 0; + uint8_t ref_type = 0; + + /* Each Subrequest has at least 7 Bytes */ + if (nb < SUB_REQUEST_LENGHT) { + rsp_length = response_exception( + ctx, &sft, + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp, TRUE, + "Illegal nb of subrequests %d in write_general_reference \n", nb); + break; + } + rsp_length = ctx->backend->build_response_basis(&sft, rsp); + if (rsp_length + nb >= MODBUS_MAX_READ_REGISTERS) { + rsp_length = response_exception( + ctx, &sft, + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp, TRUE, + "Responselenght exceeds telegram-size %d in subrequests %d in write_general_reference \n", + rsp_length + nb, nsr); - rsp_length = ctx->backend->build_response_basis(&sft, rsp); - if (rsp_length+nb >=MODBUS_MAX_READ_REGISTERS){ - rsp_length = response_exception( - ctx, &sft, - MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp,TRUE, - "Responselenght exceeds telegram-size %d in subrequests %d in write_general_reference \n", - rsp_length+nb,nsr); - - }else { - /* Response is a simple copy of the request */ - memcpy(rsp + rsp_length, req + offset + 1 , 1 + nb ); // number of bytes + the place for the nb itself - rsp_length += nb + 1; - - do{ - offset +=2; - ref_type=req[offset]; - if (ref_type!=SUB_REQUEST_REF_TYPE){ - rsp_length = response_exception( - ctx, &sft, - MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp, TRUE, - "Illegal reference Type %d in subrequests %d in write_general_reference \n", - ref_type,nsr); - }else{ - uint16_t file_no = (req[offset + 1] << 8) + req[offset + 2]; - uint16_t f_address = (req[offset + 3] << 8) + req[offset + 4]; - uint16_t nb_write = (req[offset + 5] << 8) + req[offset + 6]; - - offset+=SUB_REQUEST_LENGHT; - nb-=SUB_REQUEST_LENGHT; - - if ((file_no==0)||(file_no > MODBUS_MAX_REFERENCE_FILES)||(mb_mapping->file_registers[file_no-1]==NULL)){ - rsp_length = response_exception( - ctx, &sft, - MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp,TRUE, - "Illegal parameter file %d in subrequests %d in write_general_reference \n", - file_no,nsr); - break; - }else { - /* Write Registers to file at position adress */ - for (i = f_address; i < f_address + nb_write; i++) { - mb_mapping->file_registers[file_no-1][i]=(req[offset] <<8) + req[offset+1]; - offset+=2; - nb-=2; - } - } + } else { + /* Response is a simple copy of the request */ + memcpy(rsp + rsp_length, req + offset + 1, 1 + nb); // number of bytes + the place for the nb itself + rsp_length += nb + 1; + + do { + offset += 2; + ref_type = req[offset]; + if (ref_type != SUB_REQUEST_REF_TYPE) { + rsp_length = response_exception( + ctx, &sft, + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp, TRUE, + "Illegal reference Type %d in subrequests %d in write_general_reference \n", + ref_type, nsr); + } else { + uint16_t file_no = (req[offset + 1] << 8) + req[offset + 2]; + uint16_t f_address = (req[offset + 3] << 8) + req[offset + 4]; + uint16_t nb_write = (req[offset + 5] << 8) + req[offset + 6]; + + offset += SUB_REQUEST_LENGHT; + nb -= SUB_REQUEST_LENGHT; + + if ((file_no == 0) || (file_no > MODBUS_MAX_REFERENCE_FILES) || (mb_mapping->file_registers[file_no - 1] == NULL)) { + rsp_length = response_exception( + ctx, &sft, + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp, TRUE, + "Illegal parameter file %d in subrequests %d in write_general_reference \n", + file_no, nsr); + break; + } else { + /* Write Registers to file at position adress */ + for (i = f_address; i < f_address + nb_write; i++) { + mb_mapping->file_registers[file_no - 1][i] = (req[offset] << 8) + req[offset + 1]; + offset += 2; + nb -= 2; } - nsr++; - }while (nb>0); - } - } - break; + } + } + nsr++; + } while (nb > 0); + } + } break; case MODBUS_FC_READ_GENERAL_REFERENCE: { - // Each "Read_General_Reference", aka as "Read_File", can consists of several Subrequests - uint8_t nb = req[offset + 1]; - uint16_t i; - int nsr = 0; - uint8_t ref_type=0; - int rsp_length_byte_count=0; - - /* Each Subrequest has 7 Bytes */ - if (nb % SUB_REQUEST_LENGHT != 0 ) { - rsp_length = response_exception( - ctx, &sft, - MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp,TRUE, - "Illegal nb of subrequests %d in read_general_reference \n",nb); - break; - } + // Each "Read_General_Reference", aka as "Read_File", can consists of several Subrequests + uint8_t nb = req[offset + 1]; + uint16_t i; + int nsr = 0; + uint8_t ref_type = 0; + int rsp_length_byte_count = 0; + + /* Each Subrequest has 7 Bytes */ + if (nb % SUB_REQUEST_LENGHT != 0) { + rsp_length = response_exception( + ctx, &sft, + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp, TRUE, + "Illegal nb of subrequests %d in read_general_reference \n", nb); + break; + } + + rsp_length = ctx->backend->build_response_basis(&sft, rsp); + rsp_length_byte_count = rsp_length; // Place-holder of overall message-size. + rsp[rsp_length++] = 0; - rsp_length = ctx->backend->build_response_basis(&sft, rsp); + do { + offset += 2; + ref_type = req[offset]; - rsp_length_byte_count=rsp_length; // Place-holder of overall message-size. - rsp[rsp_length++]=0; + if (ref_type != SUB_REQUEST_REF_TYPE) { + rsp_length = response_exception( + ctx, &sft, + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp, TRUE, + "Illegal reference Type %d in subrequests %d in read_general_reference \n", + ref_type, nsr); + } else { + uint16_t file_no = (req[offset + 1] << 8) + req[offset + 2]; + uint16_t f_address = (req[offset + 3] << 8) + req[offset + 4]; + uint16_t nb_read = (req[offset + 5] << 8) + req[offset + 6]; - do{ - offset +=2; - ref_type=req[offset]; + if ((file_no == 0) || (file_no > MODBUS_MAX_REFERENCE_FILES) || (mb_mapping->file_registers[file_no - 1] == NULL)) { + rsp_length = response_exception( + ctx, &sft, + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp, TRUE, + "Illegal parameter file %d in subrequests %d in read_general_reference \n", + file_no, nsr); - if (ref_type!=SUB_REQUEST_REF_TYPE){ - rsp_length = response_exception( + } else if (rsp_length + nb_read >= MODBUS_MAX_READ_REGISTERS) { + rsp_length = response_exception( ctx, &sft, - MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp,TRUE, - "Illegal reference Type %d in subrequests %d in read_general_reference \n", - ref_type,nsr); - }else{ - uint16_t file_no = (req[offset + 1] << 8) + req[offset + 2]; - uint16_t f_address = (req[offset + 3] << 8) + req[offset + 4]; - uint16_t nb_read = (req[offset + 5] << 8) + req[offset + 6]; - - if ((file_no==0)||(file_no > MODBUS_MAX_REFERENCE_FILES)||(mb_mapping->file_registers[file_no-1]==NULL)){ - rsp_length = response_exception( - ctx, &sft, - MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp,TRUE, - "Illegal parameter file %d in subrequests %d in read_general_reference \n", - file_no,nsr); - - }else if (rsp_length+nb_read>=MODBUS_MAX_READ_REGISTERS){ - rsp_length = response_exception( - ctx, &sft, - MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp,TRUE, - "Responselenght exceeds telegram-size %d in subrequests %d in read_general_reference \n", - rsp_length+nb_read,nsr); - - }else{ - rsp[rsp_length++]=nb_read; - rsp[rsp_length++]=SUB_REQUEST_REF_TYPE; - /* and read the data for the response */ - for (i = f_address; i < f_address + nb_read; i++) { - rsp[rsp_length++] = mb_mapping->file_registers[file_no-1][i] >> 8; - rsp[rsp_length++] = mb_mapping->file_registers[file_no-1][i] & 0xFF; - } - - - } - - } - offset+=SUB_REQUEST_LENGHT; - nsr++; - }while (nsr < (nb/ SUB_REQUEST_LENGHT)); - // put overall lenght of message at the reserved space in the beginning. - rsp[rsp_length_byte_count]=(rsp_length-rsp_length_byte_count)-1; + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp, TRUE, + "Responselenght exceeds telegram-size %d in subrequests %d in read_general_reference \n", + rsp_length + nb_read, nsr); - } - break; + } else { + rsp[rsp_length++] = nb_read; + rsp[rsp_length++] = SUB_REQUEST_REF_TYPE; + /* and read the data for the response */ + for (i = f_address; i < f_address + nb_read; i++) { + rsp[rsp_length++] = mb_mapping->file_registers[file_no - 1][i] >> 8; + rsp[rsp_length++] = mb_mapping->file_registers[file_no - 1][i] & 0xFF; + } + } + } + offset += SUB_REQUEST_LENGHT; + nsr++; + } while (nsr < (nb / SUB_REQUEST_LENGHT)); + // put overall lenght of message at the reserved space in the beginning. + rsp[rsp_length_byte_count] = (rsp_length - rsp_length_byte_count) - 1; + + } break; default: rsp_length = response_exception( @@ -1732,7 +1725,7 @@ int modbus_report_slave_id(modbus_t *ctx, int max_dest, uint8_t *dest) /* This implements only the simple case with one subrequest. More complex can be created with raw-message. */ /* !!! Take care, that dest must have the size of at least read_nb +1 !!! */ -int modbus_read_general_reference(modbus_t *ctx, int file_no, int read_addr, int read_nb, uint16_t *dest) +int modbus_read_general_reference(modbus_t *ctx, int file_no, int read_addr, int read_nb, uint16_t *dest) { int rc; @@ -1742,7 +1735,6 @@ int modbus_read_general_reference(modbus_t *ctx, int file_no, int read_addr, in uint8_t req[MAX_MESSAGE_LENGTH]; uint8_t rsp[MAX_MESSAGE_LENGTH]; - if (read_nb > MODBUS_MAX_READ_REGISTERS) { if (ctx->debug) { fprintf(stderr, @@ -1752,10 +1744,10 @@ int modbus_read_general_reference(modbus_t *ctx, int file_no, int read_addr, in errno = EMBMDATA; return -1; } - byte_count=SUB_REQUEST_LENGHT; + byte_count = SUB_REQUEST_LENGHT; req_length = ctx->backend->build_request_basis(ctx, MODBUS_FC_READ_GENERAL_REFERENCE, - ((byte_count<<8)|0x06), file_no, req); + ((byte_count << 8) | 0x06), file_no, req); req[req_length++] = read_addr >> 8; req[req_length++] = read_addr & 0x00ff; @@ -1774,23 +1766,22 @@ int modbus_read_general_reference(modbus_t *ctx, int file_no, int read_addr, in if (rc == -1) return -1; - rc/=2; /* rc is in byte, we count in uint16-steps */ + rc /= 2; /* rc is in byte, we count in uint16-steps */ offset = ctx->backend->header_length; - if (rc>(read_nb+1)){ /* One register is extra for size and ref-type */ + if (rc > (read_nb + 1)) { /* One register is extra for size and ref-type */ if (ctx->debug) { - fprintf(stderr, - "ERROR Too many data for destination (%d > %d)\n", - rc ,read_nb); + fprintf(stderr, + "ERROR Too many data for destination (%d > %d)\n", + rc, read_nb); } - rc=read_nb; - + rc = read_nb; } /* If rc is negative, the loop is jumped ! */ for (i = 0; i < rc; i++) { /* shift reg hi_byte to temp OR with lo_byte */ dest[i] = (rsp[offset + 2 + (i << 1)] << 8) | - rsp[offset + 3 + (i << 1)]; + rsp[offset + 3 + (i << 1)]; } } @@ -1799,7 +1790,7 @@ int modbus_read_general_reference(modbus_t *ctx, int file_no, int read_addr, in /* Write General Reference ( aka as Write File ) writes nb registers (16-bit) from an offset ( also 16-bit stepping ) of a given filenumber*/ /* This implements only the simple case with one subrequest. More complex can be created with raw-message. */ -int modbus_write_general_reference(modbus_t *ctx, int file_no, int write_addr, int write_nb, const uint16_t *src) +int modbus_write_general_reference(modbus_t *ctx, int file_no, int write_addr, int write_nb, const uint16_t *src) { int rc; @@ -1809,7 +1800,6 @@ int modbus_write_general_reference(modbus_t *ctx, int file_no, int write_addr, uint8_t req[MAX_MESSAGE_LENGTH]; uint8_t rsp[MAX_MESSAGE_LENGTH]; - if (write_nb > MODBUS_MAX_READ_REGISTERS) { if (ctx->debug) { fprintf(stderr, @@ -1819,19 +1809,19 @@ int modbus_write_general_reference(modbus_t *ctx, int file_no, int write_addr, errno = EMBMDATA; return -1; } - byte_count=SUB_REQUEST_LENGHT + (write_nb * 2); + byte_count = SUB_REQUEST_LENGHT + (write_nb * 2); req_length = ctx->backend->build_request_basis(ctx, MODBUS_FC_WRITE_GENERAL_REFERENCE, - ((byte_count<<8)|0x06), file_no, req); + ((byte_count << 8) | 0x06), file_no, req); req[req_length++] = write_addr >> 8; req[req_length++] = write_addr & 0x00ff; req[req_length++] = write_nb >> 8; req[req_length++] = write_nb & 0x00ff; - for (i=0;i>8; - req[req_length++]=src[i]&0xff; + for (i = 0; i < write_nb; i++) { + req[req_length++] = src[i] >> 8; + req[req_length++] = src[i] & 0xff; } rc = send_msg(ctx, req, req_length); @@ -1842,12 +1832,12 @@ int modbus_write_general_reference(modbus_t *ctx, int file_no, int write_addr, return -1; rc = check_confirmation(ctx, req, rsp, rc); - + if (rc == -1) return -1; - rc/=2; /* rc is in byte, we count in uint16-steps */ - + rc /= 2; /* rc is in byte, we count in uint16-steps */ + #if 0 // Does it make sense to copy back the response to the caller ? It's a copy of the request offset = ctx->backend->header_length; @@ -1859,7 +1849,7 @@ int modbus_write_general_reference(modbus_t *ctx, int file_no, int write_addr, } #endif - } + } return rc; } void _modbus_init_common(modbus_t *ctx) @@ -2149,8 +2139,8 @@ modbus_mapping_t* modbus_mapping_new_start_address( nb_input_registers * sizeof(uint16_t)); } - for (i=0; i < MODBUS_MAX_REFERENCE_FILES ; i ++){ - mb_mapping->file_registers[i]=NULL; + for (i = 0; i < MODBUS_MAX_REFERENCE_FILES; i++) { + mb_mapping->file_registers[i] = NULL; } return mb_mapping; @@ -2169,24 +2159,23 @@ modbus_mapping_t* modbus_mapping_new(int nb_bits, int nb_input_bits, The modbus_mapping_new() function shall return the new allocated structure if successful. Otherwise it shall return NULL and set errno to ENOMEM. */ -modbus_mapping_t* modbus_mapping_new_extend(int nb_bits, int nb_input_bits, - int nb_registers, int nb_input_registers , uint16_t nb_file_register[MODBUS_MAX_REFERENCE_FILES] ) +modbus_mapping_t *modbus_mapping_new_extend(int nb_bits, int nb_input_bits, + int nb_registers, int nb_input_registers, uint16_t nb_file_register[MODBUS_MAX_REFERENCE_FILES]) { - int i; - - modbus_mapping_t *mb_mapping = modbus_mapping_new( nb_bits, nb_input_bits, nb_registers, nb_input_registers); + int i; - if (mb_mapping) { - for (i=0; i < MODBUS_MAX_REFERENCE_FILES ; i ++){ - if (nb_file_register[i]){ - mb_mapping->file_registers[i]=(uint16_t *) malloc(nb_file_register[i] * sizeof(uint16_t)); - memset(mb_mapping->file_registers[i],0,nb_file_register[i] * sizeof(uint16_t)); - } - } - } + modbus_mapping_t *mb_mapping = modbus_mapping_new(nb_bits, nb_input_bits, nb_registers, nb_input_registers); - return mb_mapping; + if (mb_mapping) { + for (i = 0; i < MODBUS_MAX_REFERENCE_FILES; i++) { + if (nb_file_register[i]) { + mb_mapping->file_registers[i] = (uint16_t *)malloc(nb_file_register[i] * sizeof(uint16_t)); + memset(mb_mapping->file_registers[i], 0, nb_file_register[i] * sizeof(uint16_t)); + } + } + } + return mb_mapping; } /* Allocates 4 arrays to store bits, input bits, registers and inputs @@ -2195,7 +2184,7 @@ modbus_mapping_t* modbus_mapping_new_extend(int nb_bits, int nb_input_bits, The modbus_mapping_new() function shall return the new allocated structure if successful. Otherwise it shall return NULL and set errno to ENOMEM. */ -MODBUS_API modbus_mapping_t* modbus_mapping_new_start_address_extend( +MODBUS_API modbus_mapping_t *modbus_mapping_new_start_address_extend( unsigned int start_bits, unsigned int nb_bits, unsigned int start_input_bits, unsigned int nb_input_bits, unsigned int start_registers, unsigned int nb_registers, @@ -2205,19 +2194,17 @@ MODBUS_API modbus_mapping_t* modbus_mapping_new_start_address_extend( int i; - modbus_mapping_t *mb_mapping = modbus_mapping_new_start_address( start_bits, nb_bits, start_input_bits, nb_input_bits, start_registers, nb_registers, start_input_registers, nb_input_registers); - + modbus_mapping_t *mb_mapping = modbus_mapping_new_start_address(start_bits, nb_bits, start_input_bits, nb_input_bits, start_registers, nb_registers, start_input_registers, nb_input_registers); if (mb_mapping) { - for (i=0; i < MODBUS_MAX_REFERENCE_FILES ; i ++){ - if (nb_file_registers[i]){ - mb_mapping->file_registers[i]=(uint16_t *) malloc(nb_file_registers[i] * sizeof(uint16_t)); - memset(mb_mapping->file_registers[i],0,nb_file_registers[i] * sizeof(uint16_t)); - } - } + for (i = 0; i < MODBUS_MAX_REFERENCE_FILES; i++) { + if (nb_file_registers[i]) { + mb_mapping->file_registers[i] = (uint16_t *)malloc(nb_file_registers[i] * sizeof(uint16_t)); + memset(mb_mapping->file_registers[i], 0, nb_file_registers[i] * sizeof(uint16_t)); + } + } } return mb_mapping; - } /* Frees the 4 arrays */ void modbus_mapping_free(modbus_mapping_t *mb_mapping) @@ -2228,10 +2215,10 @@ void modbus_mapping_free(modbus_mapping_t *mb_mapping) return; } - for (i=0; i < MODBUS_MAX_REFERENCE_FILES ; i ++){ - if (mb_mapping->file_registers[i]){ - free(mb_mapping->file_registers[i]); - } + for (i = 0; i < MODBUS_MAX_REFERENCE_FILES; i++) { + if (mb_mapping->file_registers[i]) { + free(mb_mapping->file_registers[i]); + } } free(mb_mapping->tab_input_registers); free(mb_mapping->tab_registers); diff --git a/src/modbus.h b/src/modbus.h index 0cd9d31d1..40eab6bb1 100644 --- a/src/modbus.h +++ b/src/modbus.h @@ -219,8 +219,8 @@ MODBUS_API int modbus_mask_write_register(modbus_t *ctx, int addr, uint16_t and_ MODBUS_API 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); -MODBUS_API int modbus_read_general_reference(modbus_t *ctx, int file_no, int read_addr, int read_nb, uint16_t *dest); -MODBUS_API int modbus_write_general_reference(modbus_t *ctx, int file_no, int write_addr, int write_nb, const uint16_t *src); +MODBUS_API int modbus_read_general_reference(modbus_t *ctx, int file_no, int read_addr, int read_nb, uint16_t *dest); +MODBUS_API int modbus_write_general_reference(modbus_t *ctx, int file_no, int write_addr, int write_nb, const uint16_t *src); MODBUS_API int modbus_report_slave_id(modbus_t *ctx, int max_dest, uint8_t *dest); @@ -230,18 +230,17 @@ MODBUS_API modbus_mapping_t* modbus_mapping_new_start_address( unsigned int start_registers, unsigned int nb_registers, unsigned int start_input_registers, unsigned int nb_input_registers); -MODBUS_API modbus_mapping_t* modbus_mapping_new_start_address_extend( +MODBUS_API modbus_mapping_t *modbus_mapping_new_start_address_extend( unsigned int start_bits, unsigned int nb_bits, unsigned int start_input_bits, unsigned int nb_input_bits, unsigned int start_registers, unsigned int nb_registers, unsigned int start_input_registers, unsigned int nb_input_registers, - uint16_t nb_file_registers[MODBUS_MAX_REFERENCE_FILES] ); + uint16_t nb_file_registers[MODBUS_MAX_REFERENCE_FILES]); MODBUS_API modbus_mapping_t* modbus_mapping_new(int nb_bits, int nb_input_bits, int nb_registers, int nb_input_registers); -MODBUS_API modbus_mapping_t* modbus_mapping_new_extend(int nb_bits, int nb_input_bits, - int nb_registers, int nb_input_registers - , uint16_t nb_file_registers[MODBUS_MAX_REFERENCE_FILES] ); +MODBUS_API modbus_mapping_t *modbus_mapping_new_extend(int nb_bits, int nb_input_bits, + int nb_registers, int nb_input_registers, uint16_t nb_file_registers[MODBUS_MAX_REFERENCE_FILES]); MODBUS_API void modbus_mapping_free(modbus_mapping_t *mb_mapping); diff --git a/tests/unit-test-client.c b/tests/unit-test-client.c index b521b9b10..fa92eb0f7 100644 --- a/tests/unit-test-client.c +++ b/tests/unit-test-client.c @@ -52,7 +52,7 @@ int main(int argc, char *argv[]) uint16_t *tab_rp_file = NULL; uint16_t *tab_rp_registers_bad = NULL; modbus_t *ctx = NULL; - int i,j; + int i, j; uint8_t value; int nb_points; int rc; @@ -66,8 +66,10 @@ int main(int argc, char *argv[]) int use_backend; int success = FALSE; int old_slave; - char devicename[MAX_DEVICENAME_LENGHT]={0,}; - int baudrate=115200; + char devicename[MAX_DEVICENAME_LENGHT] = { + 0, + }; + int baudrate = 115200; if (argc > 1) { if (strcmp(argv[1], "tcp") == 0) { use_backend = TCP; @@ -84,15 +86,13 @@ int main(int argc, char *argv[]) use_backend = TCP; } - if (argc>2) - { - strncpy(devicename,argv[2],MAX_DEVICENAME_LENGHT); - }else{ - strncpy(devicename,"/dev/ttyUSB1",MAX_DEVICENAME_LENGHT); + if (argc > 2) { + strncpy(devicename, argv[2], MAX_DEVICENAME_LENGHT); + } else { + strncpy(devicename, "/dev/ttyUSB1", MAX_DEVICENAME_LENGHT); } - if (argc>3) - { - baudrate=atoi(argv[3]); + if (argc > 3) { + baudrate = atoi(argv[3]); } if (use_backend == TCP) { @@ -140,10 +140,9 @@ int main(int argc, char *argv[]) tab_rp_registers = (uint16_t *) malloc(nb_points * sizeof(uint16_t)); memset(tab_rp_registers, 0, nb_points * sizeof(uint16_t)); - tab_rp_file = (uint16_t *) malloc((MAX_REGISTER_PER_QUERY+2) * sizeof(uint16_t)); - memset(tab_rp_file, 0, (MAX_REGISTER_PER_QUERY+2) * sizeof(uint16_t)); - - + tab_rp_file = (uint16_t *)malloc((MAX_REGISTER_PER_QUERY + 2) * sizeof(uint16_t)); + memset(tab_rp_file, 0, (MAX_REGISTER_PER_QUERY + 2) * sizeof(uint16_t)); + printf("\nTEST WRITE/READ:\n"); /** COIL BITS **/ @@ -675,100 +674,93 @@ int main(int argc, char *argv[]) printf("* modbus_read_registers at special address: "); ASSERT_TRUE(rc == -1 && errno == EMBXSBUSY, ""); - - /** Read File*/ + /** Read File*/ printf("\nTEST READ GENERAL REFERENCE\n"); { - rc = modbus_read_general_reference(ctx, 1, 10 , MAX_REGISTER_PER_QUERY, tab_rp_file ); - printf("modbus_read_general_reference: "); + rc = modbus_read_general_reference(ctx, 1, 10, MAX_REGISTER_PER_QUERY, tab_rp_file); + printf("modbus_read_general_reference: "); - if (rc < (MAX_REGISTER_PER_QUERY+1)) { // 2 bytes per register + 2 bytes header - printf("FAILED (nb points %d)\n", rc); - goto close; - } + if (rc < (MAX_REGISTER_PER_QUERY + 1)) { // 2 bytes per register + 2 bytes header + printf("FAILED (nb points %d)\n", rc); + goto close; + } - if (((tab_rp_file[0])>>8) != MAX_REGISTER_PER_QUERY) { + if (((tab_rp_file[0]) >> 8) != MAX_REGISTER_PER_QUERY) { printf("FAILED Received size wrong(%0X != %0X)\n", - (tab_rp_file[0])>>8, + (tab_rp_file[0]) >> 8, MAX_REGISTER_PER_QUERY); goto close; - } + } - if ((tab_rp_file[0]&0xff) != 0x06 ) { + if ((tab_rp_file[0] & 0xff) != 0x06) { printf("FAILED Received Subrequest Reference(%0X != %0X)\n", - tab_rp_file[0]&0xff, + tab_rp_file[0] & 0xff, 0x06); goto close; - } + } - for (i=0; i < MAX_REGISTER_PER_QUERY; i++) { - if (tab_rp_file[i+1] != 0) { - printf("FAILED (%0X != %0X)\n", - tab_rp_file[i+1], - 0); - goto close; + for (i = 0; i < MAX_REGISTER_PER_QUERY; i++) { + if (tab_rp_file[i + 1] != 0) { + printf("FAILED (%0X != %0X)\n", + tab_rp_file[i + 1], + 0); + goto close; + } } + printf("OK\n"); } - printf("OK\n"); - } - - printf("\nTEST WRITE GENERAL REFERENCE\n"); { - for (i=1; i < 5 ; i++){ - rc = modbus_write_general_reference(ctx, i, i*7 , UT_FILE_REGISTER_NB-i, &UT_FILE_REGISTER_TAB[i] ); + for (i = 1; i < 5; i++) { + rc = modbus_write_general_reference(ctx, i, i * 7, UT_FILE_REGISTER_NB - i, &UT_FILE_REGISTER_TAB[i]); - printf("modbus_write_general_reference File_no %d: ",i); + printf("modbus_write_general_reference File_no %d: ", i); - if (rc < (UT_FILE_REGISTER_NB+1-i)) { // 2 bytes per register + 2 bytes header - printf("FAILED (nb points %d)\n", rc); - goto close; - } - printf("OK\n"); - - } + if (rc < (UT_FILE_REGISTER_NB + 1 - i)) { // 2 bytes per register + 2 bytes header + printf("FAILED (nb points %d)\n", rc); + goto close; + } + printf("OK\n"); + } - for (i=1; i < 5 ; i++){ - rc = modbus_read_general_reference(ctx, i, i*7 , UT_FILE_REGISTER_NB-1, tab_rp_file ); + for (i = 1; i < 5; i++) { + rc = modbus_read_general_reference(ctx, i, i * 7, UT_FILE_REGISTER_NB - 1, tab_rp_file); - printf("modbus_read_general_reference File_no %d: ",i); + printf("modbus_read_general_reference File_no %d: ", i); - if (rc < (UT_FILE_REGISTER_NB+1-i)) { // 2 bytes per register + 2 bytes header - printf("FAILED (nb points %d)\n", rc); - goto close; - } + if (rc < (UT_FILE_REGISTER_NB + 1 - i)) { // 2 bytes per register + 2 bytes header + printf("FAILED (nb points %d)\n", rc); + goto close; + } - printf("OK , Verify : "); + printf("OK , Verify : "); - for (j=0; j < (UT_FILE_REGISTER_NB-i); j++) { - if (tab_rp_file[j+1] != UT_FILE_REGISTER_TAB[j+i]) { - printf("FAILED (%0X != %0X) at %d \n", - tab_rp_file[j+1], - UT_FILE_REGISTER_TAB[j+i], j); - goto close; - } - } - printf("OK\n"); + for (j = 0; j < (UT_FILE_REGISTER_NB - i); j++) { + if (tab_rp_file[j + 1] != UT_FILE_REGISTER_TAB[j + i]) { + printf("FAILED (%0X != %0X) at %d \n", + tab_rp_file[j + 1], + UT_FILE_REGISTER_TAB[j + i], j); + goto close; } + } + printf("OK\n"); } + } - /* Writing to a non existing file */ - rc = modbus_write_general_reference(ctx, 6, 0 , UT_FILE_REGISTER_NB, UT_FILE_REGISTER_TAB ); - - printf("modbus_write_general_reference File_no 6 "); - - if (rc == -1 && errno ==EMBXILVAL) { // This should fail - printf("OK\n"); - }else{ - printf("FAILED (nb points %d) errno %d \n", rc, errno ); - goto close; - } - + /* Writing to a non existing file */ + rc = modbus_write_general_reference(ctx, 6, 0, UT_FILE_REGISTER_NB, UT_FILE_REGISTER_TAB); + printf("modbus_write_general_reference File_no 6 "); + if (rc == -1 && errno == EMBXILVAL) { // This should fail + printf("OK\n"); + } else { + printf("FAILED (nb points %d) errno %d \n", rc, errno); + goto close; + } /** Run a few tests to challenge the server code **/ if (test_server(ctx, use_backend) == -1) { diff --git a/tests/unit-test-server.c b/tests/unit-test-server.c index f77692489..6f8d65019 100644 --- a/tests/unit-test-server.c +++ b/tests/unit-test-server.c @@ -39,8 +39,10 @@ int main(int argc, char*argv[]) int use_backend; uint8_t *query; int header_length; - char devicename[MAX_DEVICENAME_LENGHT]={0,}; - int baudrate=115200; + char devicename[MAX_DEVICENAME_LENGHT] = { + 0, + }; + int baudrate = 115200; if (argc > 1) { if (strcmp(argv[1], "tcp") == 0) { @@ -58,15 +60,13 @@ int main(int argc, char*argv[]) use_backend = TCP; } - if (argc>2) - { - strncpy(devicename,argv[2],MAX_DEVICENAME_LENGHT); - }else{ - strncpy(devicename,"/dev/ttyUSB0",MAX_DEVICENAME_LENGHT); + if (argc > 2) { + strncpy(devicename, argv[2], MAX_DEVICENAME_LENGHT); + } else { + strncpy(devicename, "/dev/ttyUSB0", MAX_DEVICENAME_LENGHT); } - if (argc>3) - { - baudrate=atoi(argv[3]); + if (argc > 3) { + baudrate = atoi(argv[3]); } if (use_backend == TCP) { @@ -84,13 +84,11 @@ int main(int argc, char*argv[]) modbus_set_debug(ctx, TRUE); - - - mb_mapping = modbus_mapping_new_start_address_extend ( + mb_mapping = modbus_mapping_new_start_address_extend( UT_BITS_ADDRESS, UT_BITS_NB, UT_INPUT_BITS_ADDRESS, UT_INPUT_BITS_NB, UT_REGISTERS_ADDRESS, UT_REGISTERS_NB_MAX, - UT_INPUT_REGISTERS_ADDRESS, UT_INPUT_REGISTERS_NB, + UT_INPUT_REGISTERS_ADDRESS, UT_INPUT_REGISTERS_NB, UT_FILE_REGISTERS_NB); if (mb_mapping == NULL) {