Commit 66c59d6f852811900f4b7730d0d5d8f321f2226f

Authored by Stéphane Raimbault
1 parent 5ab6c0e1

Change indent level from 8 to 4

.dir-locals.el
1 ((nil . ((indent-tabs-mode . nil) 1 ((nil . ((indent-tabs-mode . nil)
2 - (c-basic-offset . 8) 2 + (c-basic-offset . 4)
3 (fill-column . 80)))) 3 (fill-column . 80))))
4 4
src/modbus.c
@@ -16,16 +16,16 @@ @@ -16,16 +16,16 @@
16 */ 16 */
17 17
18 /* 18 /*
19 - The library is designed to send and receive data from a device that  
20 - communicate via the Modbus protocol. 19 + The library is designed to send and receive data from a device that
  20 + communicate via the Modbus protocol.
21 21
22 - The function names used are inspired by the Modicon Modbus Protocol  
23 - Reference Guide which can be obtained from Schneider at  
24 - www.schneiderautomation.com. 22 + The function names used are inspired by the Modicon Modbus Protocol
  23 + Reference Guide which can be obtained from Schneider at
  24 + www.schneiderautomation.com.
25 25
26 - Documentation:  
27 - http://www.easysw.com/~mike/serial/serial.html  
28 - http://copyleft.free.fr/wordpress/index.php/libmodbus/ 26 + Documentation:
  27 + http://www.easysw.com/~mike/serial/serial.html
  28 + http://copyleft.free.fr/wordpress/index.php/libmodbus/
29 */ 29 */
30 30
31 #include <stdio.h> 31 #include <stdio.h>
@@ -72,205 +72,205 @@ const unsigned int libmodbus_version_micro = LIBMODBUS_VERSION_MICRO; @@ -72,205 +72,205 @@ const unsigned int libmodbus_version_micro = LIBMODBUS_VERSION_MICRO;
72 /* This structure reduces the number of params in functions and so 72 /* This structure reduces the number of params in functions and so
73 * optimizes the speed of execution (~ 37%). */ 73 * optimizes the speed of execution (~ 37%). */
74 typedef struct { 74 typedef struct {
75 - int slave;  
76 - int function;  
77 - int t_id; 75 + int slave;
  76 + int function;
  77 + int t_id;
78 } sft_t; 78 } sft_t;
79 79
80 /* Table of CRC values for high-order byte */ 80 /* Table of CRC values for high-order byte */
81 static uint8_t table_crc_hi[] = { 81 static uint8_t table_crc_hi[] = {
82 - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,  
83 - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,  
84 - 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,  
85 - 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,  
86 - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,  
87 - 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,  
88 - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,  
89 - 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,  
90 - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,  
91 - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,  
92 - 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,  
93 - 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,  
94 - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,  
95 - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,  
96 - 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,  
97 - 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,  
98 - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,  
99 - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,  
100 - 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,  
101 - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,  
102 - 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,  
103 - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,  
104 - 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,  
105 - 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,  
106 - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,  
107 - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 82 + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
  83 + 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  84 + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
  85 + 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
  86 + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
  87 + 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
  88 + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
  89 + 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  90 + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
  91 + 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
  92 + 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
  93 + 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
  94 + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
  95 + 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
  96 + 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
  97 + 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
  98 + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
  99 + 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  100 + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
  101 + 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  102 + 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
  103 + 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
  104 + 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
  105 + 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  106 + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
  107 + 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
108 }; 108 };
109 109
110 /* Table of CRC values for low-order byte */ 110 /* Table of CRC values for low-order byte */
111 static uint8_t table_crc_lo[] = { 111 static uint8_t table_crc_lo[] = {
112 - 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,  
113 - 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,  
114 - 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,  
115 - 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,  
116 - 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,  
117 - 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,  
118 - 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,  
119 - 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,  
120 - 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,  
121 - 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,  
122 - 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,  
123 - 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,  
124 - 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,  
125 - 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,  
126 - 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,  
127 - 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,  
128 - 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,  
129 - 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,  
130 - 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,  
131 - 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,  
132 - 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,  
133 - 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,  
134 - 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,  
135 - 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,  
136 - 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,  
137 - 0x43, 0x83, 0x41, 0x81, 0x80, 0x40 112 + 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
  113 + 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
  114 + 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
  115 + 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
  116 + 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
  117 + 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
  118 + 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
  119 + 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
  120 + 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
  121 + 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
  122 + 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
  123 + 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
  124 + 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
  125 + 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
  126 + 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
  127 + 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
  128 + 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
  129 + 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
  130 + 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
  131 + 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
  132 + 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
  133 + 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
  134 + 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
  135 + 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
  136 + 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
  137 + 0x43, 0x83, 0x41, 0x81, 0x80, 0x40
138 }; 138 };
139 139
140 static const int TAB_HEADER_LENGTH[2] = { 140 static const int TAB_HEADER_LENGTH[2] = {
141 - HEADER_LENGTH_RTU,  
142 - HEADER_LENGTH_TCP 141 + HEADER_LENGTH_RTU,
  142 + HEADER_LENGTH_TCP
143 }; 143 };
144 144
145 static const int TAB_CHECKSUM_LENGTH[2] = { 145 static const int TAB_CHECKSUM_LENGTH[2] = {
146 - CHECKSUM_LENGTH_RTU,  
147 - CHECKSUM_LENGTH_TCP 146 + CHECKSUM_LENGTH_RTU,
  147 + CHECKSUM_LENGTH_TCP
148 }; 148 };
149 149
150 static const int TAB_MAX_ADU_LENGTH[2] = { 150 static const int TAB_MAX_ADU_LENGTH[2] = {
151 - MAX_ADU_LENGTH_RTU,  
152 - MAX_ADU_LENGTH_TCP, 151 + MAX_ADU_LENGTH_RTU,
  152 + MAX_ADU_LENGTH_TCP,
153 }; 153 };
154 154
155 const char *modbus_strerror(int errnum) { 155 const char *modbus_strerror(int errnum) {
156 - switch (errnum) {  
157 - case EMBXILFUN:  
158 - return "Illegal function";  
159 - case EMBXILADD:  
160 - return "Illegal data address";  
161 - case EMBXILVAL:  
162 - return "Illegal data value";  
163 - case EMBXSFAIL:  
164 - return "Slave device or server failure";  
165 - case EMBXACK:  
166 - return "Acknowledge";  
167 - case EMBXSBUSY:  
168 - return "Slave device or server is busy";  
169 - case EMBXNACK:  
170 - return "Negative acknowledge";  
171 - case EMBXMEMPAR:  
172 - return "Memory parity error";  
173 - case EMBXGPATH:  
174 - return "Gateway path unavailable";  
175 - case EMBXGTAR:  
176 - return "Target device failed to respond";  
177 - case EMBBADCRC:  
178 - return "Invalid CRC";  
179 - case EMBBADDATA:  
180 - return "Invalid data";  
181 - case EMBBADEXC:  
182 - return "Invalid exception code";  
183 - case EMBMDATA:  
184 - return "Too many data";  
185 - default:  
186 - return strerror(errnum);  
187 - } 156 + switch (errnum) {
  157 + case EMBXILFUN:
  158 + return "Illegal function";
  159 + case EMBXILADD:
  160 + return "Illegal data address";
  161 + case EMBXILVAL:
  162 + return "Illegal data value";
  163 + case EMBXSFAIL:
  164 + return "Slave device or server failure";
  165 + case EMBXACK:
  166 + return "Acknowledge";
  167 + case EMBXSBUSY:
  168 + return "Slave device or server is busy";
  169 + case EMBXNACK:
  170 + return "Negative acknowledge";
  171 + case EMBXMEMPAR:
  172 + return "Memory parity error";
  173 + case EMBXGPATH:
  174 + return "Gateway path unavailable";
  175 + case EMBXGTAR:
  176 + return "Target device failed to respond";
  177 + case EMBBADCRC:
  178 + return "Invalid CRC";
  179 + case EMBBADDATA:
  180 + return "Invalid data";
  181 + case EMBBADEXC:
  182 + return "Invalid exception code";
  183 + case EMBMDATA:
  184 + return "Too many data";
  185 + default:
  186 + return strerror(errnum);
  187 + }
188 } 188 }
189 189
190 static void error_print(modbus_param_t *mb_param, const char *context) 190 static void error_print(modbus_param_t *mb_param, const char *context)
191 { 191 {
192 - if (mb_param->debug) {  
193 - fprintf(stderr, "ERROR %s", modbus_strerror(errno));  
194 - if (context != NULL) {  
195 - fprintf(stderr, ": %s\n", context);  
196 - } else {  
197 - fprintf(stderr, "\n");  
198 - } 192 + if (mb_param->debug) {
  193 + fprintf(stderr, "ERROR %s", modbus_strerror(errno));
  194 + if (context != NULL) {
  195 + fprintf(stderr, ": %s\n", context);
  196 + } else {
  197 + fprintf(stderr, "\n");
199 } 198 }
  199 + }
200 } 200 }
201 201
202 int modbus_flush(modbus_param_t *mb_param) 202 int modbus_flush(modbus_param_t *mb_param)
203 { 203 {
204 - int rc; 204 + int rc;
205 205
206 - if (mb_param->type_com == RTU) {  
207 - rc = tcflush(mb_param->fd, TCIOFLUSH);  
208 - } else {  
209 - do {  
210 - /* Extract the garbage from the socket */  
211 - char devnull[MAX_ADU_LENGTH_TCP]; 206 + if (mb_param->type_com == RTU) {
  207 + rc = tcflush(mb_param->fd, TCIOFLUSH);
  208 + } else {
  209 + do {
  210 + /* Extract the garbage from the socket */
  211 + char devnull[MAX_ADU_LENGTH_TCP];
212 #if (!HAVE_DECL___CYGWIN__) 212 #if (!HAVE_DECL___CYGWIN__)
213 - rc = recv(mb_param->fd, devnull, MAX_ADU_LENGTH_TCP, MSG_DONTWAIT); 213 + rc = recv(mb_param->fd, devnull, MAX_ADU_LENGTH_TCP, MSG_DONTWAIT);
214 #else 214 #else
215 - /* On Cygwin, it's a bit more complicated to not wait */  
216 - fd_set rfds;  
217 - struct timeval tv;  
218 -  
219 - tv.tv_sec = 0;  
220 - tv.tv_usec = 0;  
221 - FD_ZERO(&rfds);  
222 - FD_SET(mb_param->fd, &rfds);  
223 - rc = select(mb_param->fd+1, &rfds, NULL, NULL, &tv);  
224 - if (rc == -1) {  
225 - return -1;  
226 - }  
227 -  
228 - rc = recv(mb_param->fd, devnull, MAX_ADU_LENGTH_TCP, 0); 215 + /* On Cygwin, it's a bit more complicated to not wait */
  216 + fd_set rfds;
  217 + struct timeval tv;
  218 +
  219 + tv.tv_sec = 0;
  220 + tv.tv_usec = 0;
  221 + FD_ZERO(&rfds);
  222 + FD_SET(mb_param->fd, &rfds);
  223 + rc = select(mb_param->fd+1, &rfds, NULL, NULL, &tv);
  224 + if (rc == -1) {
  225 + return -1;
  226 + }
  227 +
  228 + rc = recv(mb_param->fd, devnull, MAX_ADU_LENGTH_TCP, 0);
229 #endif 229 #endif
230 - if (mb_param->debug && rc != -1) {  
231 - printf("\n%d bytes flushed\n", rc);  
232 - }  
233 - } while (rc > 0);  
234 - } 230 + if (mb_param->debug && rc != -1) {
  231 + printf("\n%d bytes flushed\n", rc);
  232 + }
  233 + } while (rc > 0);
  234 + }
235 235
236 - return rc; 236 + return rc;
237 } 237 }
238 238
239 /* Computes the length of the expected response */ 239 /* Computes the length of the expected response */
240 static unsigned int compute_response_length(modbus_param_t *mb_param, 240 static unsigned int compute_response_length(modbus_param_t *mb_param,
241 uint8_t *query) 241 uint8_t *query)
242 { 242 {
243 - int length;  
244 - int offset;  
245 -  
246 - offset = TAB_HEADER_LENGTH[mb_param->type_com];  
247 -  
248 - switch (query[offset]) {  
249 - case FC_READ_COIL_STATUS:  
250 - case FC_READ_INPUT_STATUS: {  
251 - /* Header + nb values (code from force_multiple_coils) */  
252 - int nb = (query[offset + 3] << 8) | query[offset + 4];  
253 - length = 2 + (nb / 8) + ((nb % 8) ? 1 : 0);  
254 - }  
255 - break;  
256 - case FC_READ_HOLDING_REGISTERS:  
257 - case FC_READ_INPUT_REGISTERS:  
258 - /* Header + 2 * nb values */  
259 - length = 2 + 2 * (query[offset + 3] << 8 |  
260 - query[offset + 4]);  
261 - break;  
262 - case FC_READ_EXCEPTION_STATUS:  
263 - length = 3;  
264 - break;  
265 - case FC_REPORT_SLAVE_ID:  
266 - /* The response is device specific (the header provides the  
267 - length) */  
268 - return MSG_LENGTH_UNDEFINED;  
269 - default:  
270 - length = 5;  
271 - }  
272 -  
273 - return length + offset + TAB_CHECKSUM_LENGTH[mb_param->type_com]; 243 + int length;
  244 + int offset;
  245 +
  246 + offset = TAB_HEADER_LENGTH[mb_param->type_com];
  247 +
  248 + switch (query[offset]) {
  249 + case FC_READ_COIL_STATUS:
  250 + case FC_READ_INPUT_STATUS: {
  251 + /* Header + nb values (code from force_multiple_coils) */
  252 + int nb = (query[offset + 3] << 8) | query[offset + 4];
  253 + length = 2 + (nb / 8) + ((nb % 8) ? 1 : 0);
  254 + }
  255 + break;
  256 + case FC_READ_HOLDING_REGISTERS:
  257 + case FC_READ_INPUT_REGISTERS:
  258 + /* Header + 2 * nb values */
  259 + length = 2 + 2 * (query[offset + 3] << 8 |
  260 + query[offset + 4]);
  261 + break;
  262 + case FC_READ_EXCEPTION_STATUS:
  263 + length = 3;
  264 + break;
  265 + case FC_REPORT_SLAVE_ID:
  266 + /* The response is device specific (the header provides the
  267 + length) */
  268 + return MSG_LENGTH_UNDEFINED;
  269 + default:
  270 + length = 5;
  271 + }
  272 +
  273 + return length + offset + TAB_CHECKSUM_LENGTH[mb_param->type_com];
274 } 274 }
275 275
276 /* Builds a RTU query header */ 276 /* Builds a RTU query header */
@@ -278,14 +278,14 @@ static int build_query_basis_rtu(int slave, int function, @@ -278,14 +278,14 @@ static int build_query_basis_rtu(int slave, int function,
278 int start_addr, int nb, 278 int start_addr, int nb,
279 uint8_t *query) 279 uint8_t *query)
280 { 280 {
281 - query[0] = slave;  
282 - query[1] = function;  
283 - query[2] = start_addr >> 8;  
284 - query[3] = start_addr & 0x00ff;  
285 - query[4] = nb >> 8;  
286 - query[5] = nb & 0x00ff;  
287 -  
288 - return PRESET_QUERY_LENGTH_RTU; 281 + query[0] = slave;
  282 + query[1] = function;
  283 + query[2] = start_addr >> 8;
  284 + query[3] = start_addr & 0x00ff;
  285 + query[4] = nb >> 8;
  286 + query[5] = nb & 0x00ff;
  287 +
  288 + return PRESET_QUERY_LENGTH_RTU;
289 } 289 }
290 290
291 /* Builds a TCP query header */ 291 /* Builds a TCP query header */
@@ -294,105 +294,105 @@ static int build_query_basis_tcp(int slave, int function, @@ -294,105 +294,105 @@ static int build_query_basis_tcp(int slave, int function,
294 uint8_t *query) 294 uint8_t *query)
295 { 295 {
296 296
297 - /* Extract from MODBUS Messaging on TCP/IP Implementation Guide V1.0b  
298 - (page 23/46):  
299 - The transaction identifier is used to associate the future response  
300 - with the request. So, at a time, on a TCP connection, this identifier  
301 - must be unique. */  
302 - static uint16_t t_id = 0;  
303 -  
304 - /* Transaction ID */  
305 - if (t_id < UINT16_MAX)  
306 - t_id++;  
307 - else  
308 - t_id = 0;  
309 - query[0] = t_id >> 8;  
310 - query[1] = t_id & 0x00ff;  
311 -  
312 - /* Protocol Modbus */  
313 - query[2] = 0;  
314 - query[3] = 0;  
315 -  
316 - /* Length will be defined later by set_query_length_tcp at offsets 4  
317 - and 5 */  
318 -  
319 - query[6] = slave;  
320 - query[7] = function;  
321 - query[8] = start_addr >> 8;  
322 - query[9] = start_addr & 0x00ff;  
323 - query[10] = nb >> 8;  
324 - query[11] = nb & 0x00ff;  
325 -  
326 - return PRESET_QUERY_LENGTH_TCP; 297 + /* Extract from MODBUS Messaging on TCP/IP Implementation Guide V1.0b
  298 + (page 23/46):
  299 + The transaction identifier is used to associate the future response
  300 + with the request. So, at a time, on a TCP connection, this identifier
  301 + must be unique. */
  302 + static uint16_t t_id = 0;
  303 +
  304 + /* Transaction ID */
  305 + if (t_id < UINT16_MAX)
  306 + t_id++;
  307 + else
  308 + t_id = 0;
  309 + query[0] = t_id >> 8;
  310 + query[1] = t_id & 0x00ff;
  311 +
  312 + /* Protocol Modbus */
  313 + query[2] = 0;
  314 + query[3] = 0;
  315 +
  316 + /* Length will be defined later by set_query_length_tcp at offsets 4
  317 + and 5 */
  318 +
  319 + query[6] = slave;
  320 + query[7] = function;
  321 + query[8] = start_addr >> 8;
  322 + query[9] = start_addr & 0x00ff;
  323 + query[10] = nb >> 8;
  324 + query[11] = nb & 0x00ff;
  325 +
  326 + return PRESET_QUERY_LENGTH_TCP;
327 } 327 }
328 328
329 static int build_query_basis(modbus_param_t *mb_param, int slave, 329 static int build_query_basis(modbus_param_t *mb_param, int slave,
330 int function, int start_addr, 330 int function, int start_addr,
331 int nb, uint8_t *query) 331 int nb, uint8_t *query)
332 { 332 {
333 - if (mb_param->type_com == RTU)  
334 - return build_query_basis_rtu(slave, function,  
335 - start_addr, nb, query);  
336 - else  
337 - return build_query_basis_tcp(slave, function,  
338 - start_addr, nb, query); 333 + if (mb_param->type_com == RTU)
  334 + return build_query_basis_rtu(slave, function,
  335 + start_addr, nb, query);
  336 + else
  337 + return build_query_basis_tcp(slave, function,
  338 + start_addr, nb, query);
339 } 339 }
340 340
341 /* Builds a RTU response header */ 341 /* Builds a RTU response header */
342 static int build_response_basis_rtu(sft_t *sft, uint8_t *response) 342 static int build_response_basis_rtu(sft_t *sft, uint8_t *response)
343 { 343 {
344 - response[0] = sft->slave;  
345 - response[1] = sft->function; 344 + response[0] = sft->slave;
  345 + response[1] = sft->function;
346 346
347 - return PRESET_RESPONSE_LENGTH_RTU; 347 + return PRESET_RESPONSE_LENGTH_RTU;
348 } 348 }
349 349
350 /* Builds a TCP response header */ 350 /* Builds a TCP response header */
351 static int build_response_basis_tcp(sft_t *sft, uint8_t *response) 351 static int build_response_basis_tcp(sft_t *sft, uint8_t *response)
352 { 352 {
353 - /* Extract from MODBUS Messaging on TCP/IP Implementation  
354 - Guide V1.0b (page 23/46):  
355 - The transaction identifier is used to associate the future  
356 - response with the request. */  
357 - response[0] = sft->t_id >> 8;  
358 - response[1] = sft->t_id & 0x00ff; 353 + /* Extract from MODBUS Messaging on TCP/IP Implementation
  354 + Guide V1.0b (page 23/46):
  355 + The transaction identifier is used to associate the future
  356 + response with the request. */
  357 + response[0] = sft->t_id >> 8;
  358 + response[1] = sft->t_id & 0x00ff;
359 359
360 - /* Protocol Modbus */  
361 - response[2] = 0;  
362 - response[3] = 0; 360 + /* Protocol Modbus */
  361 + response[2] = 0;
  362 + response[3] = 0;
363 363
364 - /* Length will be set later by modbus_send (4 and 5) */ 364 + /* Length will be set later by modbus_send (4 and 5) */
365 365
366 - response[6] = 0xFF;  
367 - response[7] = sft->function; 366 + response[6] = 0xFF;
  367 + response[7] = sft->function;
368 368
369 - return PRESET_RESPONSE_LENGTH_TCP; 369 + return PRESET_RESPONSE_LENGTH_TCP;
370 } 370 }
371 371
372 static int build_response_basis(modbus_param_t *mb_param, sft_t *sft, 372 static int build_response_basis(modbus_param_t *mb_param, sft_t *sft,
373 uint8_t *response) 373 uint8_t *response)
374 { 374 {
375 - if (mb_param->type_com == RTU)  
376 - return build_response_basis_rtu(sft, response);  
377 - else  
378 - return build_response_basis_tcp(sft, response); 375 + if (mb_param->type_com == RTU)
  376 + return build_response_basis_rtu(sft, response);
  377 + else
  378 + return build_response_basis_tcp(sft, response);
379 } 379 }
380 380
381 /* Fast CRC */ 381 /* Fast CRC */
382 static uint16_t crc16(uint8_t *buffer, uint16_t buffer_length) 382 static uint16_t crc16(uint8_t *buffer, uint16_t buffer_length)
383 { 383 {
384 - uint8_t crc_hi = 0xFF; /* high CRC byte initialized */  
385 - uint8_t crc_lo = 0xFF; /* low CRC byte initialized */  
386 - unsigned int i; /* will index into CRC lookup */  
387 -  
388 - /* pass through message buffer */  
389 - while (buffer_length--) {  
390 - i = crc_hi ^ *buffer++; /* calculate the CRC */  
391 - crc_hi = crc_lo ^ table_crc_hi[i];  
392 - crc_lo = table_crc_lo[i];  
393 - }  
394 -  
395 - return (crc_hi << 8 | crc_lo); 384 + uint8_t crc_hi = 0xFF; /* high CRC byte initialized */
  385 + uint8_t crc_lo = 0xFF; /* low CRC byte initialized */
  386 + unsigned int i; /* will index into CRC lookup */
  387 +
  388 + /* pass through message buffer */
  389 + while (buffer_length--) {
  390 + i = crc_hi ^ *buffer++; /* calculate the CRC */
  391 + crc_hi = crc_lo ^ table_crc_hi[i];
  392 + crc_lo = table_crc_lo[i];
  393 + }
  394 +
  395 + return (crc_hi << 8 | crc_lo);
396 } 396 }
397 397
398 /* The check_crc16 function shall return the message length if the CRC is 398 /* The check_crc16 function shall return the message length if the CRC is
@@ -401,164 +401,163 @@ static int check_crc16(modbus_param_t *mb_param, @@ -401,164 +401,163 @@ static int check_crc16(modbus_param_t *mb_param,
401 uint8_t *msg, 401 uint8_t *msg,
402 const int msg_length) 402 const int msg_length)
403 { 403 {
404 - uint16_t crc_calculated;  
405 - uint16_t crc_received; 404 + uint16_t crc_calculated;
  405 + uint16_t crc_received;
406 406
407 - crc_calculated = crc16(msg, msg_length - 2);  
408 - crc_received = (msg[msg_length - 2] << 8) | msg[msg_length - 1]; 407 + crc_calculated = crc16(msg, msg_length - 2);
  408 + crc_received = (msg[msg_length - 2] << 8) | msg[msg_length - 1];
409 409
410 - /* Check CRC of msg */  
411 - if (crc_calculated == crc_received) {  
412 - return msg_length;  
413 - } else {  
414 - if (mb_param->debug) {  
415 - fprintf(stderr, "ERROR CRC received %0X != CRC calculated %0X\n",  
416 - crc_received, crc_calculated);  
417 - }  
418 - if (mb_param->error_recovery) {  
419 - modbus_flush(mb_param);  
420 - }  
421 - errno = EMBBADCRC;  
422 - return -1; 410 + /* Check CRC of msg */
  411 + if (crc_calculated == crc_received) {
  412 + return msg_length;
  413 + } else {
  414 + if (mb_param->debug) {
  415 + fprintf(stderr, "ERROR CRC received %0X != CRC calculated %0X\n",
  416 + crc_received, crc_calculated);
  417 + }
  418 + if (mb_param->error_recovery) {
  419 + modbus_flush(mb_param);
423 } 420 }
  421 + errno = EMBBADCRC;
  422 + return -1;
  423 + }
