Commit d3aecacf6ff34a7378153e8384346a43f288773c

Authored by Stéphane Raimbault
1 parent 741022ce

Major changes - Added slave functions (not finished)

- (error_treat): used string instead of message
- added a define for each function code supported
- added compute_query_size_header/data functions to read messages
- added new function manage_query to manage queries and send the right
  response
- s/receive_response/receive_msg/
- major changes to receive_msg to handle query
- changed return value of check_crc16
- added response_io_status
- comments
- added functions to allocate/free a modbus mapping
Showing 2 changed files with 565 additions and 230 deletions
src/modbus.c
1 /* 1 /*
2 - Copyright (C) 2001-2005 Stéphane Raimbault <stephane.raimbault@free.fr> 2 + Copyright (C) 2001-2007 Stéphane Raimbault <stephane.raimbault@gmail.com>
3 3
4 This library is free software; you can redistribute it and/or 4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public 5 modify it under the terms of the GNU Lesser General Public
@@ -126,11 +126,12 @@ static int read_reg_response(modbus_param_t *mb_param, @@ -126,11 +126,12 @@ static int read_reg_response(modbus_param_t *mb_param,
126 int *data_dest, 126 int *data_dest,
127 unsigned char *query); 127 unsigned char *query);
128 128
129 -static void error_treat(int ret, const char *message, modbus_param_t *mb_param) 129 +/* Treats errors and flush or close connection if necessary */
  130 +static void error_treat(int ret, const char *string, modbus_param_t *mb_param)
130 { 131 {
131 if (ret == -1) 132 if (ret == -1)
132 - perror(message);  
133 - g_print("\n\nERROR %s\n\n", message); 133 + perror(string);
  134 + g_print("\n\nERROR %s\n\n", string);
134 135
135 if (mb_param->type_com == RTU) { 136 if (mb_param->type_com == RTU) {
136 tcflush(mb_param->fd, TCIOFLUSH); 137 tcflush(mb_param->fd, TCIOFLUSH);
@@ -140,6 +141,7 @@ static void error_treat(int ret, const char *message, modbus_param_t *mb_param) @@ -140,6 +141,7 @@ static void error_treat(int ret, const char *message, modbus_param_t *mb_param)
140 } 141 }
141 } 142 }
142 143
  144 +/* Computes the size of the expected response */
