Commit 52ab1bbea760ed8eaca184f7d875a2f52a116d0f
Committed by
Stéphane Raimbault
1 parent
1776a350
Introduce offsets in modbus mappings
This allows to place the coils/registers at any virtual start address, not only at address 0. This can be useful e.g. when the server has to fulfill a specification in which registers are expected at predefined locations. Signed-off-by: Michael Heimpold <mhei@heimpold.de>
Showing
5 changed files
with
152 additions
and
37 deletions
doc/Makefile.am
doc/modbus_mapping_new.txt
| ... | ... | @@ -18,6 +18,9 @@ The *modbus_mapping_new()* function shall allocate four arrays to store bits, |
| 18 | 18 | input bits, registers and inputs registers. The pointers are stored in |
| 19 | 19 | modbus_mapping_t structure. All values of the arrays are initialized to zero. |
| 20 | 20 | |
| 21 | +This function is equivalent to a call of the _modbus_mapping_offset_new()_ function | |
| 22 | +with all offsets set to zero. | |
| 23 | + | |
| 21 | 24 | If it isn't necessary to allocate an array for a specific type of data, you can |
| 22 | 25 | pass the zero value in argument, the associated pointer will be NULL. |
| 23 | 26 | |
| ... | ... | @@ -40,7 +43,7 @@ EXAMPLE |
| 40 | 43 | ------- |
| 41 | 44 | [source,c] |
| 42 | 45 | ------------------- |
| 43 | -/* The fist value of each array is accessible from the 0 address. */ | |
| 46 | +/* The first value of each array is accessible from the 0 address. */ | |
| 44 | 47 | mb_mapping = modbus_mapping_new(BITS_ADDRESS + BITS_NB, |
| 45 | 48 | INPUT_BITS_ADDRESS + INPUT_BITS_NB, |
| 46 | 49 | REGISTERS_ADDRESS + REGISTERS_NB, | ... | ... |
doc/modbus_mapping_offset_new.txt
0 → 100644
| 1 | +modbus_mapping_offset_new(3) | |
| 2 | +============================ | |
| 3 | + | |
| 4 | + | |
| 5 | +NAME | |
| 6 | +---- | |
| 7 | +modbus_mapping_offset_new - allocate four arrays of bits and registers | |
| 8 | + | |
| 9 | + | |
| 10 | +SYNOPSIS | |
| 11 | +-------- | |
| 12 | +*modbus_mapping_t* modbus_mapping_new(int 'nb_bits', int 'offset_bits', | |
| 13 | + int 'nb_input_bits', int 'offset_input_bits', | |
| 14 | + int 'nb_registers', int 'offset_registers', | |
| 15 | + int 'nb_input_registers', int 'offset_input_registers');* | |
| 16 | + | |
| 17 | + | |
| 18 | +DESCRIPTION | |
| 19 | +----------- | |
| 20 | +The _modbus_mapping_offset_new()_ function shall allocate four arrays to store bits, | |
| 21 | +input bits, registers and inputs registers. The pointers are stored in | |
| 22 | +modbus_mapping_t structure. All values of the arrays are initialized to zero. | |
| 23 | + | |
| 24 | +The different offsets make it possible to place the mapping at any address in | |
| 25 | +each address space. | |
| 26 | + | |
| 27 | +If it isn't necessary to allocate an array for a specific type of data, you can | |
| 28 | +pass the zero value in argument, the associated pointer will be NULL. | |
| 29 | + | |
| 30 | +This function is convenient to handle requests in a Modbus server/slave. | |
| 31 | + | |
| 32 | + | |
| 33 | +RETURN VALUE | |
| 34 | +------------ | |
| 35 | +The _modbus_mapping_offset_new()_ function shall return the new allocated structure if | |
| 36 | +successful. Otherwise it shall return NULL and set errno. | |
| 37 | + | |
| 38 | + | |
| 39 | +ERRORS | |
| 40 | +------ | |
| 41 | +ENOMEM:: | |
| 42 | +Not enough memory | |
| 43 | + | |
| 44 | + | |
| 45 | +EXAMPLE | |
| 46 | +------- | |
| 47 | +[source,c] | |
| 48 | +------------------- | |
| 49 | +/* The first value of each array is accessible at address 4. */ | |
| 50 | +mb_mapping = modbus_mapping_offset_new(BITS_ADDRESS + BITS_NB, 4, | |
| 51 | + INPUT_BITS_ADDRESS + INPUT_BITS_NB, 4, | |
| 52 | + REGISTERS_ADDRESS + REGISTERS_NB, 4, | |
| 53 | + INPUT_REGISTERS_ADDRESS + INPUT_REGISTERS_NB, 4); | |
| 54 | +if (mb_mapping == NULL) { | |
| 55 | + fprintf(stderr, "Failed to allocate the mapping: %s\n", | |
| 56 | + modbus_strerror(errno)); | |
| 57 | + modbus_free(ctx); | |
| 58 | + return -1; | |
| 59 | +} | |
| 60 | +------------------- | |
| 61 | + | |
| 62 | +SEE ALSO | |
| 63 | +-------- | |
| 64 | +linkmb:modbus_mapping_free[3] | |
| 65 | + | |
| 66 | + | |
| 67 | +AUTHORS | |
| 68 | +------- | |
| 69 | +The libmodbus documentation was written by Stéphane Raimbault | |
| 70 | +<stephane.raimbault@gmail.com> | ... | ... |
src/modbus.c
| ... | ... | @@ -706,6 +706,7 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, |
| 706 | 706 | switch (function) { |
| 707 | 707 | case MODBUS_FC_READ_COILS: { |
| 708 | 708 | int nb = (req[offset + 3] << 8) + req[offset + 4]; |
| 709 | + int addr = address - mb_mapping->offset_bits; | |
| 709 | 710 | |
| 710 | 711 | if (nb < 1 || MODBUS_MAX_READ_BITS < nb) { |
| 711 | 712 | if (ctx->debug) { |
| ... | ... | @@ -718,10 +719,10 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, |
| 718 | 719 | rsp_length = response_exception( |
| 719 | 720 | ctx, &sft, |
| 720 | 721 | MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp); |
| 721 | - } else if ((address + nb) > mb_mapping->nb_bits) { | |
| 722 | + } else if (address < mb_mapping->offset_bits || (addr + nb) > mb_mapping->nb_bits) { | |
| 722 | 723 | if (ctx->debug) { |
| 723 | 724 | fprintf(stderr, "Illegal data address 0x%0X in read_bits\n", |
| 724 | - address + nb); | |
| 725 | + address < mb_mapping->offset_bits ? address : address + nb); | |
| 725 | 726 | } |
| 726 | 727 | rsp_length = response_exception( |
| 727 | 728 | ctx, &sft, |
| ... | ... | @@ -729,7 +730,7 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, |
| 729 | 730 | } else { |
| 730 | 731 | rsp_length = ctx->backend->build_response_basis(&sft, rsp); |
| 731 | 732 | rsp[rsp_length++] = (nb / 8) + ((nb % 8) ? 1 : 0); |
| 732 | - rsp_length = response_io_status(address, nb, | |
| 733 | + rsp_length = response_io_status(addr, nb, | |
| 733 | 734 | mb_mapping->tab_bits, |
| 734 | 735 | rsp, rsp_length); |
| 735 | 736 | } |
| ... | ... | @@ -739,6 +740,7 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, |
| 739 | 740 | /* Similar to coil status (but too many arguments to use a |
| 740 | 741 | * function) */ |
| 741 | 742 | int nb = (req[offset + 3] << 8) + req[offset + 4]; |
| 743 | + int addr = address - mb_mapping->offset_input_bits; | |
| 742 | 744 | |
| 743 | 745 | if (nb < 1 || MODBUS_MAX_READ_BITS < nb) { |
| 744 | 746 | if (ctx->debug) { |
| ... | ... | @@ -751,10 +753,10 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, |
| 751 | 753 | rsp_length = response_exception( |
| 752 | 754 | ctx, &sft, |
| 753 | 755 | MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp); |
| 754 | - } else if ((address + nb) > mb_mapping->nb_input_bits) { | |
| 756 | + } else if (address < mb_mapping->offset_input_bits || (addr + nb) > mb_mapping->nb_input_bits) { | |
| 755 | 757 | if (ctx->debug) { |
| 756 | 758 | fprintf(stderr, "Illegal data address 0x%0X in read_input_bits\n", |
| 757 | - address + nb); | |
| 759 | + address < mb_mapping->offset_input_bits ? address : address + nb); | |
| 758 | 760 | } |
| 759 | 761 | rsp_length = response_exception( |
| 760 | 762 | ctx, &sft, |
| ... | ... | @@ -762,7 +764,7 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, |
| 762 | 764 | } else { |
| 763 | 765 | rsp_length = ctx->backend->build_response_basis(&sft, rsp); |
| 764 | 766 | rsp[rsp_length++] = (nb / 8) + ((nb % 8) ? 1 : 0); |
| 765 | - rsp_length = response_io_status(address, nb, | |
| 767 | + rsp_length = response_io_status(addr, nb, | |
| 766 | 768 | mb_mapping->tab_input_bits, |
| 767 | 769 | rsp, rsp_length); |
| 768 | 770 | } |
| ... | ... | @@ -770,6 +772,7 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, |
| 770 | 772 | break; |
| 771 | 773 | case MODBUS_FC_READ_HOLDING_REGISTERS: { |
| 772 | 774 | int nb = (req[offset + 3] << 8) + req[offset + 4]; |
| 775 | + int addr = address - mb_mapping->offset_registers; | |
| 773 | 776 | |
| 774 | 777 | if (nb < 1 || MODBUS_MAX_READ_REGISTERS < nb) { |
| 775 | 778 | if (ctx->debug) { |
| ... | ... | @@ -782,10 +785,10 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, |
| 782 | 785 | rsp_length = response_exception( |
| 783 | 786 | ctx, &sft, |
| 784 | 787 | MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp); |
| 785 | - } else if ((address + nb) > mb_mapping->nb_registers) { | |
| 788 | + } else if (address < mb_mapping->offset_registers || (addr + nb) > mb_mapping->nb_registers) { | |
| 786 | 789 | if (ctx->debug) { |
| 787 | 790 | fprintf(stderr, "Illegal data address 0x%0X in read_registers\n", |
| 788 | - address + nb); | |
| 791 | + address < mb_mapping->offset_registers ? address : address + nb); | |
| 789 | 792 | } |
| 790 | 793 | rsp_length = response_exception( |
| 791 | 794 | ctx, &sft, |
| ... | ... | @@ -795,7 +798,7 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, |
| 795 | 798 | |
| 796 | 799 | rsp_length = ctx->backend->build_response_basis(&sft, rsp); |
| 797 | 800 | rsp[rsp_length++] = nb << 1; |
| 798 | - for (i = address; i < address + nb; i++) { | |
| 801 | + for (i = addr; i < addr + nb; i++) { | |
| 799 | 802 | rsp[rsp_length++] = mb_mapping->tab_registers[i] >> 8; |
| 800 | 803 | rsp[rsp_length++] = mb_mapping->tab_registers[i] & 0xFF; |
| 801 | 804 | } |
| ... | ... | @@ -806,6 +809,7 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, |
| 806 | 809 | /* Similar to holding registers (but too many arguments to use a |
| 807 | 810 | * function) */ |
| 808 | 811 | int nb = (req[offset + 3] << 8) + req[offset + 4]; |
| 812 | + int addr = address - mb_mapping->offset_input_registers; | |
| 809 | 813 | |
| 810 | 814 | if (nb < 1 || MODBUS_MAX_READ_REGISTERS < nb) { |
| 811 | 815 | if (ctx->debug) { |
| ... | ... | @@ -818,10 +822,10 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, |
| 818 | 822 | rsp_length = response_exception( |
| 819 | 823 | ctx, &sft, |
| 820 | 824 | MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp); |
| 821 | - } else if ((address + nb) > mb_mapping->nb_input_registers) { | |
| 825 | + } else if (address < mb_mapping->offset_input_registers || (addr + nb) > mb_mapping->nb_input_registers) { | |
| 822 | 826 | if (ctx->debug) { |
| 823 | 827 | fprintf(stderr, "Illegal data address 0x%0X in read_input_registers\n", |
| 824 | - address + nb); | |
| 828 | + address < mb_mapping->offset_input_registers ? address : address + nb); | |
| 825 | 829 | } |
| 826 | 830 | rsp_length = response_exception( |
| 827 | 831 | ctx, &sft, |
| ... | ... | @@ -831,15 +835,17 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, |
| 831 | 835 | |
| 832 | 836 | rsp_length = ctx->backend->build_response_basis(&sft, rsp); |
| 833 | 837 | rsp[rsp_length++] = nb << 1; |
| 834 | - for (i = address; i < address + nb; i++) { | |
| 838 | + for (i = addr; i < addr + nb; i++) { | |
| 835 | 839 | rsp[rsp_length++] = mb_mapping->tab_input_registers[i] >> 8; |
| 836 | 840 | rsp[rsp_length++] = mb_mapping->tab_input_registers[i] & 0xFF; |
| 837 | 841 | } |
| 838 | 842 | } |
| 839 | 843 | } |
| 840 | 844 | break; |
| 841 | - case MODBUS_FC_WRITE_SINGLE_COIL: | |
| 842 | - if (address >= mb_mapping->nb_bits) { | |
| 845 | + case MODBUS_FC_WRITE_SINGLE_COIL: { | |
| 846 | + int addr = address - mb_mapping->offset_bits; | |
| 847 | + | |
| 848 | + if (address < mb_mapping->offset_bits || addr >= mb_mapping->nb_bits) { | |
| 843 | 849 | if (ctx->debug) { |
| 844 | 850 | fprintf(stderr, |
| 845 | 851 | "Illegal data address 0x%0X in write_bit\n", |
| ... | ... | @@ -852,7 +858,7 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, |
| 852 | 858 | int data = (req[offset + 3] << 8) + req[offset + 4]; |
| 853 | 859 | |
| 854 | 860 | if (data == 0xFF00 || data == 0x0) { |
| 855 | - mb_mapping->tab_bits[address] = (data) ? ON : OFF; | |
| 861 | + mb_mapping->tab_bits[addr] = (data) ? ON : OFF; | |
| 856 | 862 | memcpy(rsp, req, req_length); |
| 857 | 863 | rsp_length = req_length; |
| 858 | 864 | } else { |
| ... | ... | @@ -866,9 +872,12 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, |
| 866 | 872 | MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp); |
| 867 | 873 | } |
| 868 | 874 | } |
| 875 | + } | |
| 869 | 876 | break; |
| 870 | - case MODBUS_FC_WRITE_SINGLE_REGISTER: | |
| 871 | - if (address >= mb_mapping->nb_registers) { | |
| 877 | + case MODBUS_FC_WRITE_SINGLE_REGISTER: { | |
| 878 | + int addr = address - mb_mapping->offset_registers; | |
| 879 | + | |
| 880 | + if (address < mb_mapping->offset_registers || addr >= mb_mapping->nb_registers) { | |
| 872 | 881 | if (ctx->debug) { |
| 873 | 882 | fprintf(stderr, "Illegal data address 0x%0X in write_register\n", |
| 874 | 883 | address); |
| ... | ... | @@ -879,13 +888,15 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, |
| 879 | 888 | } else { |
| 880 | 889 | int data = (req[offset + 3] << 8) + req[offset + 4]; |
| 881 | 890 | |
| 882 | - mb_mapping->tab_registers[address] = data; | |
| 891 | + mb_mapping->tab_registers[addr] = data; | |
| 883 | 892 | memcpy(rsp, req, req_length); |
| 884 | 893 | rsp_length = req_length; |
| 885 | 894 | } |
| 895 | + } | |
| 886 | 896 | break; |
| 887 | 897 | case MODBUS_FC_WRITE_MULTIPLE_COILS: { |
| 888 | 898 | int nb = (req[offset + 3] << 8) + req[offset + 4]; |
| 899 | + int addr = address - mb_mapping->offset_bits; | |
| 889 | 900 | |
| 890 | 901 | if (nb < 1 || MODBUS_MAX_WRITE_BITS < nb) { |
| 891 | 902 | if (ctx->debug) { |
| ... | ... | @@ -901,17 +912,17 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, |
| 901 | 912 | rsp_length = response_exception( |
| 902 | 913 | ctx, &sft, |
| 903 | 914 | MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp); |
| 904 | - } else if ((address + nb) > mb_mapping->nb_bits) { | |
| 915 | + } else if (address < mb_mapping->offset_bits || (addr + nb) > mb_mapping->nb_bits) { | |
| 905 | 916 | if (ctx->debug) { |
| 906 | 917 | fprintf(stderr, "Illegal data address 0x%0X in write_bits\n", |
| 907 | - address + nb); | |
| 918 | + address < mb_mapping->offset_bits ? address : address + nb); | |
| 908 | 919 | } |
| 909 | 920 | rsp_length = response_exception( |
| 910 | 921 | ctx, &sft, |
| 911 | 922 | MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp); |
| 912 | 923 | } else { |
| 913 | 924 | /* 6 = byte count */ |
| 914 | - modbus_set_bits_from_bytes(mb_mapping->tab_bits, address, nb, &req[offset + 6]); | |
| 925 | + modbus_set_bits_from_bytes(mb_mapping->tab_bits, addr, nb, &req[offset + 6]); | |
| 915 | 926 | |
| 916 | 927 | rsp_length = ctx->backend->build_response_basis(&sft, rsp); |
| 917 | 928 | /* 4 to copy the bit address (2) and the quantity of bits */ |
| ... | ... | @@ -922,6 +933,8 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, |
| 922 | 933 | break; |
| 923 | 934 | case MODBUS_FC_WRITE_MULTIPLE_REGISTERS: { |
| 924 | 935 | int nb = (req[offset + 3] << 8) + req[offset + 4]; |
| 936 | + int addr = address - mb_mapping->offset_registers; | |
| 937 | + | |
| 925 | 938 | if (nb < 1 || MODBUS_MAX_WRITE_REGISTERS < nb) { |
| 926 | 939 | if (ctx->debug) { |
| 927 | 940 | fprintf(stderr, |
| ... | ... | @@ -936,17 +949,17 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, |
| 936 | 949 | rsp_length = response_exception( |
| 937 | 950 | ctx, &sft, |
| 938 | 951 | MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp); |
| 939 | - } else if ((address + nb) > mb_mapping->nb_registers) { | |
| 952 | + } else if (address < mb_mapping->offset_registers || (addr + nb) > mb_mapping->nb_registers) { | |
| 940 | 953 | if (ctx->debug) { |
| 941 | 954 | fprintf(stderr, "Illegal data address 0x%0X in write_registers\n", |
| 942 | - address + nb); | |
| 955 | + address < mb_mapping->offset_registers ? address : address + nb); | |
| 943 | 956 | } |
| 944 | 957 | rsp_length = response_exception( |
| 945 | 958 | ctx, &sft, |
| 946 | 959 | MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp); |
| 947 | 960 | } else { |
| 948 | 961 | int i, j; |
| 949 | - for (i = address, j = 6; i < address + nb; i++, j += 2) { | |
| 962 | + for (i = addr, j = 6; i < addr + nb; i++, j += 2) { | |
| 950 | 963 | /* 6 and 7 = first value */ |
| 951 | 964 | mb_mapping->tab_registers[i] = |
| 952 | 965 | (req[offset + j] << 8) + req[offset + j + 1]; |
| ... | ... | @@ -983,8 +996,10 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, |
| 983 | 996 | errno = ENOPROTOOPT; |
| 984 | 997 | return -1; |
| 985 | 998 | break; |
| 986 | - case MODBUS_FC_MASK_WRITE_REGISTER: | |
| 987 | - if (address >= mb_mapping->nb_registers) { | |
| 999 | + case MODBUS_FC_MASK_WRITE_REGISTER: { | |
| 1000 | + int addr = address - mb_mapping->offset_registers; | |
| 1001 | + | |
| 1002 | + if (address < mb_mapping->offset_registers || addr >= mb_mapping->nb_registers) { | |
| 988 | 1003 | if (ctx->debug) { |
| 989 | 1004 | fprintf(stderr, "Illegal data address 0x%0X in write_register\n", |
| 990 | 1005 | address); |
| ... | ... | @@ -993,21 +1008,24 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, |
| 993 | 1008 | ctx, &sft, |
| 994 | 1009 | MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp); |
| 995 | 1010 | } else { |
| 996 | - uint16_t data = mb_mapping->tab_registers[address]; | |
| 1011 | + uint16_t data = mb_mapping->tab_registers[addr]; | |
| 997 | 1012 | uint16_t and = (req[offset + 3] << 8) + req[offset + 4]; |
| 998 | 1013 | uint16_t or = (req[offset + 5] << 8) + req[offset + 6]; |
| 999 | 1014 | |
| 1000 | 1015 | data = (data & and) | (or & (~and)); |
| 1001 | - mb_mapping->tab_registers[address] = data; | |
| 1016 | + mb_mapping->tab_registers[addr] = data; | |
| 1002 | 1017 | memcpy(rsp, req, req_length); |
| 1003 | 1018 | rsp_length = req_length; |
| 1004 | 1019 | } |
| 1020 | + } | |
| 1005 | 1021 | break; |
| 1006 | 1022 | case MODBUS_FC_WRITE_AND_READ_REGISTERS: { |
| 1007 | 1023 | int nb = (req[offset + 3] << 8) + req[offset + 4]; |
| 1008 | 1024 | uint16_t address_write = (req[offset + 5] << 8) + req[offset + 6]; |
| 1009 | 1025 | int nb_write = (req[offset + 7] << 8) + req[offset + 8]; |
| 1010 | 1026 | int nb_write_bytes = req[offset + 9]; |
| 1027 | + int addr = address - mb_mapping->offset_registers; | |
| 1028 | + int addr_write = address_write - mb_mapping->offset_registers; | |
| 1011 | 1029 | |
| 1012 | 1030 | if (nb_write < 1 || MODBUS_MAX_WR_WRITE_REGISTERS < nb_write || |
| 1013 | 1031 | nb < 1 || MODBUS_MAX_WR_READ_REGISTERS < nb || |
| ... | ... | @@ -1023,12 +1041,15 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, |
| 1023 | 1041 | rsp_length = response_exception( |
| 1024 | 1042 | ctx, &sft, |
| 1025 | 1043 | MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp); |
| 1026 | - } else if ((address + nb) > mb_mapping->nb_registers || | |
| 1027 | - (address_write + nb_write) > mb_mapping->nb_registers) { | |
| 1044 | + } else if (address < mb_mapping->offset_registers || | |
| 1045 | + (addr + nb) > mb_mapping->nb_registers || | |
| 1046 | + address_write < mb_mapping->offset_registers || | |
| 1047 | + (addr_write + nb_write) > mb_mapping->nb_registers) { | |
| 1028 | 1048 | if (ctx->debug) { |
| 1029 | 1049 | fprintf(stderr, |
| 1030 | 1050 | "Illegal data read address 0x%0X or write address 0x%0X write_and_read_registers\n", |
| 1031 | - address + nb, address_write + nb_write); | |
| 1051 | + address < mb_mapping->offset_registers ? address : address + nb, | |
| 1052 | + address_write < mb_mapping->offset_registers ? address_write : address_write + nb_write); | |
| 1032 | 1053 | } |
| 1033 | 1054 | rsp_length = response_exception(ctx, &sft, |
| 1034 | 1055 | MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp); |
| ... | ... | @@ -1039,13 +1060,13 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, |
| 1039 | 1060 | |
| 1040 | 1061 | /* Write first. |
| 1041 | 1062 | 10 and 11 are the offset of the first values to write */ |
| 1042 | - for (i = address_write, j = 10; i < address_write + nb_write; i++, j += 2) { | |
| 1063 | + for (i = addr_write, j = 10; i < addr_write + nb_write; i++, j += 2) { | |
| 1043 | 1064 | mb_mapping->tab_registers[i] = |
| 1044 | 1065 | (req[offset + j] << 8) + req[offset + j + 1]; |
| 1045 | 1066 | } |
| 1046 | 1067 | |
| 1047 | 1068 | /* and read the data for the response */ |
| 1048 | - for (i = address; i < address + nb; i++) { | |
| 1069 | + for (i = addr; i < addr + nb; i++) { | |
| 1049 | 1070 | rsp[rsp_length++] = mb_mapping->tab_registers[i] >> 8; |
| 1050 | 1071 | rsp[rsp_length++] = mb_mapping->tab_registers[i] & 0xFF; |
| 1051 | 1072 | } |
| ... | ... | @@ -1786,10 +1807,12 @@ int modbus_set_debug(modbus_t *ctx, int flag) |
| 1786 | 1807 | /* Allocates 4 arrays to store bits, input bits, registers and inputs |
| 1787 | 1808 | registers. The pointers are stored in modbus_mapping structure. |
| 1788 | 1809 | |
| 1789 | - The modbus_mapping_new() function shall return the new allocated structure if | |
| 1810 | + The modbus_mapping_offset_new() function shall return the new allocated structure if | |
| 1790 | 1811 | successful. Otherwise it shall return NULL and set errno to ENOMEM. */ |
| 1791 | -modbus_mapping_t* modbus_mapping_new(int nb_bits, int nb_input_bits, | |
| 1792 | - int nb_registers, int nb_input_registers) | |
| 1812 | +modbus_mapping_t* modbus_mapping_offset_new(int nb_bits, int offset_bits, | |
| 1813 | + int nb_input_bits, int offset_input_bits, | |
| 1814 | + int nb_registers, int offset_registers, | |
| 1815 | + int nb_input_registers, int offset_input_registers) | |
| 1793 | 1816 | { |
| 1794 | 1817 | modbus_mapping_t *mb_mapping; |
| 1795 | 1818 | |
| ... | ... | @@ -1800,6 +1823,7 @@ modbus_mapping_t* modbus_mapping_new(int nb_bits, int nb_input_bits, |
| 1800 | 1823 | |
| 1801 | 1824 | /* 0X */ |
| 1802 | 1825 | mb_mapping->nb_bits = nb_bits; |
| 1826 | + mb_mapping->offset_bits = offset_bits; | |
| 1803 | 1827 | if (nb_bits == 0) { |
| 1804 | 1828 | mb_mapping->tab_bits = NULL; |
| 1805 | 1829 | } else { |
| ... | ... | @@ -1815,6 +1839,7 @@ modbus_mapping_t* modbus_mapping_new(int nb_bits, int nb_input_bits, |
| 1815 | 1839 | |
| 1816 | 1840 | /* 1X */ |
| 1817 | 1841 | mb_mapping->nb_input_bits = nb_input_bits; |
| 1842 | + mb_mapping->offset_input_bits = offset_input_bits; | |
| 1818 | 1843 | if (nb_input_bits == 0) { |
| 1819 | 1844 | mb_mapping->tab_input_bits = NULL; |
| 1820 | 1845 | } else { |
| ... | ... | @@ -1830,6 +1855,7 @@ modbus_mapping_t* modbus_mapping_new(int nb_bits, int nb_input_bits, |
| 1830 | 1855 | |
| 1831 | 1856 | /* 4X */ |
| 1832 | 1857 | mb_mapping->nb_registers = nb_registers; |
| 1858 | + mb_mapping->offset_registers = offset_registers; | |
| 1833 | 1859 | if (nb_registers == 0) { |
| 1834 | 1860 | mb_mapping->tab_registers = NULL; |
| 1835 | 1861 | } else { |
| ... | ... | @@ -1846,6 +1872,7 @@ modbus_mapping_t* modbus_mapping_new(int nb_bits, int nb_input_bits, |
| 1846 | 1872 | |
| 1847 | 1873 | /* 3X */ |
| 1848 | 1874 | mb_mapping->nb_input_registers = nb_input_registers; |
| 1875 | + mb_mapping->offset_input_registers = offset_input_registers; | |
| 1849 | 1876 | if (nb_input_registers == 0) { |
| 1850 | 1877 | mb_mapping->tab_input_registers = NULL; |
| 1851 | 1878 | } else { |
| ... | ... | @@ -1865,6 +1892,12 @@ modbus_mapping_t* modbus_mapping_new(int nb_bits, int nb_input_bits, |
| 1865 | 1892 | return mb_mapping; |
| 1866 | 1893 | } |
| 1867 | 1894 | |
| 1895 | +modbus_mapping_t* modbus_mapping_new(int nb_bits, int nb_input_bits, | |
| 1896 | + int nb_registers, int nb_input_registers) | |
| 1897 | +{ | |
| 1898 | + return modbus_mapping_offset_new(nb_bits, 0, nb_input_bits, 0, nb_registers, 0, nb_input_registers, 0); | |
| 1899 | +} | |
| 1900 | + | |
| 1868 | 1901 | /* Frees the 4 arrays */ |
| 1869 | 1902 | void modbus_mapping_free(modbus_mapping_t *mb_mapping) |
| 1870 | 1903 | { | ... | ... |
src/modbus.h
| ... | ... | @@ -156,9 +156,13 @@ typedef struct _modbus modbus_t; |
| 156 | 156 | |
| 157 | 157 | typedef struct { |
| 158 | 158 | int nb_bits; |
| 159 | + int offset_bits; | |
| 159 | 160 | int nb_input_bits; |
| 161 | + int offset_input_bits; | |
| 160 | 162 | int nb_input_registers; |
| 163 | + int offset_input_registers; | |
| 161 | 164 | int nb_registers; |
| 165 | + int offset_registers; | |
| 162 | 166 | uint8_t *tab_bits; |
| 163 | 167 | uint8_t *tab_input_bits; |
| 164 | 168 | uint16_t *tab_input_registers; |
| ... | ... | @@ -209,6 +213,10 @@ MODBUS_API int modbus_write_and_read_registers(modbus_t *ctx, int write_addr, in |
| 209 | 213 | uint16_t *dest); |
| 210 | 214 | MODBUS_API int modbus_report_slave_id(modbus_t *ctx, int max_dest, uint8_t *dest); |
| 211 | 215 | |
| 216 | +MODBUS_API modbus_mapping_t* modbus_mapping_offset_new(int nb_bits, int offset_bits, | |
| 217 | + int nb_input_bits, int offset_input_bits, | |
| 218 | + int nb_registers, int offset_registers, | |
| 219 | + int nb_input_registers, int offset_input_registers); | |
| 212 | 220 | MODBUS_API modbus_mapping_t* modbus_mapping_new(int nb_bits, int nb_input_bits, |
| 213 | 221 | int nb_registers, int nb_input_registers); |
| 214 | 222 | MODBUS_API void modbus_mapping_free(modbus_mapping_t *mb_mapping); | ... | ... |