424 } 424 }
425 425
426 /* Sends a query/response over a serial or a TCP communication */ 426 /* Sends a query/response over a serial or a TCP communication */
427 static int modbus_send(modbus_param_t *mb_param, uint8_t *query, 427 static int modbus_send(modbus_param_t *mb_param, uint8_t *query,
428 int query_length) 428 int query_length)
429 { 429 {
430 - int rc;  
431 - uint16_t s_crc;  
432 - int i;  
433 -  
434 - if (mb_param->type_com == RTU) {  
435 - s_crc = crc16(query, query_length);  
436 - query[query_length++] = s_crc >> 8;  
437 - query[query_length++] = s_crc & 0x00FF;  
438 - } else {  
439 - /* Substract the header length to the message length */  
440 - int mbap_length = query_length - 6;  
441 -  
442 - query[4] = mbap_length >> 8;  
443 - query[5] = mbap_length & 0x00FF;  
444 - } 430 + int rc;
  431 + uint16_t s_crc;
  432 + int i;
  433 +
  434 + if (mb_param->type_com == RTU) {
  435 + s_crc = crc16(query, query_length);
  436 + query[query_length++] = s_crc >> 8;
  437 + query[query_length++] = s_crc & 0x00FF;
  438 + } else {
  439 + /* Substract the header length to the message length */
  440 + int mbap_length = query_length - 6;
  441 +
  442 + query[4] = mbap_length >> 8;
  443 + query[5] = mbap_length & 0x00FF;
  444 + }
  445 +
  446 + if (mb_param->debug) {
  447 + for (i = 0; i < query_length; i++)
  448 + printf("[%.2X]", query[i]);
  449 + printf("\n");
  450 + }
  451 +
  452 + /* In recovery mode, the write command will be issued until to be
  453 + successful! Disabled by default.
  454 + */
  455 + do {
  456 + if (mb_param->type_com == RTU)
  457 + rc = write(mb_param->fd, query, query_length);
  458 + else
  459 + /* MSG_NOSIGNAL
  460 + Requests not to send SIGPIPE on errors on stream oriented
  461 + sockets when the other end breaks the connection. The EPIPE
  462 + error is still returned. */
  463 + rc = send(mb_param->fd, query, query_length, MSG_NOSIGNAL);
445 464
446 - if (mb_param->debug) {  
447 - for (i = 0; i < query_length; i++)  
448 - printf("[%.2X]", query[i]);  
449 - printf("\n"); 465 + if (rc == -1) {
  466 + error_print(mb_param, NULL);
  467 + if (mb_param->error_recovery &&
  468 + (errno == EBADF || errno == ECONNRESET || errno == EPIPE)) {
  469 + modbus_close(mb_param);
  470 + modbus_connect(mb_param);
  471 + }
450 } 472 }
  473 + } while (mb_param->error_recovery && rc == -1);
451 474
452 - /* In recovery mode, the write command will be issued until to be  
453 - successful! Disabled by default.  
454 - */  
455 - do {  
456 - if (mb_param->type_com == RTU)  
457 - rc = write(mb_param->fd, query, query_length);  
458 - else  
459 - /* MSG_NOSIGNAL  
460 - Requests not to send SIGPIPE on errors on stream oriented  
461 - sockets when the other end breaks the connection. The EPIPE  
462 - error is still returned. */  
463 - rc = send(mb_param->fd, query, query_length, MSG_NOSIGNAL);  
464 -  
465 - if (rc == -1) {  
466 - error_print(mb_param, NULL);  
467 - if (mb_param->error_recovery && (errno == EBADF ||  
468 - errno == ECONNRESET || errno == EPIPE)) {  
469 - modbus_close(mb_param);  
470 - modbus_connect(mb_param);  
471 - }  
472 - }  
473 - } while (mb_param->error_recovery && rc == -1); 475 + if (rc > 0 && rc != query_length) {
  476 + errno = EMBBADDATA;
  477 + return -1;
  478 + }
474 479
475 - if (rc > 0 && rc != query_length) {  
476 - errno = EMBBADDATA;  
477 - return -1;  
478 - }  
479 -  
480 - return rc; 480 + return rc;
481 } 481 }
482 482
483 /* Computes the length of the header following the function code */ 483 /* Computes the length of the header following the function code */
484 static uint8_t compute_query_length_header(int function) 484 static uint8_t compute_query_length_header(int function)
485 { 485 {
486 - int length;  
487 -  
488 - if (function <= FC_FORCE_SINGLE_COIL ||  
489 - function == FC_PRESET_SINGLE_REGISTER)  
490 - /* Read and single write */  
491 - length = 4;  
492 - else if (function == FC_FORCE_MULTIPLE_COILS ||  
493 - function == FC_PRESET_MULTIPLE_REGISTERS)  
494 - /* Multiple write */  
495 - length = 5;  
496 - else if (function == FC_REPORT_SLAVE_ID)  
497 - length = 1;  
498 - else  
499 - length = 0;  
500 -  
501 - return length; 486 + int length;
  487 +
  488 + if (function <= FC_FORCE_SINGLE_COIL ||
  489 + function == FC_PRESET_SINGLE_REGISTER)
  490 + /* Read and single write */
  491 + length = 4;
  492 + else if (function == FC_FORCE_MULTIPLE_COILS ||
  493 + function == FC_PRESET_MULTIPLE_REGISTERS)
  494 + /* Multiple write */
  495 + length = 5;
  496 + else if (function == FC_REPORT_SLAVE_ID)
  497 + length = 1;
  498 + else
  499 + length = 0;
  500 +
  501 + return length;
502 } 502 }
503 503
504 /* Computes the length of the data to write in the query */ 504 /* Computes the length of the data to write in the query */
505 static int compute_query_length_data(modbus_param_t *mb_param, uint8_t *msg) 505 static int compute_query_length_data(modbus_param_t *mb_param, uint8_t *msg)
506 { 506 {
507 - int function = msg[TAB_HEADER_LENGTH[mb_param->type_com]];  
508 - int length;  
509 -  
510 - if (function == FC_FORCE_MULTIPLE_COILS ||  
511 - function == FC_PRESET_MULTIPLE_REGISTERS)  
512 - length = msg[TAB_HEADER_LENGTH[mb_param->type_com] + 5];  
513 - else if (function == FC_REPORT_SLAVE_ID)  
514 - length = msg[TAB_HEADER_LENGTH[mb_param->type_com] + 1];  
515 - else  
516 - length = 0; 507 + int function = msg[TAB_HEADER_LENGTH[mb_param->type_com]];
  508 + int length;
517 509
518 - length += TAB_CHECKSUM_LENGTH[mb_param->type_com]; 510 + if (function == FC_FORCE_MULTIPLE_COILS ||
  511 + function == FC_PRESET_MULTIPLE_REGISTERS)
  512 + length = msg[TAB_HEADER_LENGTH[mb_param->type_com] + 5];
  513 + else if (function == FC_REPORT_SLAVE_ID)
  514 + length = msg[TAB_HEADER_LENGTH[mb_param->type_com] + 1];
  515 + else
  516 + length = 0;
519 517
520 - return length; 518 + length += TAB_CHECKSUM_LENGTH[mb_param->type_com];
  519 +
  520 + return length;
521 } 521 }
522 522
523 -#define WAIT_DATA() \  
524 -{ \  
525 - while ((s_rc = select(mb_param->fd+1, &rfds, NULL, NULL, &tv)) == -1) { \  
526 - if (errno == EINTR) { \  
527 - if (mb_param->debug) { \  
528 - fprintf(stderr, \  
529 - "A non blocked signal was caught\n"); \  
530 - } \  
531 - /* Necessary after an error */ \  
532 - FD_ZERO(&rfds); \  
533 - FD_SET(mb_param->fd, &rfds); \  
534 - } else { \  
535 - error_print(mb_param, "select"); \  
536 - if (mb_param->error_recovery && (errno == EBADF)) { \  
537 - modbus_close(mb_param); \  
538 - modbus_connect(mb_param); \  
539 - errno = EBADF; \  
540 - return -1; \  
541 - } else { \  
542 - return -1; \  
543 - } \  
544 - } \  
545 - } \  
546 - \  
547 - if (s_rc == 0) { \  
548 - /* Timeout */ \  
549 - if (msg_length == (TAB_HEADER_LENGTH[mb_param->type_com] + 2 + \  
550 - TAB_CHECKSUM_LENGTH[mb_param->type_com])) { \  
551 - /* Optimization allowed because exception response is \  
552 - the smallest trame in modbus protocol (3) so always \  
553 - raise a timeout error. \  
554 - Temporary error before exception analyze. */ \  
555 - errno = EMBUNKEXC; \  
556 - } else { \  
557 - errno = ETIMEDOUT; \  
558 - error_print(mb_param, "select"); \  
559 - } \  
560 - return -1; \  
561 - } \ 523 +#define WAIT_DATA() { \
  524 + while ((s_rc = select(mb_param->fd+1, &rfds, NULL, NULL, &tv)) == -1) { \
  525 + if (errno == EINTR) { \
  526 + if (mb_param->debug) { \
  527 + fprintf(stderr, \
  528 + "A non blocked signal was caught\n"); \
  529 + } \
  530 + /* Necessary after an error */ \
  531 + FD_ZERO(&rfds); \
  532 + FD_SET(mb_param->fd, &rfds); \
  533 + } else { \
  534 + error_print(mb_param, "select"); \
  535 + if (mb_param->error_recovery && (errno == EBADF)) { \
  536 + modbus_close(mb_param); \
  537 + modbus_connect(mb_param); \
  538 + errno = EBADF; \
  539 + return -1; \
  540 + } else { \
  541 + return -1; \
  542 + } \
  543 + } \
  544 + } \
  545 + \
  546 + if (s_rc == 0) { \
  547 + /* Timeout */ \
  548 + if (msg_length == (TAB_HEADER_LENGTH[mb_param->type_com] + 2 + \
  549 + TAB_CHECKSUM_LENGTH[mb_param->type_com])) { \
  550 + /* Optimization allowed because exception response is \
  551 + the smallest trame in modbus protocol (3) so always \
  552 + raise a timeout error. \
  553 + Temporary error before exception analyze. */ \
  554 + errno = EMBUNKEXC; \
  555 + } else { \
  556 + errno = ETIMEDOUT; \
  557 + error_print(mb_param, "select"); \
  558 + } \
  559 + return -1; \
  560 + } \
562 } 561 }
563 562
564 /* Waits a reply from a modbus slave or a query from a modbus master. 563 /* Waits a reply from a modbus slave or a query from a modbus master.
@@ -580,144 +579,144 @@ static int receive_msg(modbus_param_t *mb_param, @@ -580,144 +579,144 @@ static int receive_msg(modbus_param_t *mb_param,
580 int msg_length_computed, 579 int msg_length_computed,
581 uint8_t *msg) 580 uint8_t *msg)
582 { 581 {
583 - int s_rc;  
584 - int read_rc;  
585 - fd_set rfds;  
586 - struct timeval tv;  
587 - int length_to_read;  
588 - uint8_t *p_msg;  
589 - enum { FUNCTION, BYTE, COMPLETE };  
590 - int state;  
591 -  
592 - int msg_length = 0; 582 + int s_rc;
  583 + int read_rc;
  584 + fd_set rfds;
  585 + struct timeval tv;
  586 + int length_to_read;
  587 + uint8_t *p_msg;
  588 + enum { FUNCTION, BYTE, COMPLETE };
  589 + int state;
  590 +
  591 + int msg_length = 0;
  592 +
  593 + if (mb_param->debug) {
  594 + if (msg_length_computed == MSG_LENGTH_UNDEFINED)
  595 + printf("Waiting for a message...\n");
  596 + else
  597 + printf("Waiting for a message (%d bytes)...\n",
  598 + msg_length_computed);
  599 + }
  600 +
  601 + /* Add a file descriptor to the set */
  602 + FD_ZERO(&rfds);
  603 + FD_SET(mb_param->fd, &rfds);
  604 +
  605 + if (msg_length_computed == MSG_LENGTH_UNDEFINED) {
  606 + /* Wait for a message */
  607 + tv.tv_sec = 60;
  608 + tv.tv_usec = 0;
  609 +
  610 + /* The message length is undefined (query receiving) so
  611 + * we need to analyse the message step by step.
  612 + * At the first step, we want to reach the function
  613 + * code because all packets have that information. */
  614 + state = FUNCTION;
  615 + msg_length_computed = TAB_HEADER_LENGTH[mb_param->type_com] + 1;
  616 + } else {
  617 + tv.tv_sec = mb_param->timeout_begin.tv_sec;
  618 + tv.tv_usec = mb_param->timeout_begin.tv_usec;
  619 + state = COMPLETE;
  620 + }
  621 +
  622 + length_to_read = msg_length_computed;
  623 +
  624 + s_rc = 0;
  625 + WAIT_DATA();
  626 +
  627 + p_msg = msg;
  628 + while (s_rc) {
  629 + if (mb_param->type_com == RTU)
  630 + read_rc = read(mb_param->fd, p_msg, length_to_read);
  631 + else
  632 + read_rc = recv(mb_param->fd, p_msg, length_to_read, 0);
593 633
594 - if (mb_param->debug) {  
595 - if (msg_length_computed == MSG_LENGTH_UNDEFINED)  
596 - printf("Waiting for a message...\n");  
597 - else  
598 - printf("Waiting for a message (%d bytes)...\n",  
599 - msg_length_computed); 634 + if (read_rc == 0) {
  635 + errno = ECONNRESET;
  636 + read_rc = -1;
600 } 637 }
601 638
602 - /* Add a file descriptor to the set */  
603 - FD_ZERO(&rfds);  
604 - FD_SET(mb_param->fd, &rfds);  
605 -  
606 - if (msg_length_computed == MSG_LENGTH_UNDEFINED) {  
607 - /* Wait for a message */  
608 - tv.tv_sec = 60;  
609 - tv.tv_usec = 0;  
610 -  
611 - /* The message length is undefined (query receiving) so  
612 - * we need to analyse the message step by step.  
613 - * At the first step, we want to reach the function  
614 - * code because all packets have that information. */  
615 - state = FUNCTION;  
616 - msg_length_computed = TAB_HEADER_LENGTH[mb_param->type_com] + 1;  
617 - } else {  
618 - tv.tv_sec = mb_param->timeout_begin.tv_sec;  
619 - tv.tv_usec = mb_param->timeout_begin.tv_usec;  
620 - state = COMPLETE; 639 + if (read_rc == -1) {
  640 + error_print(mb_param, "read");
  641 + if (mb_param->error_recovery && (errno == ECONNRESET ||
  642 + errno == ECONNREFUSED)) {
  643 + modbus_close(mb_param);
  644 + modbus_connect(mb_param);
  645 + /* Could be removed by previous calls */
  646 + errno = ECONNRESET;
  647 + return -1;
  648 + }
  649 + return -1;
621 } 650 }
622 651
623 - length_to_read = msg_length_computed;  
624 -  
625 - s_rc = 0;  
626 - WAIT_DATA();  
627 -  
628 - p_msg = msg;  
629 - while (s_rc) {  
630 - if (mb_param->type_com == RTU)  
631 - read_rc = read(mb_param->fd, p_msg, length_to_read);  
632 - else  
633 - read_rc = recv(mb_param->fd, p_msg, length_to_read, 0);  
634 -  
635 - if (read_rc == 0) {  
636 - errno = ECONNRESET;  
637 - read_rc = -1;  
638 - }  
639 -  
640 - if (read_rc == -1) {  
641 - error_print(mb_param, "read");  
642 - if (mb_param->error_recovery && (errno == ECONNRESET ||  
643 - errno == ECONNREFUSED)) {  
644 - modbus_close(mb_param);  
645 - modbus_connect(mb_param);  
646 - /* Could be removed by previous calls */  
647 - errno = ECONNRESET;  
648 - return -1;  
649 - }  
650 - return -1;  
651 - }  
652 -  
653 - /* Sums bytes received */  
654 - msg_length += read_rc; 652 + /* Sums bytes received */
  653 + msg_length += read_rc;
655 654
656 - /* Display the hex code of each character received */  
657 - if (mb_param->debug) {  
658 - int i;  
659 - for (i=0; i < read_rc; i++)  
660 - printf("<%.2X>", p_msg[i]);  
661 - }  
662 -  
663 - if (msg_length < msg_length_computed) {  
664 - /* Message incomplete */  
665 - length_to_read = msg_length_computed - msg_length;  
666 - } else {  
667 - switch (state) {  
668 - case FUNCTION:  
669 - /* Function code position */  
670 - length_to_read = compute_query_length_header(  
671 - msg[TAB_HEADER_LENGTH[mb_param->type_com]]);  
672 - msg_length_computed += length_to_read;  
673 - /* It's useless to check the value of  
674 - msg_length_computed in this case (only  
675 - defined values are used). */  
676 - state = BYTE;  
677 - break;  
678 - case BYTE:  
679 - length_to_read = compute_query_length_data(mb_param, msg);  
680 - msg_length_computed += length_to_read;  
681 - if (msg_length_computed > TAB_MAX_ADU_LENGTH[mb_param->type_com]) {  
682 - errno = EMBBADDATA;  
683 - error_print(mb_param, "too many data");  
684 - return -1;  
685 - }  
686 - state = COMPLETE;  
687 - break;  
688 - case COMPLETE:  
689 - length_to_read = 0;  
690 - break;  
691 - }  
692 - }  
693 -  
694 - /* Moves the pointer to receive other data */  
695 - p_msg = &(p_msg[read_rc]);  
696 -  
697 - if (length_to_read > 0) {  
698 - /* If no character at the buffer wait  
699 - TIME_OUT_END_OF_TRAME before to generate an error. */  
700 - tv.tv_sec = mb_param->timeout_end.tv_sec;  
701 - tv.tv_usec = mb_param->timeout_end.tv_usec; 655 + /* Display the hex code of each character received */
  656 + if (mb_param->debug) {
  657 + int i;
  658 + for (i=0; i < read_rc; i++)
  659 + printf("<%.2X>", p_msg[i]);
  660 + }
702 661
703 - WAIT_DATA();  
704 - } else {  
705 - /* All chars are received */  
706 - s_rc = FALSE; 662 + if (msg_length < msg_length_computed) {
  663 + /* Message incomplete */
  664 + length_to_read = msg_length_computed - msg_length;
  665 + } else {
  666 + switch (state) {
  667 + case FUNCTION:
  668 + /* Function code position */
  669 + length_to_read = compute_query_length_header(
  670 + msg[TAB_HEADER_LENGTH[mb_param->type_com]]);
  671 + msg_length_computed += length_to_read;
  672 + /* It's useless to check the value of
  673 + msg_length_computed in this case (only
  674 + defined values are used). */
  675 + state = BYTE;
  676 + break;
  677 + case BYTE:
  678 + length_to_read = compute_query_length_data(mb_param, msg);
  679 + msg_length_computed += length_to_read;
  680 + if (msg_length_computed > TAB_MAX_ADU_LENGTH[mb_param->type_com]) {
  681 + errno = EMBBADDATA;
  682 + error_print(mb_param, "too many data");
  683 + return -1;
707 } 684 }
  685 + state = COMPLETE;
  686 + break;
  687 + case COMPLETE:
  688 + length_to_read = 0;
  689 + break;
  690 + }
708 } 691 }
709 692
710 - if (mb_param->debug)  
711 - printf("\n"); 693 + /* Moves the pointer to receive other data */
  694 + p_msg = &(p_msg[read_rc]);
712 695
713 - if (mb_param->type_com == RTU) {  
714 - /* Returns msg_length on success and a negative value on  
715 - failure */  
716 - return check_crc16(mb_param, msg, msg_length); 696 + if (length_to_read > 0) {
  697 + /* If no character at the buffer wait
  698 + TIME_OUT_END_OF_TRAME before to generate an error. */
  699 + tv.tv_sec = mb_param->timeout_end.tv_sec;
  700 + tv.tv_usec = mb_param->timeout_end.tv_usec;
  701 +
  702 + WAIT_DATA();
717 } else { 703 } else {
718 - /* OK */  
719 - return msg_length;  
720 - } 704 + /* All chars are received */
  705 + s_rc = FALSE;
  706 + }
  707 + }
  708 +
  709 + if (mb_param->debug)
  710 + printf("\n");
  711 +
  712 + if (mb_param->type_com == RTU) {
  713 + /* Returns msg_length on success and a negative value on
  714 + failure */
  715 + return check_crc16(mb_param, msg, msg_length);
  716 + } else {
  717 + /* OK */
  718 + return msg_length;
  719 + }
721 } 720 }
722 721
723 /* Listens for any query from a modbus master in TCP, requires the socket file 722 /* Listens for any query from a modbus master in TCP, requires the socket file
@@ -728,12 +727,12 @@ static int receive_msg(modbus_param_t *mb_param, @@ -728,12 +727,12 @@ static int receive_msg(modbus_param_t *mb_param,
728 byte length if successul. Otherwise, it shall return -1 and errno is set. */ 727 byte length if successul. Otherwise, it shall return -1 and errno is set. */
729 int modbus_slave_receive(modbus_param_t *mb_param, int sockfd, uint8_t *query) 728 int modbus_slave_receive(modbus_param_t *mb_param, int sockfd, uint8_t *query)
730 { 729 {
731 - if (sockfd != -1) {  
732 - mb_param->fd = sockfd;  
733 - } 730 + if (sockfd != -1) {
  731 + mb_param->fd = sockfd;
  732 + }
734 733
735 - /* The length of the query to receive isn't known. */  
736 - return receive_msg(mb_param, MSG_LENGTH_UNDEFINED, query); 734 + /* The length of the query to receive isn't known. */
  735 + return receive_msg(mb_param, MSG_LENGTH_UNDEFINED, query);
737 } 736 }
738 737
739 /* Receives the response and checks values (and checksum in RTU). 738 /* Receives the response and checks values (and checksum in RTU).
@@ -747,127 +746,127 @@ static int modbus_receive(modbus_param_t *mb_param, @@ -747,127 +746,127 @@ static int modbus_receive(modbus_param_t *mb_param,
747 uint8_t *query, 746 uint8_t *query,
748 uint8_t *response) 747 uint8_t *response)
749 { 748 {
750 - int rc;  
751 - int response_length_computed;  
752 - int offset = TAB_HEADER_LENGTH[mb_param->type_com];  
753 -  
754 - response_length_computed = compute_response_length(mb_param, query);  
755 - rc = receive_msg(mb_param, response_length_computed, response);  
756 - if (rc != -1) {  
757 - /* GOOD RESPONSE */  
758 - int query_nb_value;  
759 - int response_nb_value;  
760 -  
761 - /* The number of values is returned if it's corresponding  
762 - * to the query */  
763 - switch (response[offset]) {  
764 - case FC_READ_COIL_STATUS:  
765 - case FC_READ_INPUT_STATUS:  
766 - /* Read functions, 8 values in a byte (nb  
767 - * of values in the query and byte count in  
768 - * the response. */  
769 - query_nb_value = (query[offset + 3] << 8) + query[offset + 4];  
770 - query_nb_value = (query_nb_value / 8) + ((query_nb_value % 8) ? 1 : 0);  
771 - response_nb_value = response[offset + 1];  
772 - break;  
773 - case FC_READ_HOLDING_REGISTERS:  
774 - case FC_READ_INPUT_REGISTERS:  
775 - /* Read functions 1 value = 2 bytes */  
776 - query_nb_value = (query[offset + 3] << 8) + query[offset + 4];  
777 - response_nb_value = (response[offset + 1] / 2);  
778 - break;  
779 - case FC_FORCE_MULTIPLE_COILS:  
780 - case FC_PRESET_MULTIPLE_REGISTERS:  
781 - /* N Write functions */  
782 - query_nb_value = (query[offset + 3] << 8) + query[offset + 4];  
783 - response_nb_value = (response[offset + 3] << 8) | response[offset + 4];  
784 - break;  
785 - case FC_REPORT_SLAVE_ID:  
786 - /* Report slave ID (bytes received) */  
787 - query_nb_value = response_nb_value = rc;  
788 - break;  
789 - default:  
790 - /* 1 Write functions & others */  
791 - query_nb_value = response_nb_value = 1;  
792 - } 749 + int rc;
  750 + int response_length_computed;
  751 + int offset = TAB_HEADER_LENGTH[mb_param->type_com];
  752 +
  753 + response_length_computed = compute_response_length(mb_param, query);
  754 + rc = receive_msg(mb_param, response_length_computed, response);
  755 + if (rc != -1) {
  756 + /* GOOD RESPONSE */
  757 + int query_nb_value;
  758 + int response_nb_value;
  759 +
  760 + /* The number of values is returned if it's corresponding
  761 + * to the query */
  762 + switch (response[offset]) {
  763 + case FC_READ_COIL_STATUS:
  764 + case FC_READ_INPUT_STATUS:
  765 + /* Read functions, 8 values in a byte (nb
  766 + * of values in the query and byte count in
  767 + * the response. */
  768 + query_nb_value = (query[offset + 3] << 8) + query[offset + 4];
  769 + query_nb_value = (query_nb_value / 8) + ((query_nb_value % 8) ? 1 : 0);
  770 + response_nb_value = response[offset + 1];
  771 + break;
  772 + case FC_READ_HOLDING_REGISTERS:
  773 + case FC_READ_INPUT_REGISTERS:
  774 + /* Read functions 1 value = 2 bytes */
  775 + query_nb_value = (query[offset + 3] << 8) + query[offset + 4];
  776 + response_nb_value = (response[offset + 1] / 2);
  777 + break;
  778 + case FC_FORCE_MULTIPLE_COILS:
  779 + case FC_PRESET_MULTIPLE_REGISTERS:
  780 + /* N Write functions */
  781 + query_nb_value = (query[offset + 3] << 8) + query[offset + 4];
  782 + response_nb_value = (response[offset + 3] << 8) | response[offset + 4];
  783 + break;
  784 + case FC_REPORT_SLAVE_ID:
  785 + /* Report slave ID (bytes received) */
  786 + query_nb_value = response_nb_value = rc;
  787 + break;
  788 + default:
  789 + /* 1 Write functions & others */
  790 + query_nb_value = response_nb_value = 1;
  791 + }
793 792
794 - if (query_nb_value == response_nb_value) {  
795 - rc = response_nb_value;  
796 - } else {  
797 - if (mb_param->debug) {  
798 - fprintf(stderr,  
799 - "Quantity not corresponding to the query (%d != %d)\n",  
800 - response_nb_value, query_nb_value);  
801 - }  
802 - errno = EMBBADDATA;  
803 - rc = -1;  
804 - }  
805 - } else if (errno == EMBUNKEXC) {  
806 - /* EXCEPTION CODE RECEIVED */  
807 -  
808 - /* CRC must be checked here (not done in receive_msg) */  
809 - if (mb_param->type_com == RTU) {  
810 - rc = check_crc16(mb_param, response, EXCEPTION_RESPONSE_LENGTH_RTU);  
811 - if (rc == -1)  
812 - return -1;  
813 - } 793 + if (query_nb_value == response_nb_value) {
  794 + rc = response_nb_value;
  795 + } else {
  796 + if (mb_param->debug) {
  797 + fprintf(stderr,
  798 + "Quantity not corresponding to the query (%d != %d)\n",
  799 + response_nb_value, query_nb_value);
  800 + }
  801 + errno = EMBBADDATA;
  802 + rc = -1;
  803 + }
  804 + } else if (errno == EMBUNKEXC) {
  805 + /* EXCEPTION CODE RECEIVED */
814 806
815 - /* Check for exception response.  
816 - 0x80 + function is stored in the exception  
817 - response. */  
818 - if (0x80 + query[offset] == response[offset]) {  
819 - int exception_code = response[offset + 1];  
820 - if (exception_code < MODBUS_EXCEPTION_MAX) {  
821 - errno = MODBUS_ENOBASE + exception_code;  
822 - } else {  
823 - errno = EMBBADEXC;  
824 - }  
825 - error_print(mb_param, NULL);  
826 - return -1;  
827 - } 807 + /* CRC must be checked here (not done in receive_msg) */
  808 + if (mb_param->type_com == RTU) {
  809 + rc = check_crc16(mb_param, response, EXCEPTION_RESPONSE_LENGTH_RTU);
  810 + if (rc == -1)
  811 + return -1;
  812 + }
  813 +
  814 + /* Check for exception response.
  815 + 0x80 + function is stored in the exception
  816 + response. */
  817 + if (0x80 + query[offset] == response[offset]) {
  818 + int exception_code = response[offset + 1];
  819 + if (exception_code < MODBUS_EXCEPTION_MAX) {
  820 + errno = MODBUS_ENOBASE + exception_code;
  821 + } else {
  822 + errno = EMBBADEXC;
  823 + }
  824 + error_print(mb_param, NULL);
  825 + return -1;
828 } 826 }
  827 + }