143 static unsigned int compute_response_size(modbus_param_t *mb_param, 145 static unsigned int compute_response_size(modbus_param_t *mb_param,
144 unsigned char *query) 146 unsigned char *query)
145 { 147 {
@@ -149,18 +151,21 @@ static unsigned int compute_response_size(modbus_param_t *mb_param, @@ -149,18 +151,21 @@ static unsigned int compute_response_size(modbus_param_t *mb_param,
149 offset = mb_param->header_length; 151 offset = mb_param->header_length;
150 152
151 switch (query[offset + 1]) { 153 switch (query[offset + 1]) {
152 - case 0x01: { 154 + case FC_READ_COIL_STATUS:
  155 + case FC_READ_INPUT_STATUS: {
153 /* Header + nb values (code from force_multiple_coils) */ 156 /* Header + nb values (code from force_multiple_coils) */
154 int coil_count = (query[offset + 4] << 8) | query[offset + 5]; 157 int coil_count = (query[offset + 4] << 8) | query[offset + 5];
155 response_size_computed = 3 + 158 response_size_computed = 3 +
156 (coil_count / 8) + ((coil_count % 8) ? 1 : 0); 159 (coil_count / 8) + ((coil_count % 8) ? 1 : 0);
157 - } break;  
158 - case 0x03: 160 + }
  161 + break;
  162 + case FC_READ_HOLDING_REGISTERS:
  163 + case FC_READ_INPUT_REGISTERS:
159 /* Header + 2 * nb values */ 164 /* Header + 2 * nb values */
160 response_size_computed = 3 + 165 response_size_computed = 3 +
161 2 * (query[offset + 4] << 8 | query[offset + 5]); 166 2 * (query[offset + 4] << 8 | query[offset + 5]);
162 break; 167 break;
163 - case 0x07: 168 + case FC_READ_EXCEPTION_STATUS:
164 response_size_computed = 4; 169 response_size_computed = 4;
165 break; 170 break;
166 default: 171 default:
@@ -172,10 +177,9 @@ static unsigned int compute_response_size(modbus_param_t *mb_param, @@ -172,10 +177,9 @@ static unsigned int compute_response_size(modbus_param_t *mb_param,
172 return response_size_computed; 177 return response_size_computed;
173 } 178 }
174 179
175 -/* The following functions construct the required query into  
176 - a modbus query packet */  
177 -int build_request_packet_rtu(int slave, int function, int start_addr,  
178 - int count, unsigned char *packet) 180 +/* Buils a RTU header */
  181 +int build_query_packet_rtu(int slave, int function, int start_addr,
  182 + int count, unsigned char *packet)
179 { 183 {
180 packet[0] = slave; 184 packet[0] = slave;
181 packet[1] = function; 185 packet[1] = function;
@@ -187,8 +191,9 @@ int build_request_packet_rtu(int slave, int function, int start_addr, @@ -187,8 +191,9 @@ int build_request_packet_rtu(int slave, int function, int start_addr,
187 return PRESET_QUERY_SIZE_RTU; 191 return PRESET_QUERY_SIZE_RTU;
188 } 192 }
189 193
190 -int build_request_packet_tcp(int slave, int function, int start_addr,  
191 - int count, unsigned char *packet) 194 +/* Builds a TCP header */
  195 +int build_query_packet_tcp(int slave, int function, int start_addr,
  196 + int count, unsigned char *packet)
192 { 197 {
193 static unsigned short t_id = 0; 198 static unsigned short t_id = 0;
194 199
@@ -206,7 +211,7 @@ int build_request_packet_tcp(int slave, int function, int start_addr, @@ -206,7 +211,7 @@ int build_request_packet_tcp(int slave, int function, int start_addr,
206 211
207 /* Length to fix later with set_packet_length_tcp (4 and 5) */ 212 /* Length to fix later with set_packet_length_tcp (4 and 5) */
208 213
209 - packet[6] = 0xFF; 214 + packet[6] = slave;
210 packet[7] = function; 215 packet[7] = function;
211 packet[8] = start_addr >> 8; 216 packet[8] = start_addr >> 8;
212 packet[9] = start_addr & 0x00ff; 217 packet[9] = start_addr & 0x00ff;
@@ -216,6 +221,66 @@ int build_request_packet_tcp(int slave, int function, int start_addr, @@ -216,6 +221,66 @@ int build_request_packet_tcp(int slave, int function, int start_addr,
216 return PRESET_QUERY_SIZE_TCP; 221 return PRESET_QUERY_SIZE_TCP;
217 } 222 }
218 223
  224 +int build_query_packet(modbus_param_t *mb_param, int slave,
  225 + int function, int start_addr,
  226 + int count, unsigned char *packet)
  227 +{
  228 + if (mb_param->type_com == RTU)
  229 + return build_query_packet_rtu(slave, function, start_addr,
  230 + count, packet);
  231 + else
  232 + return build_query_packet_tcp(slave, function, start_addr,
  233 + count, packet);
  234 +}
  235 +
  236 +
  237 +int build_response_packet_rtu(int slave, int function, int byte_count, unsigned char *packet)
  238 +{
  239 + packet[0] = slave;
  240 + packet[1] = function;
  241 + packet[2] = byte_count;
  242 +
  243 + /* FIXME +1 */
  244 + return PRESET_RESPONSE_SIZE_RTU+1;
  245 +}
  246 +
  247 +int build_response_packet_tcp(int slave, int function, int byte_count, unsigned char *packet)
  248 +{
  249 + static unsigned short t_id = 0;
  250 +
  251 + /* Transaction ID */
  252 + if (t_id < USHRT_MAX)
  253 + t_id++;
  254 + else
  255 + t_id = 0;
  256 + packet[0] = t_id >> 8;
  257 + packet[1] = t_id & 0x00ff;
  258 +
  259 + /* Protocol Modbus */
  260 + packet[2] = 0;
  261 + packet[3] = 0;
  262 +
  263 + /* Length to fix later with set_packet_length_tcp (4 and 5) */
  264 +
  265 + packet[6] = slave;
  266 + packet[7] = function;
  267 +
  268 + packet[8] = byte_count;
  269 +
  270 + /* FIXME +1 */
  271 + return PRESET_RESPONSE_SIZE_TCP+1;
  272 +}
  273 +
  274 +int build_response_packet(modbus_param_t *mb_param, int slave,
  275 + int function, int byte_count, unsigned char *packet)
  276 +{
  277 + if (mb_param->type_com == RTU)
  278 + return build_response_packet_rtu(slave, function, byte_count, packet);
  279 + else
  280 + return build_response_packet_tcp(slave, function, byte_count, packet);
  281 +}
  282 +
  283 +/* Sets the length of TCP message in the message */
219 void set_packet_length_tcp(unsigned char *packet, size_t packet_size) 284 void set_packet_length_tcp(unsigned char *packet, size_t packet_size)
220 { 285 {
221 unsigned short mbap_length; 286 unsigned short mbap_length;
@@ -227,18 +292,6 @@ void set_packet_length_tcp(unsigned char *packet, size_t packet_size) @@ -227,18 +292,6 @@ void set_packet_length_tcp(unsigned char *packet, size_t packet_size)
227 packet[5] = mbap_length & 0x00FF; 292 packet[5] = mbap_length & 0x00FF;
228 } 293 }
229 294
230 -int build_request_packet(modbus_param_t *mb_param, int slave,  
231 - int function, int start_addr,  
232 - int count, unsigned char *packet)  
233 -{  
234 - if (mb_param->type_com == RTU)  
235 - return build_request_packet_rtu(slave, function, start_addr,  
236 - count, packet);  
237 - else  
238 - return build_request_packet_tcp(slave, function, start_addr,  
239 - count, packet);  
240 -}  
241 -  
242 /* Fast CRC */ 295 /* Fast CRC */
243 static unsigned short crc16(unsigned char *buffer, 296 static unsigned short crc16(unsigned char *buffer,
244 unsigned short buffer_length) 297 unsigned short buffer_length)
@@ -257,9 +310,51 @@ static unsigned short crc16(unsigned char *buffer, @@ -257,9 +310,51 @@ static unsigned short crc16(unsigned char *buffer,
257 return (crc_hi << 8 | crc_lo); 310 return (crc_hi << 8 | crc_lo);
258 } 311 }
259 312
260 -/* Function to send a query out to a modbus slave */  
261 -static int modbus_query(modbus_param_t *mb_param, unsigned char *query,  
262 - size_t query_size) 313 +/* If CRC is correct returns 0 else returns INVALID_CRC */
  314 +int check_crc16(modbus_param_t *mb_param,
  315 + unsigned char *msg,
  316 + int msg_size)
  317 +{
  318 + int ret;
  319 +
  320 + if (mb_param->type_com == RTU) {
  321 + unsigned short crc_calc;
  322 + unsigned short crc_received;
  323 + unsigned char recv_crc_hi;
  324 + unsigned char recv_crc_lo;
  325 +
  326 + crc_calc = crc16(msg, msg_size - 2);
  327 +
  328 + recv_crc_hi = msg[msg_size - 2];
  329 + recv_crc_lo = msg[msg_size - 1];
  330 +
  331 + crc_received = msg[msg_size - 2];
  332 + crc_received = crc_received << 8;
  333 + crc_received = crc_received | msg[msg_size - 1];
  334 +
  335 + /* Check CRC of msg */
  336 + if (crc_calc == crc_received) {
  337 + ret = 0;
  338 + } else {
  339 + char *s_error;
  340 + s_error = g_strdup_printf(
  341 + "invalid crc received %0X - crc_calc %0X",
  342 + crc_received, crc_calc);
  343 + error_treat(0, s_error, mb_param);
  344 + g_free(s_error);
  345 + ret = INVALID_CRC;
  346 + }
  347 + } else {
  348 + /* In TCP, the modbus CRC is not present (see HDLC level) */
  349 + ret = 0;
  350 + }
  351 +
  352 + return ret;
  353 +}
  354 +
  355 +/* Sends a query/response over a serial or a TCP communication */
  356 +static int modbus_send(modbus_param_t *mb_param, unsigned char *query,
  357 + size_t query_size)
263 { 358 {
264 int write_ret; 359 int write_ret;
265 unsigned short s_crc; 360 unsigned short s_crc;
@@ -296,6 +391,44 @@ static int modbus_query(modbus_param_t *mb_param, unsigned char *query, @@ -296,6 +391,44 @@ static int modbus_query(modbus_param_t *mb_param, unsigned char *query,
296 return write_ret; 391 return write_ret;
297 } 392 }
298 393
  394 +/* Computes the size of the header following the function code */
  395 +int compute_query_size_header(int function)
  396 +{
  397 + int byte;
  398 +
  399 + if (function <= FC_FORCE_SINGLE_COIL)
  400 + /* Read and single write */
  401 + byte = 4;
  402 + else if (function == FC_FORCE_MULTIPLE_COILS ||
  403 + function == FC_PRESET_MULTIPLE_REGISTERS)
  404 + /* Multiple write */
  405 + byte = 5;
  406 + else
  407 + byte = 0;
  408 +
  409 + g_print("compute_query_size_header FC %d, B%d\n", function, byte);
  410 +
  411 + return byte;
  412 +}
  413 +
  414 +/* Computes the size of the data to write in the query */
  415 +int compute_query_size_data(modbus_param_t *mb_param, unsigned char *msg)
  416 +{
  417 + int function = msg[mb_param->header_length + 1];
  418 + int byte;
  419 +
  420 + if (function == FC_FORCE_MULTIPLE_COILS ||
  421 + function == FC_PRESET_MULTIPLE_REGISTERS)
  422 + byte = msg[mb_param->header_length + 6];
  423 + else
  424 + byte = 0;
  425 +
  426 + byte += mb_param->checksum_size;
  427 + g_print("compute_query_size_data FC %d, B %d\n", function, byte);
  428 +
  429 + return byte;
  430 +}
  431 +
299 #define WAIT_DATA() \ 432 #define WAIT_DATA() \
300 { \ 433 { \
301 while ((select_ret = select(mb_param->fd+1, &rfds, NULL, NULL, &tv)) == -1) { \ 434 while ((select_ret = select(mb_param->fd+1, &rfds, NULL, NULL, &tv)) == -1) { \
@@ -316,77 +449,119 @@ static int modbus_query(modbus_param_t *mb_param, unsigned char *query, @@ -316,77 +449,119 @@ static int modbus_query(modbus_param_t *mb_param, unsigned char *query,
316 } \ 449 } \
317 } 450 }
318 451
319 -/* Function to monitor for the reply from the modbus slave. 452 +/* Monitors for the reply from the modbus slave or to receive query
  453 + from a modbus master.
320 This function blocks for timeout seconds if there is no reply. 454 This function blocks for timeout seconds if there is no reply.
321 455
  456 + msg_size_computed must be set to MSG_SIZE_COMPUTED if undefined
  457 +
322 Returns: 458 Returns:
323 - - error_code 0 == OK, < 0 == error  
324 - - (arg) total number of characters received.  
325 -*/  
326 -int receive_response(modbus_param_t *mb_param,  
327 - int response_size_computed,  
328 - unsigned char *response,  
329 - int *response_size) 459 + - 0: OK, <0: error
  460 + - msg_size: number of characters received. */
  461 +int receive_msg(modbus_param_t *mb_param,
  462 + int msg_size_computed,
  463 + unsigned char *msg,
  464 + int *msg_size)
330 { 465 {
331 int select_ret; 466 int select_ret;
332 int read_ret; 467 int read_ret;
333 fd_set rfds; 468 fd_set rfds;
334 struct timeval tv; 469 struct timeval tv;
335 int size_to_read; 470 int size_to_read;
336 - unsigned char *p_response; 471 + unsigned char *p_msg;
  472 + enum { FUNCTION, BYTE, COMPLETE };
  473 + int state;
337 474
338 - if (mb_param->debug)  
339 - g_print("Waiting for response (%d)...\n", response_size_computed); 475 + if (mb_param->debug) {
  476 + if (msg_size_computed == MSG_SIZE_UNDEFINED)
  477 + g_print("Waiting for a message...\n");
  478 + else
  479 + g_print("Waiting for a message (%d bytes)...\n", msg_size_computed);
  480 + }
340 481
341 /* Add a file descriptor to the set */ 482 /* Add a file descriptor to the set */
342 FD_ZERO(&rfds); 483 FD_ZERO(&rfds);
343 FD_SET(mb_param->fd, &rfds); 484 FD_SET(mb_param->fd, &rfds);
344 -  
345 - /* Wait for a response */  
346 - tv.tv_sec = 0;  
347 - tv.tv_usec = TIME_OUT_BEGIN_OF_TRAME;  
348 485
  486 + if (msg_size_computed == MSG_SIZE_UNDEFINED) {
  487 + /* Wait for a message */
  488 + tv.tv_sec = 60;
  489 + tv.tv_usec = 0;
  490 +
  491 + /* The message size is undefined (query receiving) so
  492 + * we need to analyse the message step by step.
  493 + * In the first step, we want to reach the function code */
  494 + msg_size_computed = mb_param->header_length + 2;
  495 + state = FUNCTION;
  496 + } else {
  497 + tv.tv_sec = 0;
  498 + tv.tv_usec = TIME_OUT_BEGIN_OF_TRAME;
  499 + state = COMPLETE;
  500 + }
  501 +
  502 + size_to_read = msg_size_computed;
349 WAIT_DATA(); 503 WAIT_DATA();
350 504
351 - /* Read the trame */  
352 - (*response_size) = 0;  
353 - size_to_read = response_size_computed;  
354 - p_response = response; 505 + /* Read the msg */
  506 + (*msg_size) = 0;
  507 + p_msg = msg;
355 508
356 while (select_ret) { 509 while (select_ret) {
357 if (mb_param->type_com == RTU) 510 if (mb_param->type_com == RTU)
358 - read_ret = read(mb_param->fd, p_response, size_to_read); 511 + read_ret = read(mb_param->fd, p_msg, size_to_read);
359 else 512 else
360 - read_ret = recv(mb_param->fd, p_response, size_to_read, 0); 513 + read_ret = recv(mb_param->fd, p_msg, size_to_read, 0);
361 514
362 if (read_ret == -1) { 515 if (read_ret == -1) {
363 error_treat(read_ret, "Read port/socket failure", mb_param); 516 error_treat(read_ret, "Read port/socket failure", mb_param);
364 return PORT_SOCKET_FAILURE; 517 return PORT_SOCKET_FAILURE;
365 - } else {  
366 - /* Sums bytes received */  
367 - (*response_size) += read_ret; 518 + }
368 519
369 - /* Display the hex code of each  
370 - * character received */  
371 - if (mb_param->debug) {  
372 - int i;  
373 - for (i=0; i < read_ret; i++)  
374 - g_print("<%.2X>", p_response[i]);  
375 - }  
376 - /* Moves the pointer to receive other datas */  
377 - p_response = &(p_response[read_ret]);  
378 - size_to_read = response_size_computed - (*response_size); 520 + /* Sums bytes received */
  521 + (*msg_size) += read_ret;
  522 + if ((*msg_size) > MAX_PACKET_SIZE) {
  523 + error_treat(0, "Too many datas", mb_param);
  524 + return TOO_MANY_DATAS;
  525 + }
  526 +
  527 + /* Display the hex code of each character received */
  528 + if (mb_param->debug) {
  529 + int i;
  530 + for (i=0; i < read_ret; i++)
  531 + g_print("<%.2X>", p_msg[i]);
  532 + }
379 533
380 - if ((*response_size) > MAX_PACKET_SIZE) {  
381 - error_treat(0, "Too many datas", mb_param);  
382 - return TOO_MANY_DATAS; 534 + if ((*msg_size) < msg_size_computed) {
  535 + /* Message incomplete */
  536 + size_to_read = msg_size_computed - (*msg_size);
  537 + } else {
  538 + switch (state) {
  539 + case FUNCTION:
  540 + /* Function code position */
  541 + size_to_read = compute_query_size_header(msg[mb_param->header_length + 1]);
  542 + msg_size_computed += size_to_read;
  543 + state = BYTE;
  544 + g_print("\nBYTE:");
  545 + break;
  546 + case BYTE:
  547 + size_to_read = compute_query_size_data(mb_param, msg);
  548 + msg_size_computed += size_to_read;
  549 + state = COMPLETE;
  550 + g_print("\nCOMPLETE:");
  551 + break;
  552 + case COMPLETE:
  553 + size_to_read = 0;
  554 + break;
383 } 555 }
384 } 556 }
  557 + g_print(" size to read %d\n", size_to_read);
  558 +
  559 + /* Moves the pointer to receive other datas */
  560 + p_msg = &(p_msg[read_ret]);
385 561
386 if (size_to_read > 0) { 562 if (size_to_read > 0) {
387 /* If no character at the buffer wait 563 /* If no character at the buffer wait
388 - TIME_OUT_END_OF_TRAME before to generate an error.  
389 - */ 564 + TIME_OUT_END_OF_TRAME before to generate an error. */
390 tv.tv_sec = 0; 565 tv.tv_sec = 0;
391 tv.tv_usec = TIME_OUT_END_OF_TRAME; 566 tv.tv_usec = TIME_OUT_END_OF_TRAME;
392 567
@@ -404,99 +579,50 @@ int receive_response(modbus_param_t *mb_param, @@ -404,99 +579,50 @@ int receive_response(modbus_param_t *mb_param,
404 return 0; 579 return 0;
405 } 580 }
406 581
407 -static int check_crc16(modbus_param_t *mb_param,  
408 - unsigned char *response,  
409 - int response_size)  
410 -{  
411 - int ret;  
412 -  
413 - if (mb_param->type_com == RTU) {  
414 - unsigned short crc_calc;  
415 - unsigned short crc_received;  
416 - unsigned char recv_crc_hi;  
417 - unsigned char recv_crc_lo;  
418 -  
419 - crc_calc = crc16(response, response_size - 2);  
420 -  
421 - recv_crc_hi = (unsigned) response[response_size - 2];  
422 - recv_crc_lo = (unsigned) response[response_size - 1];  
423 -  
424 - crc_received = response[response_size - 2];  
425 - crc_received = (unsigned) crc_received << 8;  
426 - crc_received = crc_received |  
427 - (unsigned) response[response_size - 1];  
428 -  
429 - /* Check CRC of response */  
430 - if (crc_calc == crc_received) {  
431 - ret = TRUE;  
432 - } else {  
433 - char *message;  
434 - message = g_strdup_printf(  
435 - "invalid crc received %0X - crc_calc %0X",  
436 - crc_received, crc_calc);  
437 - error_treat(0, message, mb_param);  
438 - g_free(message);  
439 - ret = INVALID_CRC;  
440 - }  
441 - } else {  
442 - /* In TCP, CRC doesn't exist but it doesn't check  
443 - length because it's not really useful */  
444 - ret = TRUE;  
445 - }  
446 -  
447 - return ret;  
448 -}  
449 582
450 -/* Function to the correct response is returned and that the checksum  
451 - is correct. 583 +/* Checks whether the right response is returned with good checksum.
452 584
453 Returns: 585 Returns:
454 - the numbers of values (bits or word) if success 586 - the numbers of values (bits or word) if success
455 - less than 0 for exception errors 587 - less than 0 for exception errors
456 588
457 - Note: All functions used for sending or receiving data via modbus  
458 - return these values.  
459 -*/  
460 -  
461 -static int modbus_response(modbus_param_t *mb_param,  
462 - unsigned char *query,  
463 - unsigned char *response) 589 + Note: All functions used to send or receive data with modbus return
  590 + these values. */
  591 +static int modbus_check_response(modbus_param_t *mb_param,
  592 + unsigned char *query,
  593 + unsigned char *response)
464 { 594 {
465 int response_size; 595 int response_size;
466 - int response_size_computed;  
467 - int offset = mb_param->header_length;  
468 - int error_code; 596 + int response_size_computed; int offset = mb_param->header_length;
  597 + int ret;
469 598
470 response_size_computed = compute_response_size(mb_param, query); 599 response_size_computed = compute_response_size(mb_param, query);
471 - error_code = receive_response(mb_param, response_size_computed,  
472 - response, &response_size);  
473 - if (error_code == 0) {  
474 - /* No error */  
475 - int ret;  
476 - 600 + ret = receive_msg(mb_param, response_size_computed, response, &response_size);
  601 + if (ret == 0) {
  602 + /* Check message */
477 ret = check_crc16(mb_param, response, response_size); 603 ret = check_crc16(mb_param, response, response_size);
478 - if (ret != TRUE) 604 + if (ret != 0)
479 return ret; 605 return ret;
480 606
481 /* Good response */ 607 /* Good response */
482 switch (response[offset + 1]) { 608 switch (response[offset + 1]) {
483 - case 0x01:  
484 - case 0x02: 609 + case FC_READ_COIL_STATUS:
  610 + case FC_READ_INPUT_STATUS:
485 /* Read functions 1 value = 1 byte */ 611 /* Read functions 1 value = 1 byte */
486 response_size = response[offset + 2]; 612 response_size = response[offset + 2];
487 break; 613 break;
488 - case 0x03:  
489 - case 0x04: 614 + case FC_READ_HOLDING_REGISTERS:
  615 + case FC_READ_INPUT_REGISTERS:
490 /* Read functions 1 value = 2 bytes */ 616 /* Read functions 1 value = 2 bytes */
491 response_size = response[offset + 2] / 2; 617 response_size = response[offset + 2] / 2;
492 break; 618 break;
493 - case 0x0F:  
494 - case 0x10: 619 + case FC_FORCE_MULTIPLE_COILS:
  620 + case FC_PRESET_MULTIPLE_REGISTERS:
495 /* N Write functions */ 621 /* N Write functions */
496 response_size = response[offset + 4] << 8 | 622 response_size = response[offset + 4] << 8 |
497 response[offset + 5]; 623 response[offset + 5];
498 break; 624 break;
499 - case 0x11: 625 + case FC_REPORT_SLAVE_ID:
500 /* Report slave ID (bytes received) */ 626 /* Report slave ID (bytes received) */
501 break; 627 break;
502 default: 628 default:
@@ -504,16 +630,14 @@ static int modbus_response(modbus_param_t *mb_param, @@ -504,16 +630,14 @@ static int modbus_response(modbus_param_t *mb_param,
504 response_size = 1; 630 response_size = 1;
505 } 631 }
506 632
507 - } else if (error_code == COMM_TIME_OUT && 633 + } else if (ret == COMM_TIME_OUT &&
508 response_size == offset + 3 + mb_param->checksum_size) { 634 response_size == offset + 3 + mb_param->checksum_size) {
509 /* Optimisation allowed because exception response is 635 /* Optimisation allowed because exception response is
510 the smallest trame in modbus protocol (3) so always 636 the smallest trame in modbus protocol (3) so always
511 raise an timeout error */ 637 raise an timeout error */
512 - int ret;  
513 -  
514 /* CRC */ 638 /* CRC */
515 ret = check_crc16(mb_param, response, response_size); 639 ret = check_crc16(mb_param, response, response_size);
516 - if (ret != TRUE) 640 + if (ret != 0)
517 return ret; 641 return ret;
518 642
519 /* Check for exception response 643 /* Check for exception response
@@ -530,26 +654,148 @@ static int modbus_response(modbus_param_t *mb_param, @@ -530,26 +654,148 @@ static int modbus_response(modbus_param_t *mb_param,
530 /* The chances are low to hit this 654 /* The chances are low to hit this
531 case but can avoid a vicious 655 case but can avoid a vicious
532 segfault */ 656 segfault */
533 - char *message;  
534 - message = g_strdup_printf( 657 + char *s_error;
  658 + s_error = g_strdup_printf(
535 "Invalid exception code %d", 659 "Invalid exception code %d",
536 response[offset + 2]); 660 response[offset + 2]);
537 - error_treat(0, message, mb_param);  
538 - g_free(message); 661 + error_treat(0, s_error, mb_param);
  662 + g_free(s_error);
539 return INVALID_EXCEPTION_CODE; 663 return INVALID_EXCEPTION_CODE;
540 } 664 }
541 } 665 }
542 - } else if (error_code == COMM_TIME_OUT) { 666 + } else if (ret == COMM_TIME_OUT) {
543 error_treat(0, "Communication time out", mb_param); 667 error_treat(0, "Communication time out", mb_param);
544 return COMM_TIME_OUT; 668 return COMM_TIME_OUT;
545 } else { 669 } else {
546 - return error_code; 670 + return ret;
547 } 671 }
548 672
549 return response_size; 673 return response_size;
550 } 674 }
551 675
552 -/* Read IO status */ 676 +int response_io_status(int address, int count,
  677 + int nb_io_status, unsigned char *tab_io_status,
  678 + unsigned char *response, int offset)
  679 +{
  680 + unsigned char shift = 0;
  681 + unsigned char byte = 0;
  682 + int i;
  683 +
  684 + for (i = address; i < address+count; i++) {
  685 + byte |= tab_io_status[i] << shift;
  686 + if (shift == 7) {
  687 + /* Byte is full */
  688 + response[offset++] = byte;
  689 + byte = shift = 0;
  690 + } else {
  691 + shift++;
  692 + }
  693 + }
  694 +
  695 + if (shift != 0)
  696 + response[offset++] = byte;
  697 +
  698 + return offset;
  699 +}
  700 +
  701 +/* Manages the received query.
  702 + Analyses the query and constructs a response */
  703 +void manage_query(modbus_param_t *mb_param, unsigned char *query,
  704 + int query_size, modbus_mapping_t *mb_mapping)
  705 +{
  706 + int offset = mb_param->header_length;
  707 + int slave = query[offset];
  708 + int function = query[offset+1];
  709 + int address = (query[offset+2] << 8) + query[offset+3];
  710 + /* FIXME count/data */
  711 + int count;
  712 + int data;
  713 + unsigned char response[MAX_PACKET_SIZE];
  714 + int byte_count;
  715 + int i;
  716 +
  717 + /* FIXME address illegal used in mb_mapping->tab_X */
  718 +
  719 + switch (function) {
  720 + case FC_READ_COIL_STATUS:
  721 + count = (query[offset+4] << 8) + query[offset+5];
  722 + byte_count = (count / 8.0) + ((count % 8) ? 1 : 0);
  723 + offset = build_response_packet(mb_param, slave, function, byte_count, response);
  724 + offset = response_io_status(address, count,
  725 + mb_mapping->nb_coil_status, mb_mapping->tab_coil_status,
  726 + response, offset);
  727 + break;
  728 + case FC_READ_INPUT_STATUS:
  729 + count = (query[offset+4] << 8) + query[offset+5];
  730 + byte_count = (count / 8.0) + ((count % 8) ? 1 : 0);
  731 + offset = build_response_packet(mb_param, slave, function, byte_count, response);
  732 + offset = response_io_status(address, count,
  733 + mb_mapping->nb_input_status, mb_mapping->tab_input_status,
  734 + response, offset);
  735 + break;
  736 + case FC_READ_HOLDING_REGISTERS:
  737 + count = (query[offset+4] << 8) + query[offset+5];
  738 + byte_count = 2 * count;
  739 + offset = build_response_packet(mb_param, slave, function, byte_count, response);
  740 + g_print("offset %d\n", offset);
  741 + for (i = address; i < address + count; i++) {
  742 + response[offset++] = mb_mapping->tab_holding_registers[i] >> 8;
  743 + response[offset++] = mb_mapping->tab_holding_registers[i] & 0xFF;
  744 + }
  745 + g_print("fin offset %d\n", offset);
  746 + break;
  747 + case FC_READ_INPUT_REGISTERS:
  748 + count = (query[offset+4] << 8) + query[offset+5];
  749 + byte_count = 2 * count;
  750 + offset = build_response_packet(mb_param, slave, function, byte_count, response);
  751 + for (i = address; i < address + count; i++) {
  752 + response[offset++] = mb_mapping->tab_input_registers[i] >> 8;
  753 + response[offset++] = mb_mapping->tab_input_registers[i] & 0xFF;
  754 + }
  755 + break;
  756 + case FC_FORCE_SINGLE_COIL:
  757 + data = (query[offset+4] << 8) + query[offset+5];
  758 + if (data == 0xFF00)
  759 + mb_mapping->tab_coil_status[address] = ON;
  760 + else if (data == 0x0)
  761 + mb_mapping->tab_coil_status[address] = OFF;
  762 + else
  763 + g_print("FIXME Error %d\n", data);
  764 + g_print("FIXME works only in TCP mode (CRC)");
  765 + memcpy(response, query, query_size);
  766 + offset = query_size;
  767 + break;
  768 + case FC_PRESET_SINGLE_REGISTER:
  769 + case FC_READ_EXCEPTION_STATUS:
  770 + case FC_FORCE_MULTIPLE_COILS:
  771 + case FC_PRESET_MULTIPLE_REGISTERS:
  772 + case FC_REPORT_SLAVE_ID:
  773 + g_print("Not implemented\n");
  774 + break;
  775 + }
  776 +
  777 + modbus_send(mb_param, response, offset);
  778 +}
  779 +
  780 +/* Listens any message on a socket or file descriptor.
  781 + Returns:
  782 + - 0 if OK, or a negative error number if the request fails
  783 + - query, message received
  784 + - query_size, size in bytes of the message */
  785 +int modbus_listen(modbus_param_t *mb_param, unsigned char *query, int *query_size)
  786 +{
  787 + int offset = mb_param->header_length;
  788 + int ret;
  789 +
  790 + ret = receive_msg(mb_param, MSG_SIZE_UNDEFINED, query, query_size);
  791 + if (ret == 0) {
  792 + ret = check_crc16(mb_param, query, *query_size);
  793 + }
  794 +
  795 + return ret;
  796 +}
  797 +
  798 +/* Reads IO status */
553 static int read_io_status(modbus_param_t *mb_param, int slave, int function, 799 static int read_io_status(modbus_param_t *mb_param, int slave, int function,
554 int start_addr, int count, int *data_dest) 800 int start_addr, int count, int *data_dest)
555 { 801 {
@@ -560,10 +806,10 @@ static int read_io_status(modbus_param_t *mb_param, int slave, int function, @@ -560,10 +806,10 @@ static int read_io_status(modbus_param_t *mb_param, int slave, int function,
560 unsigned char query[MIN_QUERY_SIZE]; 806 unsigned char query[MIN_QUERY_SIZE];
561 unsigned char response[MAX_PACKET_SIZE]; 807 unsigned char response[MAX_PACKET_SIZE];
562 808
563 - query_size = build_request_packet(mb_param, slave, function,  
564 - start_addr, count, query); 809 + query_size = build_query_packet(mb_param, slave, function,
  810 + start_addr, count, query);
565 811
566 - query_ret = modbus_query(mb_param, query, query_size); 812 + query_ret = modbus_send(mb_param, query, query_size);
567 if (query_ret > 0) { 813 if (query_ret > 0) {
568 int i, temp, bit; 814 int i, temp, bit;
569 int pos = 0; 815 int pos = 0;
@@ -571,7 +817,7 @@ static int read_io_status(modbus_param_t *mb_param, int slave, int function, @@ -571,7 +817,7 @@ static int read_io_status(modbus_param_t *mb_param, int slave, int function,
571 int offset; 817 int offset;
572 int offset_length; 818 int offset_length;
573 819
574 - response_ret = modbus_response(mb_param, query, response); 820 + response_ret = modbus_check_response(mb_param, query, response);
575 offset = mb_param->header_length; 821 offset = mb_param->header_length;
576 822
577 offset_length = offset + response_ret; 823 offset_length = offset + response_ret;
@@ -579,10 +825,8 @@ static int read_io_status(modbus_param_t *mb_param, int slave, int function, @@ -579,10 +825,8 @@ static int read_io_status(modbus_param_t *mb_param, int slave, int function,
579 /* Shift reg hi_byte to temp */ 825 /* Shift reg hi_byte to temp */
580 temp = response[3 + i]; 826 temp = response[3 + i];
581 827
582 - for (bit = 0x01;  
583 - (bit & 0xff) && (processed < count);) {  
584 - data_dest[pos++] =  
585 - (temp & bit) ? TRUE : FALSE; 828 + for (bit = 0x01; (bit & 0xff) && (processed < count);) {
  829 + data_dest[pos++] = (temp & bit) ? TRUE : FALSE;
586 processed++; 830 processed++;
587 bit = bit << 1; 831 bit = bit << 1;
588 } 832 }
@@ -596,15 +840,14 @@ static int read_io_status(modbus_param_t *mb_param, int slave, int function, @@ -596,15 +840,14 @@ static int read_io_status(modbus_param_t *mb_param, int slave, int function,
596 } 840 }
597 841
598 /* Reads the boolean status of coils and sets the array elements 842 /* Reads the boolean status of coils and sets the array elements
599 - in the destination to TRUE or FALSE */ 843 + in the destination to TRUE or FALSE. */
600 int read_coil_status(modbus_param_t *mb_param, int slave, int start_addr, 844 int read_coil_status(modbus_param_t *mb_param, int slave, int start_addr,
601 int count, int *data_dest) 845 int count, int *data_dest)
602 { 846 {
603 - int function = 0x01;  
604 int status; 847 int status;
605 848
606 - status = read_io_status(mb_param, slave, function, start_addr,  
607 - count, data_dest); 849 + status = read_io_status(mb_param, slave, FC_READ_COIL_STATUS,
  850 + start_addr, count, data_dest);
608 851
609 if (status > 0) 852 if (status > 0)
610 status = count; 853 status = count;
@@ -612,15 +855,15 @@ int read_coil_status(modbus_param_t *mb_param, int slave, int start_addr, @@ -612,15 +855,15 @@ int read_coil_status(modbus_param_t *mb_param, int slave, int start_addr,
612 return status; 855 return status;
613 } 856 }
614 857
  858 +
615 /* Same as read_coil_status but reads the slaves input table */ 859 /* Same as read_coil_status but reads the slaves input table */
616 int read_input_status(modbus_param_t *mb_param, int slave, int start_addr, 860 int read_input_status(modbus_param_t *mb_param, int slave, int start_addr,
617 int count, int *data_dest) 861 int count, int *data_dest)
618 { 862 {
619 - int function = 0x02;  
620 int status; 863 int status;
621 864
622 - status = read_io_status(mb_param, slave, function, start_addr,  
623 - count, data_dest); 865 + status = read_io_status(mb_param, slave, FC_READ_INPUT_STATUS,
  866 + start_addr, count, data_dest);
624 867
625 if (status > 0) 868 if (status > 0)
626 status = count; 869 status = count;
@@ -628,7 +871,7 @@ int read_input_status(modbus_param_t *mb_param, int slave, int start_addr, @@ -628,7 +871,7 @@ int read_input_status(modbus_param_t *mb_param, int slave, int start_addr,
628 return status; 871 return status;
629 } 872 }
630 873
631 -/* Read the data from a modbus slave and put that data into an array */ 874 +/* Reads the data from a modbus slave and put that data into an array */
632 static int read_registers(modbus_param_t *mb_param, int slave, int function, 875 static int read_registers(modbus_param_t *mb_param, int slave, int function,
633 int start_addr, int count, int *data_dest) 876 int start_addr, int count, int *data_dest)
634 { 877 {
@@ -637,10 +880,10 @@ static int read_registers(modbus_param_t *mb_param, int slave, int function, @@ -637,10 +880,10 @@ static int read_registers(modbus_param_t *mb_param, int slave, int function,
637 int query_ret; 880 int query_ret;
638 unsigned char query[MIN_QUERY_SIZE]; 881 unsigned char query[MIN_QUERY_SIZE];
639 882
640 - query_size = build_request_packet(mb_param, slave, function,  
641 - start_addr, count, query); 883 + query_size = build_query_packet(mb_param, slave, function,
  884 + start_addr, count, query);
642 885
643 - query_ret = modbus_query(mb_param, query, query_size); 886 + query_ret = modbus_send(mb_param, query, query_size);
644 if (query_ret > 0) 887 if (query_ret > 0)
645 status = read_reg_response(mb_param, data_dest, query); 888 status = read_reg_response(mb_param, data_dest, query);
646 else 889 else
@@ -649,12 +892,11 @@ static int read_registers(modbus_param_t *mb_param, int slave, int function, @@ -649,12 +892,11 @@ static int read_registers(modbus_param_t *mb_param, int slave, int function,
649 return status; 892 return status;
650 } 893 }
651 894
652 -/* Read the holding registers in a slave and put the data into an 895 +/* Reads the holding registers in a slave and put the data into an
653 array */ 896 array */
654 int read_holding_registers(modbus_param_t *mb_param, int slave, 897 int read_holding_registers(modbus_param_t *mb_param, int slave,
655 int start_addr, int count, int *data_dest) 898 int start_addr, int count, int *data_dest)
656 { 899 {
657 - int function = 0x03;  
658 int status; 900 int status;
659 901
660 if (count > MAX_READ_HOLD_REGS) { 902 if (count > MAX_READ_HOLD_REGS) {
@@ -662,17 +904,16 @@ int read_holding_registers(modbus_param_t *mb_param, int slave, @@ -662,17 +904,16 @@ int read_holding_registers(modbus_param_t *mb_param, int slave,
662 count = MAX_READ_HOLD_REGS; 904 count = MAX_READ_HOLD_REGS;
663 } 905 }
664 906
665 - status = read_registers(mb_param, slave, function, 907 + status = read_registers(mb_param, slave, FC_READ_HOLDING_REGISTERS,
666 start_addr, count, data_dest); 908 start_addr, count, data_dest);
667 return status; 909 return status;
668 } 910 }
669 911
670 -/* Read the input registers in a slave and put the data into 912 +/* Reads the input registers in a slave and put the data into
671 an array */ 913 an array */
672 int read_input_registers(modbus_param_t *mb_param, int slave, 914 int read_input_registers(modbus_param_t *mb_param, int slave,
673 int start_addr, int count, int *data_dest) 915 int start_addr, int count, int *data_dest)
674 { 916 {
675 - int function = 0x04;  
676 int status; 917 int status;
677 918
678 if (count > MAX_READ_INPUT_REGS) { 919 if (count > MAX_READ_INPUT_REGS) {
@@ -680,7 +921,7 @@ int read_input_registers(modbus_param_t *mb_param, int slave, @@ -680,7 +921,7 @@ int read_input_registers(modbus_param_t *mb_param, int slave,
680 count = MAX_READ_INPUT_REGS; 921 count = MAX_READ_INPUT_REGS;
681 } 922 }
682 923
683 - status = read_registers(mb_param, slave, function, 924 + status = read_registers(mb_param, slave, FC_READ_INPUT_REGISTERS,
684 start_addr, count, data_dest); 925 start_addr, count, data_dest);
685 926
686 return status; 927 return status;
@@ -696,7 +937,7 @@ static int read_reg_response(modbus_param_t *mb_param, int *data_dest, @@ -696,7 +937,7 @@ static int read_reg_response(modbus_param_t *mb_param, int *data_dest,
696 int offset; 937 int offset;
697 int i; 938 int i;
698 939
699 - response_ret = modbus_response(mb_param, query, response); 940 + response_ret = modbus_check_response(mb_param, query, response);
700 941
701 offset = mb_param->header_length; 942 offset = mb_param->header_length;
702 943
@@ -716,7 +957,7 @@ static int preset_response(modbus_param_t *mb_param, unsigned char *query) @@ -716,7 +957,7 @@ static int preset_response(modbus_param_t *mb_param, unsigned char *query)
716 int ret; 957 int ret;
717 unsigned char response[MAX_PACKET_SIZE]; 958 unsigned char response[MAX_PACKET_SIZE];
718 959
719 - ret = modbus_response(mb_param, query, response); 960 + ret = modbus_check_response(mb_param, query, response);
720 961
721 return ret; 962 return ret;
722 } 963 }
@@ -730,10 +971,10 @@ static int set_single(modbus_param_t *mb_param, int slave, int function, @@ -730,10 +971,10 @@ static int set_single(modbus_param_t *mb_param, int slave, int function,
730 int query_ret; 971 int query_ret;
731 unsigned char query[MAX_PACKET_SIZE]; 972 unsigned char query[MAX_PACKET_SIZE];
732 973
733 - query_size = build_request_packet(mb_param, slave, function,  
734 - addr, value, query); 974 + query_size = build_query_packet(mb_param, slave, function,
  975 + addr, value, query);
735 976
736 - query_ret = modbus_query(mb_param, query, query_size); 977 + query_ret = modbus_send(mb_param, query, query_size);
737 if (query_ret > 0) 978 if (query_ret > 0)
738 status = preset_response(mb_param, query); 979 status = preset_response(mb_param, query);
739 else 980 else
@@ -743,17 +984,16 @@ static int set_single(modbus_param_t *mb_param, int slave, int function, @@ -743,17 +984,16 @@ static int set_single(modbus_param_t *mb_param, int slave, int function,
743 } 984 }
744 985
745 986
746 -/* Turn on or off a single coil on the slave device */ 987 +/* Turns on or off a single coil on the slave device */
747 int force_single_coil(modbus_param_t *mb_param, int slave, 988 int force_single_coil(modbus_param_t *mb_param, int slave,
748 int coil_addr, int state) 989 int coil_addr, int state)
749 { 990 {
750 - int function = 0x05;  
751 int status; 991 int status;
752 992
753 if (state) 993 if (state)
754 state = 0xFF00; 994 state = 0xFF00;
755 995
756 - status = set_single(mb_param, slave, function, coil_addr, state); 996 + status = set_single(mb_param, slave, FC_FORCE_SINGLE_COIL, coil_addr, state);
757 997
758 return status; 998 return status;
759 } 999 }
@@ -762,10 +1002,9 @@ int force_single_coil(modbus_param_t *mb_param, int slave, @@ -762,10 +1002,9 @@ int force_single_coil(modbus_param_t *mb_param, int slave,
762 int preset_single_register(modbus_param_t *mb_param, int slave, 1002 int preset_single_register(modbus_param_t *mb_param, int slave,
763 int reg_addr, int value) 1003 int reg_addr, int value)
764 { 1004 {
765 - int function = 0x06;  
766 int status; 1005 int status;
767 1006
768 - status = set_single(mb_param, slave, function, reg_addr, value); 1007 + status = set_single(mb_param, slave, FC_PRESET_SINGLE_REGISTER, reg_addr, value);
769 1008
770 return status; 1009 return status;
771 } 1010 }
@@ -776,7 +1015,6 @@ int force_multiple_coils(modbus_param_t *mb_param, int slave, @@ -776,7 +1015,6 @@ int force_multiple_coils(modbus_param_t *mb_param, int slave,
776 int start_addr, int coil_count, 1015 int start_addr, int coil_count,
777 int *data_src) 1016 int *data_src)
778 { 1017 {
779 - int function = 0x0F;  
780 int i; 1018 int i;
781 int byte_count; 1019 int byte_count;
782 int query_size; 1020 int query_size;
@@ -791,8 +1029,8 @@ int force_multiple_coils(modbus_param_t *mb_param, int slave, @@ -791,8 +1029,8 @@ int force_multiple_coils(modbus_param_t *mb_param, int slave,
791 coil_count = MAX_WRITE_COILS; 1029 coil_count = MAX_WRITE_COILS;
792 } 1030 }
793 1031
794 - query_size = build_request_packet(mb_param, slave, function,  
795 - start_addr, coil_count, query); 1032 + query_size = build_query_packet(mb_param, slave, FC_FORCE_MULTIPLE_COILS,
  1033 + start_addr, coil_count, query);
796 byte_count = (coil_count / 8) + ((coil_count % 8) ? 1 : 0); 1034 byte_count = (coil_count / 8) + ((coil_count % 8) ? 1 : 0);
797 query[query_size++] = byte_count; 1035 query[query_size++] = byte_count;
798 1036
@@ -814,7 +1052,7 @@ int force_multiple_coils(modbus_param_t *mb_param, int slave, @@ -814,7 +1052,7 @@ int force_multiple_coils(modbus_param_t *mb_param, int slave,
814 query_size++; 1052 query_size++;
815 } 1053 }
816 1054
817 - query_ret = modbus_query(mb_param, query, query_size); 1055 + query_ret = modbus_send(mb_param, query, query_size);
818 if (query_ret > 0) 1056 if (query_ret > 0)
819 status = preset_response(mb_param, query); 1057 status = preset_response(mb_param, query);
820 else 1058 else
@@ -823,11 +1061,10 @@ int force_multiple_coils(modbus_param_t *mb_param, int slave, @@ -823,11 +1061,10 @@ int force_multiple_coils(modbus_param_t *mb_param, int slave,
823 return status; 1061 return status;
824 } 1062 }
825 1063
826 -/* Copy the values in an array to an array on the slave */ 1064 +/* Copies the values in an array to an array on the slave */
827 int preset_multiple_registers(modbus_param_t *mb_param, int slave, 1065 int preset_multiple_registers(modbus_param_t *mb_param, int slave,
828 int start_addr, int reg_count, int *data_src) 1066 int start_addr, int reg_count, int *data_src)
829 { 1067 {
830 - int function = 0x10;  
831 int i; 1068 int i;
832 int query_size; 1069 int query_size;
833 int byte_count; 1070 int byte_count;
@@ -841,8 +1078,9 @@ int preset_multiple_registers(modbus_param_t *mb_param, int slave, @@ -841,8 +1078,9 @@ int preset_multiple_registers(modbus_param_t *mb_param, int slave,
841 reg_count = MAX_WRITE_REGS; 1078 reg_count = MAX_WRITE_REGS;
842 } 1079 }
843 1080
844 - query_size = build_request_packet(mb_param, slave, function,  
845 - start_addr, reg_count, query); 1081 + query_size = build_query_packet(mb_param, slave,
  1082 + FC_PRESET_MULTIPLE_REGISTERS,
  1083 + start_addr, reg_count, query);
846 byte_count = reg_count * 2; 1084 byte_count = reg_count * 2;
847 query[query_size++] = byte_count; 1085 query[query_size++] = byte_count;
848 1086
@@ -851,7 +1089,7 @@ int preset_multiple_registers(modbus_param_t *mb_param, int slave, @@ -851,7 +1089,7 @@ int preset_multiple_registers(modbus_param_t *mb_param, int slave,
851 query[query_size++] = data_src[i] & 0x00FF; 1089 query[query_size++] = data_src[i] & 0x00FF;
852 } 1090 }
853 1091
854 - query_ret = modbus_query(mb_param, query, query_size); 1092 + query_ret = modbus_send(mb_param, query, query_size);
855 if (query_ret > 0) 1093 if (query_ret > 0)
856 status = preset_response(mb_param, query); 1094 status = preset_response(mb_param, query);
857 else 1095 else
@@ -864,7 +1102,6 @@ int preset_multiple_registers(modbus_param_t *mb_param, int slave, @@ -864,7 +1102,6 @@ int preset_multiple_registers(modbus_param_t *mb_param, int slave,
864 int report_slave_id(modbus_param_t *mb_param, int slave, 1102 int report_slave_id(modbus_param_t *mb_param, int slave,
865 unsigned char *data_dest) 1103 unsigned char *data_dest)
866 { 1104 {
867 - int function = 0x11;  
868 int query_size; 1105 int query_size;
869 int query_ret; 1106 int query_ret;
870 int response_ret; 1107 int response_ret;
@@ -872,13 +1109,13 @@ int report_slave_id(modbus_param_t *mb_param, int slave, @@ -872,13 +1109,13 @@ int report_slave_id(modbus_param_t *mb_param, int slave,
872 unsigned char query[MIN_QUERY_SIZE]; 1109 unsigned char query[MIN_QUERY_SIZE];
873 unsigned char response[MAX_PACKET_SIZE]; 1110 unsigned char response[MAX_PACKET_SIZE];
874 1111
875 - query_size = build_request_packet(mb_param, slave, function,  
876 - 0, 0, query); 1112 + query_size = build_query_packet(mb_param, slave, FC_REPORT_SLAVE_ID,
  1113 + 0, 0, query);
877 1114
878 /* start_addr and count are not used */ 1115 /* start_addr and count are not used */
879 query_size -= 4; 1116 query_size -= 4;
880 1117
881 - query_ret = modbus_query(mb_param, query, query_size); 1118 + query_ret = modbus_send(mb_param, query, query_size);
882 if (query_ret > 0) { 1119 if (query_ret > 0) {
883 int i; 1120 int i;
884 int offset; 1121 int offset;
@@ -886,7 +1123,7 @@ int report_slave_id(modbus_param_t *mb_param, int slave, @@ -886,7 +1123,7 @@ int report_slave_id(modbus_param_t *mb_param, int slave,
886 1123
887 /* Byte count, slave id, run indicator status, 1124 /* Byte count, slave id, run indicator status,
888 additional data */ 1125 additional data */
889 - response_ret = modbus_response(mb_param, query, response); 1126 + response_ret = modbus_check_response(mb_param, query, response);
890 1127
891 offset = mb_param->header_length; 1128 offset = mb_param->header_length;
892 offset_length = offset + response_ret; 1129 offset_length = offset + response_ret;
@@ -1181,6 +1418,7 @@ static int modbus_connect_rtu(modbus_param_t *mb_param) @@ -1181,6 +1418,7 @@ static int modbus_connect_rtu(modbus_param_t *mb_param)
1181 return 0; 1418 return 0;
1182 } 1419 }
1183 1420
  1421 +/* Establishes a modbus connection with a modbus slave */
1184 static int modbus_connect_tcp(modbus_param_t *mb_param) 1422 static int modbus_connect_tcp(modbus_param_t *mb_param)
1185 { 1423 {
1186 int ret; 1424 int ret;
@@ -1232,6 +1470,7 @@ static int modbus_connect_tcp(modbus_param_t *mb_param) @@ -1232,6 +1470,7 @@ static int modbus_connect_tcp(modbus_param_t *mb_param)
1232 return 0; 1470 return 0;
1233 } 1471 }
1234 1472
  1473 +/* Establishes a modbus connexion */
1235 int modbus_connect(modbus_param_t *mb_param) 1474 int modbus_connect(modbus_param_t *mb_param)
1236 { 1475 {
1237 int ret; 1476 int ret;
@@ -1244,7 +1483,63 @@ int modbus_connect(modbus_param_t *mb_param) @@ -1244,7 +1483,63 @@ int modbus_connect(modbus_param_t *mb_param)
1244 return ret; 1483 return ret;
1245 } 1484 }
1246 1485
1247 -void modbus_listen_tcp(modbus_param_t *mb_param) 1486 +/* Allocates 4 arrays to store coils, input status, input registers and
  1487 + holding registers. The pointers are stored in modbus_mapping structure.
  1488 +
  1489 + Returns: TRUE if ok, FALSE on failure
  1490 +
  1491 + */
  1492 +int modbus_mapping_new(modbus_mapping_t *mb_mapping,
  1493 + int nb_coil_status, int nb_input_status,
  1494 + int nb_input_registers, int nb_holding_registers)
  1495 +{
  1496 + /* 0X */
  1497 + mb_mapping->nb_coil_status = nb_coil_status;
  1498 + mb_mapping->tab_coil_status = (unsigned char *) g_malloc0(nb_coil_status * sizeof(unsigned char));
  1499 + if (mb_mapping->tab_coil_status == NULL)
  1500 + return FALSE;
  1501 +
  1502 + /* 1X */
  1503 + mb_mapping->nb_input_status = nb_input_status;
  1504 + mb_mapping->tab_input_status = (unsigned char *) g_malloc0(nb_input_status * sizeof(unsigned char));
  1505 + if (mb_mapping->tab_input_status == NULL) {
  1506 + g_free(mb_mapping->tab_coil_status);
  1507 + return FALSE;
  1508 + }
  1509 +
  1510 + /* 3X */
  1511 + mb_mapping->nb_input_registers = nb_input_registers;
  1512 + mb_mapping->tab_input_registers = (unsigned short *) g_malloc0(nb_input_registers * sizeof(unsigned short));
  1513 + if (mb_mapping->tab_input_registers == NULL) {
  1514 + g_free(mb_mapping->tab_coil_status);
  1515 + g_free(mb_mapping->tab_input_status);
  1516 + return FALSE;
  1517 + }
  1518 +
  1519 + /* 4X */
  1520 + mb_mapping->nb_holding_registers = nb_holding_registers;
  1521 + mb_mapping->tab_holding_registers = (unsigned short *) g_malloc0(nb_holding_registers * sizeof(unsigned short));
  1522 + if (mb_mapping->tab_holding_registers == NULL) {
  1523 + g_free(mb_mapping->tab_coil_status);
  1524 + g_free(mb_mapping->tab_input_status);
  1525 + g_free(mb_mapping->tab_input_registers);
  1526 + return FALSE;
  1527 + }
  1528 +
  1529 + return TRUE;
  1530 +}
  1531 +
  1532 +/* Frees the 4 arrays */
  1533 +void modbus_mapping_free(modbus_mapping_t *mb_mapping)
  1534 +{
  1535 + g_free(mb_mapping->tab_coil_status);
  1536 + g_free(mb_mapping->tab_input_status);
  1537 + g_free(mb_mapping->tab_input_registers);
  1538 + g_free(mb_mapping->tab_holding_registers);
  1539 +}
  1540 +
  1541 +/* Listens for any query from a modbus master */
  1542 +int modbus_init_listen_tcp(modbus_param_t *mb_param)
1248 { 1543 {
1249 int ret; 1544 int ret;
1250 int new_socket; 1545 int new_socket;
@@ -1290,22 +1585,17 @@ void modbus_listen_tcp(modbus_param_t *mb_param) @@ -1290,22 +1585,17 @@ void modbus_listen_tcp(modbus_param_t *mb_param)
1290 if (ret < 0) { 1585 if (ret < 0) {
1291 perror("accept"); 1586 perror("accept");
1292 close(new_socket); 1587 close(new_socket);
1293 - exit(1); 1588 + new_socket = 0;
  1589 + exit(1);
1294 } else { 1590 } else {
1295 - unsigned char response[MAX_PACKET_SIZE];  
1296 - int response_size;  
1297 -  
1298 g_print("The client %s is connected\n", 1591 g_print("The client %s is connected\n",
1299 inet_ntoa(addr.sin_addr)); 1592 inet_ntoa(addr.sin_addr));
1300 -  
1301 - receive_response(mb_param, MAX_PACKET_SIZE,  
1302 - response, &response_size);  
1303 } 1593 }
1304 1594
1305 - close(new_socket); 1595 + return new_socket;
1306 } 1596 }
1307 1597
1308 -/* Close the file descriptor */ 1598 +/* Closes the file descriptor in RTU mode */
1309 static void modbus_close_rtu(modbus_param_t *mb_param) 1599 static void modbus_close_rtu(modbus_param_t *mb_param)
1310 { 1600 {
1311 if (tcsetattr(mb_param->fd, TCSANOW, &(mb_param->old_tios)) < 0) 1601 if (tcsetattr(mb_param->fd, TCSANOW, &(mb_param->old_tios)) < 0)
@@ -1314,12 +1604,14 @@ static void modbus_close_rtu(modbus_param_t *mb_param) @@ -1314,12 +1604,14 @@ static void modbus_close_rtu(modbus_param_t *mb_param)
1314 close(mb_param->fd); 1604 close(mb_param->fd);
1315 } 1605 }
1316 1606
  1607 +/* Closes the network connection and socket in TCP mode */
1317 static void modbus_close_tcp(modbus_param_t *mb_param) 1608 static void modbus_close_tcp(modbus_param_t *mb_param)
1318 { 1609 {
1319 shutdown(mb_param->fd, SHUT_RDWR); 1610 shutdown(mb_param->fd, SHUT_RDWR);
1320 close(mb_param->fd); 1611 close(mb_param->fd);
1321 } 1612 }
1322 1613
  1614 +/* Closes a modbus connection */
1323 void modbus_close(modbus_param_t *mb_param) 1615 void modbus_close(modbus_param_t *mb_param)
1324 { 1616 {
1325 if (mb_param->type_com == RTU) 1617 if (mb_param->type_com == RTU)
@@ -1328,6 +1620,7 @@ void modbus_close(modbus_param_t *mb_param) @@ -1328,6 +1620,7 @@ void modbus_close(modbus_param_t *mb_param)
1328 modbus_close_tcp(mb_param); 1620 modbus_close_tcp(mb_param);
1329 } 1621 }
1330 1622
  1623 +/* Activates the debug messages */
1331 void modbus_set_debug(modbus_param_t *mb_param, int boolean) 1624 void modbus_set_debug(modbus_param_t *mb_param, int boolean)
1332 { 1625 {
1333 mb_param->debug = boolean; 1626 mb_param->debug = boolean;
src/modbus.h
1 /* 1 /*
2 - Copyright (C) 2001-2005 Stéphane Raimbault <stephane.raimbault@free.fr> 2 + Copyright (C) 2001-2007 Stéphane Raimbault <stephane.raimbault@gmail.com>
3 3
4 This library is free software; you can redistribute it and/or 4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public 5 modify it under the terms of the GNU Lesser General Public
@@ -27,11 +27,13 @@ @@ -27,11 +27,13 @@
27 27
28 #define MODBUS_TCP_PORT 502 28 #define MODBUS_TCP_PORT 502
29 29
30 -#define HEADER_LENGTH_RTU 0  
31 -#define PRESET_QUERY_SIZE_RTU 6 30 +#define HEADER_LENGTH_RTU 0
  31 +#define PRESET_QUERY_SIZE_RTU 6
  32 +#define PRESET_RESPONSE_SIZE_RTU 2
32 33
33 -#define HEADER_LENGTH_TCP 6  
34 -#define PRESET_QUERY_SIZE_TCP 12 34 +#define HEADER_LENGTH_TCP 6
  35 +#define PRESET_QUERY_SIZE_TCP 12
  36 +#define PRESET_RESPONSE_SIZE_TCP 8
35 37
36 #define CHECKSUM_SIZE_RTU 2 38 #define CHECKSUM_SIZE_RTU 2
37 #define CHECKSUM_SIZE_TCP 0 39 #define CHECKSUM_SIZE_TCP 0
@@ -62,6 +64,26 @@ @@ -62,6 +64,26 @@
62 #define TRUE 1 64 #define TRUE 1
63 #endif 65 #endif
64 66
  67 +#ifndef OFF
  68 +#define OFF 0
  69 +#endif
  70 +
  71 +#ifndef ON
  72 +#define ON 1
  73 +#endif
  74 +
  75 +/* Function codes */
  76 +#define FC_READ_COIL_STATUS 0x01 /* discretes inputs */
  77 +#define FC_READ_INPUT_STATUS 0x02 /* discretes outputs */
  78 +#define FC_READ_HOLDING_REGISTERS 0x03
  79 +#define FC_READ_INPUT_REGISTERS 0x04
  80 +#define FC_FORCE_SINGLE_COIL 0x05
  81 +#define FC_PRESET_SINGLE_REGISTER 0x06
  82 +#define FC_READ_EXCEPTION_STATUS 0x07
  83 +#define FC_FORCE_MULTIPLE_COILS 0x0F
  84 +#define FC_PRESET_MULTIPLE_REGISTERS 0x10
  85 +#define FC_REPORT_SLAVE_ID 0x11
  86 +
65 /* Protocol exceptions */ 87 /* Protocol exceptions */
66 #define ILLEGAL_FUNCTION -0x01 88 #define ILLEGAL_FUNCTION -0x01
67 #define ILLEGAL_DATA_ADDRESS -0x02 89 #define ILLEGAL_DATA_ADDRESS -0x02
@@ -84,17 +106,20 @@ @@ -84,17 +106,20 @@
84 #define INVALID_CRC -0x10 106 #define INVALID_CRC -0x10
85 #define INVALID_EXCEPTION_CODE -0x11 107 #define INVALID_EXCEPTION_CODE -0x11
86 108
  109 +/* Internal using */
  110 +#define MSG_SIZE_UNDEFINED -1
  111 +
87 typedef enum { RTU, TCP } type_com_t; 112 typedef enum { RTU, TCP } type_com_t;
88 113
89 -typedef struct _modbus_param_t { 114 +typedef struct {
90 /* Communication : RTU or TCP */ 115 /* Communication : RTU or TCP */
91 type_com_t type_com; 116 type_com_t type_com;
92 /* Device: "/dev/ttyS0" */ 117 /* Device: "/dev/ttyS0" */
93 char device[11]; 118 char device[11];
94 - /* Bauds: 19200 */  
95 - int baud_i;  
96 /* Parity: "even", "odd", "none" */ 119 /* Parity: "even", "odd", "none" */
97 char parity[5]; 120 char parity[5];
  121 + /* Bauds: 19200 */
  122 + int baud_i;
98 /* Data bit */ 123 /* Data bit */
99 int data_bit; 124 int data_bit;
100 /* Stop bit */ 125 /* Stop bit */
@@ -113,6 +138,17 @@ typedef struct _modbus_param_t { @@ -113,6 +138,17 @@ typedef struct _modbus_param_t {
113 int checksum_size; 138 int checksum_size;
114 } modbus_param_t; 139 } modbus_param_t;
115 140
  141 +typedef struct {
  142 + int nb_coil_status;
  143 + int nb_input_status;
  144 + int nb_input_registers;
  145 + int nb_holding_registers;
  146 + unsigned char *tab_coil_status;
  147 + unsigned char *tab_input_status;
  148 + unsigned short *tab_input_registers;
  149 + unsigned short *tab_holding_registers;
  150 +} modbus_mapping_t;
  151 +
116 /* All functions used for sending or receiving data return : 152 /* All functions used for sending or receiving data return :
117 - the numbers of values (bits or word) if success (0 or more) 153 - the numbers of values (bits or word) if success (0 or more)
118 - less than 0 for exceptions errors 154 - less than 0 for exceptions errors
@@ -127,18 +163,18 @@ int read_coil_status(modbus_param_t *mb_param, int slave, @@ -127,18 +163,18 @@ int read_coil_status(modbus_param_t *mb_param, int slave,
127 int read_input_status(modbus_param_t *mb_param, int slave, 163 int read_input_status(modbus_param_t *mb_param, int slave,
128 int start_addr, int count, int *dest); 164 int start_addr, int count, int *dest);
129 165
130 -/* Read the holding registers in a slave and put the data into an 166 +/* Reads the holding registers in a slave and put the data into an
131 array */ 167 array */
132 int read_holding_registers(modbus_param_t *mb_param, int slave, 168 int read_holding_registers(modbus_param_t *mb_param, int slave,
133 int start_addr, int count, int *dest); 169 int start_addr, int count, int *dest);
134 170
135 171
136 -/* Read the input registers in a slave and put the data into an 172 +/* Reads the input registers in a slave and put the data into an
137 array */ 173 array */
138 int read_input_registers(modbus_param_t *mb_param, int slave, 174 int read_input_registers(modbus_param_t *mb_param, int slave,
139 int start_addr, int count, int *dest); 175 int start_addr, int count, int *dest);
140 176
141 -/* Turn on or off a single coil on the slave device */ 177 +/* Turns on or off a single coil on the slave device */
142 int force_single_coil(modbus_param_t *mb_param, int slave, 178 int force_single_coil(modbus_param_t *mb_param, int slave,
143 int coil_addr, int state); 179 int coil_addr, int state);
144 180
@@ -174,26 +210,32 @@ void modbus_init_rtu(modbus_param_t *mb_param, char *device, @@ -174,26 +210,32 @@ void modbus_init_rtu(modbus_param_t *mb_param, char *device,
174 void modbus_init_tcp(modbus_param_t *mb_param, char *ip_address); 210 void modbus_init_tcp(modbus_param_t *mb_param, char *ip_address);
175 211
176 212
177 -/* This function sets up a serial port for RTU communications to  
178 - modbus or a TCP connexion */ 213 +/* Sets up a serial port for RTU communications to modbus or a TCP
  214 + connexion */
179 int modbus_connect(modbus_param_t *mb_param); 215 int modbus_connect(modbus_param_t *mb_param);
180 216
181 -/* This function closes the serial port and restores the previous port  
182 - configuration or close the TCP connexion */ 217 +/* Closes the serial port and restores the previous port configuration
  218 + or close the TCP connexion */
183 void modbus_close(modbus_param_t *mb_param); 219 void modbus_close(modbus_param_t *mb_param);
184 220
185 -/* Set in debug mode */ 221 +/* Sets debug mode */
186 void modbus_set_debug(modbus_param_t *mb_param, int boolean); 222 void modbus_set_debug(modbus_param_t *mb_param, int boolean);
187 223
188 -/* Useful for a 'daemon' */  
189 -void modbus_listen_tcp(modbus_param_t *mb_param); 224 +/* Slave/client functions */
  225 +int modbus_mapping_new(modbus_mapping_t *mb_mapping,
  226 + int nb_coil_status, int nb_input_status,
  227 + int nb_input_registers, int nb_holding_registers);
  228 +void modbus_mapping_free(modbus_mapping_t *mb_mapping);
  229 +
  230 +int modbus_init_listen_tcp(modbus_param_t *mb_param);
190 231
191 -/* Non implemented : 232 +int modbus_listen(modbus_param_t *mb_param, unsigned char *query, int *query_size);
  233 +
  234 +void manage_query(modbus_param_t *mb_param, unsigned char *query,
  235 + int query_size, modbus_mapping_t *mb_mapping);
  236 +
  237 +/* Not implemented :
192 - read_exception_status() 238 - read_exception_status()
193 */ 239 */
194 240
195 -/* Find out what a master is trying to ask this slave device */  
196 -int get_slave_query_tcp(modbus_param_t *mb_param, int *slave_addr, int *query,  
197 - int *start_addr, int *point_count, int *data);  
198 -  
199 #endif /* _MODBUS_H_ */ 241 #endif /* _MODBUS_H_ */