829 828
830 - return rc; 829 + return rc;
831 } 830 }
832 831
833 static int response_io_status(int address, int nb, 832 static int response_io_status(int address, int nb,
834 uint8_t *tab_io_status, 833 uint8_t *tab_io_status,
835 uint8_t *response, int offset) 834 uint8_t *response, int offset)
836 { 835 {
837 - int shift = 0;  
838 - int byte = 0;  
839 - int i;  
840 -  
841 - for (i = address; i < address+nb; i++) {  
842 - byte |= tab_io_status[i] << shift;  
843 - if (shift == 7) {  
844 - /* Byte is full */  
845 - response[offset++] = byte;  
846 - byte = shift = 0;  
847 - } else {  
848 - shift++;  
849 - } 836 + int shift = 0;
  837 + int byte = 0;
  838 + int i;
  839 +
  840 + for (i = address; i < address+nb; i++) {
  841 + byte |= tab_io_status[i] << shift;
  842 + if (shift == 7) {
  843 + /* Byte is full */
  844 + response[offset++] = byte;
  845 + byte = shift = 0;
  846 + } else {
  847 + shift++;
850 } 848 }
  849 + }
851 850
852 - if (shift != 0)  
853 - response[offset++] = byte; 851 + if (shift != 0)
  852 + response[offset++] = byte;
854 853
855 - return offset; 854 + return offset;
856 } 855 }
857 856
858 /* Build the exception response */ 857 /* Build the exception response */
859 static int response_exception(modbus_param_t *mb_param, sft_t *sft, 858 static int response_exception(modbus_param_t *mb_param, sft_t *sft,
860 int exception_code, uint8_t *response) 859 int exception_code, uint8_t *response)
861 { 860 {
862 - int response_length; 861 + int response_length;
863 862
864 - sft->function = sft->function + 0x80;  
865 - response_length = build_response_basis(mb_param, sft, response); 863 + sft->function = sft->function + 0x80;
  864 + response_length = build_response_basis(mb_param, sft, response);
866 865
867 - /* Positive exception code */  
868 - response[response_length++] = exception_code; 866 + /* Positive exception code */
  867 + response[response_length++] = exception_code;
869 868
870 - return response_length; 869 + return response_length;
871 } 870 }
872 871
873 /* Manages the received query. 872 /* Manages the received query.
@@ -879,277 +878,277 @@ static int response_exception(modbus_param_t *mb_param, sft_t *sft, @@ -879,277 +878,277 @@ static int response_exception(modbus_param_t *mb_param, sft_t *sft,
879 int modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query, 878 int modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query,
880 int query_length, modbus_mapping_t *mb_mapping) 879 int query_length, modbus_mapping_t *mb_mapping)
881 { 880 {
882 - int offset = TAB_HEADER_LENGTH[mb_param->type_com];  
883 - int slave = query[offset - 1];  
884 - int function = query[offset];  
885 - uint16_t address = (query[offset + 1] << 8) + query[offset + 2];  
886 - uint8_t response[MAX_MESSAGE_LENGTH];  
887 - int resp_length = 0;  
888 - sft_t sft;  
889 -  
890 - /* Filter on the Modbus unit identifier (slave) in RTU mode */  
891 - if (mb_param->type_com == RTU &&  
892 - slave != mb_param->slave && slave != MODBUS_BROADCAST_ADDRESS) {  
893 - /* Ignores the query (not for me) */  
894 - if (mb_param->debug) {  
895 - printf("Request for slave %d ignored (not %d)\n",  
896 - slave, mb_param->slave);  
897 - }  
898 - return 0; 881 + int offset = TAB_HEADER_LENGTH[mb_param->type_com];
  882 + int slave = query[offset - 1];
  883 + int function = query[offset];
  884 + uint16_t address = (query[offset + 1] << 8) + query[offset + 2];
  885 + uint8_t response[MAX_MESSAGE_LENGTH];
  886 + int resp_length = 0;
  887 + sft_t sft;
  888 +
  889 + /* Filter on the Modbus unit identifier (slave) in RTU mode */
  890 + if (mb_param->type_com == RTU &&
  891 + slave != mb_param->slave && slave != MODBUS_BROADCAST_ADDRESS) {
  892 + /* Ignores the query (not for me) */
  893 + if (mb_param->debug) {
  894 + printf("Request for slave %d ignored (not %d)\n",
  895 + slave, mb_param->slave);
899 } 896 }
900 -  
901 - sft.slave = slave;  
902 - sft.function = function;  
903 - if (mb_param->type_com == TCP) {  
904 - sft.t_id = (query[0] << 8) + query[1]; 897 + return 0;
  898 + }
  899 +
  900 + sft.slave = slave;
  901 + sft.function = function;
  902 + if (mb_param->type_com == TCP) {
  903 + sft.t_id = (query[0] << 8) + query[1];
  904 + } else {
  905 + sft.t_id = 0;
  906 + query_length -= CHECKSUM_LENGTH_RTU;
  907 + }
  908 +
  909 + switch (function) {
  910 + case FC_READ_COIL_STATUS: {
  911 + int nb = (query[offset + 3] << 8) + query[offset + 4];
  912 +
  913 + if ((address + nb) > mb_mapping->nb_coil_status) {
  914 + if (mb_param->debug) {
  915 + fprintf(stderr, "Illegal data address %0X in read_coil_status\n",
  916 + address + nb);
  917 + }
  918 + resp_length = response_exception(
  919 + mb_param, &sft,
  920 + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);
905 } else { 921 } else {
906 - sft.t_id = 0;  
907 - query_length -= CHECKSUM_LENGTH_RTU;  
908 - }  
909 -  
910 - switch (function) {  
911 - case FC_READ_COIL_STATUS: {  
912 - int nb = (query[offset + 3] << 8) + query[offset + 4];  
913 -  
914 - if ((address + nb) > mb_mapping->nb_coil_status) {  
915 - if (mb_param->debug) {  
916 - fprintf(stderr, "Illegal data address %0X in read_coil_status\n",  
917 - address + nb);  
918 - }  
919 - resp_length = response_exception(  
920 - mb_param, &sft,  
921 - MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);  
922 - } else {  
923 - resp_length = build_response_basis(mb_param, &sft, response);  
924 - response[resp_length++] = (nb / 8) + ((nb % 8) ? 1 : 0);  
925 - resp_length = response_io_status(address, nb,  
926 - mb_mapping->tab_coil_status,  
927 - response, resp_length);  
928 - }  
929 - }  
930 - break;  
931 - case FC_READ_INPUT_STATUS: {  
932 - /* Similar to coil status (but too much arguments to use a  
933 - * function) */  
934 - int nb = (query[offset + 3] << 8) + query[offset + 4];  
935 -  
936 - if ((address + nb) > mb_mapping->nb_input_status) {  
937 - if (mb_param->debug) {  
938 - fprintf(stderr, "Illegal data address %0X in read_input_status\n",  
939 - address + nb);  
940 - }  
941 - resp_length = response_exception(  
942 - mb_param, &sft,  
943 - MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);  
944 - } else {  
945 - resp_length = build_response_basis(mb_param, &sft, response);  
946 - response[resp_length++] = (nb / 8) + ((nb % 8) ? 1 : 0);  
947 - resp_length = response_io_status(address, nb,  
948 - mb_mapping->tab_input_status,  
949 - response, resp_length);  
950 - }  
951 - }  
952 - break;  
953 - case FC_READ_HOLDING_REGISTERS: {  
954 - int nb = (query[offset + 3] << 8) + query[offset + 4];  
955 -  
956 - if ((address + nb) > mb_mapping->nb_holding_registers) {  
957 - if (mb_param->debug) {  
958 - fprintf(stderr, "Illegal data address %0X in read_holding_registers\n",  
959 - address + nb);  
960 - }  
961 - resp_length = response_exception(  
962 - mb_param, &sft,  
963 - MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);  
964 - } else {  
965 - int i;  
966 -  
967 - resp_length = build_response_basis(mb_param, &sft, response);  
968 - response[resp_length++] = nb << 1;  
969 - for (i = address; i < address + nb; i++) {  
970 - response[resp_length++] = mb_mapping->tab_holding_registers[i] >> 8;  
971 - response[resp_length++] = mb_mapping->tab_holding_registers[i] & 0xFF;  
972 - }  
973 - }  
974 - }  
975 - break;  
976 - case FC_READ_INPUT_REGISTERS: {  
977 - /* Similar to holding registers (but too much arguments to use a  
978 - * function) */  
979 - int nb = (query[offset + 3] << 8) + query[offset + 4];  
980 -  
981 - if ((address + nb) > mb_mapping->nb_input_registers) {  
982 - if (mb_param->debug) {  
983 - fprintf(stderr, "Illegal data address %0X in read_input_registers\n",  
984 - address + nb);  
985 - }  
986 - resp_length = response_exception(  
987 - mb_param, &sft,  
988 - MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);  
989 - } else {  
990 - int i;  
991 -  
992 - resp_length = build_response_basis(mb_param, &sft, response);  
993 - response[resp_length++] = nb << 1;  
994 - for (i = address; i < address + nb; i++) {  
995 - response[resp_length++] = mb_mapping->tab_input_registers[i] >> 8;  
996 - response[resp_length++] = mb_mapping->tab_input_registers[i] & 0xFF;  
997 - }  
998 - }  
999 - }  
1000 - break;  
1001 - case FC_FORCE_SINGLE_COIL:  
1002 - if (address >= mb_mapping->nb_coil_status) {  
1003 - if (mb_param->debug) {  
1004 - fprintf(stderr, "Illegal data address %0X in force_singe_coil\n",  
1005 - address);  
1006 - }  
1007 - resp_length = response_exception(  
1008 - mb_param, &sft,  
1009 - MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);  
1010 - } else {  
1011 - int data = (query[offset + 3] << 8) + query[offset + 4];  
1012 -  
1013 - if (data == 0xFF00 || data == 0x0) {  
1014 - mb_mapping->tab_coil_status[address] = (data) ? ON : OFF;  
1015 -  
1016 - /* In RTU mode, the CRC is computed and added  
1017 - to the query by modbus_send, the computed  
1018 - CRC will be same and optimisation is  
1019 - possible here (FIXME). */  
1020 - memcpy(response, query, query_length);  
1021 - resp_length = query_length;  
1022 - } else {  
1023 - if (mb_param->debug) {  
1024 - fprintf(stderr, "Illegal data value %0X in force_single_coil request at address %0X\n",  
1025 - data, address);  
1026 - }  
1027 - resp_length = response_exception(  
1028 - mb_param, &sft,  
1029 - MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, response);  
1030 - }  
1031 - }  
1032 - break;  
1033 - case FC_PRESET_SINGLE_REGISTER:  
1034 - if (address >= mb_mapping->nb_holding_registers) {  
1035 - if (mb_param->debug) {  
1036 - fprintf(stderr, "Illegal data address %0X in preset_holding_register\n",  
1037 - address);  
1038 - }  
1039 - resp_length = response_exception(  
1040 - mb_param, &sft,  
1041 - MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);  
1042 - } else {  
1043 - int data = (query[offset + 3] << 8) + query[offset + 4];  
1044 -  
1045 - mb_mapping->tab_holding_registers[address] = data;  
1046 - memcpy(response, query, query_length);  
1047 - resp_length = query_length;  
1048 - }  
1049 - break;  
1050 - case FC_FORCE_MULTIPLE_COILS: {  
1051 - int nb = (query[offset + 3] << 8) + query[offset + 4];  
1052 -  
1053 - if ((address + nb) > mb_mapping->nb_coil_status) {  
1054 - if (mb_param->debug) {  
1055 - fprintf(stderr, "Illegal data address %0X in force_multiple_coils\n",  
1056 - address + nb);  
1057 - }  
1058 - resp_length = response_exception(  
1059 - mb_param, &sft,  
1060 - MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);  
1061 - } else {  
1062 - /* 6 = byte count */  
1063 - set_bits_from_bytes(mb_mapping->tab_coil_status, address, nb, &query[offset + 6]);  
1064 -  
1065 - resp_length = build_response_basis(mb_param, &sft, response);  
1066 - /* 4 to copy the coil address (2) and the quantity of coils */  
1067 - memcpy(response + resp_length, query + resp_length, 4);  
1068 - resp_length += 4;  
1069 - }  
1070 - }  
1071 - break;  
1072 - case FC_PRESET_MULTIPLE_REGISTERS: {  
1073 - int nb = (query[offset + 3] << 8) + query[offset + 4];  
1074 -  
1075 - if ((address + nb) > mb_mapping->nb_holding_registers) {  
1076 - if (mb_param->debug) {  
1077 - fprintf(stderr, "Illegal data address %0X in preset_multiple_registers\n",  
1078 - address + nb);  
1079 - }  
1080 - resp_length = response_exception(  
1081 - mb_param, &sft,  
1082 - MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);  
1083 - } else {  
1084 - int i, j;  
1085 - for (i = address, j = 6; i < address + nb; i++, j += 2) {  
1086 - /* 6 and 7 = first value */  
1087 - mb_mapping->tab_holding_registers[i] =  
1088 - (query[offset + j] << 8) + query[offset + j + 1];  
1089 - }  
1090 -  
1091 - resp_length = build_response_basis(mb_param, &sft, response);  
1092 - /* 4 to copy the address (2) and the no. of registers */  
1093 - memcpy(response + resp_length, query + resp_length, 4);  
1094 - resp_length += 4;  
1095 - }  
1096 - }  
1097 - break;  
1098 - case FC_READ_EXCEPTION_STATUS:  
1099 - case FC_REPORT_SLAVE_ID: 922 + resp_length = build_response_basis(mb_param, &sft, response);
  923 + response[resp_length++] = (nb / 8) + ((nb % 8) ? 1 : 0);
  924 + resp_length = response_io_status(address, nb,
  925 + mb_mapping->tab_coil_status,
  926 + response, resp_length);
  927 + }
  928 + }
  929 + break;
  930 + case FC_READ_INPUT_STATUS: {
  931 + /* Similar to coil status (but too much arguments to use a
  932 + * function) */
  933 + int nb = (query[offset + 3] << 8) + query[offset + 4];
  934 +
  935 + if ((address + nb) > mb_mapping->nb_input_status) {
  936 + if (mb_param->debug) {
  937 + fprintf(stderr, "Illegal data address %0X in read_input_status\n",
  938 + address + nb);
  939 + }
  940 + resp_length = response_exception(
  941 + mb_param, &sft,
  942 + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);
  943 + } else {
  944 + resp_length = build_response_basis(mb_param, &sft, response);
  945 + response[resp_length++] = (nb / 8) + ((nb % 8) ? 1 : 0);
  946 + resp_length = response_io_status(address, nb,
  947 + mb_mapping->tab_input_status,
  948 + response, resp_length);
  949 + }
  950 + }
  951 + break;
  952 + case FC_READ_HOLDING_REGISTERS: {
  953 + int nb = (query[offset + 3] << 8) + query[offset + 4];
  954 +
  955 + if ((address + nb) > mb_mapping->nb_holding_registers) {
  956 + if (mb_param->debug) {
  957 + fprintf(stderr, "Illegal data address %0X in read_holding_registers\n",
  958 + address + nb);
  959 + }
  960 + resp_length = response_exception(
  961 + mb_param, &sft,
  962 + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);
  963 + } else {
  964 + int i;
  965 +
  966 + resp_length = build_response_basis(mb_param, &sft, response);
  967 + response[resp_length++] = nb << 1;
  968 + for (i = address; i < address + nb; i++) {
  969 + response[resp_length++] = mb_mapping->tab_holding_registers[i] >> 8;
  970 + response[resp_length++] = mb_mapping->tab_holding_registers[i] & 0xFF;
  971 + }
  972 + }
  973 + }
  974 + break;
  975 + case FC_READ_INPUT_REGISTERS: {
  976 + /* Similar to holding registers (but too much arguments to use a
  977 + * function) */
  978 + int nb = (query[offset + 3] << 8) + query[offset + 4];
  979 +
  980 + if ((address + nb) > mb_mapping->nb_input_registers) {
  981 + if (mb_param->debug) {
  982 + fprintf(stderr, "Illegal data address %0X in read_input_registers\n",
  983 + address + nb);
  984 + }
  985 + resp_length = response_exception(
  986 + mb_param, &sft,
  987 + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);
  988 + } else {
  989 + int i;
  990 +
  991 + resp_length = build_response_basis(mb_param, &sft, response);
  992 + response[resp_length++] = nb << 1;
  993 + for (i = address; i < address + nb; i++) {
  994 + response[resp_length++] = mb_mapping->tab_input_registers[i] >> 8;
  995 + response[resp_length++] = mb_mapping->tab_input_registers[i] & 0xFF;
  996 + }
  997 + }
  998 + }
  999 + break;
  1000 + case FC_FORCE_SINGLE_COIL:
  1001 + if (address >= mb_mapping->nb_coil_status) {
  1002 + if (mb_param->debug) {
  1003 + fprintf(stderr, "Illegal data address %0X in force_singe_coil\n",
  1004 + address);
  1005 + }
  1006 + resp_length = response_exception(
  1007 + mb_param, &sft,
  1008 + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);
  1009 + } else {
  1010 + int data = (query[offset + 3] << 8) + query[offset + 4];
  1011 +
  1012 + if (data == 0xFF00 || data == 0x0) {
  1013 + mb_mapping->tab_coil_status[address] = (data) ? ON : OFF;
  1014 +
  1015 + /* In RTU mode, the CRC is computed and added
  1016 + to the query by modbus_send, the computed
  1017 + CRC will be same and optimisation is
  1018 + possible here (FIXME). */
  1019 + memcpy(response, query, query_length);
  1020 + resp_length = query_length;
  1021 + } else {
1100 if (mb_param->debug) { 1022 if (mb_param->debug) {
1101 - fprintf(stderr, "FIXME Not implemented\n"); 1023 + fprintf(stderr, "Illegal data value %0X in force_single_coil request at address %0X\n",
  1024 + data, address);
1102 } 1025 }
1103 - errno = ENOPROTOOPT;  
1104 - return -1;  
1105 - break;  
1106 - default:  
1107 - /* FIXME Invalid function exception */  
1108 - break; 1026 + resp_length = response_exception(
  1027 + mb_param, &sft,
  1028 + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, response);
  1029 + }
  1030 + }
  1031 + break;
  1032 + case FC_PRESET_SINGLE_REGISTER:
  1033 + if (address >= mb_mapping->nb_holding_registers) {
  1034 + if (mb_param->debug) {
  1035 + fprintf(stderr, "Illegal data address %0X in preset_holding_register\n",
  1036 + address);
  1037 + }
  1038 + resp_length = response_exception(
  1039 + mb_param, &sft,
  1040 + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);
  1041 + } else {
  1042 + int data = (query[offset + 3] << 8) + query[offset + 4];
  1043 +
  1044 + mb_mapping->tab_holding_registers[address] = data;
  1045 + memcpy(response, query, query_length);
  1046 + resp_length = query_length;
  1047 + }
  1048 + break;
  1049 + case FC_FORCE_MULTIPLE_COILS: {
  1050 + int nb = (query[offset + 3] << 8) + query[offset + 4];
  1051 +
  1052 + if ((address + nb) > mb_mapping->nb_coil_status) {
  1053 + if (mb_param->debug) {
  1054 + fprintf(stderr, "Illegal data address %0X in force_multiple_coils\n",
  1055 + address + nb);
  1056 + }
  1057 + resp_length = response_exception(
  1058 + mb_param, &sft,
  1059 + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);
  1060 + } else {
  1061 + /* 6 = byte count */
  1062 + set_bits_from_bytes(mb_mapping->tab_coil_status, address, nb, &query[offset + 6]);
  1063 +
  1064 + resp_length = build_response_basis(mb_param, &sft, response);
  1065 + /* 4 to copy the coil address (2) and the quantity of coils */
  1066 + memcpy(response + resp_length, query + resp_length, 4);
  1067 + resp_length += 4;
  1068 + }
  1069 + }
  1070 + break;
  1071 + case FC_PRESET_MULTIPLE_REGISTERS: {
  1072 + int nb = (query[offset + 3] << 8) + query[offset + 4];
  1073 +
  1074 + if ((address + nb) > mb_mapping->nb_holding_registers) {
  1075 + if (mb_param->debug) {
  1076 + fprintf(stderr, "Illegal data address %0X in preset_multiple_registers\n",
  1077 + address + nb);
  1078 + }
  1079 + resp_length = response_exception(
  1080 + mb_param, &sft,
  1081 + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);
  1082 + } else {
  1083 + int i, j;
  1084 + for (i = address, j = 6; i < address + nb; i++, j += 2) {
  1085 + /* 6 and 7 = first value */
  1086 + mb_mapping->tab_holding_registers[i] =
  1087 + (query[offset + j] << 8) + query[offset + j + 1];
  1088 + }
  1089 +
  1090 + resp_length = build_response_basis(mb_param, &sft, response);
  1091 + /* 4 to copy the address (2) and the no. of registers */
  1092 + memcpy(response + resp_length, query + resp_length, 4);
  1093 + resp_length += 4;
  1094 + }
  1095 + }
  1096 + break;
  1097 + case FC_READ_EXCEPTION_STATUS:
  1098 + case FC_REPORT_SLAVE_ID:
  1099 + if (mb_param->debug) {
  1100 + fprintf(stderr, "FIXME Not implemented\n");
1109 } 1101 }
  1102 + errno = ENOPROTOOPT;
  1103 + return -1;
  1104 + break;
  1105 + default:
  1106 + /* FIXME Invalid function exception */
  1107 + break;
  1108 + }
1110 1109
1111 - return modbus_send(mb_param, response, resp_length); 1110 + return modbus_send(mb_param, response, resp_length);
1112 } 1111 }
1113 1112
1114 /* Reads IO status */ 1113 /* Reads IO status */
1115 static int read_io_status(modbus_param_t *mb_param, int slave, int function, 1114 static int read_io_status(modbus_param_t *mb_param, int slave, int function,
1116 int start_addr, int nb, uint8_t *data_dest) 1115 int start_addr, int nb, uint8_t *data_dest)
1117 { 1116 {
1118 - int rc;  
1119 - int query_length; 1117 + int rc;
  1118 + int query_length;
1120 1119
1121 - uint8_t query[MIN_QUERY_LENGTH];  
1122 - uint8_t response[MAX_MESSAGE_LENGTH]; 1120 + uint8_t query[MIN_QUERY_LENGTH];
  1121 + uint8_t response[MAX_MESSAGE_LENGTH];
1123 1122
1124 - query_length = build_query_basis(mb_param, slave, function,  
1125 - start_addr, nb, query); 1123 + query_length = build_query_basis(mb_param, slave, function,
  1124 + start_addr, nb, query);
1126 1125
1127 - rc = modbus_send(mb_param, query, query_length);  
1128 - if (rc > 0) {  
1129 - int i, temp, bit;  
1130 - int pos = 0;  
1131 - int offset;  
1132 - int offset_end; 1126 + rc = modbus_send(mb_param, query, query_length);
  1127 + if (rc > 0) {
  1128 + int i, temp, bit;
  1129 + int pos = 0;
  1130 + int offset;
  1131 + int offset_end;
1133 1132
1134 - rc = modbus_receive(mb_param, query, response);  
1135 - if (rc == -1)  
1136 - return -1; 1133 + rc = modbus_receive(mb_param, query, response);
  1134 + if (rc == -1)
  1135 + return -1;
1137 1136
1138 - offset = TAB_HEADER_LENGTH[mb_param->type_com];  
1139 - offset_end = offset + rc;  
1140 - for (i = offset; i < offset_end; i++) {  
1141 - /* Shift reg hi_byte to temp */  
1142 - temp = response[i + 2]; 1137 + offset = TAB_HEADER_LENGTH[mb_param->type_com];
  1138 + offset_end = offset + rc;
  1139 + for (i = offset; i < offset_end; i++) {
  1140 + /* Shift reg hi_byte to temp */
  1141 + temp = response[i + 2];
1143 1142
1144 - for (bit = 0x01; (bit & 0xff) && (pos < nb);) {  
1145 - data_dest[pos++] = (temp & bit) ? TRUE : FALSE;  
1146 - bit = bit << 1;  
1147 - } 1143 + for (bit = 0x01; (bit & 0xff) && (pos < nb);) {
  1144 + data_dest[pos++] = (temp & bit) ? TRUE : FALSE;
  1145 + bit = bit << 1;
  1146 + }
1148 1147
1149 - }  
1150 } 1148 }
  1149 + }
1151 1150
1152 - return rc; 1151 + return rc;
1153 } 1152 }
1154 1153
1155 /* Reads the boolean status of coils and sets the array elements 1154 /* Reads the boolean status of coils and sets the array elements
@@ -1157,25 +1156,25 @@ static int read_io_status(modbus_param_t *mb_param, int slave, int function, @@ -1157,25 +1156,25 @@ static int read_io_status(modbus_param_t *mb_param, int slave, int function,
1157 int read_coil_status(modbus_param_t *mb_param, int slave, int start_addr, 1156 int read_coil_status(modbus_param_t *mb_param, int slave, int start_addr,
1158 int nb, uint8_t *data_dest) 1157 int nb, uint8_t *data_dest)
1159 { 1158 {
1160 - int rc; 1159 + int rc;
1161 1160
1162 - if (nb > MAX_STATUS) {  
1163 - if (mb_param->debug) {  
1164 - fprintf(stderr,  
1165 - "ERROR Too many coils status requested (%d > %d)\n",  
1166 - nb, MAX_STATUS);  
1167 - }  
1168 - errno = EMBMDATA;  
1169 - return -1; 1161 + if (nb > MAX_STATUS) {
  1162 + if (mb_param->debug) {
  1163 + fprintf(stderr,
  1164 + "ERROR Too many coils status requested (%d > %d)\n",
  1165 + nb, MAX_STATUS);
1170 } 1166 }
  1167 + errno = EMBMDATA;
  1168 + return -1;
  1169 + }
1171 1170
1172 - rc = read_io_status(mb_param, slave, FC_READ_COIL_STATUS, start_addr,  
1173 - nb, data_dest); 1171 + rc = read_io_status(mb_param, slave, FC_READ_COIL_STATUS, start_addr,
  1172 + nb, data_dest);
1174 1173
1175 - if (rc == -1)  
1176 - return -1;  
1177 - else  
1178 - return nb; 1174 + if (rc == -1)
  1175 + return -1;
  1176 + else
  1177 + return nb;
1179 } 1178 }
1180 1179
1181 1180
@@ -1183,67 +1182,67 @@ int read_coil_status(modbus_param_t *mb_param, int slave, int start_addr, @@ -1183,67 +1182,67 @@ int read_coil_status(modbus_param_t *mb_param, int slave, int start_addr,
1183 int read_input_status(modbus_param_t *mb_param, int slave, int start_addr, 1182 int read_input_status(modbus_param_t *mb_param, int slave, int start_addr,
1184 int nb, uint8_t *data_dest) 1183 int nb, uint8_t *data_dest)
1185 { 1184 {
1186 - int rc; 1185 + int rc;
1187 1186
1188 - if (nb > MAX_STATUS) {  
1189 - if (mb_param->debug) {  
1190 - fprintf(stderr,  
1191 - "ERROR Too many input status requested (%d > %d)\n",  
1192 - nb, MAX_STATUS);  
1193 - }  
1194 - errno = EMBMDATA;  
1195 - return -1; 1187 + if (nb > MAX_STATUS) {
  1188 + if (mb_param->debug) {
  1189 + fprintf(stderr,
  1190 + "ERROR Too many input status requested (%d > %d)\n",
  1191 + nb, MAX_STATUS);
1196 } 1192 }
  1193 + errno = EMBMDATA;
  1194 + return -1;
  1195 + }
1197 1196
1198 - rc = read_io_status(mb_param, slave, FC_READ_INPUT_STATUS, start_addr,  
1199 - nb, data_dest); 1197 + rc = read_io_status(mb_param, slave, FC_READ_INPUT_STATUS, start_addr,
  1198 + nb, data_dest);
1200 1199
1201 - if (rc == -1)  
1202 - return -1;  
1203 - else  
1204 - return nb; 1200 + if (rc == -1)
  1201 + return -1;
  1202 + else
  1203 + return nb;
1205 } 1204 }
1206 1205
1207 /* Reads the data from a modbus slave and put that data into an array */ 1206 /* Reads the data from a modbus slave and put that data into an array */
1208 static int read_registers(modbus_param_t *mb_param, int slave, int function, 1207 static int read_registers(modbus_param_t *mb_param, int slave, int function,
1209 int start_addr, int nb, uint16_t *data_dest) 1208 int start_addr, int nb, uint16_t *data_dest)
1210 { 1209 {
1211 - int rc;  
1212 - int query_length;  
1213 - uint8_t query[MIN_QUERY_LENGTH];  
1214 - uint8_t response[MAX_MESSAGE_LENGTH]; 1210 + int rc;
  1211 + int query_length;
  1212 + uint8_t query[MIN_QUERY_LENGTH];
  1213 + uint8_t response[MAX_MESSAGE_LENGTH];
1215 1214
1216 - if (nb > MAX_REGISTERS) {  
1217 - if (mb_param->debug) {  
1218 - fprintf(stderr,  
1219 - "ERROR Too many holding registers requested (%d > %d)\n",  
1220 - nb, MAX_REGISTERS);  
1221 - }  
1222 - errno = EMBMDATA;  
1223 - return -1; 1215 + if (nb > MAX_REGISTERS) {
  1216 + if (mb_param->debug) {
  1217 + fprintf(stderr,
  1218 + "ERROR Too many holding registers requested (%d > %d)\n",
  1219 + nb, MAX_REGISTERS);
1224 } 1220 }
  1221 + errno = EMBMDATA;
  1222 + return -1;
  1223 + }
1225 1224
1226 - query_length = build_query_basis(mb_param, slave, function,  
1227 - start_addr, nb, query); 1225 + query_length = build_query_basis(mb_param, slave, function,
  1226 + start_addr, nb, query);
1228 1227
1229 - rc = modbus_send(mb_param, query, query_length);  
1230 - if (rc > 0) {  
1231 - int offset;  
1232 - int i; 1228 + rc = modbus_send(mb_param, query, query_length);
  1229 + if (rc > 0) {
  1230 + int offset;
  1231 + int i;
1233 1232
1234 - rc = modbus_receive(mb_param, query, response); 1233 + rc = modbus_receive(mb_param, query, response);
1235 1234
1236 - offset = TAB_HEADER_LENGTH[mb_param->type_com]; 1235 + offset = TAB_HEADER_LENGTH[mb_param->type_com];
1237 1236
1238 - /* If rc is negative, the loop is jumped ! */  
1239 - for (i = 0; i < rc; i++) {  
1240 - /* shift reg hi_byte to temp OR with lo_byte */  
1241 - data_dest[i] = (response[offset + 2 + (i << 1)] << 8) |  
1242 - response[offset + 3 + (i << 1)];  
1243 - } 1237 + /* If rc is negative, the loop is jumped ! */
  1238 + for (i = 0; i < rc; i++) {
  1239 + /* shift reg hi_byte to temp OR with lo_byte */
  1240 + data_dest[i] = (response[offset + 2 + (i << 1)] << 8) |
  1241 + response[offset + 3 + (i << 1)];
1244 } 1242 }
  1243 + }
1245 1244
1246 - return rc; 1245 + return rc;
1247 } 1246 }
1248 1247
1249 /* Reads the holding registers in a slave and put the data into an 1248 /* Reads the holding registers in a slave and put the data into an
@@ -1251,21 +1250,21 @@ static int read_registers(modbus_param_t *mb_param, int slave, int function, @@ -1251,21 +1250,21 @@ static int read_registers(modbus_param_t *mb_param, int slave, int function,
1251 int read_holding_registers(modbus_param_t *mb_param, int slave, 1250 int read_holding_registers(modbus_param_t *mb_param, int slave,
1252 int start_addr, int nb, uint16_t *data_dest) 1251 int start_addr, int nb, uint16_t *data_dest)
1253 { 1252 {
1254 - int status; 1253 + int status;
1255 1254
1256 - if (nb > MAX_REGISTERS) {  
1257 - if (mb_param->debug) {  
1258 - fprintf(stderr,  
1259 - "ERROR Too many holding registers requested (%d > %d)\n",  
1260 - nb, MAX_REGISTERS);  
1261 - }  
1262 - errno = EMBMDATA;  
1263 - return -1; 1255 + if (nb > MAX_REGISTERS) {
  1256 + if (mb_param->debug) {
  1257 + fprintf(stderr,
  1258 + "ERROR Too many holding registers requested (%d > %d)\n",
  1259 + nb, MAX_REGISTERS);
1264 } 1260 }
  1261 + errno = EMBMDATA;
  1262 + return -1;
  1263 + }
1265 1264
1266 - status = read_registers(mb_param, slave, FC_READ_HOLDING_REGISTERS,  
1267 - start_addr, nb, data_dest);  
1268 - return status; 1265 + status = read_registers(mb_param, slave, FC_READ_HOLDING_REGISTERS,
  1266 + start_addr, nb, data_dest);
  1267 + return status;
1269 } 1268 }
1270 1269
1271 /* Reads the input registers in a slave and put the data into 1270 /* Reads the input registers in a slave and put the data into
@@ -1273,20 +1272,20 @@ int read_holding_registers(modbus_param_t *mb_param, int slave, @@ -1273,20 +1272,20 @@ int read_holding_registers(modbus_param_t *mb_param, int slave,
1273 int read_input_registers(modbus_param_t *mb_param, int slave, int start_addr, 1272 int read_input_registers(modbus_param_t *mb_param, int slave, int start_addr,
1274 int nb, uint16_t *data_dest) 1273 int nb, uint16_t *data_dest)
1275 { 1274 {
1276 - int status; 1275 + int status;
1277 1276
1278 - if (nb > MAX_REGISTERS) {  
1279 - fprintf(stderr,  
1280 - "ERROR Too many input registers requested (%d > %d)\n",  
1281 - nb, MAX_REGISTERS);  
1282 - errno = EMBMDATA;  
1283 - return -1;  
1284 - } 1277 + if (nb > MAX_REGISTERS) {
  1278 + fprintf(stderr,
  1279 + "ERROR Too many input registers requested (%d > %d)\n",
  1280 + nb, MAX_REGISTERS);
  1281 + errno = EMBMDATA;
  1282 + return -1;
  1283 + }
1285 1284
1286 - status = read_registers(mb_param, slave, FC_READ_INPUT_REGISTERS,  
1287 - start_addr, nb, data_dest); 1285 + status = read_registers(mb_param, slave, FC_READ_INPUT_REGISTERS,
  1286 + start_addr, nb, data_dest);
1288 1287
1289 - return status; 1288 + return status;
1290 } 1289 }
1291 1290
1292 /* Sends a value to a register in a slave. 1291 /* Sends a value to a register in a slave.
@@ -1294,187 +1293,187 @@ int read_input_registers(modbus_param_t *mb_param, int slave, int start_addr, @@ -1294,187 +1293,187 @@ int read_input_registers(modbus_param_t *mb_param, int slave, int start_addr,
1294 static int set_single(modbus_param_t *mb_param, int slave, int function, 1293 static int set_single(modbus_param_t *mb_param, int slave, int function,
1295 int addr, int value) 1294 int addr, int value)
1296 { 1295 {
1297 - int rc;  
1298 - int query_length;  
1299 - uint8_t query[MIN_QUERY_LENGTH];  
1300 -  
1301 - query_length = build_query_basis(mb_param, slave, function,  
1302 - addr, value, query);  
1303 -  
1304 - rc = modbus_send(mb_param, query, query_length);  
1305 - if (rc > 0) {  
1306 - /* Used by force_single_coil and  
1307 - * preset_single_register */  
1308 - uint8_t response[MIN_QUERY_LENGTH];  
1309 - rc = modbus_receive(mb_param, query, response);  
1310 - }  
1311 -  
1312 - return rc; 1296 + int rc;
  1297 + int query_length;
  1298 + uint8_t query[MIN_QUERY_LENGTH];
  1299 +
  1300 + query_length = build_query_basis(mb_param, slave, function,
  1301 + addr, value, query);
  1302 +
  1303 + rc = modbus_send(mb_param, query, query_length);
  1304 + if (rc > 0) {
  1305 + /* Used by force_single_coil and
  1306 + * preset_single_register */
  1307 + uint8_t response[MIN_QUERY_LENGTH];
  1308 + rc = modbus_receive(mb_param, query, response);
  1309 + }
  1310 +
  1311 + return rc;
1313 } 1312 }
1314 1313
1315 /* Turns ON or OFF a single coil in the slave device */ 1314 /* Turns ON or OFF a single coil in the slave device */
1316 int force_single_coil(modbus_param_t *mb_param, int slave, int coil_addr, int state) 1315 int force_single_coil(modbus_param_t *mb_param, int slave, int coil_addr, int state)
1317 { 1316 {
1318 - int status; 1317 + int status;
1319 1318
1320 - if (state)  
1321 - state = 0xFF00; 1319 + if (state)
  1320 + state = 0xFF00;
1322 1321
1323 - status = set_single(mb_param, slave, FC_FORCE_SINGLE_COIL,  
1324 - coil_addr, state); 1322 + status = set_single(mb_param, slave, FC_FORCE_SINGLE_COIL,
  1323 + coil_addr, state);
1325 1324
1326 - return status; 1325 + return status;
1327 } 1326 }
1328 1327
1329 /* Sets a value in one holding register in the slave device */ 1328 /* Sets a value in one holding register in the slave device */
1330 int preset_single_register(modbus_param_t *mb_param, int slave, int reg_addr, 1329 int preset_single_register(modbus_param_t *mb_param, int slave, int reg_addr,
1331 int value) 1330 int value)
1332 { 1331 {
1333 - int status; 1332 + int status;
1334 1333
1335 - status = set_single(mb_param, slave, FC_PRESET_SINGLE_REGISTER,  
1336 - reg_addr, value); 1334 + status = set_single(mb_param, slave, FC_PRESET_SINGLE_REGISTER,
  1335 + reg_addr, value);
1337 1336
1338 - return status; 1337 + return status;
1339 } 1338 }
1340 1339
1341 /* Sets/resets the coils in the slave from an array in argument */ 1340 /* Sets/resets the coils in the slave from an array in argument */
1342 int force_multiple_coils(modbus_param_t *mb_param, int slave, int start_addr, 1341 int force_multiple_coils(modbus_param_t *mb_param, int slave, int start_addr,
1343 int nb, const uint8_t *data_src) 1342 int nb, const uint8_t *data_src)
1344 { 1343 {
1345 - int rc;  
1346 - int i;  
1347 - int byte_count;  
1348 - int query_length;  
1349 - int coil_check = 0;  
1350 - int pos = 0; 1344 + int rc;
  1345 + int i;
  1346 + int byte_count;
  1347 + int query_length;
  1348 + int coil_check = 0;
  1349 + int pos = 0;
1351 1350
1352 - uint8_t query[MAX_MESSAGE_LENGTH]; 1351 + uint8_t query[MAX_MESSAGE_LENGTH];
1353 1352
1354 - if (nb > MAX_STATUS) {  
1355 - if (mb_param->debug) {  
1356 - fprintf(stderr, "ERROR Writing to too many coils (%d > %d)\n",  
1357 - nb, MAX_STATUS);  
1358 - }  
1359 - errno = EMBMDATA;  
1360 - return -1; 1353 + if (nb > MAX_STATUS) {
  1354 + if (mb_param->debug) {
  1355 + fprintf(stderr, "ERROR Writing to too many coils (%d > %d)\n",
  1356 + nb, MAX_STATUS);
1361 } 1357 }
  1358 + errno = EMBMDATA;
  1359 + return -1;
  1360 + }
1362 1361
1363 - query_length = build_query_basis(mb_param, slave, FC_FORCE_MULTIPLE_COILS,  
1364 - start_addr, nb, query);  
1365 - byte_count = (nb / 8) + ((nb % 8) ? 1 : 0);  
1366 - query[query_length++] = byte_count; 1362 + query_length = build_query_basis(mb_param, slave, FC_FORCE_MULTIPLE_COILS,
  1363 + start_addr, nb, query);
  1364 + byte_count = (nb / 8) + ((nb % 8) ? 1 : 0);
  1365 + query[query_length++] = byte_count;
1367 1366
1368 - for (i = 0; i < byte_count; i++) {  
1369 - int bit; 1367 + for (i = 0; i < byte_count; i++) {
  1368 + int bit;
1370 1369
1371 - bit = 0x01;  
1372 - query[query_length] = 0; 1370 + bit = 0x01;
  1371 + query[query_length] = 0;
1373 1372
1374 - while ((bit & 0xFF) && (coil_check++ < nb)) {  
1375 - if (data_src[pos++])  
1376 - query[query_length] |= bit;  
1377 - else  
1378 - query[query_length] &=~ bit; 1373 + while ((bit & 0xFF) && (coil_check++ < nb)) {
  1374 + if (data_src[pos++])
  1375 + query[query_length] |= bit;
  1376 + else
  1377 + query[query_length] &=~ bit;
1379 1378
1380 - bit = bit << 1;  
1381 - }  
1382 - query_length++; 1379 + bit = bit << 1;
1383 } 1380 }
  1381 + query_length++;
  1382 + }
1384 1383
1385 - rc = modbus_send(mb_param, query, query_length);  
1386 - if (rc > 0) {  
1387 - uint8_t response[MAX_MESSAGE_LENGTH];  
1388 - rc = modbus_receive(mb_param, query, response);  
1389 - } 1384 + rc = modbus_send(mb_param, query, query_length);
  1385 + if (rc > 0) {
  1386 + uint8_t response[MAX_MESSAGE_LENGTH];
  1387 + rc = modbus_receive(mb_param, query, response);
  1388 + }
1390 1389
1391 1390
1392 - return rc; 1391 + return rc;
1393 } 1392 }
1394 1393
1395 /* Copies the values in the slave from the array given in argument */ 1394 /* Copies the values in the slave from the array given in argument */
1396 int preset_multiple_registers(modbus_param_t *mb_param, int slave, int start_addr, 1395 int preset_multiple_registers(modbus_param_t *mb_param, int slave, int start_addr,
1397 int nb, const uint16_t *data_src) 1396 int nb, const uint16_t *data_src)
1398 { 1397 {
1399 - int rc;  
1400 - int i;  
1401 - int query_length;  
1402 - int byte_count;  
1403 -  
1404 - uint8_t query[MAX_MESSAGE_LENGTH];  
1405 -  
1406 - if (nb > MAX_REGISTERS) {  
1407 - if (mb_param->debug) {  
1408 - fprintf(stderr,  
1409 - "ERROR Trying to write to too many registers (%d > %d)\n",  
1410 - nb, MAX_REGISTERS);  
1411 - }  
1412 - errno = EMBMDATA;  
1413 - return -1;  
1414 - }  
1415 -  
1416 - query_length = build_query_basis(mb_param, slave, FC_PRESET_MULTIPLE_REGISTERS,  
1417 - start_addr, nb, query);  
1418 - byte_count = nb * 2;  
1419 - query[query_length++] = byte_count; 1398 + int rc;
  1399 + int i;
  1400 + int query_length;
  1401 + int byte_count;
1420 1402
1421 - for (i = 0; i < nb; i++) {  
1422 - query[query_length++] = data_src[i] >> 8;  
1423 - query[query_length++] = data_src[i] & 0x00FF;  
1424 - } 1403 + uint8_t query[MAX_MESSAGE_LENGTH];
1425 1404
1426 - rc = modbus_send(mb_param, query, query_length);  
1427 - if (rc > 0) {  
1428 - uint8_t response[MAX_MESSAGE_LENGTH];  
1429 - rc = modbus_receive(mb_param, query, response);  
1430 - } 1405 + if (nb > MAX_REGISTERS) {
  1406 + if (mb_param->debug) {
  1407 + fprintf(stderr,
  1408 + "ERROR Trying to write to too many registers (%d > %d)\n",
  1409 + nb, MAX_REGISTERS);
  1410 + }
  1411 + errno = EMBMDATA;
  1412 + return -1;
  1413 + }
  1414 +
  1415 + query_length = build_query_basis(mb_param, slave, FC_PRESET_MULTIPLE_REGISTERS,
  1416 + start_addr, nb, query);
  1417 + byte_count = nb * 2;
  1418 + query[query_length++] = byte_count;
  1419 +
  1420 + for (i = 0; i < nb; i++) {
  1421 + query[query_length++] = data_src[i] >> 8;
  1422 + query[query_length++] = data_src[i] & 0x00FF;
  1423 + }
  1424 +
  1425 + rc = modbus_send(mb_param, query, query_length);
  1426 + if (rc > 0) {
  1427 + uint8_t response[MAX_MESSAGE_LENGTH];
  1428 + rc = modbus_receive(mb_param, query, response);
  1429 + }
1431 1430
1432 - return rc; 1431 + return rc;
1433 } 1432 }
1434 1433
1435 /* Request the slave ID */ 1434 /* Request the slave ID */
1436 int report_slave_id(modbus_param_t *mb_param, int slave, uint8_t *data_dest) 1435 int report_slave_id(modbus_param_t *mb_param, int slave, uint8_t *data_dest)
1437 { 1436 {
1438 - int rc;  
1439 - int query_length;  
1440 - uint8_t query[MIN_QUERY_LENGTH];  
1441 -  
1442 - query_length = build_query_basis(mb_param, slave,  
1443 - FC_REPORT_SLAVE_ID, 0, 0, query);  
1444 -  
1445 - /* HACKISH, start_addr and count are not used */  
1446 - query_length -= 4;  
1447 -  
1448 - rc = modbus_send(mb_param, query, query_length);  
1449 - if (rc > 0) {  
1450 - int i;  
1451 - int offset;  
1452 - int offset_end;  
1453 - uint8_t response[MAX_MESSAGE_LENGTH];  
1454 -  
1455 - /* Byte count, slave id, run indicator status,  
1456 - additional data */  
1457 - rc = modbus_receive(mb_param, query, response);  
1458 - if (rc == -1)  
1459 - return rc;  
1460 -  
1461 - offset = TAB_HEADER_LENGTH[mb_param->type_com] - 1;  
1462 - offset_end = offset + rc;  
1463 -  
1464 - for (i = offset; i < offset_end; i++)  
1465 - data_dest[i] = response[i];  
1466 - } 1437 + int rc;
  1438 + int query_length;
  1439 + uint8_t query[MIN_QUERY_LENGTH];
  1440 +
  1441 + query_length = build_query_basis(mb_param, slave,
  1442 + FC_REPORT_SLAVE_ID, 0, 0, query);
  1443 +
  1444 + /* HACKISH, start_addr and count are not used */
  1445 + query_length -= 4;
  1446 +
  1447 + rc = modbus_send(mb_param, query, query_length);
  1448 + if (rc > 0) {
  1449 + int i;
  1450 + int offset;
  1451 + int offset_end;
  1452 + uint8_t response[MAX_MESSAGE_LENGTH];
  1453 +
  1454 + /* Byte count, slave id, run indicator status,
  1455 + additional data */
  1456 + rc = modbus_receive(mb_param, query, response);
  1457 + if (rc == -1)
  1458 + return rc;
  1459 +
  1460 + offset = TAB_HEADER_LENGTH[mb_param->type_com] - 1;
  1461 + offset_end = offset + rc;
  1462 +
  1463 + for (i = offset; i < offset_end; i++)
  1464 + data_dest[i] = response[i];
  1465 + }
1467 1466
1468 - return rc; 1467 + return rc;
1469 } 1468 }
1470 1469
1471 void init_common(modbus_param_t *mb_param) 1470 void init_common(modbus_param_t *mb_param)
1472 { 1471 {
1473 - mb_param->timeout_begin.tv_sec = 0;  
1474 - mb_param->timeout_begin.tv_usec = TIME_OUT_BEGIN_OF_TRAME; 1472 + mb_param->timeout_begin.tv_sec = 0;
  1473 + mb_param->timeout_begin.tv_usec = TIME_OUT_BEGIN_OF_TRAME;
1475 1474
1476 - mb_param->timeout_end.tv_sec = 0;  
1477 - mb_param->timeout_end.tv_usec = TIME_OUT_END_OF_TRAME; 1475 + mb_param->timeout_end.tv_sec = 0;
  1476 + mb_param->timeout_end.tv_usec = TIME_OUT_END_OF_TRAME;
1478 } 1477 }
1479 1478
1480 /* Initializes the modbus_param_t structure for RTU 1479 /* Initializes the modbus_param_t structure for RTU
@@ -1486,26 +1485,26 @@ void init_common(modbus_param_t *mb_param) @@ -1486,26 +1485,26 @@ void init_common(modbus_param_t *mb_param)
1486 - slave: slave number 1485 - slave: slave number
1487 */ 1486 */
1488 int modbus_init_rtu(modbus_param_t *mb_param, const char *device, 1487 int modbus_init_rtu(modbus_param_t *mb_param, const char *device,
1489 - int baud, char parity, int data_bit,  
1490 - int stop_bit, int slave) 1488 + int baud, char parity, int data_bit,
  1489 + int stop_bit, int slave)
1491 { 1490 {
1492 - memset(mb_param, 0, sizeof(modbus_param_t));  
1493 - init_common(mb_param);  
1494 -  
1495 - strcpy(mb_param->device, device);  
1496 - mb_param->baud = baud;  
1497 - if (parity == 'N' || parity == 'E' || parity == 'O') {  
1498 - mb_param->parity = parity;  
1499 - } else {  
1500 - errno = EINVAL;  
1501 - return -1;  
1502 - }  
1503 - mb_param->debug = FALSE;  
1504 - mb_param->data_bit = data_bit;  
1505 - mb_param->stop_bit = stop_bit;  
1506 - mb_param->type_com = RTU;  
1507 - mb_param->error_recovery = FALSE;  
1508 - return modbus_set_slave(mb_param, slave); 1491 + memset(mb_param, 0, sizeof(modbus_param_t));
  1492 + init_common(mb_param);
  1493 +
  1494 + strcpy(mb_param->device, device);
  1495 + mb_param->baud = baud;
  1496 + if (parity == 'N' || parity == 'E' || parity == 'O') {
  1497 + mb_param->parity = parity;
  1498 + } else {
  1499 + errno = EINVAL;
  1500 + return -1;
  1501 + }
  1502 + mb_param->debug = FALSE;
  1503 + mb_param->data_bit = data_bit;
  1504 + mb_param->stop_bit = stop_bit;
  1505 + mb_param->type_com = RTU;
  1506 + mb_param->error_recovery = FALSE;
  1507 + return modbus_set_slave(mb_param, slave);
1509 } 1508 }
1510 1509
1511 /* Initializes the modbus_param_t structure for TCP. 1510 /* Initializes the modbus_param_t structure for TCP.
@@ -1519,437 +1518,437 @@ int modbus_init_rtu(modbus_param_t *mb_param, const char *device, @@ -1519,437 +1518,437 @@ int modbus_init_rtu(modbus_param_t *mb_param, const char *device,
1519 */ 1518 */
1520 int modbus_init_tcp(modbus_param_t *mb_param, const char *ip, int port) 1519 int modbus_init_tcp(modbus_param_t *mb_param, const char *ip, int port)
1521 { 1520 {
1522 - memset(mb_param, 0, sizeof(modbus_param_t));  
1523 - init_common(mb_param); 1521 + memset(mb_param, 0, sizeof(modbus_param_t));
  1522 + init_common(mb_param);
1524 1523
1525 - strncpy(mb_param->ip, ip, sizeof(char)*16);  
1526 - mb_param->port = port;  
1527 - mb_param->type_com = TCP;  
1528 - mb_param->error_recovery = FALSE;  
1529 - /* Can be changed after to reach remote serial Modbus device */  
1530 - mb_param->slave = 0xFF; 1524 + strncpy(mb_param->ip, ip, sizeof(char)*16);
  1525 + mb_param->port = port;
  1526 + mb_param->type_com = TCP;
  1527 + mb_param->error_recovery = FALSE;
  1528 + /* Can be changed after to reach remote serial Modbus device */
  1529 + mb_param->slave = 0xFF;
1531 1530
1532 - return 0; 1531 + return 0;
1533 } 1532 }
1534 1533
1535 /* Define the slave number, the special value MODBUS_TCP_SLAVE (0xFF) can be 1534 /* Define the slave number, the special value MODBUS_TCP_SLAVE (0xFF) can be
1536 * used in TCP mode to restore the default value. */ 1535 * used in TCP mode to restore the default value. */
1537 int modbus_set_slave(modbus_param_t *mb_param, int slave) 1536 int modbus_set_slave(modbus_param_t *mb_param, int slave)
1538 { 1537 {
1539 - if (slave >= 1 && slave <= 247) {  
1540 - mb_param->slave = slave;  
1541 - } else if (mb_param->type_com == TCP && slave == MODBUS_TCP_SLAVE) {  
1542 - mb_param->slave = slave;  
1543 - } else {  
1544 - errno = EINVAL;  
1545 - return -1;  
1546 - }  
1547 -  
1548 - return 0; 1538 + if (slave >= 1 && slave <= 247) {
  1539 + mb_param->slave = slave;
  1540 + } else if (mb_param->type_com == TCP && slave == MODBUS_TCP_SLAVE) {
  1541 + mb_param->slave = slave;
  1542 + } else {
  1543 + errno = EINVAL;
  1544 + return -1;
  1545 + }
  1546 +
  1547 + return 0;
1549 } 1548 }
1550 1549
1551 /* 1550 /*
1552 - When disabled (default), it is expected that the application will check for  
1553 - error returns and deal with them as necessary. 1551 + When disabled (default), it is expected that the application will check for
  1552 + error returns and deal with them as necessary.
1554 1553
1555 - It's not recommanded to enable error recovery for slave/server. 1554 + It's not recommanded to enable error recovery for slave/server.
1556 1555
1557 - When enabled, the library will attempt an immediate reconnection which may  
1558 - hang for several seconds if the network to the remote target unit is down.  
1559 - The write will try a infinite close/connect loop until to be successful and  
1560 - the select/read calls will just try to retablish the connection one time then  
1561 - will return an error (if the connecton was down, the values to read are  
1562 - certainly not available anymore after reconnection, except for slave/server). 1556 + When enabled, the library will attempt an immediate reconnection which may
  1557 + hang for several seconds if the network to the remote target unit is down.
  1558 + The write will try a infinite close/connect loop until to be successful and
  1559 + the select/read calls will just try to retablish the connection one time then
  1560 + will return an error (if the connecton was down, the values to read are
  1561 + certainly not available anymore after reconnection, except for slave/server).
1563 */ 1562 */
1564 int modbus_set_error_recovery(modbus_param_t *mb_param, int enabled) 1563 int modbus_set_error_recovery(modbus_param_t *mb_param, int enabled)
1565 { 1564 {
1566 - if (enabled == TRUE || enabled == FALSE) {  
1567 - mb_param->error_recovery = (uint8_t) enabled;  
1568 - } else {  
1569 - errno = EINVAL;  
1570 - return -1;  
1571 - }  
1572 -  
1573 - return 0; 1565 + if (enabled == TRUE || enabled == FALSE) {
  1566 + mb_param->error_recovery = (uint8_t) enabled;
  1567 + } else {
  1568 + errno = EINVAL;
  1569 + return -1;
  1570 + }
  1571 +
  1572 + return 0;
1574 } 1573 }
1575 1574
1576 /* Get the timeout of begin of trame */ 1575 /* Get the timeout of begin of trame */
1577 void modbus_get_timeout_begin(modbus_param_t *mb_param, struct timeval *timeout) 1576 void modbus_get_timeout_begin(modbus_param_t *mb_param, struct timeval *timeout)
1578 { 1577 {
1579 - *timeout = mb_param->timeout_begin; 1578 + *timeout = mb_param->timeout_begin;
1580 } 1579 }
1581 1580
1582 /* Set timeout when waiting the beginning of a trame */ 1581 /* Set timeout when waiting the beginning of a trame */
1583 void modbus_set_timeout_begin(modbus_param_t *mb_param, const struct timeval *timeout) 1582 void modbus_set_timeout_begin(modbus_param_t *mb_param, const struct timeval *timeout)
1584 { 1583 {
1585 - mb_param->timeout_begin = *timeout; 1584 + mb_param->timeout_begin = *timeout;
1586 } 1585 }
1587 1586
1588 /* Get the timeout of end of trame */ 1587 /* Get the timeout of end of trame */
1589 void modbus_get_timeout_end(modbus_param_t *mb_param, struct timeval *timeout) 1588 void modbus_get_timeout_end(modbus_param_t *mb_param, struct timeval *timeout)
1590 { 1589 {
1591 - *timeout = mb_param->timeout_end; 1590 + *timeout = mb_param->timeout_end;
1592 } 1591 }
1593 1592
1594 /* Set timeout when waiting the end of a trame */ 1593 /* Set timeout when waiting the end of a trame */
1595 void modbus_set_timeout_end(modbus_param_t *mb_param, const struct timeval *timeout) 1594 void modbus_set_timeout_end(modbus_param_t *mb_param, const struct timeval *timeout)
1596 { 1595 {
1597 - mb_param->timeout_end = *timeout; 1596 + mb_param->timeout_end = *timeout;
1598 } 1597 }
1599 1598
1600 /* Sets up a serial port for RTU communications */ 1599 /* Sets up a serial port for RTU communications */
1601 static int modbus_connect_rtu(modbus_param_t *mb_param) 1600 static int modbus_connect_rtu(modbus_param_t *mb_param)
1602 { 1601 {
1603 - struct termios tios;  
1604 - speed_t speed;  
1605 - 1602 + struct termios tios;
  1603 + speed_t speed;
  1604 +
  1605 + if (mb_param->debug) {
  1606 + printf("Opening %s at %d bauds (%c, %d, %d)\n",
  1607 + mb_param->device, mb_param->baud, mb_param->parity,
  1608 + mb_param->data_bit, mb_param->stop_bit);
  1609 + }
  1610 +
  1611 + /* The O_NOCTTY flag tells UNIX that this program doesn't want
  1612 + to be the "controlling terminal" for that port. If you
  1613 + don't specify this then any input (such as keyboard abort
  1614 + signals and so forth) will affect your process
  1615 +
  1616 + Timeouts are ignored in canonical input mode or when the
  1617 + NDELAY option is set on the file via open or fcntl */
  1618 + mb_param->fd = open(mb_param->device, O_RDWR | O_NOCTTY | O_NDELAY | O_EXCL);
  1619 + if (mb_param->fd == -1) {
  1620 + fprintf(stderr, "ERROR Can't open the device %s (%s)\n",
  1621 + mb_param->device, strerror(errno));
  1622 + return -1;
  1623 + }
  1624 +
  1625 + /* Save */
  1626 + tcgetattr(mb_param->fd, &(mb_param->old_tios));
  1627 +
  1628 + memset(&tios, 0, sizeof(struct termios));
  1629 +
  1630 + /* C_ISPEED Input baud (new interface)
  1631 + C_OSPEED Output baud (new interface)
  1632 + */
  1633 + switch (mb_param->baud) {
  1634 + case 110:
  1635 + speed = B110;
  1636 + break;
  1637 + case 300:
  1638 + speed = B300;
  1639 + break;
  1640 + case 600:
  1641 + speed = B600;
  1642 + break;
  1643 + case 1200:
  1644 + speed = B1200;
  1645 + break;
  1646 + case 2400:
  1647 + speed = B2400;
  1648 + break;
  1649 + case 4800:
  1650 + speed = B4800;
  1651 + break;
  1652 + case 9600:
  1653 + speed = B9600;
  1654 + break;
  1655 + case 19200:
  1656 + speed = B19200;
  1657 + break;
  1658 + case 38400:
  1659 + speed = B38400;
  1660 + break;
  1661 + case 57600:
  1662 + speed = B57600;
  1663 + break;
  1664 + case 115200:
  1665 + speed = B115200;
  1666 + break;
  1667 + default:
  1668 + speed = B9600;
1606 if (mb_param->debug) { 1669 if (mb_param->debug) {
1607 - printf("Opening %s at %d bauds (%c, %d, %d)\n",  
1608 - mb_param->device, mb_param->baud, mb_param->parity,  
1609 - mb_param->data_bit, mb_param->stop_bit);  
1610 - }  
1611 -  
1612 - /* The O_NOCTTY flag tells UNIX that this program doesn't want  
1613 - to be the "controlling terminal" for that port. If you  
1614 - don't specify this then any input (such as keyboard abort  
1615 - signals and so forth) will affect your process  
1616 -  
1617 - Timeouts are ignored in canonical input mode or when the  
1618 - NDELAY option is set on the file via open or fcntl */  
1619 - mb_param->fd = open(mb_param->device, O_RDWR | O_NOCTTY | O_NDELAY | O_EXCL);  
1620 - if (mb_param->fd == -1) {  
1621 - fprintf(stderr, "ERROR Can't open the device %s (%s)\n",  
1622 - mb_param->device, strerror(errno));  
1623 - return -1;  
1624 - }  
1625 -  
1626 - /* Save */  
1627 - tcgetattr(mb_param->fd, &(mb_param->old_tios));  
1628 -  
1629 - memset(&tios, 0, sizeof(struct termios));  
1630 -  
1631 - /* C_ISPEED Input baud (new interface)  
1632 - C_OSPEED Output baud (new interface)  
1633 - */  
1634 - switch (mb_param->baud) {  
1635 - case 110:  
1636 - speed = B110;  
1637 - break;  
1638 - case 300:  
1639 - speed = B300;  
1640 - break;  
1641 - case 600:  
1642 - speed = B600;  
1643 - break;  
1644 - case 1200:  
1645 - speed = B1200;  
1646 - break;  
1647 - case 2400:  
1648 - speed = B2400;  
1649 - break;  
1650 - case 4800:  
1651 - speed = B4800;  
1652 - break;  
1653 - case 9600:  
1654 - speed = B9600;  
1655 - break;  
1656 - case 19200:  
1657 - speed = B19200;  
1658 - break;  
1659 - case 38400:  
1660 - speed = B38400;  
1661 - break;  
1662 - case 57600:  
1663 - speed = B57600;  
1664 - break;  
1665 - case 115200:  
1666 - speed = B115200;  
1667 - break;  
1668 - default:  
1669 - speed = B9600;  
1670 - if (mb_param->debug) {  
1671 - fprintf(stderr,  
1672 - "WARNING Unknown baud rate %d for %s (B9600 used)\n",  
1673 - mb_param->baud, mb_param->device);  
1674 - }  
1675 - }  
1676 -  
1677 - /* Set the baud rate */  
1678 - if ((cfsetispeed(&tios, speed) < 0) ||  
1679 - (cfsetospeed(&tios, speed) < 0)) {  
1680 - return -1;  
1681 - }  
1682 -  
1683 - /* C_CFLAG Control options  
1684 - CLOCAL Local line - do not change "owner" of port  
1685 - CREAD Enable receiver  
1686 - */  
1687 - tios.c_cflag |= (CREAD | CLOCAL);  
1688 - /* CSIZE, HUPCL, CRTSCTS (hardware flow control) */  
1689 -  
1690 - /* Set data bits (5, 6, 7, 8 bits)  
1691 - CSIZE Bit mask for data bits  
1692 - */  
1693 - tios.c_cflag &= ~CSIZE;  
1694 - switch (mb_param->data_bit) {  
1695 - case 5:  
1696 - tios.c_cflag |= CS5;  
1697 - break;  
1698 - case 6:  
1699 - tios.c_cflag |= CS6;  
1700 - break;  
1701 - case 7:  
1702 - tios.c_cflag |= CS7;  
1703 - break;  
1704 - case 8:  
1705 - default:  
1706 - tios.c_cflag |= CS8;  
1707 - break;  
1708 - }  
1709 -  
1710 - /* Stop bit (1 or 2) */  
1711 - if (mb_param->stop_bit == 1)  
1712 - tios.c_cflag &=~ CSTOPB;  
1713 - else /* 2 */  
1714 - tios.c_cflag |= CSTOPB;  
1715 -  
1716 - /* PARENB Enable parity bit  
1717 - PARODD Use odd parity instead of even */  
1718 - if (mb_param->parity == 'N') {  
1719 - /* None */  
1720 - tios.c_cflag &=~ PARENB;  
1721 - } else if (mb_param->parity == 'E') {  
1722 - /* Even */  
1723 - tios.c_cflag |= PARENB;  
1724 - tios.c_cflag &=~ PARODD;  
1725 - } else {  
1726 - /* Odd */  
1727 - tios.c_cflag |= PARENB;  
1728 - tios.c_cflag |= PARODD;  
1729 - }  
1730 -  
1731 - /* Read the man page of termios if you need more information. */  
1732 -  
1733 - /* This field isn't used on POSIX systems  
1734 - tios.c_line = 0;  
1735 - */  
1736 -  
1737 - /* C_LFLAG Line options  
1738 -  
1739 - ISIG Enable SIGINTR, SIGSUSP, SIGDSUSP, and SIGQUIT signals  
1740 - ICANON Enable canonical input (else raw)  
1741 - XCASE Map uppercase \lowercase (obsolete)  
1742 - ECHO Enable echoing of input characters  
1743 - ECHOE Echo erase character as BS-SP-BS  
1744 - ECHOK Echo NL after kill character  
1745 - ECHONL Echo NL  
1746 - NOFLSH Disable flushing of input buffers after  
1747 - interrupt or quit characters  
1748 - IEXTEN Enable extended functions  
1749 - ECHOCTL Echo control characters as ^char and delete as ~?  
1750 - ECHOPRT Echo erased character as character erased  
1751 - ECHOKE BS-SP-BS entire line on line kill  
1752 - FLUSHO Output being flushed  
1753 - PENDIN Retype pending input at next read or input char  
1754 - TOSTOP Send SIGTTOU for background output  
1755 -  
1756 - Canonical input is line-oriented. Input characters are put  
1757 - into a buffer which can be edited interactively by the user  
1758 - until a CR (carriage return) or LF (line feed) character is  
1759 - received.  
1760 -  
1761 - Raw input is unprocessed. Input characters are passed  
1762 - through exactly as they are received, when they are  
1763 - received. Generally you'll deselect the ICANON, ECHO,  
1764 - ECHOE, and ISIG options when using raw input  
1765 - */  
1766 -  
1767 - /* Raw input */  
1768 - tios.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);  
1769 -  
1770 - /* C_IFLAG Input options  
1771 -  
1772 - Constant Description  
1773 - INPCK Enable parity check  
1774 - IGNPAR Ignore parity errors  
1775 - PARMRK Mark parity errors  
1776 - ISTRIP Strip parity bits  
1777 - IXON Enable software flow control (outgoing)  
1778 - IXOFF Enable software flow control (incoming)  
1779 - IXANY Allow any character to start flow again  
1780 - IGNBRK Ignore break condition  
1781 - BRKINT Send a SIGINT when a break condition is detected  
1782 - INLCR Map NL to CR  
1783 - IGNCR Ignore CR  
1784 - ICRNL Map CR to NL  
1785 - IUCLC Map uppercase to lowercase  
1786 - IMAXBEL Echo BEL on input line too long  
1787 - */  
1788 - if (mb_param->parity == 'N') {  
1789 - /* None */  
1790 - tios.c_iflag &= ~INPCK;  
1791 - } else {  
1792 - tios.c_iflag |= INPCK;  
1793 - }  
1794 -  
1795 - /* Software flow control is disabled */  
1796 - tios.c_iflag &= ~(IXON | IXOFF | IXANY);  
1797 -  
1798 - /* C_OFLAG Output options  
1799 - OPOST Postprocess output (not set = raw output)  
1800 - ONLCR Map NL to CR-NL  
1801 -  
1802 - ONCLR ant others needs OPOST to be enabled  
1803 - */  
1804 -  
1805 - /* Raw ouput */  
1806 - tios.c_oflag &=~ OPOST;  
1807 -  
1808 - /* C_CC Control characters  
1809 - VMIN Minimum number of characters to read  
1810 - VTIME Time to wait for data (tenths of seconds)  
1811 -  
1812 - UNIX serial interface drivers provide the ability to  
1813 - specify character and packet timeouts. Two elements of the  
1814 - c_cc array are used for timeouts: VMIN and VTIME. Timeouts  
1815 - are ignored in canonical input mode or when the NDELAY  
1816 - option is set on the file via open or fcntl.  
1817 -  
1818 - VMIN specifies the minimum number of characters to read. If  
1819 - it is set to 0, then the VTIME value specifies the time to  
1820 - wait for every character read. Note that this does not mean  
1821 - that a read call for N bytes will wait for N characters to  
1822 - come in. Rather, the timeout will apply to the first  
1823 - character and the read call will return the number of  
1824 - characters immediately available (up to the number you  
1825 - request).  
1826 -  
1827 - If VMIN is non-zero, VTIME specifies the time to wait for  
1828 - the first character read. If a character is read within the  
1829 - time given, any read will block (wait) until all VMIN  
1830 - characters are read. That is, once the first character is  
1831 - read, the serial interface driver expects to receive an  
1832 - entire packet of characters (VMIN bytes total). If no  
1833 - character is read within the time allowed, then the call to  
1834 - read returns 0. This method allows you to tell the serial  
1835 - driver you need exactly N bytes and any read call will  
1836 - return 0 or N bytes. However, the timeout only applies to  
1837 - the first character read, so if for some reason the driver  
1838 - misses one character inside the N byte packet then the read  
1839 - call could block forever waiting for additional input  
1840 - characters.  
1841 -  
1842 - VTIME specifies the amount of time to wait for incoming  
1843 - characters in tenths of seconds. If VTIME is set to 0 (the  
1844 - default), reads will block (wait) indefinitely unless the  
1845 - NDELAY option is set on the port with open or fcntl.  
1846 - */  
1847 - /* Unused because we use open with the NDELAY option */  
1848 - tios.c_cc[VMIN] = 0;  
1849 - tios.c_cc[VTIME] = 0;  
1850 -  
1851 - if (tcsetattr(mb_param->fd, TCSANOW, &tios) < 0) {  
1852 - return -1;  
1853 - }  
1854 -  
1855 - return 0; 1670 + fprintf(stderr,
  1671 + "WARNING Unknown baud rate %d for %s (B9600 used)\n",
  1672 + mb_param->baud, mb_param->device);
  1673 + }
  1674 + }
  1675 +
  1676 + /* Set the baud rate */
  1677 + if ((cfsetispeed(&tios, speed) < 0) ||
  1678 + (cfsetospeed(&tios, speed) < 0)) {
  1679 + return -1;
  1680 + }
  1681 +
  1682 + /* C_CFLAG Control options
  1683 + CLOCAL Local line - do not change "owner" of port
  1684 + CREAD Enable receiver
  1685 + */
  1686 + tios.c_cflag |= (CREAD | CLOCAL);
  1687 + /* CSIZE, HUPCL, CRTSCTS (hardware flow control) */
  1688 +
  1689 + /* Set data bits (5, 6, 7, 8 bits)
  1690 + CSIZE Bit mask for data bits
  1691 + */
  1692 + tios.c_cflag &= ~CSIZE;
  1693 + switch (mb_param->data_bit) {
  1694 + case 5:
  1695 + tios.c_cflag |= CS5;
  1696 + break;
  1697 + case 6:
  1698 + tios.c_cflag |= CS6;
  1699 + break;
  1700 + case 7:
  1701 + tios.c_cflag |= CS7;
  1702 + break;
  1703 + case 8:
  1704 + default:
  1705 + tios.c_cflag |= CS8;
  1706 + break;
  1707 + }
  1708 +
  1709 + /* Stop bit (1 or 2) */
  1710 + if (mb_param->stop_bit == 1)
  1711 + tios.c_cflag &=~ CSTOPB;
  1712 + else /* 2 */
  1713 + tios.c_cflag |= CSTOPB;
  1714 +
  1715 + /* PARENB Enable parity bit
  1716 + PARODD Use odd parity instead of even */
  1717 + if (mb_param->parity == 'N') {
  1718 + /* None */
  1719 + tios.c_cflag &=~ PARENB;
  1720 + } else if (mb_param->parity == 'E') {
  1721 + /* Even */
  1722 + tios.c_cflag |= PARENB;
  1723 + tios.c_cflag &=~ PARODD;
  1724 + } else {
  1725 + /* Odd */
  1726 + tios.c_cflag |= PARENB;
  1727 + tios.c_cflag |= PARODD;
  1728 + }
  1729 +
  1730 + /* Read the man page of termios if you need more information. */
  1731 +
  1732 + /* This field isn't used on POSIX systems
  1733 + tios.c_line = 0;
  1734 + */
  1735 +
  1736 + /* C_LFLAG Line options
  1737 +
  1738 + ISIG Enable SIGINTR, SIGSUSP, SIGDSUSP, and SIGQUIT signals
  1739 + ICANON Enable canonical input (else raw)
  1740 + XCASE Map uppercase \lowercase (obsolete)
  1741 + ECHO Enable echoing of input characters
  1742 + ECHOE Echo erase character as BS-SP-BS
  1743 + ECHOK Echo NL after kill character
  1744 + ECHONL Echo NL
  1745 + NOFLSH Disable flushing of input buffers after
  1746 + interrupt or quit characters
  1747 + IEXTEN Enable extended functions
  1748 + ECHOCTL Echo control characters as ^char and delete as ~?
  1749 + ECHOPRT Echo erased character as character erased
  1750 + ECHOKE BS-SP-BS entire line on line kill
  1751 + FLUSHO Output being flushed
  1752 + PENDIN Retype pending input at next read or input char
  1753 + TOSTOP Send SIGTTOU for background output
  1754 +
  1755 + Canonical input is line-oriented. Input characters are put
  1756 + into a buffer which can be edited interactively by the user
  1757 + until a CR (carriage return) or LF (line feed) character is
  1758 + received.
  1759 +
  1760 + Raw input is unprocessed. Input characters are passed
  1761 + through exactly as they are received, when they are
  1762 + received. Generally you'll deselect the ICANON, ECHO,
  1763 + ECHOE, and ISIG options when using raw input
  1764 + */
  1765 +
  1766 + /* Raw input */
  1767 + tios.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
  1768 +
  1769 + /* C_IFLAG Input options
  1770 +
  1771 + Constant Description
  1772 + INPCK Enable parity check
  1773 + IGNPAR Ignore parity errors
  1774 + PARMRK Mark parity errors
  1775 + ISTRIP Strip parity bits
  1776 + IXON Enable software flow control (outgoing)
  1777 + IXOFF Enable software flow control (incoming)
  1778 + IXANY Allow any character to start flow again
  1779 + IGNBRK Ignore break condition
  1780 + BRKINT Send a SIGINT when a break condition is detected
  1781 + INLCR Map NL to CR
  1782 + IGNCR Ignore CR
  1783 + ICRNL Map CR to NL
  1784 + IUCLC Map uppercase to lowercase
  1785 + IMAXBEL Echo BEL on input line too long
  1786 + */
  1787 + if (mb_param->parity == 'N') {
  1788 + /* None */
  1789 + tios.c_iflag &= ~INPCK;
  1790 + } else {
  1791 + tios.c_iflag |= INPCK;
  1792 + }
  1793 +
  1794 + /* Software flow control is disabled */
  1795 + tios.c_iflag &= ~(IXON | IXOFF | IXANY);
  1796 +
  1797 + /* C_OFLAG Output options
  1798 + OPOST Postprocess output (not set = raw output)
  1799 + ONLCR Map NL to CR-NL
  1800 +
  1801 + ONCLR ant others needs OPOST to be enabled
  1802 + */
  1803 +
  1804 + /* Raw ouput */
  1805 + tios.c_oflag &=~ OPOST;
  1806 +
  1807 + /* C_CC Control characters
  1808 + VMIN Minimum number of characters to read
  1809 + VTIME Time to wait for data (tenths of seconds)
  1810 +
  1811 + UNIX serial interface drivers provide the ability to
  1812 + specify character and packet timeouts. Two elements of the
  1813 + c_cc array are used for timeouts: VMIN and VTIME. Timeouts
  1814 + are ignored in canonical input mode or when the NDELAY
  1815 + option is set on the file via open or fcntl.
  1816 +
  1817 + VMIN specifies the minimum number of characters to read. If
  1818 + it is set to 0, then the VTIME value specifies the time to
  1819 + wait for every character read. Note that this does not mean
  1820 + that a read call for N bytes will wait for N characters to
  1821 + come in. Rather, the timeout will apply to the first
  1822 + character and the read call will return the number of
  1823 + characters immediately available (up to the number you
  1824 + request).
  1825 +
  1826 + If VMIN is non-zero, VTIME specifies the time to wait for
  1827 + the first character read. If a character is read within the
  1828 + time given, any read will block (wait) until all VMIN
  1829 + characters are read. That is, once the first character is
  1830 + read, the serial interface driver expects to receive an
  1831 + entire packet of characters (VMIN bytes total). If no
  1832 + character is read within the time allowed, then the call to
  1833 + read returns 0. This method allows you to tell the serial
  1834 + driver you need exactly N bytes and any read call will
  1835 + return 0 or N bytes. However, the timeout only applies to
  1836 + the first character read, so if for some reason the driver
  1837 + misses one character inside the N byte packet then the read
  1838 + call could block forever waiting for additional input
  1839 + characters.
  1840 +
  1841 + VTIME specifies the amount of time to wait for incoming
  1842 + characters in tenths of seconds. If VTIME is set to 0 (the
  1843 + default), reads will block (wait) indefinitely unless the
  1844 + NDELAY option is set on the port with open or fcntl.
  1845 + */
  1846 + /* Unused because we use open with the NDELAY option */
  1847 + tios.c_cc[VMIN] = 0;
  1848 + tios.c_cc[VTIME] = 0;
  1849 +
  1850 + if (tcsetattr(mb_param->fd, TCSANOW, &tios) < 0) {
  1851 + return -1;
  1852 + }
  1853 +
  1854 + return 0;
1856 } 1855 }
1857 1856
1858 /* Establishes a modbus TCP connection with a modbus slave */ 1857 /* Establishes a modbus TCP connection with a modbus slave */
1859 static int modbus_connect_tcp(modbus_param_t *mb_param) 1858 static int modbus_connect_tcp(modbus_param_t *mb_param)
1860 { 1859 {
1861 - int rc;  
1862 - int option;  
1863 - struct sockaddr_in addr;  
1864 -  
1865 - mb_param->fd = socket(PF_INET, SOCK_STREAM, 0);  
1866 - if (mb_param->fd == -1) {  
1867 - return -1;  
1868 - }  
1869 -  
1870 - /* Set the TCP no delay flag */  
1871 - /* SOL_TCP = IPPROTO_TCP */  
1872 - option = 1;  
1873 - rc = setsockopt(mb_param->fd, IPPROTO_TCP, TCP_NODELAY,  
1874 - (const void *)&option, sizeof(int));  
1875 - if (rc == -1) {  
1876 - close(mb_param->fd);  
1877 - return -1;  
1878 - } 1860 + int rc;
  1861 + int option;
  1862 + struct sockaddr_in addr;
  1863 +
  1864 + mb_param->fd = socket(PF_INET, SOCK_STREAM, 0);
  1865 + if (mb_param->fd == -1) {
  1866 + return -1;
  1867 + }
  1868 +
  1869 + /* Set the TCP no delay flag */
  1870 + /* SOL_TCP = IPPROTO_TCP */
  1871 + option = 1;
  1872 + rc = setsockopt(mb_param->fd, IPPROTO_TCP, TCP_NODELAY,
  1873 + (const void *)&option, sizeof(int));
  1874 + if (rc == -1) {
  1875 + close(mb_param->fd);
  1876 + return -1;
  1877 + }
1879 1878
1880 #if (!HAVE_DECL___CYGWIN__) 1879 #if (!HAVE_DECL___CYGWIN__)
1881 - /**  
1882 - * Cygwin defines IPTOS_LOWDELAY but can't handle that flag so it's  
1883 - * necessary to workaround that problem.  
1884 - **/  
1885 - /* Set the IP low delay option */  
1886 - option = IPTOS_LOWDELAY;  
1887 - rc = setsockopt(mb_param->fd, IPPROTO_IP, IP_TOS,  
1888 - (const void *)&option, sizeof(int));  
1889 - if (rc == -1) {  
1890 - close(mb_param->fd);  
1891 - return -1;  
1892 - } 1880 + /**
  1881 + * Cygwin defines IPTOS_LOWDELAY but can't handle that flag so it's
  1882 + * necessary to workaround that problem.
  1883 + **/
  1884 + /* Set the IP low delay option */
  1885 + option = IPTOS_LOWDELAY;
  1886 + rc = setsockopt(mb_param->fd, IPPROTO_IP, IP_TOS,
  1887 + (const void *)&option, sizeof(int));
  1888 + if (rc == -1) {
  1889 + close(mb_param->fd);
  1890 + return -1;
  1891 + }
1893 #endif 1892 #endif
1894 1893
1895 - if (mb_param->debug) {  
1896 - printf("Connecting to %s\n", mb_param->ip);  
1897 - } 1894 + if (mb_param->debug) {
  1895 + printf("Connecting to %s\n", mb_param->ip);
  1896 + }
1898 1897
1899 - addr.sin_family = AF_INET;  
1900 - addr.sin_port = htons(mb_param->port);  
1901 - addr.sin_addr.s_addr = inet_addr(mb_param->ip);  
1902 - rc = connect(mb_param->fd, (struct sockaddr *)&addr,  
1903 - sizeof(struct sockaddr_in));  
1904 - if (rc == -1) {  
1905 - close(mb_param->fd);  
1906 - return -1;  
1907 - } 1898 + addr.sin_family = AF_INET;
  1899 + addr.sin_port = htons(mb_param->port);
  1900 + addr.sin_addr.s_addr = inet_addr(mb_param->ip);
  1901 + rc = connect(mb_param->fd, (struct sockaddr *)&addr,
  1902 + sizeof(struct sockaddr_in));
  1903 + if (rc == -1) {
  1904 + close(mb_param->fd);
  1905 + return -1;
  1906 + }
1908 1907
1909 - return 0; 1908 + return 0;
1910 } 1909 }
1911 1910
1912 /* Establishes a modbus connexion. 1911 /* Establishes a modbus connexion.
1913 Returns 0 on success or -1 on failure. */ 1912 Returns 0 on success or -1 on failure. */
1914 int modbus_connect(modbus_param_t *mb_param) 1913 int modbus_connect(modbus_param_t *mb_param)
1915 { 1914 {
1916 - int rc; 1915 + int rc;
1917 1916
1918 - if (mb_param->type_com == RTU)  
1919 - rc = modbus_connect_rtu(mb_param);  
1920 - else  
1921 - rc = modbus_connect_tcp(mb_param); 1917 + if (mb_param->type_com == RTU)
  1918 + rc = modbus_connect_rtu(mb_param);
  1919 + else
  1920 + rc = modbus_connect_tcp(mb_param);
1922 1921
1923 - return rc; 1922 + return rc;
1924 } 1923 }
1925 1924
1926 /* Closes the file descriptor in RTU mode */ 1925 /* Closes the file descriptor in RTU mode */
1927 static void modbus_close_rtu(modbus_param_t *mb_param) 1926 static void modbus_close_rtu(modbus_param_t *mb_param)
1928 { 1927 {
1929 - tcsetattr(mb_param->fd, TCSANOW, &(mb_param->old_tios));  
1930 - close(mb_param->fd); 1928 + tcsetattr(mb_param->fd, TCSANOW, &(mb_param->old_tios));
  1929 + close(mb_param->fd);
1931 } 1930 }
1932 1931
1933 /* Closes the network connection and socket in TCP mode */ 1932 /* Closes the network connection and socket in TCP mode */
1934 static void modbus_close_tcp(modbus_param_t *mb_param) 1933 static void modbus_close_tcp(modbus_param_t *mb_param)
1935 { 1934 {
1936 - shutdown(mb_param->fd, SHUT_RDWR);  
1937 - close(mb_param->fd); 1935 + shutdown(mb_param->fd, SHUT_RDWR);
  1936 + close(mb_param->fd);
1938 } 1937 }
1939 1938
1940 /* Closes a modbus connection */ 1939 /* Closes a modbus connection */
1941 void modbus_close(modbus_param_t *mb_param) 1940 void modbus_close(modbus_param_t *mb_param)
1942 { 1941 {
1943 - if (mb_param->type_com == RTU)  
1944 - modbus_close_rtu(mb_param);  
1945 - else  
1946 - modbus_close_tcp(mb_param); 1942 + if (mb_param->type_com == RTU)
  1943 + modbus_close_rtu(mb_param);
  1944 + else
  1945 + modbus_close_tcp(mb_param);
1947 } 1946 }
1948 1947
1949 /* Activates the debug messages */ 1948 /* Activates the debug messages */
1950 void modbus_set_debug(modbus_param_t *mb_param, int boolean) 1949 void modbus_set_debug(modbus_param_t *mb_param, int boolean)
1951 { 1950 {
1952 - mb_param->debug = boolean; 1951 + mb_param->debug = boolean;
1953 } 1952 }
1954 1953
1955 /* Allocates 4 arrays to store coils, input status, input registers and 1954 /* Allocates 4 arrays to store coils, input status, input registers and
@@ -1962,103 +1961,103 @@ int modbus_mapping_new(modbus_mapping_t *mb_mapping, @@ -1962,103 +1961,103 @@ int modbus_mapping_new(modbus_mapping_t *mb_mapping,
1962 int nb_coil_status, int nb_input_status, 1961 int nb_coil_status, int nb_input_status,
1963 int nb_holding_registers, int nb_input_registers) 1962 int nb_holding_registers, int nb_input_registers)
1964 { 1963 {
1965 - /* 0X */  
1966 - mb_mapping->nb_coil_status = nb_coil_status;  
1967 - mb_mapping->tab_coil_status =  
1968 - (uint8_t *) malloc(nb_coil_status * sizeof(uint8_t));  
1969 - if (mb_mapping->tab_coil_status == NULL) {  
1970 - errno = ENOMEM;  
1971 - return -1;  
1972 - }  
1973 - memset(mb_mapping->tab_coil_status, 0,  
1974 - nb_coil_status * sizeof(uint8_t));  
1975 -  
1976 - /* 1X */  
1977 - mb_mapping->nb_input_status = nb_input_status;  
1978 - mb_mapping->tab_input_status =  
1979 - (uint8_t *) malloc(nb_input_status * sizeof(uint8_t));  
1980 - if (mb_mapping->tab_input_status == NULL) {  
1981 - free(mb_mapping->tab_coil_status);  
1982 - errno = ENOMEM;  
1983 - return -1;  
1984 - }  
1985 - memset(mb_mapping->tab_input_status, 0,  
1986 - nb_input_status * sizeof(uint8_t));  
1987 -  
1988 - /* 4X */  
1989 - mb_mapping->nb_holding_registers = nb_holding_registers;  
1990 - mb_mapping->tab_holding_registers =  
1991 - (uint16_t *) malloc(nb_holding_registers * sizeof(uint16_t));  
1992 - if (mb_mapping->tab_holding_registers == NULL) {  
1993 - free(mb_mapping->tab_coil_status);  
1994 - free(mb_mapping->tab_input_status);  
1995 - errno = ENOMEM;  
1996 - return -1;  
1997 - }  
1998 - memset(mb_mapping->tab_holding_registers, 0,  
1999 - nb_holding_registers * sizeof(uint16_t));  
2000 -  
2001 - /* 3X */  
2002 - mb_mapping->nb_input_registers = nb_input_registers;  
2003 - mb_mapping->tab_input_registers =  
2004 - (uint16_t *) malloc(nb_input_registers * sizeof(uint16_t));  
2005 - if (mb_mapping->tab_input_registers == NULL) {  
2006 - free(mb_mapping->tab_coil_status);  
2007 - free(mb_mapping->tab_input_status);  
2008 - free(mb_mapping->tab_holding_registers);  
2009 - errno = ENOMEM;  
2010 - return -1;  
2011 - }  
2012 - memset(mb_mapping->tab_input_registers, 0,  
2013 - nb_input_registers * sizeof(uint16_t)); 1964 + /* 0X */
  1965 + mb_mapping->nb_coil_status = nb_coil_status;
  1966 + mb_mapping->tab_coil_status =
  1967 + (uint8_t *) malloc(nb_coil_status * sizeof(uint8_t));
  1968 + if (mb_mapping->tab_coil_status == NULL) {
  1969 + errno = ENOMEM;
  1970 + return -1;
  1971 + }
  1972 + memset(mb_mapping->tab_coil_status, 0,
  1973 + nb_coil_status * sizeof(uint8_t));
  1974 +
  1975 + /* 1X */
  1976 + mb_mapping->nb_input_status = nb_input_status;
  1977 + mb_mapping->tab_input_status =
  1978 + (uint8_t *) malloc(nb_input_status * sizeof(uint8_t));
  1979 + if (mb_mapping->tab_input_status == NULL) {
  1980 + free(mb_mapping->tab_coil_status);
  1981 + errno = ENOMEM;
  1982 + return -1;
  1983 + }
  1984 + memset(mb_mapping->tab_input_status, 0,
  1985 + nb_input_status * sizeof(uint8_t));
  1986 +
  1987 + /* 4X */
  1988 + mb_mapping->nb_holding_registers = nb_holding_registers;
  1989 + mb_mapping->tab_holding_registers =
  1990 + (uint16_t *) malloc(nb_holding_registers * sizeof(uint16_t));
  1991 + if (mb_mapping->tab_holding_registers == NULL) {
  1992 + free(mb_mapping->tab_coil_status);
  1993 + free(mb_mapping->tab_input_status);
  1994 + errno = ENOMEM;
  1995 + return -1;
  1996 + }
  1997 + memset(mb_mapping->tab_holding_registers, 0,
  1998 + nb_holding_registers * sizeof(uint16_t));
  1999 +
  2000 + /* 3X */
  2001 + mb_mapping->nb_input_registers = nb_input_registers;
  2002 + mb_mapping->tab_input_registers =
  2003 + (uint16_t *) malloc(nb_input_registers * sizeof(uint16_t));
  2004 + if (mb_mapping->tab_input_registers == NULL) {
  2005 + free(mb_mapping->tab_coil_status);
  2006 + free(mb_mapping->tab_input_status);
  2007 + free(mb_mapping->tab_holding_registers);
  2008 + errno = ENOMEM;
  2009 + return -1;
  2010 + }
  2011 + memset(mb_mapping->tab_input_registers, 0,
  2012 + nb_input_registers * sizeof(uint16_t));
2014 2013
2015 - return 0; 2014 + return 0;
2016 } 2015 }
2017 2016
2018 /* Frees the 4 arrays */ 2017 /* Frees the 4 arrays */
2019 void modbus_mapping_free(modbus_mapping_t *mb_mapping) 2018 void modbus_mapping_free(modbus_mapping_t *mb_mapping)
2020 { 2019 {
2021 - free(mb_mapping->tab_coil_status);  
2022 - free(mb_mapping->tab_input_status);  
2023 - free(mb_mapping->tab_holding_registers);  
2024 - free(mb_mapping->tab_input_registers); 2020 + free(mb_mapping->tab_coil_status);
  2021 + free(mb_mapping->tab_input_status);
  2022 + free(mb_mapping->tab_holding_registers);
  2023 + free(mb_mapping->tab_input_registers);
2025 } 2024 }
2026 2025
2027 /* Listens for any query from one or many modbus masters in TCP */ 2026 /* Listens for any query from one or many modbus masters in TCP */
2028 int modbus_slave_listen_tcp(modbus_param_t *mb_param, int nb_connection) 2027 int modbus_slave_listen_tcp(modbus_param_t *mb_param, int nb_connection)
2029 { 2028 {
2030 - int new_socket;  
2031 - int yes;  
2032 - struct sockaddr_in addr;  
2033 -  
2034 - new_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);  
2035 - if (new_socket == -1) {  
2036 - return -1;  
2037 - }  
2038 -  
2039 - yes = 1;  
2040 - if (setsockopt(new_socket, SOL_SOCKET, SO_REUSEADDR,  
2041 - (char *) &yes, sizeof(yes)) == -1) {  
2042 - close(new_socket);  
2043 - return -1;  
2044 - }  
2045 -  
2046 - memset(&addr, 0, sizeof(addr));  
2047 - addr.sin_family = AF_INET;  
2048 - /* If the modbus port is < to 1024, we need the setuid root. */  
2049 - addr.sin_port = htons(mb_param->port);  
2050 - addr.sin_addr.s_addr = INADDR_ANY;  
2051 - if (bind(new_socket, (struct sockaddr *)&addr, sizeof(addr)) == -1) {  
2052 - close(new_socket);  
2053 - return -1;  
2054 - }  
2055 -  
2056 - if (listen(new_socket, nb_connection) == -1) {  
2057 - close(new_socket);  
2058 - return -1;  
2059 - }  
2060 -  
2061 - return new_socket; 2029 + int new_socket;
  2030 + int yes;
  2031 + struct sockaddr_in addr;
  2032 +
  2033 + new_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
  2034 + if (new_socket == -1) {
  2035 + return -1;
  2036 + }
  2037 +
  2038 + yes = 1;
  2039 + if (setsockopt(new_socket, SOL_SOCKET, SO_REUSEADDR,
  2040 + (char *) &yes, sizeof(yes)) == -1) {
  2041 + close(new_socket);
  2042 + return -1;
  2043 + }
  2044 +
  2045 + memset(&addr, 0, sizeof(addr));
  2046 + addr.sin_family = AF_INET;
  2047 + /* If the modbus port is < to 1024, we need the setuid root. */
  2048 + addr.sin_port = htons(mb_param->port);
  2049 + addr.sin_addr.s_addr = INADDR_ANY;
  2050 + if (bind(new_socket, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
  2051 + close(new_socket);
  2052 + return -1;
  2053 + }
  2054 +
  2055 + if (listen(new_socket, nb_connection) == -1) {
  2056 + close(new_socket);
  2057 + return -1;
  2058 + }
  2059 +
  2060 + return new_socket;
2062 } 2061 }
2063 2062
2064 /* On success, the function return a non-negative integer that is a descriptor 2063 /* On success, the function return a non-negative integer that is a descriptor
@@ -2066,30 +2065,30 @@ int modbus_slave_listen_tcp(modbus_param_t *mb_param, int nb_connection) @@ -2066,30 +2065,30 @@ int modbus_slave_listen_tcp(modbus_param_t *mb_param, int nb_connection)
2066 appropriately. */ 2065 appropriately. */
2067 int modbus_slave_accept_tcp(modbus_param_t *mb_param, int *socket) 2066 int modbus_slave_accept_tcp(modbus_param_t *mb_param, int *socket)
2068 { 2067 {
2069 - struct sockaddr_in addr;  
2070 - socklen_t addrlen;  
2071 -  
2072 - addrlen = sizeof(struct sockaddr_in);  
2073 - mb_param->fd = accept(*socket, (struct sockaddr *)&addr, &addrlen);  
2074 - if (mb_param->fd == -1) {  
2075 - close(*socket);  
2076 - *socket = 0;  
2077 - return -1;  
2078 - }  
2079 -  
2080 - if (mb_param->debug) {  
2081 - printf("The client %s is connected\n",  
2082 - inet_ntoa(addr.sin_addr));  
2083 - }  
2084 -  
2085 - return mb_param->fd; 2068 + struct sockaddr_in addr;
  2069 + socklen_t addrlen;
  2070 +
  2071 + addrlen = sizeof(struct sockaddr_in);
  2072 + mb_param->fd = accept(*socket, (struct sockaddr *)&addr, &addrlen);
  2073 + if (mb_param->fd == -1) {
  2074 + close(*socket);
  2075 + *socket = 0;
  2076 + return -1;
  2077 + }
  2078 +
  2079 + if (mb_param->debug) {
  2080 + printf("The client %s is connected\n",
  2081 + inet_ntoa(addr.sin_addr));
  2082 + }
  2083 +
  2084 + return mb_param->fd;
2086 } 2085 }
2087 2086
2088 /* Closes a TCP socket */ 2087 /* Closes a TCP socket */
2089 void modbus_slave_close_tcp(int socket) 2088 void modbus_slave_close_tcp(int socket)
2090 { 2089 {
2091 - shutdown(socket, SHUT_RDWR);  
2092 - close(socket); 2090 + shutdown(socket, SHUT_RDWR);
  2091 + close(socket);
2093 } 2092 }
2094 2093
2095 /** Utils **/ 2094 /** Utils **/
@@ -2098,11 +2097,11 @@ void modbus_slave_close_tcp(int socket) @@ -2098,11 +2097,11 @@ void modbus_slave_close_tcp(int socket)
2098 the byte value are set) */ 2097 the byte value are set) */
2099 void set_bits_from_byte(uint8_t *dest, int address, const uint8_t value) 2098 void set_bits_from_byte(uint8_t *dest, int address, const uint8_t value)
2100 { 2099 {
2101 - int i; 2100 + int i;
2102 2101
2103 - for (i=0; i<8; i++) {  
2104 - dest[address+i] = (value & (1 << i)) ? ON : OFF;  
2105 - } 2102 + for (i=0; i<8; i++) {
  2103 + dest[address+i] = (value & (1 << i)) ? ON : OFF;
  2104 + }
2106 } 2105 }
2107 2106
2108 /* Sets many input/coil status from a table of bytes (only the bits 2107 /* Sets many input/coil status from a table of bytes (only the bits
@@ -2110,53 +2109,53 @@ void set_bits_from_byte(uint8_t *dest, int address, const uint8_t value) @@ -2110,53 +2109,53 @@ void set_bits_from_byte(uint8_t *dest, int address, const uint8_t value)
2110 void set_bits_from_bytes(uint8_t *dest, int address, unsigned int nb_bits, 2109 void set_bits_from_bytes(uint8_t *dest, int address, unsigned int nb_bits,
2111 const uint8_t tab_byte[]) 2110 const uint8_t tab_byte[])
2112 { 2111 {
2113 - int i;  
2114 - int shift = 0;  
2115 -  
2116 - for (i = address; i < address + nb_bits; i++) {  
2117 - dest[i] = tab_byte[(i - address) / 8] & (1 << shift) ? ON : OFF;  
2118 - /* gcc doesn't like: shift = (++shift) % 8; */  
2119 - shift++;  
2120 - shift %= 8;  
2121 - } 2112 + int i;
  2113 + int shift = 0;
  2114 +
  2115 + for (i = address; i < address + nb_bits; i++) {
  2116 + dest[i] = tab_byte[(i - address) / 8] & (1 << shift) ? ON : OFF;
  2117 + /* gcc doesn't like: shift = (++shift) % 8; */
  2118 + shift++;
  2119 + shift %= 8;
  2120 + }
2122 } 2121 }
2123 2122
2124 /* Gets the byte value from many input/coil status. 2123 /* Gets the byte value from many input/coil status.
2125 To obtain a full byte, set nb_bits to 8. */ 2124 To obtain a full byte, set nb_bits to 8. */
2126 uint8_t get_byte_from_bits(const uint8_t *src, int address, unsigned int nb_bits) 2125 uint8_t get_byte_from_bits(const uint8_t *src, int address, unsigned int nb_bits)
2127 { 2126 {
2128 - int i;  
2129 - uint8_t value = 0; 2127 + int i;
  2128 + uint8_t value = 0;
2130 2129
2131 - if (nb_bits > 8) {  
2132 - assert(nb_bits < 8);  
2133 - nb_bits = 8;  
2134 - } 2130 + if (nb_bits > 8) {
  2131 + assert(nb_bits < 8);
  2132 + nb_bits = 8;
  2133 + }
2135 2134
2136 - for (i=0; i < nb_bits; i++) {  
2137 - value |= (src[address+i] << i);  
2138 - } 2135 + for (i=0; i < nb_bits; i++) {
  2136 + value |= (src[address+i] << i);
  2137 + }
2139 2138
2140 - return value; 2139 + return value;
2141 } 2140 }
2142 2141
2143 /* Read a float from 4 bytes in Modbus format */ 2142 /* Read a float from 4 bytes in Modbus format */
2144 float modbus_read_float(const uint16_t *src) 2143 float modbus_read_float(const uint16_t *src)
2145 { 2144 {
2146 - float r = 0.0f;  
2147 - uint32_t i; 2145 + float r = 0.0f;
  2146 + uint32_t i;
2148 2147
2149 - i = (((uint32_t)src[1]) << 16) + src[0];  
2150 - memcpy(&r, &i, sizeof (r));  
2151 - return r; 2148 + i = (((uint32_t)src[1]) << 16) + src[0];
  2149 + memcpy(&r, &i, sizeof (r));
  2150 + return r;
2152 } 2151 }
2153 2152
2154 /* Write a float to 4 bytes in Modbus format */ 2153 /* Write a float to 4 bytes in Modbus format */
2155 void modbus_write_float(float real, uint16_t *dest) 2154 void modbus_write_float(float real, uint16_t *dest)
2156 { 2155 {
2157 - uint32_t i = 0; 2156 + uint32_t i = 0;
2158 2157
2159 - memcpy(&i, &real, sizeof (i));  
2160 - dest[0] = (uint16_t)i;  
2161 - dest[1] = (uint16_t)(i >> 16); 2158 + memcpy(&i, &real, sizeof (i));
  2159 + dest[0] = (uint16_t)i;
  2160 + dest[1] = (uint16_t)(i >> 16);
2162 } 2161 }
src/modbus.h.in
@@ -59,7 +59,7 @@ extern &quot;C&quot; { @@ -59,7 +59,7 @@ extern &quot;C&quot; {
59 * Maximum between : 59 * Maximum between :
60 * - HEADER_LENGTH_TCP (7) + function (1) + address (2) + number (2) 60 * - HEADER_LENGTH_TCP (7) + function (1) + address (2) + number (2)
61 * - HEADER_LENGTH_RTU (1) + function (1) + address (2) + number (2) + CRC (2) 61 * - HEADER_LENGTH_RTU (1) + function (1) + address (2) + number (2) + CRC (2)
62 -*/ 62 + */
63 #define MIN_QUERY_LENGTH 12 63 #define MIN_QUERY_LENGTH 12
64 64
65 /* Modbus_Application_Protocol_V1_1b.pdf Chapter 4 Section 1 Page 5: 65 /* Modbus_Application_Protocol_V1_1b.pdf Chapter 4 Section 1 Page 5:
@@ -123,20 +123,20 @@ extern &quot;C&quot; { @@ -123,20 +123,20 @@ extern &quot;C&quot; {
123 #define MODBUS_ENOBASE 112345678 123 #define MODBUS_ENOBASE 112345678
124 124
125 /* Protocol exceptions */ 125 /* Protocol exceptions */
126 -enum {  
127 - MODBUS_EXCEPTION_ILLEGAL_FUNCTION = 0x01,  
128 - MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS,  
129 - MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,  
130 - MODBUS_EXCEPTION_SLAVE_OR_SERVER_FAILURE,  
131 - MODBUS_EXCEPTION_ACKNOWLEDGE,  
132 - MODBUS_EXCEPTION_SLAVE_OR_SERVER_BUSY,  
133 - MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE,  
134 - MODBUS_EXCEPTION_MEMORY_PARITY,  
135 - MODBUS_EXCEPTION_NOT_DEFINED,  
136 - MODBUS_EXCEPTION_GATEWAY_PATH,  
137 - MODBUS_EXCEPTION_GATEWAY_TARGET,  
138 - MODBUS_EXCEPTION_MAX  
139 -}; 126 +typedef enum {
  127 + MODBUS_EXCEPTION_ILLEGAL_FUNCTION = 0x01,
  128 + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS,
  129 + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
  130 + MODBUS_EXCEPTION_SLAVE_OR_SERVER_FAILURE,
  131 + MODBUS_EXCEPTION_ACKNOWLEDGE,
  132 + MODBUS_EXCEPTION_SLAVE_OR_SERVER_BUSY,
  133 + MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE,
  134 + MODBUS_EXCEPTION_MEMORY_PARITY,
  135 + MODBUS_EXCEPTION_NOT_DEFINED,
  136 + MODBUS_EXCEPTION_GATEWAY_PATH,
  137 + MODBUS_EXCEPTION_GATEWAY_TARGET,
  138 + MODBUS_EXCEPTION_MAX
  139 +} modbus_exception_t;
140 140
141 #define EMBXILFUN (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_FUNCTION) 141 #define EMBXILFUN (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_FUNCTION)
142 #define EMBXILADD (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS) 142 #define EMBXILADD (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS)
@@ -177,20 +177,20 @@ enum { @@ -177,20 +177,20 @@ enum {
177 #define LIBMODBUS_VERSION_STRING "@LIBMODBUS_VERSION@" 177 #define LIBMODBUS_VERSION_STRING "@LIBMODBUS_VERSION@"
178 178
179 /* Numerically encoded version libmb, like 0x010203 */ 179 /* Numerically encoded version libmb, like 0x010203 */
180 -#define LIBMODBUS_VERSION_HEX ((LIBMODBUS_MAJOR_VERSION << 24) | \  
181 - (LIBMODBUS_MINOR_VERSION << 16) | \ 180 +#define LIBMODBUS_VERSION_HEX ((LIBMODBUS_MAJOR_VERSION << 24) | \
  181 + (LIBMODBUS_MINOR_VERSION << 16) | \
182 (LIBMODBUS_MICRO_VERSION << 8)) 182 (LIBMODBUS_MICRO_VERSION << 8))
183 183
184 /* Evaluates to True if the version of libmb is greater than @major, @minor and 184 /* Evaluates to True if the version of libmb is greater than @major, @minor and
185 * @micro 185 * @micro
186 */ 186 */
187 -#define LIBMODBUS_VERSION_CHECK(major,minor,micro) \  
188 - (LIBMODBUS_VERSION_MAJOR > (major) || \  
189 - (LIBMODBUS_VERSION_MAJOR == (major) && \  
190 - LIBMODBUS_VERSION_MINOR > (minor)) || \  
191 - (LIBMODBUS_VERSION_MAJOR == (major) && \  
192 - LIBMODBUS_VERSION_MINOR == (minor) && \  
193 - LIBMODBUS_VERSION_MICRO >= (micro))) 187 +#define LIBMODBUS_VERSION_CHECK(major,minor,micro) \
  188 + (LIBMODBUS_VERSION_MAJOR > (major) || \
  189 + (LIBMODBUS_VERSION_MAJOR == (major) && \
  190 + LIBMODBUS_VERSION_MINOR > (minor)) || \
  191 + (LIBMODBUS_VERSION_MAJOR == (major) && \
  192 + LIBMODBUS_VERSION_MINOR == (minor) && \
  193 + LIBMODBUS_VERSION_MICRO >= (micro)))
194 194
195 extern const unsigned int libmodbus_version_major; 195 extern const unsigned int libmodbus_version_major;
196 extern const unsigned int libmodbus_version_minor; 196 extern const unsigned int libmodbus_version_minor;
@@ -200,54 +200,53 @@ typedef enum { RTU=0, TCP } type_com_t; @@ -200,54 +200,53 @@ typedef enum { RTU=0, TCP } type_com_t;
200 200
201 /* This structure is byte-aligned */ 201 /* This structure is byte-aligned */
202 typedef struct { 202 typedef struct {
203 - /* Slave address */  
204 - int slave;  
205 - /* Descriptor (tty or socket) */  
206 - int fd;  
207 - /* Communication mode: RTU or TCP */  
208 - type_com_t type_com;  
209 - /* Flag debug */  
210 - int debug;  
211 - /* TCP port */  
212 - int port;  
213 - /* Device: "/dev/ttyS0", "/dev/ttyUSB0" or "/dev/tty.USA19*"  
214 - on Mac OS X for KeySpan USB<->Serial adapters this string  
215 - had to be made bigger on OS X as the directory+file name  
216 - was bigger than 19 bytes. Making it 67 bytes for now, but  
217 - OS X does support 256 byte file names. May become a problem  
218 - in the future. */ 203 + /* Slave address */
  204 + int slave;
  205 + /* Descriptor (tty or socket) */
  206 + int fd;
  207 + /* Communication mode: RTU or TCP */
  208 + type_com_t type_com;
  209 + /* Flag debug */
  210 + int debug;
  211 + /* TCP port */
  212 + int port;
  213 + /* Device: "/dev/ttyS0", "/dev/ttyUSB0" or "/dev/tty.USA19*" on Mac OS X for
  214 + KeySpan USB<->Serial adapters this string had to be made bigger on OS X
  215 + as the directory+file name was bigger than 19 bytes. Making it 67 bytes
  216 + for now, but OS X does support 256 byte file names. May become a problem
  217 + in the future. */
219 #ifdef __APPLE_CC__ 218 #ifdef __APPLE_CC__
220 - char device[64]; 219 + char device[64];
221 #else 220 #else
222 - char device[16]; 221 + char device[16];
223 #endif 222 #endif
224 - /* Bauds: 9600, 19200, 57600, 115200, etc */  
225 - int baud;  
226 - /* Data bit */  
227 - uint8_t data_bit;  
228 - /* Stop bit */  
229 - uint8_t stop_bit;  
230 - /* Parity: 'N', 'O', 'E' */  
231 - char parity;  
232 - /* In error_treat with TCP, do a reconnect or just dump the error */  
233 - uint8_t error_recovery; 223 + /* Bauds: 9600, 19200, 57600, 115200, etc */
  224 + int baud;
  225 + /* Data bit */
  226 + uint8_t data_bit;
  227 + /* Stop bit */
  228 + uint8_t stop_bit;
  229 + /* Parity: 'N', 'O', 'E' */
  230 + char parity;
  231 + /* In error_treat with TCP, do a reconnect or just dump the error */
  232 + uint8_t error_recovery;
234 /* IP address */ 233 /* IP address */
235 - char ip[16];  
236 - /* Save old termios settings */  
237 - struct termios old_tios;  
238 - struct timeval timeout_begin;  
239 - struct timeval timeout_end; 234 + char ip[16];
  235 + /* Save old termios settings */
  236 + struct termios old_tios;
  237 + struct timeval timeout_begin;
  238 + struct timeval timeout_end;
240 } modbus_param_t; 239 } modbus_param_t;
241 240
242 typedef struct { 241 typedef struct {
243 - int nb_coil_status;  
244 - int nb_input_status;  
245 - int nb_input_registers;  
246 - int nb_holding_registers;  
247 - uint8_t *tab_coil_status;  
248 - uint8_t *tab_input_status;  
249 - uint16_t *tab_input_registers;  
250 - uint16_t *tab_holding_registers; 242 + int nb_coil_status;
  243 + int nb_input_status;
  244 + int nb_input_registers;
  245 + int nb_holding_registers;
  246 + uint8_t *tab_coil_status;
  247 + uint8_t *tab_input_status;
  248 + uint16_t *tab_input_registers;
  249 + uint16_t *tab_holding_registers;
251 } modbus_mapping_t; 250 } modbus_mapping_t;
252 251
253 int modbus_init_rtu(modbus_param_t *mb_param, const char *device, 252 int modbus_init_rtu(modbus_param_t *mb_param, const char *device,
tests/bandwidth-master.c
@@ -33,123 +33,123 @@ @@ -33,123 +33,123 @@
33 33
34 uint32_t gettime_ms(void) 34 uint32_t gettime_ms(void)
35 { 35 {
36 - struct timeval tv;  
37 - gettimeofday (&tv, NULL); 36 + struct timeval tv;
  37 + gettimeofday (&tv, NULL);
38 38
39 - return (uint32_t) tv.tv_sec * 1000 + tv.tv_usec / 1000; 39 + return (uint32_t) tv.tv_sec * 1000 + tv.tv_usec / 1000;
40 } 40 }
41 41
42 int main(void) 42 int main(void)
43 { 43 {
44 - uint8_t *tab_rp_status;  
45 - uint16_t *tab_rp_registers;  
46 - modbus_param_t mb_param;  
47 - int i;  
48 - int nb_points;  
49 - double elapsed;  
50 - uint32_t start;  
51 - uint32_t end;  
52 - uint32_t bytes;  
53 - uint32_t rate;  
54 - int rc;  
55 -  
56 - /* TCP */  
57 - modbus_init_tcp(&mb_param, "127.0.0.1", 1502);  
58 - rc = modbus_connect(&mb_param); 44 + uint8_t *tab_rp_status;
  45 + uint16_t *tab_rp_registers;
  46 + modbus_param_t mb_param;
  47 + int i;
  48 + int nb_points;
  49 + double elapsed;
  50 + uint32_t start;
  51 + uint32_t end;
  52 + uint32_t bytes;
  53 + uint32_t rate;
  54 + int rc;
  55 +
  56 + /* TCP */
  57 + modbus_init_tcp(&mb_param, "127.0.0.1", 1502);
  58 + rc = modbus_connect(&mb_param);
  59 + if (rc == -1) {
  60 + fprintf(stderr, "Connexion failed: %s\n",
  61 + modbus_strerror(errno));
  62 + return -1;
  63 + }
  64 +
  65 + /* Allocate and initialize the memory to store the status */
  66 + tab_rp_status = (uint8_t *) malloc(MAX_STATUS * sizeof(uint8_t));
  67 + memset(tab_rp_status, 0, MAX_STATUS * sizeof(uint8_t));
  68 +
  69 + /* Allocate and initialize the memory to store the registers */
  70 + tab_rp_registers = (uint16_t *) malloc(MAX_REGISTERS * sizeof(uint16_t));
  71 + memset(tab_rp_registers, 0, MAX_REGISTERS * sizeof(uint16_t));
  72 +
  73 + printf("READ COIL STATUS\n\n");
  74 +
  75 + nb_points = MAX_STATUS;
  76 + start = gettime_ms();
  77 + for (i=0; i<NB_LOOPS; i++) {
  78 + rc = read_coil_status(&mb_param, SERVER_ID, 0, nb_points, tab_rp_status);
59 if (rc == -1) { 79 if (rc == -1) {
60 - fprintf(stderr, "Connexion failed: %s\n",  
61 - modbus_strerror(errno));  
62 - return -1; 80 + fprintf(stderr, "%s\n", modbus_strerror(errno));
  81 + return -1;
63 } 82 }
64 -  
65 - /* Allocate and initialize the memory to store the status */  
66 - tab_rp_status = (uint8_t *) malloc(MAX_STATUS * sizeof(uint8_t));  
67 - memset(tab_rp_status, 0, MAX_STATUS * sizeof(uint8_t));  
68 -  
69 - /* Allocate and initialize the memory to store the registers */  
70 - tab_rp_registers = (uint16_t *) malloc(MAX_REGISTERS * sizeof(uint16_t));  
71 - memset(tab_rp_registers, 0, MAX_REGISTERS * sizeof(uint16_t));  
72 -  
73 - printf("READ COIL STATUS\n\n");  
74 -  
75 - nb_points = MAX_STATUS;  
76 - start = gettime_ms();  
77 - for (i=0; i<NB_LOOPS; i++) {  
78 - rc = read_coil_status(&mb_param, SERVER_ID, 0, nb_points, tab_rp_status);  
79 - if (rc == -1) {  
80 - fprintf(stderr, "%s\n", modbus_strerror(errno));  
81 - return -1;  
82 - }  
83 - }  
84 - end = gettime_ms();  
85 - elapsed = end - start;  
86 -  
87 - rate = (NB_LOOPS * nb_points) * G_MSEC_PER_SEC / (end - start);  
88 - printf("Transfert rate in points/seconds:\n");  
89 - printf("* %'d points/s\n", rate);  
90 - printf("\n");  
91 -  
92 - bytes = NB_LOOPS * (nb_points / 8) + ((nb_points % 8) ? 1 : 0);  
93 - rate = bytes / 1024 * G_MSEC_PER_SEC / (end - start);  
94 - printf("Values:\n");  
95 - printf("* %d x %d values\n", NB_LOOPS, nb_points);  
96 - printf("* %.3f ms for %d bytes\n", elapsed, bytes);  
97 - printf("* %'d KiB/s\n", rate);  
98 - printf("\n");  
99 -  
100 - /* TCP: Query and reponse header and values */  
101 - bytes = 12 + 9 + (nb_points / 8) + ((nb_points % 8) ? 1 : 0);  
102 - printf("Values and TCP Modbus overhead:\n");  
103 - printf("* %d x %d bytes\n", NB_LOOPS, bytes);  
104 - bytes = NB_LOOPS * bytes;  
105 - rate = bytes / 1024 * G_MSEC_PER_SEC / (end - start);  
106 - printf("* %.3f ms for %d bytes\n", elapsed, bytes);  
107 - printf("* %'d KiB/s\n", rate);  
108 - printf("\n\n");  
109 -  
110 - printf("READ HOLDING REGISTERS\n\n");  
111 -  
112 - nb_points = MAX_REGISTERS;  
113 - start = gettime_ms();  
114 - for (i=0; i<NB_LOOPS; i++) {  
115 - rc = read_holding_registers(&mb_param, SERVER_ID, 0, nb_points, tab_rp_registers);  
116 - if (rc == -1) {  
117 - fprintf(stderr, "%s\n", modbus_strerror(errno));  
118 - return -1;  
119 - } 83 + }
  84 + end = gettime_ms();
  85 + elapsed = end - start;
  86 +
  87 + rate = (NB_LOOPS * nb_points) * G_MSEC_PER_SEC / (end - start);
  88 + printf("Transfert rate in points/seconds:\n");
  89 + printf("* %'d points/s\n", rate);
  90 + printf("\n");
  91 +
  92 + bytes = NB_LOOPS * (nb_points / 8) + ((nb_points % 8) ? 1 : 0);
  93 + rate = bytes / 1024 * G_MSEC_PER_SEC / (end - start);
  94 + printf("Values:\n");
  95 + printf("* %d x %d values\n", NB_LOOPS, nb_points);
  96 + printf("* %.3f ms for %d bytes\n", elapsed, bytes);
  97 + printf("* %'d KiB/s\n", rate);
  98 + printf("\n");
  99 +
  100 + /* TCP: Query and reponse header and values */
  101 + bytes = 12 + 9 + (nb_points / 8) + ((nb_points % 8) ? 1 : 0);
  102 + printf("Values and TCP Modbus overhead:\n");
  103 + printf("* %d x %d bytes\n", NB_LOOPS, bytes);
  104 + bytes = NB_LOOPS * bytes;
  105 + rate = bytes / 1024 * G_MSEC_PER_SEC / (end - start);
  106 + printf("* %.3f ms for %d bytes\n", elapsed, bytes);
  107 + printf("* %'d KiB/s\n", rate);
  108 + printf("\n\n");
  109 +
  110 + printf("READ HOLDING REGISTERS\n\n");
  111 +
  112 + nb_points = MAX_REGISTERS;
  113 + start = gettime_ms();
  114 + for (i=0; i<NB_LOOPS; i++) {
  115 + rc = read_holding_registers(&mb_param, SERVER_ID, 0, nb_points, tab_rp_registers);
  116 + if (rc == -1) {
  117 + fprintf(stderr, "%s\n", modbus_strerror(errno));
  118 + return -1;
120 } 119 }
121 - end = gettime_ms();  
122 - elapsed = end - start;  
123 -  
124 - rate = (NB_LOOPS * nb_points) * G_MSEC_PER_SEC / (end - start);  
125 - printf("Transfert rate in points/seconds:\n");  
126 - printf("* %'d registers/s\n", rate);  
127 - printf("\n");  
128 -  
129 - bytes = NB_LOOPS * nb_points * sizeof(uint16_t);  
130 - rate = bytes / 1024 * G_MSEC_PER_SEC / (end - start);  
131 - printf("Values:\n");  
132 - printf("* %d x %d values\n", NB_LOOPS, nb_points);  
133 - printf("* %.3f ms for %d bytes\n", elapsed, bytes);  
134 - printf("* %'d KiB/s\n", rate);  
135 - printf("\n");  
136 -  
137 - /* TCP:Query and reponse header and values */  
138 - bytes = 12 + 9 + (nb_points * sizeof(uint16_t));  
139 - printf("Values and TCP Modbus overhead:\n");  
140 - printf("* %d x %d bytes\n", NB_LOOPS, bytes);  
141 - bytes = NB_LOOPS * bytes;  
142 - rate = bytes / 1024 * G_MSEC_PER_SEC / (end - start);  
143 - printf("* %.3f ms for %d bytes\n", elapsed, bytes);  
144 - printf("* %'d KiB/s\n", rate);  
145 - printf("\n");  
146 -  
147 - /* Free the memory */  
148 - free(tab_rp_status);  
149 - free(tab_rp_registers);  
150 -  
151 - /* Close the connection */  
152 - modbus_close(&mb_param);  
153 -  
154 - return 0; 120 + }
  121 + end = gettime_ms();
  122 + elapsed = end - start;
  123 +
  124 + rate = (NB_LOOPS * nb_points) * G_MSEC_PER_SEC / (end - start);
  125 + printf("Transfert rate in points/seconds:\n");
  126 + printf("* %'d registers/s\n", rate);
  127 + printf("\n");
  128 +
  129 + bytes = NB_LOOPS * nb_points * sizeof(uint16_t);
  130 + rate = bytes / 1024 * G_MSEC_PER_SEC / (end - start);
  131 + printf("Values:\n");
  132 + printf("* %d x %d values\n", NB_LOOPS, nb_points);
  133 + printf("* %.3f ms for %d bytes\n", elapsed, bytes);
  134 + printf("* %'d KiB/s\n", rate);
  135 + printf("\n");
  136 +
  137 + /* TCP:Query and reponse header and values */
  138 + bytes = 12 + 9 + (nb_points * sizeof(uint16_t));
  139 + printf("Values and TCP Modbus overhead:\n");
  140 + printf("* %d x %d bytes\n", NB_LOOPS, bytes);
  141 + bytes = NB_LOOPS * bytes;
  142 + rate = bytes / 1024 * G_MSEC_PER_SEC / (end - start);
  143 + printf("* %.3f ms for %d bytes\n", elapsed, bytes);
  144 + printf("* %'d KiB/s\n", rate);
  145 + printf("\n");
  146 +
  147 + /* Free the memory */
  148 + free(tab_rp_status);
  149 + free(tab_rp_registers);
  150 +
  151 + /* Close the connection */
  152 + modbus_close(&mb_param);
  153 +
  154 + return 0;
155 } 155 }
tests/bandwidth-slave-many-up.c
@@ -31,101 +31,101 @@ modbus_mapping_t mb_mapping; @@ -31,101 +31,101 @@ modbus_mapping_t mb_mapping;
31 31
32 static void close_sigint(int dummy) 32 static void close_sigint(int dummy)
33 { 33 {
34 - modbus_slave_close_tcp(slave_socket);  
35 - modbus_mapping_free(&mb_mapping); 34 + modbus_slave_close_tcp(slave_socket);
  35 + modbus_mapping_free(&mb_mapping);
36 36
37 - exit(dummy); 37 + exit(dummy);
38 } 38 }
39 39
40 int main(void) 40 int main(void)
41 { 41 {
42 - int master_socket;  
43 - modbus_param_t mb_param;  
44 - int rc;  
45 - fd_set refset;  
46 - fd_set rdset;  
47 -  
48 - /* Maximum file descriptor number */  
49 - int fdmax;  
50 -  
51 - modbus_init_tcp(&mb_param, "127.0.0.1", 1502);  
52 -  
53 - rc = modbus_mapping_new(&mb_mapping, MAX_STATUS, 0, MAX_REGISTERS, 0);  
54 - if (rc == -1) {  
55 - fprintf(stderr, "Failed to allocate the mapping: %s\n",  
56 - modbus_strerror(errno));  
57 - return -1;  
58 - } 42 + int master_socket;
  43 + modbus_param_t mb_param;
  44 + int rc;
  45 + fd_set refset;
  46 + fd_set rdset;
59 47
60 - slave_socket = modbus_slave_listen_tcp(&mb_param, NB_CONNECTION); 48 + /* Maximum file descriptor number */
  49 + int fdmax;
61 50
62 - signal(SIGINT, close_sigint); 51 + modbus_init_tcp(&mb_param, "127.0.0.1", 1502);
63 52
64 - /* Clear the reference set of socket */  
65 - FD_ZERO(&refset);  
66 - /* Add the slave socket */  
67 - FD_SET(slave_socket, &refset); 53 + rc = modbus_mapping_new(&mb_mapping, MAX_STATUS, 0, MAX_REGISTERS, 0);
  54 + if (rc == -1) {
  55 + fprintf(stderr, "Failed to allocate the mapping: %s\n",
  56 + modbus_strerror(errno));
  57 + return -1;
  58 + }
68 59
69 - /* Keep track of the max file descriptor */  
70 - fdmax = slave_socket; 60 + slave_socket = modbus_slave_listen_tcp(&mb_param, NB_CONNECTION);
71 61
72 - for (;;) {  
73 - rdset = refset;  
74 - if (select(fdmax+1, &rdset, NULL, NULL, NULL) == -1) {  
75 - perror("Slave select() failure.");  
76 - close_sigint(1);  
77 - } 62 + signal(SIGINT, close_sigint);
  63 +
  64 + /* Clear the reference set of socket */
  65 + FD_ZERO(&refset);
  66 + /* Add the slave socket */
  67 + FD_SET(slave_socket, &refset);
  68 +
  69 + /* Keep track of the max file descriptor */
  70 + fdmax = slave_socket;
78 71
79 - /* Run through the existing connections looking for data to be  
80 - * read */  
81 - for (master_socket = 0; master_socket <= fdmax; master_socket++) {  
82 -  
83 - if (FD_ISSET(master_socket, &rdset)) {  
84 - if (master_socket == slave_socket) {  
85 - /* A client is asking a new connection */  
86 - socklen_t addrlen;  
87 - struct sockaddr_in clientaddr;  
88 - int newfd;  
89 -  
90 - /* Handle new connections */  
91 - addrlen = sizeof(clientaddr);  
92 - memset(&clientaddr, 0, sizeof(clientaddr));  
93 - newfd = accept(slave_socket, (struct sockaddr *)&clientaddr, &addrlen);  
94 - if (newfd == -1) {  
95 - perror("Server accept() error");  
96 - } else {  
97 - FD_SET(newfd, &refset);  
98 -  
99 - if (newfd > fdmax) {  
100 - /* Keep track of the maximum */  
101 - fdmax = newfd;  
102 - }  
103 - printf("New connection from %s:%d on socket %d\n",  
104 - inet_ntoa(clientaddr.sin_addr), clientaddr.sin_port, newfd);  
105 - }  
106 - } else {  
107 - /* An already connected master has sent a new query */  
108 - uint8_t query[MAX_MESSAGE_LENGTH];  
109 -  
110 - rc = modbus_slave_receive(&mb_param, master_socket, query);  
111 - if (rc != -1) {  
112 - modbus_slave_manage(&mb_param, query, rc, &mb_mapping);  
113 - } else {  
114 - /* Connection closed by the client, end of server */  
115 - printf("Connection closed on socket %d\n", master_socket);  
116 - modbus_slave_close_tcp(master_socket);  
117 -  
118 - /* Remove from reference set */  
119 - FD_CLR(master_socket, &refset);  
120 -  
121 - if (master_socket == fdmax) {  
122 - fdmax--;  
123 - }  
124 - }  
125 - } 72 + for (;;) {
  73 + rdset = refset;
  74 + if (select(fdmax+1, &rdset, NULL, NULL, NULL) == -1) {
  75 + perror("Slave select() failure.");
  76 + close_sigint(1);
  77 + }
  78 +
  79 + /* Run through the existing connections looking for data to be
  80 + * read */
  81 + for (master_socket = 0; master_socket <= fdmax; master_socket++) {
  82 +
  83 + if (FD_ISSET(master_socket, &rdset)) {
  84 + if (master_socket == slave_socket) {
  85 + /* A client is asking a new connection */
  86 + socklen_t addrlen;
  87 + struct sockaddr_in clientaddr;
  88 + int newfd;
  89 +
  90 + /* Handle new connections */
  91 + addrlen = sizeof(clientaddr);
  92 + memset(&clientaddr, 0, sizeof(clientaddr));
  93 + newfd = accept(slave_socket, (struct sockaddr *)&clientaddr, &addrlen);
  94 + if (newfd == -1) {
  95 + perror("Server accept() error");
  96 + } else {
  97 + FD_SET(newfd, &refset);
  98 +
  99 + if (newfd > fdmax) {
  100 + /* Keep track of the maximum */
  101 + fdmax = newfd;
  102 + }
  103 + printf("New connection from %s:%d on socket %d\n",
  104 + inet_ntoa(clientaddr.sin_addr), clientaddr.sin_port, newfd);
  105 + }
  106 + } else {
  107 + /* An already connected master has sent a new query */
  108 + uint8_t query[MAX_MESSAGE_LENGTH];
  109 +
  110 + rc = modbus_slave_receive(&mb_param, master_socket, query);
  111 + if (rc != -1) {
  112 + modbus_slave_manage(&mb_param, query, rc, &mb_mapping);
  113 + } else {
  114 + /* Connection closed by the client, end of server */
  115 + printf("Connection closed on socket %d\n", master_socket);
  116 + modbus_slave_close_tcp(master_socket);
  117 +
  118 + /* Remove from reference set */
  119 + FD_CLR(master_socket, &refset);
  120 +
  121 + if (master_socket == fdmax) {
  122 + fdmax--;
126 } 123 }
  124 + }
127 } 125 }
  126 + }
128 } 127 }
  128 + }
129 129
130 - return 0; 130 + return 0;
131 } 131 }
tests/bandwidth-slave-one.c
@@ -25,40 +25,40 @@ @@ -25,40 +25,40 @@
25 25
26 int main(void) 26 int main(void)
27 { 27 {
28 - int socket;  
29 - modbus_param_t mb_param;  
30 - modbus_mapping_t mb_mapping;  
31 - int rc; 28 + int socket;
  29 + modbus_param_t mb_param;
  30 + modbus_mapping_t mb_mapping;
  31 + int rc;
32 32
33 - modbus_init_tcp(&mb_param, "127.0.0.1", 1502); 33 + modbus_init_tcp(&mb_param, "127.0.0.1", 1502);
34 34
35 - rc = modbus_mapping_new(&mb_mapping, MAX_STATUS, 0, MAX_REGISTERS, 0);  
36 - if (rc == -1) {  
37 - fprintf(stderr, "Failed to allocate the mapping: %s\n",  
38 - modbus_strerror(errno));  
39 - return -1;  
40 - } 35 + rc = modbus_mapping_new(&mb_mapping, MAX_STATUS, 0, MAX_REGISTERS, 0);
  36 + if (rc == -1) {
  37 + fprintf(stderr, "Failed to allocate the mapping: %s\n",
  38 + modbus_strerror(errno));
  39 + return -1;
  40 + }
41 41
42 - socket = modbus_slave_listen_tcp(&mb_param, 1);  
43 - modbus_slave_accept_tcp(&mb_param, &socket); 42 + socket = modbus_slave_listen_tcp(&mb_param, 1);
  43 + modbus_slave_accept_tcp(&mb_param, &socket);
44 44
45 - for(;;) {  
46 - uint8_t query[MAX_MESSAGE_LENGTH]; 45 + for(;;) {
  46 + uint8_t query[MAX_MESSAGE_LENGTH];
47 47
48 - rc = modbus_slave_receive(&mb_param, -1, query);  
49 - if (rc >= 0) {  
50 - modbus_slave_manage(&mb_param, query, rc, &mb_mapping);  
51 - } else {  
52 - /* Connection closed by the client or server */  
53 - break;  
54 - } 48 + rc = modbus_slave_receive(&mb_param, -1, query);
  49 + if (rc >= 0) {
  50 + modbus_slave_manage(&mb_param, query, rc, &mb_mapping);
  51 + } else {
  52 + /* Connection closed by the client or server */
  53 + break;
55 } 54 }
  55 + }
56 56
57 - printf("Quit the loop: %s\n", modbus_strerror(errno)); 57 + printf("Quit the loop: %s\n", modbus_strerror(errno));
58 58
59 - close(socket);  
60 - modbus_mapping_free(&mb_mapping);  
61 - modbus_close(&mb_param); 59 + close(socket);
  60 + modbus_mapping_free(&mb_mapping);
  61 + modbus_close(&mb_param);
62 62
63 - return 0; 63 + return 0;
64 } 64 }
tests/random-test-master.c
@@ -47,175 +47,175 @@ @@ -47,175 +47,175 @@
47 */ 47 */
48 int main(void) 48 int main(void)
49 { 49 {
50 - int rc;  
51 - int nb_fail;  
52 - int nb_loop;  
53 - int addr;  
54 - int nb;  
55 - uint8_t *tab_rq_status;  
56 - uint8_t *tab_rp_status;  
57 - uint16_t *tab_rq_registers;  
58 - uint16_t *tab_rp_registers;  
59 - modbus_param_t mb_param;  
60 -  
61 - /*  
62 - modbus_init_rtu(&mb_param, "/dev/ttyS0", 19200, 'N', 8, 1, MY_ID);  
63 - */  
64 -  
65 - /* TCP */  
66 - modbus_init_tcp(&mb_param, "127.0.0.1", 1502);  
67 - modbus_set_debug(&mb_param, TRUE);  
68 - if (modbus_connect(&mb_param) == -1) {  
69 - fprintf(stderr, "Connection failed: %s\n",  
70 - modbus_strerror(errno));  
71 - return -1;  
72 - }  
73 -  
74 - /* Allocate and initialize the different memory spaces */  
75 - nb = ADDRESS_END - ADDRESS_START;  
76 -  
77 - tab_rq_status = (uint8_t *) malloc(nb * sizeof(uint8_t));  
78 - memset(tab_rq_status, 0, nb * sizeof(uint8_t));  
79 -  
80 - tab_rp_status = (uint8_t *) malloc(nb * sizeof(uint8_t));  
81 - memset(tab_rp_status, 0, nb * sizeof(uint8_t));  
82 -  
83 - tab_rq_registers = (uint16_t *) malloc(nb * sizeof(uint16_t));  
84 - memset(tab_rq_registers, 0, nb * sizeof(uint16_t));  
85 -  
86 - tab_rp_registers = (uint16_t *) malloc(nb * sizeof(uint16_t));  
87 - memset(tab_rp_registers, 0, nb * sizeof(uint16_t));  
88 -  
89 - nb_loop = nb_fail = 0;  
90 - while (nb_loop++ < LOOP) {  
91 - for (addr = ADDRESS_START; addr <= ADDRESS_END; addr++) {  
92 - int i;  
93 -  
94 - /* Random numbers (short) */  
95 - for (i=0; i<nb; i++) {  
96 - tab_rq_registers[i] = (uint16_t) (65535.0*rand() / (RAND_MAX + 1.0));  
97 - tab_rq_status[i] = tab_rq_registers[i] % 2;  
98 - }  
99 - nb = ADDRESS_END - addr;  
100 -  
101 - /* SINGLE COIL */  
102 - rc = force_single_coil(&mb_param, SERVER_ID, addr, tab_rq_status[0]);  
103 - if (rc != 1) {  
104 - printf("ERROR force_single_coil (%d)\n", rc);  
105 - printf("Slave = %d, address = %d, value = %d\n",  
106 - SERVER_ID, addr, tab_rq_status[0]);  
107 - nb_fail++;  
108 - } else {  
109 - rc = read_coil_status(&mb_param, SERVER_ID, addr, 1, tab_rp_status);  
110 - if (rc != 1 || tab_rq_status[0] != tab_rp_status[0]) {  
111 - printf("ERROR read_coil_status single (%d)\n", rc);  
112 - printf("Slave = %d, address = %d\n",  
113 - SERVER_ID, addr);  
114 - nb_fail++;  
115 - }  
116 - }  
117 -  
118 - /* MULTIPLE COILS */  
119 - rc = force_multiple_coils(&mb_param, SERVER_ID, addr, nb, tab_rq_status);  
120 - if (rc != nb) {  
121 - printf("ERROR force_multiple_coils (%d)\n", rc);  
122 - printf("Slave = %d, address = %d, nb = %d\n",  
123 - SERVER_ID, addr, nb);  
124 - nb_fail++;  
125 - } else {  
126 - rc = read_coil_status(&mb_param, SERVER_ID, addr, nb, tab_rp_status);  
127 - if (rc != nb) {  
128 - printf("ERROR read_coil_status\n");  
129 - printf("Slave = %d, address = %d, nb = %d\n",  
130 - SERVER_ID, addr, nb);  
131 - nb_fail++;  
132 - } else {  
133 - for (i=0; i<nb; i++) {  
134 - if (tab_rp_status[i] != tab_rq_status[i]) {  
135 - printf("ERROR read_coil_status\n");  
136 - printf("Slave = %d, address = %d, value %d (0x%X) != %d (0x%X)\n",  
137 - SERVER_ID, addr,  
138 - tab_rq_status[i], tab_rq_status[i],  
139 - tab_rp_status[i], tab_rp_status[i]);  
140 - nb_fail++;  
141 - }  
142 - }  
143 - }  
144 - }  
145 -  
146 - /* SINGLE REGISTER */  
147 - rc = preset_single_register(&mb_param, SERVER_ID, addr, tab_rq_registers[0]);  
148 - if (rc != 1) {  
149 - printf("ERROR preset_single_register (%d)\n", rc);  
150 - printf("Slave = %d, address = %d, value = %d (0x%X)\n",  
151 - SERVER_ID, addr, tab_rq_registers[0], tab_rq_registers[0]);  
152 - nb_fail++;  
153 - } else {  
154 - rc = read_holding_registers(&mb_param, SERVER_ID, addr, 1, tab_rp_registers);  
155 - if (rc != 1) {  
156 - printf("ERROR read_holding_registers single (%d)\n", rc);  
157 - printf("Slave = %d, address = %d\n",  
158 - SERVER_ID, addr);  
159 - nb_fail++;  
160 - } else {  
161 - if (tab_rq_registers[0] != tab_rp_registers[0]) {  
162 - printf("ERROR read_holding_registers single\n");  
163 - printf("Slave = %d, address = %d, value = %d (0x%X) != %d (0x%X)\n",  
164 - SERVER_ID, addr,  
165 - tab_rq_registers[0], tab_rq_registers[0],  
166 - tab_rp_registers[0], tab_rp_registers[0]);  
167 - nb_fail++;  
168 - }  
169 - } 50 + int rc;
  51 + int nb_fail;
  52 + int nb_loop;
  53 + int addr;
  54 + int nb;
  55 + uint8_t *tab_rq_status;
  56 + uint8_t *tab_rp_status;
  57 + uint16_t *tab_rq_registers;
  58 + uint16_t *tab_rp_registers;
  59 + modbus_param_t mb_param;
  60 +
  61 + /*
  62 + modbus_init_rtu(&mb_param, "/dev/ttyS0", 19200, 'N', 8, 1, MY_ID);
  63 + */
  64 +
  65 + /* TCP */
  66 + modbus_init_tcp(&mb_param, "127.0.0.1", 1502);
  67 + modbus_set_debug(&mb_param, TRUE);
  68 + if (modbus_connect(&mb_param) == -1) {
  69 + fprintf(stderr, "Connection failed: %s\n",
  70 + modbus_strerror(errno));
  71 + return -1;
  72 + }
  73 +
  74 + /* Allocate and initialize the different memory spaces */
  75 + nb = ADDRESS_END - ADDRESS_START;
  76 +
  77 + tab_rq_status = (uint8_t *) malloc(nb * sizeof(uint8_t));
  78 + memset(tab_rq_status, 0, nb * sizeof(uint8_t));
  79 +
  80 + tab_rp_status = (uint8_t *) malloc(nb * sizeof(uint8_t));
  81 + memset(tab_rp_status, 0, nb * sizeof(uint8_t));
  82 +
  83 + tab_rq_registers = (uint16_t *) malloc(nb * sizeof(uint16_t));
  84 + memset(tab_rq_registers, 0, nb * sizeof(uint16_t));
  85 +
  86 + tab_rp_registers = (uint16_t *) malloc(nb * sizeof(uint16_t));
  87 + memset(tab_rp_registers, 0, nb * sizeof(uint16_t));
  88 +
  89 + nb_loop = nb_fail = 0;
  90 + while (nb_loop++ < LOOP) {
  91 + for (addr = ADDRESS_START; addr <= ADDRESS_END; addr++) {
  92 + int i;
  93 +
  94 + /* Random numbers (short) */
  95 + for (i=0; i<nb; i++) {
  96 + tab_rq_registers[i] = (uint16_t) (65535.0*rand() / (RAND_MAX + 1.0));
  97 + tab_rq_status[i] = tab_rq_registers[i] % 2;
  98 + }
  99 + nb = ADDRESS_END - addr;
  100 +
  101 + /* SINGLE COIL */
  102 + rc = force_single_coil(&mb_param, SERVER_ID, addr, tab_rq_status[0]);
  103 + if (rc != 1) {
  104 + printf("ERROR force_single_coil (%d)\n", rc);
  105 + printf("Slave = %d, address = %d, value = %d\n",
  106 + SERVER_ID, addr, tab_rq_status[0]);
  107 + nb_fail++;
  108 + } else {
  109 + rc = read_coil_status(&mb_param, SERVER_ID, addr, 1, tab_rp_status);
  110 + if (rc != 1 || tab_rq_status[0] != tab_rp_status[0]) {
  111 + printf("ERROR read_coil_status single (%d)\n", rc);
  112 + printf("Slave = %d, address = %d\n",
  113 + SERVER_ID, addr);
  114 + nb_fail++;
  115 + }
  116 + }
  117 +
  118 + /* MULTIPLE COILS */
  119 + rc = force_multiple_coils(&mb_param, SERVER_ID, addr, nb, tab_rq_status);
  120 + if (rc != nb) {
  121 + printf("ERROR force_multiple_coils (%d)\n", rc);
  122 + printf("Slave = %d, address = %d, nb = %d\n",
  123 + SERVER_ID, addr, nb);
  124 + nb_fail++;
  125 + } else {
  126 + rc = read_coil_status(&mb_param, SERVER_ID, addr, nb, tab_rp_status);
  127 + if (rc != nb) {
  128 + printf("ERROR read_coil_status\n");
  129 + printf("Slave = %d, address = %d, nb = %d\n",
  130 + SERVER_ID, addr, nb);
  131 + nb_fail++;
  132 + } else {
  133 + for (i=0; i<nb; i++) {
  134 + if (tab_rp_status[i] != tab_rq_status[i]) {
  135 + printf("ERROR read_coil_status\n");
  136 + printf("Slave = %d, address = %d, value %d (0x%X) != %d (0x%X)\n",
  137 + SERVER_ID, addr,
  138 + tab_rq_status[i], tab_rq_status[i],
  139 + tab_rp_status[i], tab_rp_status[i]);
  140 + nb_fail++;
170 } 141 }
171 -  
172 - /* MULTIPLE REGISTERS */  
173 - rc = preset_multiple_registers(&mb_param, SERVER_ID, addr, nb,  
174 - tab_rq_registers);  
175 - if (rc != nb) {  
176 - printf("ERROR preset_multiple_registers (%d)\n", rc);  
177 - printf("Slave = %d, address = %d, nb = %d\n",  
178 - SERVER_ID, addr, nb);  
179 - nb_fail++;  
180 - } else {  
181 - rc = read_holding_registers(&mb_param, SERVER_ID, addr, nb,  
182 - tab_rp_registers);  
183 - if (rc != nb) {  
184 - printf("ERROR read_holding_registers (%d)\n", rc);  
185 - printf("Slave = %d, address = %d, nb = %d\n",  
186 - SERVER_ID, addr, nb);  
187 - nb_fail++;  
188 - } else {  
189 - for (i=0; i<nb; i++) {  
190 - if (tab_rq_registers[i] != tab_rp_registers[i]) {  
191 - printf("ERROR read_holding_registers\n");  
192 - printf("Slave = %d, address = %d, value %d (0x%X) != %d (0x%X)\n",  
193 - SERVER_ID, addr,  
194 - tab_rq_registers[i], tab_rq_registers[i],  
195 - tab_rp_registers[i], tab_rp_registers[i]);  
196 - nb_fail++;  
197 - }  
198 - }  
199 - } 142 + }
  143 + }
  144 + }
  145 +
  146 + /* SINGLE REGISTER */
  147 + rc = preset_single_register(&mb_param, SERVER_ID, addr, tab_rq_registers[0]);
  148 + if (rc != 1) {
  149 + printf("ERROR preset_single_register (%d)\n", rc);
  150 + printf("Slave = %d, address = %d, value = %d (0x%X)\n",
  151 + SERVER_ID, addr, tab_rq_registers[0], tab_rq_registers[0]);
  152 + nb_fail++;
  153 + } else {
  154 + rc = read_holding_registers(&mb_param, SERVER_ID, addr, 1, tab_rp_registers);
  155 + if (rc != 1) {
  156 + printf("ERROR read_holding_registers single (%d)\n", rc);
  157 + printf("Slave = %d, address = %d\n",
  158 + SERVER_ID, addr);
  159 + nb_fail++;
  160 + } else {
  161 + if (tab_rq_registers[0] != tab_rp_registers[0]) {
  162 + printf("ERROR read_holding_registers single\n");
  163 + printf("Slave = %d, address = %d, value = %d (0x%X) != %d (0x%X)\n",
  164 + SERVER_ID, addr,
  165 + tab_rq_registers[0], tab_rq_registers[0],
  166 + tab_rp_registers[0], tab_rp_registers[0]);
  167 + nb_fail++;
  168 + }
  169 + }
  170 + }
  171 +
  172 + /* MULTIPLE REGISTERS */
  173 + rc = preset_multiple_registers(&mb_param, SERVER_ID, addr, nb,
  174 + tab_rq_registers);
  175 + if (rc != nb) {
  176 + printf("ERROR preset_multiple_registers (%d)\n", rc);
  177 + printf("Slave = %d, address = %d, nb = %d\n",
  178 + SERVER_ID, addr, nb);
  179 + nb_fail++;
  180 + } else {
  181 + rc = read_holding_registers(&mb_param, SERVER_ID, addr, nb,
  182 + tab_rp_registers);
  183 + if (rc != nb) {
  184 + printf("ERROR read_holding_registers (%d)\n", rc);
  185 + printf("Slave = %d, address = %d, nb = %d\n",
  186 + SERVER_ID, addr, nb);
  187 + nb_fail++;
  188 + } else {
  189 + for (i=0; i<nb; i++) {
  190 + if (tab_rq_registers[i] != tab_rp_registers[i]) {
  191 + printf("ERROR read_holding_registers\n");
  192 + printf("Slave = %d, address = %d, value %d (0x%X) != %d (0x%X)\n",
  193 + SERVER_ID, addr,
  194 + tab_rq_registers[i], tab_rq_registers[i],
  195 + tab_rp_registers[i], tab_rp_registers[i]);
  196 + nb_fail++;
200 } 197 }
201 - 198 + }
202 } 199 }
  200 + }
203 201
204 - printf("Test: ");  
205 - if (nb_fail)  
206 - printf("%d FAILS\n", nb_fail);  
207 - else  
208 - printf("SUCCESS\n");  
209 } 202 }
210 203
211 - /* Free the memory */  
212 - free(tab_rq_status);  
213 - free(tab_rp_status);  
214 - free(tab_rq_registers);  
215 - free(tab_rp_registers); 204 + printf("Test: ");
  205 + if (nb_fail)
  206 + printf("%d FAILS\n", nb_fail);
  207 + else
  208 + printf("SUCCESS\n");
  209 + }
  210 +
  211 + /* Free the memory */
  212 + free(tab_rq_status);
  213 + free(tab_rp_status);
  214 + free(tab_rq_registers);
  215 + free(tab_rp_registers);
216 216
217 - /* Close the connection */  
218 - modbus_close(&mb_param); 217 + /* Close the connection */
  218 + modbus_close(&mb_param);
219 219
220 - return 0; 220 + return 0;
221 } 221 }
tests/random-test-slave.c
@@ -24,43 +24,43 @@ @@ -24,43 +24,43 @@
24 24
25 int main(void) 25 int main(void)
26 { 26 {
27 - int socket;  
28 - modbus_param_t mb_param;  
29 - modbus_mapping_t mb_mapping;  
30 - int rc; 27 + int socket;
  28 + modbus_param_t mb_param;
  29 + modbus_mapping_t mb_mapping;
  30 + int rc;
31 31
32 - modbus_init_tcp(&mb_param, "127.0.0.1", 1502);  
33 - /* modbus_set_debug(&mb_param, TRUE); */ 32 + modbus_init_tcp(&mb_param, "127.0.0.1", 1502);
  33 + /* modbus_set_debug(&mb_param, TRUE); */
34 34
35 - rc = modbus_mapping_new(&mb_mapping, 500, 500, 500, 500);  
36 - if (rc == -1) {  
37 - fprintf(stderr, "Failed to allocate the mapping: %s\n",  
38 - modbus_strerror(errno));  
39 - return -1;  
40 - } 35 + rc = modbus_mapping_new(&mb_mapping, 500, 500, 500, 500);
  36 + if (rc == -1) {
  37 + fprintf(stderr, "Failed to allocate the mapping: %s\n",
  38 + modbus_strerror(errno));
  39 + return -1;
  40 + }
41 41
42 - socket = modbus_slave_listen_tcp(&mb_param, 1);  
43 - modbus_slave_accept_tcp(&mb_param, &socket); 42 + socket = modbus_slave_listen_tcp(&mb_param, 1);
  43 + modbus_slave_accept_tcp(&mb_param, &socket);
44 44
45 - for (;;) {  
46 - uint8_t query[MAX_MESSAGE_LENGTH];  
47 - int rc; 45 + for (;;) {
  46 + uint8_t query[MAX_MESSAGE_LENGTH];
  47 + int rc;
48 48
49 - rc = modbus_slave_receive(&mb_param, -1, query);  
50 - if (rc != -1) {  
51 - /* rc is the query size */  
52 - modbus_slave_manage(&mb_param, query, rc, &mb_mapping);  
53 - } else {  
54 - /* Connection closed by the client or error */  
55 - break;  
56 - } 49 + rc = modbus_slave_receive(&mb_param, -1, query);
  50 + if (rc != -1) {
  51 + /* rc is the query size */
  52 + modbus_slave_manage(&mb_param, query, rc, &mb_mapping);
  53 + } else {
  54 + /* Connection closed by the client or error */
  55 + break;
57 } 56 }
  57 + }
58 58
59 - printf("Quit the loop: %s\n", modbus_strerror(errno)); 59 + printf("Quit the loop: %s\n", modbus_strerror(errno));
60 60
61 - close(socket);  
62 - modbus_mapping_free(&mb_mapping);  
63 - modbus_close(&mb_param); 61 + close(socket);
  62 + modbus_mapping_free(&mb_mapping);
  63 + modbus_close(&mb_param);
64 64
65 - return 0; 65 + return 0;
66 } 66 }
tests/unit-test-master.c
@@ -26,516 +26,516 @@ @@ -26,516 +26,516 @@
26 26
27 int main(void) 27 int main(void)
28 { 28 {
29 - uint8_t *tab_rp_status;  
30 - uint16_t *tab_rp_registers;  
31 - uint16_t *tab_rp_registers_bad;  
32 - modbus_param_t mb_param;  
33 - int i;  
34 - uint8_t value;  
35 - int address;  
36 - int nb_points;  
37 - int rc;  
38 - float real;  
39 - struct timeval timeout_begin_old;  
40 - struct timeval timeout_begin_new;  
41 -  
42 - /*  
43 - modbus_init_rtu(&mb_param, "/dev/ttyS0", 19200, 'N', 8, 1,  
44 - CLIENT_ID);  
45 - */  
46 -  
47 - /* TCP */  
48 - modbus_init_tcp(&mb_param, "127.0.0.1", 1502);  
49 - modbus_set_debug(&mb_param, TRUE);  
50 -  
51 - if (modbus_connect(&mb_param) == -1) {  
52 - fprintf(stderr, "Connection failed: %s\n",  
53 - modbus_strerror(errno));  
54 - return -1;  
55 - }  
56 -  
57 - /* Allocate and initialize the memory to store the status */  
58 - nb_points = (UT_COIL_STATUS_NB_POINTS > UT_INPUT_STATUS_NB_POINTS) ?  
59 - UT_COIL_STATUS_NB_POINTS : UT_INPUT_STATUS_NB_POINTS;  
60 - tab_rp_status = (uint8_t *) malloc(nb_points * sizeof(uint8_t));  
61 - memset(tab_rp_status, 0, nb_points * sizeof(uint8_t));  
62 -  
63 - /* Allocate and initialize the memory to store the registers */  
64 - nb_points = (UT_HOLDING_REGISTERS_NB_POINTS >  
65 - UT_INPUT_REGISTERS_NB_POINTS) ?  
66 - UT_HOLDING_REGISTERS_NB_POINTS : UT_INPUT_REGISTERS_NB_POINTS;  
67 - tab_rp_registers = (uint16_t *) malloc(nb_points * sizeof(uint16_t));  
68 - memset(tab_rp_registers, 0, nb_points * sizeof(uint16_t));  
69 -  
70 - printf("** UNIT TESTING **\n");  
71 -  
72 - printf("\nTEST WRITE/READ:\n");  
73 -  
74 - /** COIL STATUS **/  
75 -  
76 - /* Single */  
77 - rc = force_single_coil(&mb_param, SERVER_ID, UT_COIL_STATUS_ADDRESS, ON);  
78 - printf("1/2 force_single_coil: ");  
79 - if (rc == 1) {  
80 - printf("OK\n"); 29 + uint8_t *tab_rp_status;
  30 + uint16_t *tab_rp_registers;
  31 + uint16_t *tab_rp_registers_bad;
  32 + modbus_param_t mb_param;
  33 + int i;
  34 + uint8_t value;
  35 + int address;
  36 + int nb_points;
  37 + int rc;
  38 + float real;
  39 + struct timeval timeout_begin_old;
  40 + struct timeval timeout_begin_new;
  41 +
  42 + /*
  43 + modbus_init_rtu(&mb_param, "/dev/ttyS0", 19200, 'N', 8, 1,
  44 + CLIENT_ID);
  45 + */
  46 +
  47 + /* TCP */
  48 + modbus_init_tcp(&mb_param, "127.0.0.1", 1502);
  49 + modbus_set_debug(&mb_param, TRUE);
  50 +
  51 + if (modbus_connect(&mb_param) == -1) {
  52 + fprintf(stderr, "Connection failed: %s\n",
  53 + modbus_strerror(errno));
  54 + return -1;
  55 + }
  56 +
  57 + /* Allocate and initialize the memory to store the status */
  58 + nb_points = (UT_COIL_STATUS_NB_POINTS > UT_INPUT_STATUS_NB_POINTS) ?
  59 + UT_COIL_STATUS_NB_POINTS : UT_INPUT_STATUS_NB_POINTS;
  60 + tab_rp_status = (uint8_t *) malloc(nb_points * sizeof(uint8_t));
  61 + memset(tab_rp_status, 0, nb_points * sizeof(uint8_t));
  62 +
  63 + /* Allocate and initialize the memory to store the registers */
  64 + nb_points = (UT_HOLDING_REGISTERS_NB_POINTS >
  65 + UT_INPUT_REGISTERS_NB_POINTS) ?
  66 + UT_HOLDING_REGISTERS_NB_POINTS : UT_INPUT_REGISTERS_NB_POINTS;
  67 + tab_rp_registers = (uint16_t *) malloc(nb_points * sizeof(uint16_t));
  68 + memset(tab_rp_registers, 0, nb_points * sizeof(uint16_t));
  69 +
  70 + printf("** UNIT TESTING **\n");
  71 +
  72 + printf("\nTEST WRITE/READ:\n");
  73 +
  74 + /** COIL STATUS **/
  75 +
  76 + /* Single */
  77 + rc = force_single_coil(&mb_param, SERVER_ID, UT_COIL_STATUS_ADDRESS, ON);
  78 + printf("1/2 force_single_coil: ");
  79 + if (rc == 1) {
  80 + printf("OK\n");
  81 + } else {
  82 + printf("FAILED\n");
  83 + goto close;
  84 + }
  85 +
  86 + rc = read_coil_status(&mb_param, SERVER_ID, UT_COIL_STATUS_ADDRESS, 1,
  87 + tab_rp_status);
  88 + printf("2/2 read_coil_status: ");
  89 + if (rc != 1) {
  90 + printf("FAILED (nb points %d)\n", rc);
  91 + goto close;
  92 + }
  93 +
  94 + if (tab_rp_status[0] != ON) {
  95 + printf("FAILED (%0X = != %0X)\n", tab_rp_status[0], ON);
  96 + goto close;
  97 + }
  98 + printf("OK\n");
  99 + /* End single */
  100 +
  101 + /* Multiple coils */
  102 + {
  103 + uint8_t tab_value[UT_COIL_STATUS_NB_POINTS];
  104 +
  105 + set_bits_from_bytes(tab_value, 0, UT_COIL_STATUS_NB_POINTS,
  106 + UT_COIL_STATUS_TAB);
  107 + rc = force_multiple_coils(&mb_param, SERVER_ID,
  108 + UT_COIL_STATUS_ADDRESS,
  109 + UT_COIL_STATUS_NB_POINTS,
  110 + tab_value);
  111 + printf("1/2 force_multiple_coils: ");
  112 + if (rc == UT_COIL_STATUS_NB_POINTS) {
  113 + printf("OK\n");
81 } else { 114 } else {
82 - printf("FAILED\n");  
83 - goto close;  
84 - }  
85 -  
86 - rc = read_coil_status(&mb_param, SERVER_ID, UT_COIL_STATUS_ADDRESS, 1,  
87 - tab_rp_status);  
88 - printf("2/2 read_coil_status: ");  
89 - if (rc != 1) {  
90 - printf("FAILED (nb points %d)\n", rc);  
91 - goto close;  
92 - }  
93 -  
94 - if (tab_rp_status[0] != ON) {  
95 - printf("FAILED (%0X = != %0X)\n", tab_rp_status[0], ON);  
96 - goto close;  
97 - } 115 + printf("FAILED\n");
  116 + goto close;
  117 + }
  118 + }
  119 +
  120 + rc = read_coil_status(&mb_param, SERVER_ID, UT_COIL_STATUS_ADDRESS,
  121 + UT_COIL_STATUS_NB_POINTS, tab_rp_status);
  122 + printf("2/2 read_coil_status: ");
  123 + if (rc != UT_COIL_STATUS_NB_POINTS) {
  124 + printf("FAILED (nb points %d)\n", rc);
  125 + goto close;
  126 + }
  127 +
  128 + i = 0;
  129 + address = UT_COIL_STATUS_ADDRESS;
  130 + nb_points = UT_COIL_STATUS_NB_POINTS;
  131 + while (nb_points > 0) {
  132 + int nb_bits = (nb_points > 8) ? 8 : nb_points;
  133 +
  134 + value = get_byte_from_bits(tab_rp_status, i*8, nb_bits);
  135 + if (value != UT_COIL_STATUS_TAB[i]) {
  136 + printf("FAILED (%0X != %0X)\n",
  137 + value, UT_COIL_STATUS_TAB[i]);
  138 + goto close;
  139 + }
  140 +
  141 + nb_points -= nb_bits;
  142 + i++;
  143 + }
  144 + printf("OK\n");
  145 + /* End of multiple coils */
  146 +
  147 + /** INPUT STATUS **/
  148 + rc = read_input_status(&mb_param, SERVER_ID, UT_INPUT_STATUS_ADDRESS,
  149 + UT_INPUT_STATUS_NB_POINTS, tab_rp_status);
  150 + printf("1/1 read_input_status: ");
  151 +
  152 + if (rc != UT_INPUT_STATUS_NB_POINTS) {
  153 + printf("FAILED (nb points %d)\n", rc);
  154 + goto close;
  155 + }
  156 +
  157 + i = 0;
  158 + address = UT_INPUT_STATUS_ADDRESS;
  159 + nb_points = UT_INPUT_STATUS_NB_POINTS;
  160 + while (nb_points > 0) {
  161 + int nb_bits = (nb_points > 8) ? 8 : nb_points;
  162 +
  163 + value = get_byte_from_bits(tab_rp_status, i*8, nb_bits);
  164 + if (value != UT_INPUT_STATUS_TAB[i]) {
  165 + printf("FAILED (%0X != %0X)\n",
  166 + value, UT_INPUT_STATUS_TAB[i]);
  167 + goto close;
  168 + }
  169 +
  170 + nb_points -= nb_bits;
  171 + i++;
  172 + }
  173 + printf("OK\n");
  174 +
  175 + /** HOLDING REGISTERS **/
  176 +
  177 + /* Single register */
  178 + rc = preset_single_register(&mb_param, SERVER_ID,
  179 + UT_HOLDING_REGISTERS_ADDRESS, 0x1234);
  180 + printf("1/2 preset_single_register: ");
  181 + if (rc == 1) {
98 printf("OK\n"); 182 printf("OK\n");
99 - /* End single */  
100 -  
101 - /* Multiple coils */  
102 - {  
103 - uint8_t tab_value[UT_COIL_STATUS_NB_POINTS];  
104 -  
105 - set_bits_from_bytes(tab_value, 0, UT_COIL_STATUS_NB_POINTS,  
106 - UT_COIL_STATUS_TAB);  
107 - rc = force_multiple_coils(&mb_param, SERVER_ID,  
108 - UT_COIL_STATUS_ADDRESS,  
109 - UT_COIL_STATUS_NB_POINTS,  
110 - tab_value);  
111 - printf("1/2 force_multiple_coils: ");  
112 - if (rc == UT_COIL_STATUS_NB_POINTS) {  
113 - printf("OK\n");  
114 - } else {  
115 - printf("FAILED\n");  
116 - goto close;  
117 - }  
118 - }  
119 -  
120 - rc = read_coil_status(&mb_param, SERVER_ID, UT_COIL_STATUS_ADDRESS,  
121 - UT_COIL_STATUS_NB_POINTS, tab_rp_status);  
122 - printf("2/2 read_coil_status: ");  
123 - if (rc != UT_COIL_STATUS_NB_POINTS) {  
124 - printf("FAILED (nb points %d)\n", rc);  
125 - goto close;  
126 - }  
127 -  
128 - i = 0;  
129 - address = UT_COIL_STATUS_ADDRESS;  
130 - nb_points = UT_COIL_STATUS_NB_POINTS;  
131 - while (nb_points > 0) {  
132 - int nb_bits = (nb_points > 8) ? 8 : nb_points;  
133 -  
134 - value = get_byte_from_bits(tab_rp_status, i*8, nb_bits);  
135 - if (value != UT_COIL_STATUS_TAB[i]) {  
136 - printf("FAILED (%0X != %0X)\n",  
137 - value, UT_COIL_STATUS_TAB[i]);  
138 - goto close;  
139 - }  
140 -  
141 - nb_points -= nb_bits;  
142 - i++;  
143 - } 183 + } else {
  184 + printf("FAILED\n");
  185 + goto close;
  186 + }
  187 +
  188 + rc = read_holding_registers(&mb_param, SERVER_ID,
  189 + UT_HOLDING_REGISTERS_ADDRESS,
  190 + 1, tab_rp_registers);
  191 + printf("2/2 read_holding_registers: ");
  192 + if (rc != 1) {
  193 + printf("FAILED (nb points %d)\n", rc);
  194 + goto close;
  195 + }
  196 +
  197 + if (tab_rp_registers[0] != 0x1234) {
  198 + printf("FAILED (%0X != %0X)\n",
  199 + tab_rp_registers[0], 0x1234);
  200 + goto close;
  201 + }
  202 + printf("OK\n");
  203 + /* End of single register */
  204 +
  205 + /* Many registers */
  206 + rc = preset_multiple_registers(&mb_param, SERVER_ID,
  207 + UT_HOLDING_REGISTERS_ADDRESS,
  208 + UT_HOLDING_REGISTERS_NB_POINTS,
  209 + UT_HOLDING_REGISTERS_TAB);
  210 + printf("1/2 preset_multiple_registers: ");
  211 + if (rc == UT_HOLDING_REGISTERS_NB_POINTS) {
144 printf("OK\n"); 212 printf("OK\n");
145 - /* End of multiple coils */  
146 -  
147 - /** INPUT STATUS **/  
148 - rc = read_input_status(&mb_param, SERVER_ID, UT_INPUT_STATUS_ADDRESS,  
149 - UT_INPUT_STATUS_NB_POINTS, tab_rp_status);  
150 - printf("1/1 read_input_status: ");  
151 -  
152 - if (rc != UT_INPUT_STATUS_NB_POINTS) {  
153 - printf("FAILED (nb points %d)\n", rc);  
154 - goto close;  
155 - }  
156 -  
157 - i = 0;  
158 - address = UT_INPUT_STATUS_ADDRESS;  
159 - nb_points = UT_INPUT_STATUS_NB_POINTS;  
160 - while (nb_points > 0) {  
161 - int nb_bits = (nb_points > 8) ? 8 : nb_points;  
162 -  
163 - value = get_byte_from_bits(tab_rp_status, i*8, nb_bits);  
164 - if (value != UT_INPUT_STATUS_TAB[i]) {  
165 - printf("FAILED (%0X != %0X)\n",  
166 - value, UT_INPUT_STATUS_TAB[i]);  
167 - goto close;  
168 - }  
169 -  
170 - nb_points -= nb_bits;  
171 - i++;  
172 - } 213 + } else {
  214 + printf("FAILED\n");
  215 + goto close;
  216 + }
  217 +
  218 + rc = read_holding_registers(&mb_param, SERVER_ID,
  219 + UT_HOLDING_REGISTERS_ADDRESS,
  220 + UT_HOLDING_REGISTERS_NB_POINTS,
  221 + tab_rp_registers);
  222 + printf("2/2 read_holding_registers: ");
  223 + if (rc != UT_HOLDING_REGISTERS_NB_POINTS) {
  224 + printf("FAILED (nb points %d)\n", rc);
  225 + goto close;
  226 + }
  227 +
  228 + for (i=0; i < UT_HOLDING_REGISTERS_NB_POINTS; i++) {
  229 + if (tab_rp_registers[i] != UT_HOLDING_REGISTERS_TAB[i]) {
  230 + printf("FAILED (%0X != %0X)\n",
  231 + tab_rp_registers[i],
  232 + UT_HOLDING_REGISTERS_TAB[i]);
  233 + goto close;
  234 + }
  235 + }
  236 + printf("OK\n");
  237 + /* End of many registers */
  238 +
  239 +
  240 + /** INPUT REGISTERS **/
  241 + rc = read_input_registers(&mb_param, SERVER_ID,
  242 + UT_INPUT_REGISTERS_ADDRESS,
  243 + UT_INPUT_REGISTERS_NB_POINTS,
  244 + tab_rp_registers);
  245 + printf("1/1 read_input_registers: ");
  246 + if (rc != UT_INPUT_REGISTERS_NB_POINTS) {
  247 + printf("FAILED (nb points %d)\n", rc);
  248 + goto close;
  249 + }
  250 +
  251 + for (i=0; i < UT_INPUT_REGISTERS_NB_POINTS; i++) {
  252 + if (tab_rp_registers[i] != UT_INPUT_REGISTERS_TAB[i]) {
  253 + printf("FAILED (%0X != %0X)\n",
  254 + tab_rp_registers[i], UT_INPUT_REGISTERS_TAB[i]);
  255 + goto close;
  256 + }
  257 + }
  258 + printf("OK\n");
  259 +
  260 +
  261 + printf("\nTEST FLOATS\n");
  262 + /** FLOAT **/
  263 + printf("1/2 Write float: ");
  264 + modbus_write_float(UT_REAL, tab_rp_registers);
  265 + if (tab_rp_registers[1] == (UT_IREAL >> 16) &&
  266 + tab_rp_registers[0] == (UT_IREAL & 0xFFFF)) {
  267 + printf("OK\n");
  268 + } else {
  269 + printf("FAILED (%x != %x)\n",
  270 + *((uint32_t *)tab_rp_registers), UT_IREAL);
  271 + goto close;
  272 + }
  273 +
  274 + printf("2/2 Read float: ");
  275 + real = modbus_read_float(tab_rp_registers);
  276 + if (real == UT_REAL) {
173 printf("OK\n"); 277 printf("OK\n");
  278 + } else {
  279 + printf("FAILED (%f != %f)\n", real, UT_REAL);
  280 + goto close;
  281 + }
174 282
175 - /** HOLDING REGISTERS **/ 283 + printf("\nAt this point, error messages doesn't mean the test has failed\n");
176 284
177 - /* Single register */  
178 - rc = preset_single_register(&mb_param, SERVER_ID,  
179 - UT_HOLDING_REGISTERS_ADDRESS, 0x1234);  
180 - printf("1/2 preset_single_register: ");  
181 - if (rc == 1) {  
182 - printf("OK\n");  
183 - } else {  
184 - printf("FAILED\n");  
185 - goto close;  
186 - } 285 + /** ILLEGAL DATA ADDRESS **/
  286 + printf("\nTEST ILLEGAL DATA ADDRESS:\n");
187 287
188 - rc = read_holding_registers(&mb_param, SERVER_ID,  
189 - UT_HOLDING_REGISTERS_ADDRESS,  
190 - 1, tab_rp_registers);  
191 - printf("2/2 read_holding_registers: ");  
192 - if (rc != 1) {  
193 - printf("FAILED (nb points %d)\n", rc);  
194 - goto close;  
195 - } 288 + /* The mapping begins at 0 and ending at address + nb_points so
  289 + * the addresses below are not valid. */
196 290
197 - if (tab_rp_registers[0] != 0x1234) {  
198 - printf("FAILED (%0X != %0X)\n",  
199 - tab_rp_registers[0], 0x1234);  
200 - goto close;  
201 - } 291 + rc = read_coil_status(&mb_param, SERVER_ID,
  292 + UT_COIL_STATUS_ADDRESS,
  293 + UT_COIL_STATUS_NB_POINTS + 1,
  294 + tab_rp_status);
  295 + printf("* read_coil_status: ");
  296 + if (rc == -1 && errno == EMBXILADD)
202 printf("OK\n"); 297 printf("OK\n");
203 - /* End of single register */  
204 -  
205 - /* Many registers */  
206 - rc = preset_multiple_registers(&mb_param, SERVER_ID,  
207 - UT_HOLDING_REGISTERS_ADDRESS,  
208 - UT_HOLDING_REGISTERS_NB_POINTS,  
209 - UT_HOLDING_REGISTERS_TAB);  
210 - printf("1/2 preset_multiple_registers: ");  
211 - if (rc == UT_HOLDING_REGISTERS_NB_POINTS) {  
212 - printf("OK\n");  
213 - } else {  
214 - printf("FAILED\n");  
215 - goto close;  
216 - }  
217 -  
218 - rc = read_holding_registers(&mb_param, SERVER_ID,  
219 - UT_HOLDING_REGISTERS_ADDRESS,  
220 - UT_HOLDING_REGISTERS_NB_POINTS,  
221 - tab_rp_registers);  
222 - printf("2/2 read_holding_registers: ");  
223 - if (rc != UT_HOLDING_REGISTERS_NB_POINTS) {  
224 - printf("FAILED (nb points %d)\n", rc);  
225 - goto close;  
226 - }  
227 -  
228 - for (i=0; i < UT_HOLDING_REGISTERS_NB_POINTS; i++) {  
229 - if (tab_rp_registers[i] != UT_HOLDING_REGISTERS_TAB[i]) {  
230 - printf("FAILED (%0X != %0X)\n",  
231 - tab_rp_registers[i],  
232 - UT_HOLDING_REGISTERS_TAB[i]);  
233 - goto close;  
234 - }  
235 - } 298 + else {
  299 + printf("FAILED\n");
  300 + goto close;
  301 + }
  302 +
  303 + rc = read_input_status(&mb_param, SERVER_ID,
  304 + UT_INPUT_STATUS_ADDRESS,
  305 + UT_INPUT_STATUS_NB_POINTS + 1,
  306 + tab_rp_status);
  307 + printf("* read_input_status: ");
  308 + if (rc == -1 && errno == EMBXILADD)
236 printf("OK\n"); 309 printf("OK\n");
237 - /* End of many registers */  
238 -  
239 -  
240 - /** INPUT REGISTERS **/  
241 - rc = read_input_registers(&mb_param, SERVER_ID,  
242 - UT_INPUT_REGISTERS_ADDRESS,  
243 - UT_INPUT_REGISTERS_NB_POINTS,  
244 - tab_rp_registers);  
245 - printf("1/1 read_input_registers: ");  
246 - if (rc != UT_INPUT_REGISTERS_NB_POINTS) {  
247 - printf("FAILED (nb points %d)\n", rc);  
248 - goto close;  
249 - }  
250 -  
251 - for (i=0; i < UT_INPUT_REGISTERS_NB_POINTS; i++) {  
252 - if (tab_rp_registers[i] != UT_INPUT_REGISTERS_TAB[i]) {  
253 - printf("FAILED (%0X != %0X)\n",  
254 - tab_rp_registers[i], UT_INPUT_REGISTERS_TAB[i]);  
255 - goto close;  
256 - }  
257 - } 310 + else {
  311 + printf("FAILED\n");
  312 + goto close;
  313 + }
  314 +
  315 + rc = read_holding_registers(&mb_param, SERVER_ID,
  316 + UT_HOLDING_REGISTERS_ADDRESS,
  317 + UT_HOLDING_REGISTERS_NB_POINTS + 1,
  318 + tab_rp_registers);
  319 + printf("* read_holding_registers: ");
  320 + if (rc == -1 && errno == EMBXILADD)
258 printf("OK\n"); 321 printf("OK\n");
259 -  
260 -  
261 - printf("\nTEST FLOATS\n");  
262 - /** FLOAT **/  
263 - printf("1/2 Write float: ");  
264 - modbus_write_float(UT_REAL, tab_rp_registers);  
265 - if (tab_rp_registers[1] == (UT_IREAL >> 16) &&  
266 - tab_rp_registers[0] == (UT_IREAL & 0xFFFF)) {  
267 - printf("OK\n");  
268 - } else {  
269 - printf("FAILED (%x != %x)\n",  
270 - *((uint32_t *)tab_rp_registers), UT_IREAL);  
271 - goto close;  
272 - }  
273 -  
274 - printf("2/2 Read float: ");  
275 - real = modbus_read_float(tab_rp_registers);  
276 - if (real == UT_REAL) {  
277 - printf("OK\n");  
278 - } else {  
279 - printf("FAILED (%f != %f)\n", real, UT_REAL);  
280 - goto close;  
281 - }  
282 -  
283 - printf("\nAt this point, error messages doesn't mean the test has failed\n");  
284 -  
285 - /** ILLEGAL DATA ADDRESS **/  
286 - printf("\nTEST ILLEGAL DATA ADDRESS:\n");  
287 -  
288 - /* The mapping begins at 0 and ending at address + nb_points so  
289 - * the addresses below are not valid. */  
290 -  
291 - rc = read_coil_status(&mb_param, SERVER_ID,  
292 - UT_COIL_STATUS_ADDRESS,  
293 - UT_COIL_STATUS_NB_POINTS + 1, 322 + else {
  323 + printf("FAILED\n");
  324 + goto close;
  325 + }
  326 +
  327 + rc = read_input_registers(&mb_param, SERVER_ID,
  328 + UT_INPUT_REGISTERS_ADDRESS,
  329 + UT_INPUT_REGISTERS_NB_POINTS + 1,
  330 + tab_rp_registers);
  331 + printf("* read_input_registers: ");
  332 + if (rc == -1 && errno == EMBXILADD)
  333 + printf("OK\n");
  334 + else {
  335 + printf("FAILED\n");
  336 + goto close;
  337 + }
  338 +
  339 + rc = force_single_coil(&mb_param, SERVER_ID,
  340 + UT_COIL_STATUS_ADDRESS + UT_COIL_STATUS_NB_POINTS,
  341 + ON);
  342 + printf("* force_single_coil: ");
  343 + if (rc == -1 && errno == EMBXILADD) {
  344 + printf("OK\n");
  345 + } else {
  346 + printf("FAILED\n");
  347 + goto close;
  348 + }
  349 +
  350 + rc = force_multiple_coils(&mb_param, SERVER_ID,
  351 + UT_COIL_STATUS_ADDRESS + UT_COIL_STATUS_NB_POINTS,
  352 + UT_COIL_STATUS_NB_POINTS,
294 tab_rp_status); 353 tab_rp_status);
295 - printf("* read_coil_status: ");  
296 - if (rc == -1 && errno == EMBXILADD)  
297 - printf("OK\n");  
298 - else {  
299 - printf("FAILED\n");  
300 - goto close;  
301 - }  
302 -  
303 - rc = read_input_status(&mb_param, SERVER_ID,  
304 - UT_INPUT_STATUS_ADDRESS,  
305 - UT_INPUT_STATUS_NB_POINTS + 1,  
306 - tab_rp_status);  
307 - printf("* read_input_status: ");  
308 - if (rc == -1 && errno == EMBXILADD)  
309 - printf("OK\n");  
310 - else {  
311 - printf("FAILED\n");  
312 - goto close;  
313 - }  
314 -  
315 - rc = read_holding_registers(&mb_param, SERVER_ID,  
316 - UT_HOLDING_REGISTERS_ADDRESS,  
317 - UT_HOLDING_REGISTERS_NB_POINTS + 1,  
318 - tab_rp_registers);  
319 - printf("* read_holding_registers: ");  
320 - if (rc == -1 && errno == EMBXILADD)  
321 - printf("OK\n");  
322 - else {  
323 - printf("FAILED\n");  
324 - goto close;  
325 - }  
326 -  
327 - rc = read_input_registers(&mb_param, SERVER_ID,  
328 - UT_INPUT_REGISTERS_ADDRESS,  
329 - UT_INPUT_REGISTERS_NB_POINTS + 1,  
330 - tab_rp_registers);  
331 - printf("* read_input_registers: ");  
332 - if (rc == -1 && errno == EMBXILADD)  
333 - printf("OK\n");  
334 - else {  
335 - printf("FAILED\n");  
336 - goto close;  
337 - }  
338 -  
339 - rc = force_single_coil(&mb_param, SERVER_ID,  
340 - UT_COIL_STATUS_ADDRESS + UT_COIL_STATUS_NB_POINTS,  
341 - ON);  
342 - printf("* force_single_coil: ");  
343 - if (rc == -1 && errno == EMBXILADD) {  
344 - printf("OK\n");  
345 - } else {  
346 - printf("FAILED\n");  
347 - goto close;  
348 - }  
349 -  
350 - rc = force_multiple_coils(&mb_param, SERVER_ID,  
351 - UT_COIL_STATUS_ADDRESS + UT_COIL_STATUS_NB_POINTS,  
352 - UT_COIL_STATUS_NB_POINTS,  
353 - tab_rp_status);  
354 - printf("* force_multiple_coils: ");  
355 - if (rc == -1 && errno == EMBXILADD) {  
356 - printf("OK\n");  
357 - } else {  
358 - printf("FAILED\n");  
359 - goto close;  
360 - } 354 + printf("* force_multiple_coils: ");
  355 + if (rc == -1 && errno == EMBXILADD) {
  356 + printf("OK\n");
  357 + } else {
  358 + printf("FAILED\n");
  359 + goto close;
  360 + }
  361 +
  362 + rc = preset_multiple_registers(&mb_param, SERVER_ID,
  363 + UT_HOLDING_REGISTERS_ADDRESS + UT_HOLDING_REGISTERS_NB_POINTS,
  364 + UT_HOLDING_REGISTERS_NB_POINTS,
  365 + tab_rp_registers);
  366 + printf("* preset_multiple_registers: ");
  367 + if (rc == -1 && errno == EMBXILADD) {
  368 + printf("OK\n");
  369 + } else {
  370 + printf("FAILED\n");
  371 + goto close;
  372 + }
361 373
362 - rc = preset_multiple_registers(&mb_param, SERVER_ID,  
363 - UT_HOLDING_REGISTERS_ADDRESS + UT_HOLDING_REGISTERS_NB_POINTS,  
364 - UT_HOLDING_REGISTERS_NB_POINTS,  
365 - tab_rp_registers);  
366 - printf("* preset_multiple_registers: ");  
367 - if (rc == -1 && errno == EMBXILADD) {  
368 - printf("OK\n");  
369 - } else {  
370 - printf("FAILED\n");  
371 - goto close;  
372 - }  
373 374
  375 + /** TOO MANY DATA **/
  376 + printf("\nTEST TOO MANY DATA ERROR:\n");
374 377
375 - /** TOO MANY DATA **/  
376 - printf("\nTEST TOO MANY DATA ERROR:\n"); 378 + rc = read_coil_status(&mb_param, SERVER_ID,
  379 + UT_COIL_STATUS_ADDRESS,
  380 + MAX_STATUS + 1,
  381 + tab_rp_status);
  382 + printf("* read_coil_status: ");
  383 + if (rc == -1 && errno == EMBMDATA) {
  384 + printf("OK\n");
  385 + } else {
  386 + printf("FAILED\n");
  387 + goto close;
  388 + }
  389 +
  390 + rc = read_input_status(&mb_param, SERVER_ID,
  391 + UT_INPUT_STATUS_ADDRESS,
  392 + MAX_STATUS + 1,
  393 + tab_rp_status);
  394 + printf("* read_input_status: ");
  395 + if (rc == -1 && errno == EMBMDATA) {
  396 + printf("OK\n");
  397 + } else {
  398 + printf("FAILED\n");
  399 + goto close;
  400 + }
  401 +
  402 + rc = read_holding_registers(&mb_param, SERVER_ID,
  403 + UT_HOLDING_REGISTERS_ADDRESS,
  404 + MAX_REGISTERS + 1,
  405 + tab_rp_registers);
  406 + printf("* read_holding_registers: ");
  407 + if (rc == -1 && errno == EMBMDATA) {
  408 + printf("OK\n");
  409 + } else {
  410 + printf("FAILED\n");
  411 + goto close;
  412 + }
  413 +
  414 + rc = read_input_registers(&mb_param, SERVER_ID,
  415 + UT_INPUT_REGISTERS_ADDRESS,
  416 + MAX_REGISTERS + 1,
  417 + tab_rp_registers);
  418 + printf("* read_input_registers: ");
  419 + if (rc == -1 && errno == EMBMDATA) {
  420 + printf("OK\n");
  421 + } else {
  422 + printf("FAILED\n");
  423 + goto close;
  424 + }
377 425
378 - rc = read_coil_status(&mb_param, SERVER_ID, 426 + rc = force_multiple_coils(&mb_param, SERVER_ID,
379 UT_COIL_STATUS_ADDRESS, 427 UT_COIL_STATUS_ADDRESS,
380 MAX_STATUS + 1, 428 MAX_STATUS + 1,
381 tab_rp_status); 429 tab_rp_status);
382 - printf("* read_coil_status: ");  
383 - if (rc == -1 && errno == EMBMDATA) {  
384 - printf("OK\n");  
385 - } else {  
386 - printf("FAILED\n");  
387 - goto close;  
388 - }  
389 -  
390 - rc = read_input_status(&mb_param, SERVER_ID,  
391 - UT_INPUT_STATUS_ADDRESS,  
392 - MAX_STATUS + 1,  
393 - tab_rp_status);  
394 - printf("* read_input_status: ");  
395 - if (rc == -1 && errno == EMBMDATA) {  
396 - printf("OK\n");  
397 - } else {  
398 - printf("FAILED\n");  
399 - goto close;  
400 - }  
401 -  
402 - rc = read_holding_registers(&mb_param, SERVER_ID,  
403 - UT_HOLDING_REGISTERS_ADDRESS,  
404 - MAX_REGISTERS + 1,  
405 - tab_rp_registers);  
406 - printf("* read_holding_registers: ");  
407 - if (rc == -1 && errno == EMBMDATA) {  
408 - printf("OK\n");  
409 - } else {  
410 - printf("FAILED\n");  
411 - goto close;  
412 - }  
413 -  
414 - rc = read_input_registers(&mb_param, SERVER_ID,  
415 - UT_INPUT_REGISTERS_ADDRESS,  
416 - MAX_REGISTERS + 1,  
417 - tab_rp_registers);  
418 - printf("* read_input_registers: ");  
419 - if (rc == -1 && errno == EMBMDATA) {  
420 - printf("OK\n");  
421 - } else {  
422 - printf("FAILED\n");  
423 - goto close;  
424 - }  
425 -  
426 - rc = force_multiple_coils(&mb_param, SERVER_ID,  
427 - UT_COIL_STATUS_ADDRESS,  
428 - MAX_STATUS + 1,  
429 - tab_rp_status);  
430 - printf("* force_multiple_coils: ");  
431 - if (rc == -1 && errno == EMBMDATA) {  
432 - printf("OK\n");  
433 - } else {  
434 - goto close;  
435 - printf("FAILED\n");  
436 - }  
437 -  
438 - rc = preset_multiple_registers(&mb_param, SERVER_ID,  
439 - UT_HOLDING_REGISTERS_ADDRESS,  
440 - MAX_REGISTERS + 1,  
441 - tab_rp_registers);  
442 - printf("* preset_multiple_registers: ");  
443 - if (rc == -1 && errno == EMBMDATA) {  
444 - printf("OK\n");  
445 - } else {  
446 - printf("FAILED\n");  
447 - goto close;  
448 - }  
449 -  
450 - /** SLAVE REPLY **/  
451 - printf("\nTEST SLAVE REPLY:\n");  
452 -  
453 - rc = read_holding_registers(&mb_param, 18,  
454 - UT_HOLDING_REGISTERS_ADDRESS,  
455 - UT_HOLDING_REGISTERS_NB_POINTS,  
456 - tab_rp_registers);  
457 - printf("1/3 No or response from slave %d: ", 18);  
458 - if (mb_param.type_com == RTU) {  
459 - /* No response in RTU mode */  
460 - if (rc == -1 && errno == ETIMEDOUT) {  
461 - printf("OK\n");  
462 - } else {  
463 - printf("FAILED\n");  
464 - goto close;  
465 - } 430 + printf("* force_multiple_coils: ");
  431 + if (rc == -1 && errno == EMBMDATA) {
  432 + printf("OK\n");
  433 + } else {
  434 + goto close;
  435 + printf("FAILED\n");
  436 + }
  437 +
  438 + rc = preset_multiple_registers(&mb_param, SERVER_ID,
  439 + UT_HOLDING_REGISTERS_ADDRESS,
  440 + MAX_REGISTERS + 1,
  441 + tab_rp_registers);
  442 + printf("* preset_multiple_registers: ");
  443 + if (rc == -1 && errno == EMBMDATA) {
  444 + printf("OK\n");
  445 + } else {
  446 + printf("FAILED\n");
  447 + goto close;
  448 + }
  449 +
  450 + /** SLAVE REPLY **/
  451 + printf("\nTEST SLAVE REPLY:\n");
  452 +
  453 + rc = read_holding_registers(&mb_param, 18,
  454 + UT_HOLDING_REGISTERS_ADDRESS,
  455 + UT_HOLDING_REGISTERS_NB_POINTS,
  456 + tab_rp_registers);
  457 + printf("1/3 No or response from slave %d: ", 18);
  458 + if (mb_param.type_com == RTU) {
  459 + /* No response in RTU mode */
  460 + if (rc == -1 && errno == ETIMEDOUT) {
  461 + printf("OK\n");
466 } else { 462 } else {
467 - /* Response in TCP mode */  
468 - if (rc == UT_HOLDING_REGISTERS_NB_POINTS) {  
469 - printf("OK\n");  
470 - } else {  
471 - printf("FAILED\n");  
472 - goto close;  
473 - } 463 + printf("FAILED\n");
  464 + goto close;
474 } 465 }
475 -  
476 - rc = read_holding_registers(&mb_param, MODBUS_BROADCAST_ADDRESS,  
477 - UT_HOLDING_REGISTERS_ADDRESS,  
478 - UT_HOLDING_REGISTERS_NB_POINTS,  
479 - tab_rp_registers);  
480 - printf("2/3 Reply after a broadcast query: "); 466 + } else {
  467 + /* Response in TCP mode */
481 if (rc == UT_HOLDING_REGISTERS_NB_POINTS) { 468 if (rc == UT_HOLDING_REGISTERS_NB_POINTS) {
482 - printf("OK\n");  
483 - } else {  
484 - printf("FAILED\n");  
485 - goto close;  
486 - }  
487 -  
488 - /* Save original timeout */  
489 - modbus_get_timeout_begin(&mb_param, &timeout_begin_old);  
490 -  
491 - /* Define a new and too short timeout */  
492 - timeout_begin_new.tv_sec = 0;  
493 - timeout_begin_new.tv_usec = 0;  
494 - modbus_set_timeout_begin(&mb_param, &timeout_begin_new);  
495 -  
496 - rc = read_holding_registers(&mb_param, SERVER_ID,  
497 - UT_HOLDING_REGISTERS_ADDRESS,  
498 - UT_HOLDING_REGISTERS_NB_POINTS,  
499 - tab_rp_registers);  
500 - printf("3/3 Too short timeout: ");  
501 - if (rc == -1 && errno == ETIMEDOUT) {  
502 - printf("OK\n"); 469 + printf("OK\n");
503 } else { 470 } else {
504 - printf("FAILED\n");  
505 - goto close; 471 + printf("FAILED\n");
  472 + goto close;
506 } 473 }
  474 + }
507 475
508 - /* Restore original timeout */  
509 - modbus_set_timeout_begin(&mb_param, &timeout_begin_old);  
510 -  
511 - /** BAD RESPONSE **/  
512 - printf("\nTEST BAD RESPONSE ERROR:\n");  
513 -  
514 - /* Allocate only the required space */  
515 - tab_rp_registers_bad = (uint16_t *) malloc(  
516 - UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL * sizeof(uint16_t));  
517 - rc = read_holding_registers(&mb_param, SERVER_ID,  
518 - UT_HOLDING_REGISTERS_ADDRESS,  
519 - UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL,  
520 - tab_rp_registers_bad);  
521 - printf("* read_holding_registers: ");  
522 - if (rc == -1 && errno == EMBBADDATA) {  
523 - printf("OK\n");  
524 - } else {  
525 - printf("FAILED\n");  
526 - goto close;  
527 - }  
528 - free(tab_rp_registers_bad); 476 + rc = read_holding_registers(&mb_param, MODBUS_BROADCAST_ADDRESS,
  477 + UT_HOLDING_REGISTERS_ADDRESS,
  478 + UT_HOLDING_REGISTERS_NB_POINTS,
  479 + tab_rp_registers);
  480 + printf("2/3 Reply after a broadcast query: ");
  481 + if (rc == UT_HOLDING_REGISTERS_NB_POINTS) {
  482 + printf("OK\n");
  483 + } else {
  484 + printf("FAILED\n");
  485 + goto close;
  486 + }
  487 +
  488 + /* Save original timeout */
  489 + modbus_get_timeout_begin(&mb_param, &timeout_begin_old);
  490 +
  491 + /* Define a new and too short timeout */
  492 + timeout_begin_new.tv_sec = 0;
  493 + timeout_begin_new.tv_usec = 0;
  494 + modbus_set_timeout_begin(&mb_param, &timeout_begin_new);
  495 +
  496 + rc = read_holding_registers(&mb_param, SERVER_ID,
  497 + UT_HOLDING_REGISTERS_ADDRESS,
  498 + UT_HOLDING_REGISTERS_NB_POINTS,
  499 + tab_rp_registers);
  500 + printf("3/3 Too short timeout: ");
  501 + if (rc == -1 && errno == ETIMEDOUT) {
  502 + printf("OK\n");
  503 + } else {
  504 + printf("FAILED\n");
  505 + goto close;
  506 + }
  507 +
  508 + /* Restore original timeout */
  509 + modbus_set_timeout_begin(&mb_param, &timeout_begin_old);
  510 +
  511 + /** BAD RESPONSE **/
  512 + printf("\nTEST BAD RESPONSE ERROR:\n");
  513 +
  514 + /* Allocate only the required space */
  515 + tab_rp_registers_bad = (uint16_t *) malloc(
  516 + UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL * sizeof(uint16_t));
  517 + rc = read_holding_registers(&mb_param, SERVER_ID,
  518 + UT_HOLDING_REGISTERS_ADDRESS,
  519 + UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL,
  520 + tab_rp_registers_bad);
  521 + printf("* read_holding_registers: ");
  522 + if (rc == -1 && errno == EMBBADDATA) {
  523 + printf("OK\n");
  524 + } else {
  525 + printf("FAILED\n");
  526 + goto close;
  527 + }
  528 + free(tab_rp_registers_bad);
529 529
530 - printf("\nALL TESTS PASS WITH SUCCESS.\n"); 530 + printf("\nALL TESTS PASS WITH SUCCESS.\n");
531 531
532 close: 532 close:
533 - /* Free the memory */  
534 - free(tab_rp_status);  
535 - free(tab_rp_registers); 533 + /* Free the memory */
  534 + free(tab_rp_status);
  535 + free(tab_rp_registers);
536 536
537 - /* Close the connection */  
538 - modbus_close(&mb_param); 537 + /* Close the connection */
  538 + modbus_close(&mb_param);
539 539
540 - return 0; 540 + return 0;
541 } 541 }
tests/unit-test-slave.c
@@ -26,72 +26,72 @@ @@ -26,72 +26,72 @@
26 26
27 int main(void) 27 int main(void)
28 { 28 {
29 - int socket;  
30 - modbus_param_t mb_param;  
31 - modbus_mapping_t mb_mapping;  
32 - int rc;  
33 - int i; 29 + int socket;
  30 + modbus_param_t mb_param;
  31 + modbus_mapping_t mb_mapping;
  32 + int rc;
  33 + int i;
34 34
35 - modbus_init_tcp(&mb_param, "127.0.0.1", 1502);  
36 - modbus_set_debug(&mb_param, TRUE);  
37 - modbus_set_error_recovery(&mb_param, TRUE); 35 + modbus_init_tcp(&mb_param, "127.0.0.1", 1502);
  36 + modbus_set_debug(&mb_param, TRUE);
  37 + modbus_set_error_recovery(&mb_param, TRUE);
38 38
39 - rc = modbus_mapping_new(&mb_mapping,  
40 - UT_COIL_STATUS_ADDRESS + UT_COIL_STATUS_NB_POINTS,  
41 - UT_INPUT_STATUS_ADDRESS + UT_INPUT_STATUS_NB_POINTS,  
42 - UT_HOLDING_REGISTERS_ADDRESS + UT_HOLDING_REGISTERS_NB_POINTS,  
43 - UT_INPUT_REGISTERS_ADDRESS + UT_INPUT_REGISTERS_NB_POINTS);  
44 - if (rc == -1) {  
45 - fprintf(stderr, "Failed to allocate the mapping: %s\n",  
46 - modbus_strerror(errno));  
47 - return -1;  
48 - } 39 + rc = modbus_mapping_new(&mb_mapping,
  40 + UT_COIL_STATUS_ADDRESS + UT_COIL_STATUS_NB_POINTS,
  41 + UT_INPUT_STATUS_ADDRESS + UT_INPUT_STATUS_NB_POINTS,
  42 + UT_HOLDING_REGISTERS_ADDRESS + UT_HOLDING_REGISTERS_NB_POINTS,
  43 + UT_INPUT_REGISTERS_ADDRESS + UT_INPUT_REGISTERS_NB_POINTS);
  44 + if (rc == -1) {
  45 + fprintf(stderr, "Failed to allocate the mapping: %s\n",
  46 + modbus_strerror(errno));
  47 + return -1;
  48 + }
49 49
50 - /* Examples from PI_MODBUS_300.pdf.  
51 - Only the read-only input values are assigned. */ 50 + /* Examples from PI_MODBUS_300.pdf.
  51 + Only the read-only input values are assigned. */
52 52
53 - /** INPUT STATUS **/  
54 - set_bits_from_bytes(mb_mapping.tab_input_status,  
55 - UT_INPUT_STATUS_ADDRESS, UT_INPUT_STATUS_NB_POINTS,  
56 - UT_INPUT_STATUS_TAB); 53 + /** INPUT STATUS **/
  54 + set_bits_from_bytes(mb_mapping.tab_input_status,
  55 + UT_INPUT_STATUS_ADDRESS, UT_INPUT_STATUS_NB_POINTS,
  56 + UT_INPUT_STATUS_TAB);
57 57
58 - /** INPUT REGISTERS **/  
59 - for (i=0; i < UT_INPUT_REGISTERS_NB_POINTS; i++) {  
60 - mb_mapping.tab_input_registers[UT_INPUT_REGISTERS_ADDRESS+i] =  
61 - UT_INPUT_REGISTERS_TAB[i];;  
62 - } 58 + /** INPUT REGISTERS **/
  59 + for (i=0; i < UT_INPUT_REGISTERS_NB_POINTS; i++) {
  60 + mb_mapping.tab_input_registers[UT_INPUT_REGISTERS_ADDRESS+i] =
  61 + UT_INPUT_REGISTERS_TAB[i];;
  62 + }
63 63
64 - socket = modbus_slave_listen_tcp(&mb_param, 1);  
65 - modbus_slave_accept_tcp(&mb_param, &socket); 64 + socket = modbus_slave_listen_tcp(&mb_param, 1);
  65 + modbus_slave_accept_tcp(&mb_param, &socket);
66 66
67 - for (;;) {  
68 - uint8_t query[MAX_MESSAGE_LENGTH]; 67 + for (;;) {
  68 + uint8_t query[MAX_MESSAGE_LENGTH];
69 69
70 - rc = modbus_slave_receive(&mb_param, -1, query);  
71 - if (rc > 0) {  
72 - if (((query[HEADER_LENGTH_TCP + 3] << 8) + query[HEADER_LENGTH_TCP + 4])  
73 - == UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL) {  
74 - /* Change the number of values (offset  
75 - TCP = 6) */  
76 - query[HEADER_LENGTH_TCP + 3] = 0;  
77 - query[HEADER_LENGTH_TCP + 4] = UT_HOLDING_REGISTERS_NB_POINTS;  
78 - } 70 + rc = modbus_slave_receive(&mb_param, -1, query);
  71 + if (rc > 0) {
  72 + if (((query[HEADER_LENGTH_TCP + 3] << 8) + query[HEADER_LENGTH_TCP + 4])
  73 + == UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL) {
  74 + /* Change the number of values (offset
  75 + TCP = 6) */
  76 + query[HEADER_LENGTH_TCP + 3] = 0;
  77 + query[HEADER_LENGTH_TCP + 4] = UT_HOLDING_REGISTERS_NB_POINTS;
  78 + }
79 79
80 - rc = modbus_slave_manage(&mb_param, query, rc, &mb_mapping);  
81 - if (rc == -1) {  
82 - return -1;  
83 - }  
84 - } else {  
85 - /* Connection closed by the client or error */  
86 - break;  
87 - } 80 + rc = modbus_slave_manage(&mb_param, query, rc, &mb_mapping);
  81 + if (rc == -1) {
  82 + return -1;
  83 + }
  84 + } else {
  85 + /* Connection closed by the client or error */
  86 + break;
88 } 87 }
  88 + }
89 89
90 - printf("Quit the loop: %s\n", modbus_strerror(errno)); 90 + printf("Quit the loop: %s\n", modbus_strerror(errno));
91 91
92 - close(socket);  
93 - modbus_mapping_free(&mb_mapping);  
94 - modbus_close(&mb_param); 92 + close(socket);
  93 + modbus_mapping_free(&mb_mapping);
  94 + modbus_close(&mb_param);
95 95
96 - return 0; 96 + return 0;
97 } 97 }
tests/version.c
@@ -20,12 +20,12 @@ @@ -20,12 +20,12 @@
20 20
21 int main(void) 21 int main(void)
22 { 22 {
23 - printf("Compiled with libmodbus version %s\n", LIBMODBUS_VERSION_STRING);  
24 - printf("Linked with libmodbus version %d.%d.%d\n",  
25 - libmodbus_version_major, libmodbus_version_minor, libmodbus_version_micro); 23 + printf("Compiled with libmodbus version %s\n", LIBMODBUS_VERSION_STRING);
  24 + printf("Linked with libmodbus version %d.%d.%d\n",
  25 + libmodbus_version_major, libmodbus_version_minor, libmodbus_version_micro);
26 26
27 - if (LIBMODBUS_VERSION_CHECK(2, 1, 0)) {  
28 - printf("The functions to read/write float values are available.\n");  
29 - }  
30 - return 0; 27 + if (LIBMODBUS_VERSION_CHECK(2, 1, 0)) {
  28 + printf("The functions to read/write float values are available.\n");
  29 + }
  30 + return 0;
31 } 31 }