Commit f0e7ad217d41429930f87b884d074f04efca1f7f

Authored by Stéphane Raimbault
1 parent bb13bb7b

Error conventions of POSIX systems and error recovery

- returns -1 on error and set errno
- error recovery system was flawed
- error recovery disabled by default
- remove a malloc
modbus/modbus.c
@@ -41,6 +41,7 @@ @@ -41,6 +41,7 @@
41 #include <sys/time.h> 41 #include <sys/time.h>
42 #include <unistd.h> 42 #include <unistd.h>
43 #include <errno.h> 43 #include <errno.h>
  44 +#include <assert.h>
44 #include <limits.h> 45 #include <limits.h>
45 #include <fcntl.h> 46 #include <fcntl.h>
46 47
@@ -61,9 +62,8 @@ @@ -61,9 +62,8 @@
61 #endif 62 #endif
62 63
63 #include <config.h> 64 #include <config.h>
64 -#include <modbus/modbus.h>  
65 65
66 -#define UNKNOWN_ERROR_MSG "Not defined in modbus specification" 66 +#include <modbus/modbus.h>
67 67
68 /* Exported version */ 68 /* Exported version */
69 const unsigned int mb_version_major = MB_VERSION_MAJOR; 69 const unsigned int mb_version_major = MB_VERSION_MAJOR;
@@ -78,22 +78,6 @@ typedef struct { @@ -78,22 +78,6 @@ typedef struct {
78 int t_id; 78 int t_id;
79 } sft_t; 79 } sft_t;
80 80
81 -static const uint8_t NB_TAB_ERROR_MSG = 12;  
82 -static const char *TAB_ERROR_MSG[] = {  
83 - /* 0x00 */ UNKNOWN_ERROR_MSG,  
84 - /* 0x01 */ "Illegal function code",  
85 - /* 0x02 */ "Illegal data address",  
86 - /* 0x03 */ "Illegal data value",  
87 - /* 0x04 */ "Slave device or server failure",  
88 - /* 0x05 */ "Acknowledge",  
89 - /* 0x06 */ "Slave device or server busy",  
90 - /* 0x07 */ "Negative acknowledge",  
91 - /* 0x08 */ "Memory parity error",  
92 - /* 0x09 */ UNKNOWN_ERROR_MSG,  
93 - /* 0x0A */ "Gateway path unavailable",  
94 - /* 0x0B */ "Target device failed to respond"  
95 -};  
96 -  
97 /* Table of CRC values for high-order byte */ 81 /* Table of CRC values for high-order byte */
98 static uint8_t table_crc_hi[] = { 82 static uint8_t table_crc_hi[] = {
99 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 83 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
@@ -169,42 +153,65 @@ static const int TAB_MAX_ADU_LENGTH[2] = { @@ -169,42 +153,65 @@ static const int TAB_MAX_ADU_LENGTH[2] = {
169 MAX_ADU_LENGTH_TCP, 153 MAX_ADU_LENGTH_TCP,
170 }; 154 };
171 155
172 -/* Treats errors and flush or close connection if necessary */  
173 -static void error_treat(modbus_param_t *mb_param, int code, const char *string)  
174 -{  
175 - fprintf(stderr, "\nERROR %s (%0X)\n", string, -code); 156 +const char *modbus_strerror(int errnum) {
  157 + switch (errnum) {
  158 + case EMBXILFUN:
  159 + return "Illegal function";
  160 + case EMBXILADD:
  161 + return "Illegal data address";
  162 + case EMBXILVAL:
  163 + return "Illegal data value";
  164 + case EMBXSFAIL:
  165 + return "Slave device or server failure";
  166 + case EMBXACK:
  167 + return "Acknowledge";
  168 + case EMBXSBUSY:
  169 + return "Slave device or server is busy";
  170 + case EMBXNACK:
  171 + return "Negative acknowledge";
  172 + case EMBXMEMPAR:
  173 + return "Memory parity error";
  174 + case EMBXGPATH:
  175 + return "Gateway path unavailable";
  176 + case EMBXGTAR:
  177 + return "Target device failed to respond";
  178 + case EMBBADCRC:
  179 + return "Invalid CRC";
  180 + case EMBBADDATA:
  181 + return "Invalid data";
  182 + case EMBBADEXC:
  183 + return "Invalid exception code";
  184 + case EMBMDATA:
  185 + return "Too many data";
  186 + default:
  187 + return strerror(errnum);
  188 + }
  189 +}
176 190
177 - if (mb_param->error_handling == FLUSH_OR_CONNECT_ON_ERROR) {  
178 - switch (code) {  
179 - case INVALID_DATA:  
180 - case INVALID_CRC:  
181 - case INVALID_EXCEPTION_CODE:  
182 - modbus_flush(mb_param);  
183 - break;  
184 - case SELECT_FAILURE:  
185 - case SOCKET_FAILURE:  
186 - case CONNECTION_CLOSED:  
187 - modbus_close(mb_param);  
188 - modbus_connect(mb_param);  
189 - break;  
190 - default:  
191 - /* NOP */  
192 - break; 191 +static void error_print(modbus_param_t *mb_param, const char *context)
  192 +{
  193 + if (mb_param->debug) {
  194 + fprintf(stderr, "ERROR %s", modbus_strerror(errno));
  195 + if (context != NULL) {
  196 + fprintf(stderr, ": %s\n", context);
  197 + } else {
  198 + fprintf(stderr, "\n");
193 } 199 }
194 } 200 }
195 } 201 }
196 202
197 -void modbus_flush(modbus_param_t *mb_param) 203 +int modbus_flush(modbus_param_t *mb_param)
198 { 204 {
  205 + int rc;
  206 +
199 if (mb_param->type_com == RTU) { 207 if (mb_param->type_com == RTU) {
200 - tcflush(mb_param->fd, TCIOFLUSH); 208 + rc = tcflush(mb_param->fd, TCIOFLUSH);
201 } else { 209 } else {
202 - int ret;  
203 do { 210 do {
204 /* Extract the garbage from the socket */ 211 /* Extract the garbage from the socket */
205 char devnull[MAX_ADU_LENGTH_TCP]; 212 char devnull[MAX_ADU_LENGTH_TCP];
206 #if (!HAVE_DECL___CYGWIN__) 213 #if (!HAVE_DECL___CYGWIN__)
207 - ret = recv(mb_param->fd, devnull, MAX_ADU_LENGTH_TCP, MSG_DONTWAIT); 214 + rc = recv(mb_param->fd, devnull, MAX_ADU_LENGTH_TCP, MSG_DONTWAIT);
208 #else 215 #else
209 /* On Cygwin, it's a bit more complicated to not wait */ 216 /* On Cygwin, it's a bit more complicated to not wait */
210 fd_set rfds; 217 fd_set rfds;
@@ -214,19 +221,17 @@ void modbus_flush(modbus_param_t *mb_param) @@ -214,19 +221,17 @@ void modbus_flush(modbus_param_t *mb_param)
214 tv.tv_usec = 0; 221 tv.tv_usec = 0;
215 FD_ZERO(&rfds); 222 FD_ZERO(&rfds);
216 FD_SET(mb_param->fd, &rfds); 223 FD_SET(mb_param->fd, &rfds);
217 - ret = select(mb_param->fd+1, &rfds, NULL, NULL, &tv);  
218 - if (ret > 0) {  
219 - ret = recv(mb_param->fd, devnull, MAX_ADU_LENGTH_TCP, 0);  
220 - } else if (ret == -1) {  
221 - /* error_treat() doesn't call modbus_flush() in  
222 - this case (avoid infinite loop) */  
223 - error_treat(mb_param, SELECT_FAILURE, "Select failure"); 224 + rc = select(mb_param->fd+1, &rfds, NULL, NULL, &tv);
  225 + if (rc == -1) {
  226 + return -1;
224 } 227 }
  228 +
  229 + rc = recv(mb_param->fd, devnull, MAX_ADU_LENGTH_TCP, 0);
225 #endif 230 #endif
226 - if (mb_param->debug && ret > 0) {  
227 - printf("%d bytes flushed\n", ret); 231 + if (mb_param->debug && rc != -1) {
  232 + printf("\n%d bytes flushed\n", rc);
228 } 233 }
229 - } while (ret > 0); 234 + } while (rc > 0);
230 } 235 }
231 } 236 }
232 237
@@ -288,12 +293,11 @@ static int build_query_basis_tcp(int slave, int function, @@ -288,12 +293,11 @@ static int build_query_basis_tcp(int slave, int function,
288 uint8_t *query) 293 uint8_t *query)
289 { 294 {
290 295
291 - /* Extract from MODBUS Messaging on TCP/IP Implementation  
292 - Guide V1.0b (page 23/46):  
293 - The transaction identifier is used to associate the future  
294 - response with the request. So, at a time, on a TCP  
295 - connection, this identifier must be unique.  
296 - */ 296 + /* Extract from MODBUS Messaging on TCP/IP Implementation Guide V1.0b
  297 + (page 23/46):
  298 + The transaction identifier is used to associate the future response
  299 + with the request. So, at a time, on a TCP connection, this identifier
  300 + must be unique. */
297 static uint16_t t_id = 0; 301 static uint16_t t_id = 0;
298 302
299 /* Transaction ID */ 303 /* Transaction ID */
@@ -309,7 +313,7 @@ static int build_query_basis_tcp(int slave, int function, @@ -309,7 +313,7 @@ static int build_query_basis_tcp(int slave, int function,
309 query[3] = 0; 313 query[3] = 0;
310 314
311 /* Length will be defined later by set_query_length_tcp at offsets 4 315 /* Length will be defined later by set_query_length_tcp at offsets 4
312 - * and 5 */ 316 + and 5 */
313 317
314 query[6] = slave; 318 query[6] = slave;
315 query[7] = function; 319 query[7] = function;
@@ -400,38 +404,39 @@ static uint16_t crc16(uint8_t *buffer, uint16_t buffer_length) @@ -400,38 +404,39 @@ static uint16_t crc16(uint8_t *buffer, uint16_t buffer_length)
400 return (crc_hi << 8 | crc_lo); 404 return (crc_hi << 8 | crc_lo);
401 } 405 }
402 406
403 -/* If CRC is correct returns msg_length else returns INVALID_CRC */ 407 +/* The check_crc16 function shall return the message length if the CRC is
  408 + valid. Otherwise it shall return -1 and set errno to EMBADCRC. */
404 static int check_crc16(modbus_param_t *mb_param, 409 static int check_crc16(modbus_param_t *mb_param,
405 uint8_t *msg, 410 uint8_t *msg,
406 const int msg_length) 411 const int msg_length)
407 { 412 {
408 - int ret;  
409 - uint16_t crc_calc; 413 + uint16_t crc_calculated;
410 uint16_t crc_received; 414 uint16_t crc_received;
411 415
412 - crc_calc = crc16(msg, msg_length - 2); 416 + crc_calculated = crc16(msg, msg_length - 2);
413 crc_received = (msg[msg_length - 2] << 8) | msg[msg_length - 1]; 417 crc_received = (msg[msg_length - 2] << 8) | msg[msg_length - 1];
414 418
415 /* Check CRC of msg */ 419 /* Check CRC of msg */
416 - if (crc_calc == crc_received) {  
417 - ret = msg_length; 420 + if (crc_calculated == crc_received) {
  421 + return msg_length;
418 } else { 422 } else {
419 - char s_error[64];  
420 - sprintf(s_error,  
421 - "invalid crc received %0X - crc_calc %0X",  
422 - crc_received, crc_calc);  
423 - ret = INVALID_CRC;  
424 - error_treat(mb_param, ret, s_error); 423 + if (mb_param->debug) {
  424 + fprintf(stderr, "ERROR CRC received %0X != CRC calculated %0X\n",
  425 + crc_received, crc_calculated);
  426 + }
  427 + if (mb_param->error_recovery) {
  428 + modbus_flush(mb_param);
  429 + }
  430 + errno = EMBBADCRC;
  431 + return -1;
425 } 432 }
426 -  
427 - return ret;  
428 } 433 }
429 434
430 /* Sends a query/response over a serial or a TCP communication */ 435 /* Sends a query/response over a serial or a TCP communication */
431 static int modbus_send(modbus_param_t *mb_param, uint8_t *query, 436 static int modbus_send(modbus_param_t *mb_param, uint8_t *query,
432 int query_length) 437 int query_length)
433 { 438 {
434 - int ret; 439 + int rc;
435 uint16_t s_crc; 440 uint16_t s_crc;
436 int i; 441 int i;
437 442
@@ -449,19 +454,35 @@ static int modbus_send(modbus_param_t *mb_param, uint8_t *query, @@ -449,19 +454,35 @@ static int modbus_send(modbus_param_t *mb_param, uint8_t *query,
449 printf("\n"); 454 printf("\n");
450 } 455 }
451 456
452 - if (mb_param->type_com == RTU)  
453 - ret = write(mb_param->fd, query, query_length);  
454 - else  
455 - ret = send(mb_param->fd, query, query_length, MSG_NOSIGNAL); 457 + /* In recovery mode, the write command will be issued until to be
  458 + successful! Disabled by default.
  459 + */
  460 + do {
  461 + if (mb_param->type_com == RTU)
  462 + rc = write(mb_param->fd, query, query_length);
  463 + else
  464 + /* MSG_NOSIGNAL
  465 + Requests not to send SIGPIPE on errors on stream oriented
  466 + sockets when the other end breaks the connection. The EPIPE
  467 + error is still returned. */
  468 + rc = send(mb_param->fd, query, query_length, MSG_NOSIGNAL);
  469 +
  470 + if (rc == -1) {
  471 + error_print(mb_param, NULL);
  472 + if (mb_param->error_recovery && (errno == EBADF ||
  473 + errno == ECONNRESET || errno == EPIPE)) {
  474 + modbus_close(mb_param);
  475 + modbus_connect(mb_param);
  476 + }
  477 + }
  478 + } while (mb_param->error_recovery && rc == -1);
456 479
457 - /* Return the number of bytes written (0 to n)  
458 - or SOCKET_FAILURE on error */  
459 - if ((ret == -1) || (ret != query_length)) {  
460 - ret = SOCKET_FAILURE;  
461 - error_treat(mb_param, ret, "Write socket failure"); 480 + if (rc > 0 && rc != query_length) {
  481 + errno = EMBBADDATA;
  482 + return -1;
462 } 483 }
463 484
464 - return ret; 485 + return rc;
465 } 486 }
466 487
467 /* Computes the length of the header following the function code */ 488 /* Computes the length of the header following the function code */
@@ -504,53 +525,68 @@ static int compute_query_length_data(modbus_param_t *mb_param, uint8_t *msg) @@ -504,53 +525,68 @@ static int compute_query_length_data(modbus_param_t *mb_param, uint8_t *msg)
504 return length; 525 return length;
505 } 526 }
506 527
507 -#define WAIT_DATA() \  
508 -{ \  
509 - while ((select_ret = select(mb_param->fd+1, &rfds, NULL, NULL, &tv)) == -1) { \  
510 - if (errno == EINTR) { \  
511 - fprintf(stderr, "A non blocked signal was caught\n"); \  
512 - /* Necessary after an error */ \  
513 - FD_ZERO(&rfds); \  
514 - FD_SET(mb_param->fd, &rfds); \  
515 - } else { \  
516 - error_treat(mb_param, SELECT_FAILURE, "Select failure"); \  
517 - return SELECT_FAILURE; \  
518 - } \  
519 - } \  
520 - \  
521 - if (select_ret == 0) { \  
522 - /* Timeout */ \  
523 - if (msg_length == (TAB_HEADER_LENGTH[mb_param->type_com] + 2 + \  
524 - TAB_CHECKSUM_LENGTH[mb_param->type_com])) { \  
525 - /* Optimization allowed because exception response is \  
526 - the smallest trame in modbus protocol (3) so always \  
527 - raise a timeout error */ \  
528 - return MB_EXCEPTION; \  
529 - } else { \  
530 - /* Call to error_treat is done later to manage exceptions */ \  
531 - return SELECT_TIMEOUT; \  
532 - } \  
533 - } \ 528 +#define WAIT_DATA() \
  529 +{ \
  530 + while ((s_rc = select(mb_param->fd+1, &rfds, NULL, NULL, &tv)) == -1) { \
  531 + if (errno == EINTR) { \
  532 + if (mb_param->debug) { \
  533 + fprintf(stderr, \
  534 + "A non blocked signal was caught\n"); \
  535 + } \
  536 + /* Necessary after an error */ \
  537 + FD_ZERO(&rfds); \
  538 + FD_SET(mb_param->fd, &rfds); \
  539 + } else { \
  540 + error_print(mb_param, "select"); \
  541 + if (mb_param->error_recovery && (errno == EBADF)) { \
  542 + modbus_close(mb_param); \
  543 + modbus_connect(mb_param); \
  544 + errno = EBADF; \
  545 + return -1; \
  546 + } else { \
  547 + return -1; \
  548 + } \
  549 + } \
  550 + } \
  551 + \
  552 + if (s_rc == 0) { \
  553 + /* Timeout */ \
  554 + if (msg_length == (TAB_HEADER_LENGTH[mb_param->type_com] + 2 + \
  555 + TAB_CHECKSUM_LENGTH[mb_param->type_com])) { \
  556 + /* Optimization allowed because exception response is \
  557 + the smallest trame in modbus protocol (3) so always \
  558 + raise a timeout error. \
  559 + Temporary error before exception analyze. */ \
  560 + errno = EMBUNKEXC; \
  561 + } else { \
  562 + errno = ETIMEDOUT; \
  563 + error_print(mb_param, "select"); \
  564 + } \
  565 + return -1; \
  566 + } \
534 } 567 }
535 568
536 /* Waits a reply from a modbus slave or a query from a modbus master. 569 /* Waits a reply from a modbus slave or a query from a modbus master.
537 This function blocks if there is no replies (3 timeouts). 570 This function blocks if there is no replies (3 timeouts).
538 571
539 - In  
540 - - msg_length_computed must be set to MSG_LENGTH_UNDEFINED if undefined  
541 -  
542 - Out  
543 - - msg is an array of uint8_t to receive the message  
544 -  
545 - On success, return the number of received characters. On error, return  
546 - a negative value. 572 + The argument msg_length_computed must be set to MSG_LENGTH_UNDEFINED if
  573 + undefined.
  574 +
  575 + The function shall return the number of received characters and the received
  576 + message in an array of uint8_t if successful. Otherwise it shall return -1
  577 + and errno is set to one of the values defined below:
  578 + - ECONNRESET
  579 + - EMBBADDATA
  580 + - EMBUNKEXC
  581 + - ETIMEDOUT
  582 + - read() or recv() error codes
547 */ 583 */
548 static int receive_msg(modbus_param_t *mb_param, 584 static int receive_msg(modbus_param_t *mb_param,
549 int msg_length_computed, 585 int msg_length_computed,
550 uint8_t *msg) 586 uint8_t *msg)
551 { 587 {
552 - int select_ret;  
553 - int read_ret; 588 + int s_rc;
  589 + int read_rc;
554 fd_set rfds; 590 fd_set rfds;
555 struct timeval tv; 591 struct timeval tv;
556 int length_to_read; 592 int length_to_read;
@@ -591,32 +627,41 @@ static int receive_msg(modbus_param_t *mb_param, @@ -591,32 +627,41 @@ static int receive_msg(modbus_param_t *mb_param,
591 627
592 length_to_read = msg_length_computed; 628 length_to_read = msg_length_computed;
593 629
594 - select_ret = 0; 630 + s_rc = 0;
595 WAIT_DATA(); 631 WAIT_DATA();
596 632
597 p_msg = msg; 633 p_msg = msg;
598 - while (select_ret) { 634 + while (s_rc) {
599 if (mb_param->type_com == RTU) 635 if (mb_param->type_com == RTU)
600 - read_ret = read(mb_param->fd, p_msg, length_to_read); 636 + read_rc = read(mb_param->fd, p_msg, length_to_read);
601 else 637 else
602 - read_ret = recv(mb_param->fd, p_msg, length_to_read, 0);  
603 -  
604 - if (read_ret == 0) {  
605 - return CONNECTION_CLOSED;  
606 - } else if (read_ret < 0) {  
607 - /* The only negative possible value is -1 */  
608 - error_treat(mb_param, SOCKET_FAILURE,  
609 - "Read socket failure");  
610 - return SOCKET_FAILURE; 638 + read_rc = recv(mb_param->fd, p_msg, length_to_read, 0);
  639 +
  640 + if (read_rc == 0) {
  641 + errno = ECONNRESET;
  642 + read_rc = -1;
  643 + }
  644 +
  645 + if (read_rc == -1) {
  646 + error_print(mb_param, "read");
  647 + if (mb_param->error_recovery && (errno == ECONNRESET ||
  648 + errno == ECONNREFUSED)) {
  649 + modbus_close(mb_param);
  650 + modbus_connect(mb_param);
  651 + /* Could be removed by previous calls */
  652 + errno = ECONNRESET;
  653 + return -1;
  654 + }
  655 + return -1;
611 } 656 }
612 657
613 /* Sums bytes received */ 658 /* Sums bytes received */
614 - msg_length += read_ret; 659 + msg_length += read_rc;
615 660
616 /* Display the hex code of each character received */ 661 /* Display the hex code of each character received */
617 if (mb_param->debug) { 662 if (mb_param->debug) {
618 int i; 663 int i;
619 - for (i=0; i < read_ret; i++) 664 + for (i=0; i < read_rc; i++)
620 printf("<%.2X>", p_msg[i]); 665 printf("<%.2X>", p_msg[i]);
621 } 666 }
622 667
@@ -639,8 +684,9 @@ static int receive_msg(modbus_param_t *mb_param, @@ -639,8 +684,9 @@ static int receive_msg(modbus_param_t *mb_param,
639 length_to_read = compute_query_length_data(mb_param, msg); 684 length_to_read = compute_query_length_data(mb_param, msg);
640 msg_length_computed += length_to_read; 685 msg_length_computed += length_to_read;
641 if (msg_length_computed > TAB_MAX_ADU_LENGTH[mb_param->type_com]) { 686 if (msg_length_computed > TAB_MAX_ADU_LENGTH[mb_param->type_com]) {
642 - error_treat(mb_param, INVALID_DATA, "Too many data");  
643 - return INVALID_DATA; 687 + errno = EMBBADDATA;
  688 + error_print(mb_param, "too many data");
  689 + return -1;
644 } 690 }
645 state = COMPLETE; 691 state = COMPLETE;
646 break; 692 break;
@@ -651,7 +697,7 @@ static int receive_msg(modbus_param_t *mb_param, @@ -651,7 +697,7 @@ static int receive_msg(modbus_param_t *mb_param,
651 } 697 }
652 698
653 /* Moves the pointer to receive other data */ 699 /* Moves the pointer to receive other data */
654 - p_msg = &(p_msg[read_ret]); 700 + p_msg = &(p_msg[read_rc]);
655 701
656 if (length_to_read > 0) { 702 if (length_to_read > 0) {
657 /* If no character at the buffer wait 703 /* If no character at the buffer wait
@@ -662,7 +708,7 @@ static int receive_msg(modbus_param_t *mb_param, @@ -662,7 +708,7 @@ static int receive_msg(modbus_param_t *mb_param,
662 WAIT_DATA(); 708 WAIT_DATA();
663 } else { 709 } else {
664 /* All chars are received */ 710 /* All chars are received */
665 - select_ret = FALSE; 711 + s_rc = FALSE;
666 } 712 }
667 } 713 }
668 714
@@ -683,11 +729,8 @@ static int receive_msg(modbus_param_t *mb_param, @@ -683,11 +729,8 @@ static int receive_msg(modbus_param_t *mb_param,
683 descriptor etablished with the master device in argument or -1 to use the 729 descriptor etablished with the master device in argument or -1 to use the
684 internal one of modbus_param_t. 730 internal one of modbus_param_t.
685 731
686 - Returns:  
687 - - byte length of the message on success, or a negative error number if the  
688 - request fails  
689 - - query, message received  
690 -*/ 732 + The modbus_slave_receive function shall return the request received and its
  733 + byte length if successul. Otherwise, it shall return -1 and errno is set. */
691 int modbus_slave_receive(modbus_param_t *mb_param, int sockfd, uint8_t *query) 734 int modbus_slave_receive(modbus_param_t *mb_param, int sockfd, uint8_t *query)
692 { 735 {
693 if (sockfd != -1) { 736 if (sockfd != -1) {
@@ -700,10 +743,8 @@ int modbus_slave_receive(modbus_param_t *mb_param, int sockfd, uint8_t *query) @@ -700,10 +743,8 @@ int modbus_slave_receive(modbus_param_t *mb_param, int sockfd, uint8_t *query)
700 743
701 /* Receives the response and checks values (and checksum in RTU). 744 /* Receives the response and checks values (and checksum in RTU).
702 745
703 - Returns:  
704 - - the number of values (bits or words) if success or the response  
705 - length if no value is returned  
706 - - less than 0 for exception errors 746 + The function shall return the number of values (bits or words) and the
  747 + response if successful. Otherwise, its shall return -1 and errno is set.
707 748
708 Note: all functions used to send or receive data with modbus return 749 Note: all functions used to send or receive data with modbus return
709 these values. */ 750 these values. */
@@ -711,13 +752,13 @@ static int modbus_receive(modbus_param_t *mb_param, @@ -711,13 +752,13 @@ static int modbus_receive(modbus_param_t *mb_param,
711 uint8_t *query, 752 uint8_t *query,
712 uint8_t *response) 753 uint8_t *response)
713 { 754 {
714 - int ret; 755 + int rc;
715 int response_length_computed; 756 int response_length_computed;
716 int offset = TAB_HEADER_LENGTH[mb_param->type_com]; 757 int offset = TAB_HEADER_LENGTH[mb_param->type_com];
717 758
718 response_length_computed = compute_response_length(mb_param, query); 759 response_length_computed = compute_response_length(mb_param, query);
719 - ret = receive_msg(mb_param, response_length_computed, response);  
720 - if (ret >= 0) { 760 + rc = receive_msg(mb_param, response_length_computed, response);
  761 + if (rc != -1) {
721 /* GOOD RESPONSE */ 762 /* GOOD RESPONSE */
722 int query_nb_value; 763 int query_nb_value;
723 int response_nb_value; 764 int response_nb_value;
@@ -748,7 +789,7 @@ static int modbus_receive(modbus_param_t *mb_param, @@ -748,7 +789,7 @@ static int modbus_receive(modbus_param_t *mb_param,
748 break; 789 break;
749 case FC_REPORT_SLAVE_ID: 790 case FC_REPORT_SLAVE_ID:
750 /* Report slave ID (bytes received) */ 791 /* Report slave ID (bytes received) */
751 - query_nb_value = response_nb_value = ret; 792 + query_nb_value = response_nb_value = rc;
752 break; 793 break;
753 default: 794 default:
754 /* 1 Write functions & others */ 795 /* 1 Write functions & others */
@@ -756,58 +797,42 @@ static int modbus_receive(modbus_param_t *mb_param, @@ -756,58 +797,42 @@ static int modbus_receive(modbus_param_t *mb_param,
756 } 797 }
757 798
758 if (query_nb_value == response_nb_value) { 799 if (query_nb_value == response_nb_value) {
759 - ret = response_nb_value; 800 + rc = response_nb_value;
760 } else { 801 } else {
761 - char *s_error = malloc(64 * sizeof(char));  
762 - sprintf(s_error, "Quantity not corresponding to the query (%d != %d)",  
763 - response_nb_value, query_nb_value);  
764 - ret = INVALID_DATA;  
765 - error_treat(mb_param, ret, s_error);  
766 - free(s_error); 802 + if (mb_param->debug) {
  803 + fprintf(stderr,
  804 + "Quantity not corresponding to the query (%d != %d)\n",
  805 + response_nb_value, query_nb_value);
  806 + }
  807 + errno = EMBBADDATA;
  808 + rc = -1;
767 } 809 }
768 - } else if (ret == MB_EXCEPTION) { 810 + } else if (errno == EMBUNKEXC) {
769 /* EXCEPTION CODE RECEIVED */ 811 /* EXCEPTION CODE RECEIVED */
770 812
771 /* CRC must be checked here (not done in receive_msg) */ 813 /* CRC must be checked here (not done in receive_msg) */
772 if (mb_param->type_com == RTU) { 814 if (mb_param->type_com == RTU) {
773 - ret = check_crc16(mb_param, response, EXCEPTION_RESPONSE_LENGTH_RTU);  
774 - if (ret < 0)  
775 - return ret; 815 + rc = check_crc16(mb_param, response, EXCEPTION_RESPONSE_LENGTH_RTU);
  816 + if (rc == -1)
  817 + return -1;
776 } 818 }
777 819
778 /* Check for exception response. 820 /* Check for exception response.
779 0x80 + function is stored in the exception 821 0x80 + function is stored in the exception
780 response. */ 822 response. */
781 if (0x80 + query[offset] == response[offset]) { 823 if (0x80 + query[offset] == response[offset]) {
782 -  
783 int exception_code = response[offset + 1]; 824 int exception_code = response[offset + 1];
784 - // FIXME check test  
785 - if (exception_code < NB_TAB_ERROR_MSG) {  
786 - error_treat(mb_param, -exception_code,  
787 - TAB_ERROR_MSG[response[offset + 1]]);  
788 - /* RETURN THE EXCEPTION CODE */  
789 - /* Modbus error code is negative */  
790 - return -exception_code; 825 + if (exception_code < MODBUS_EXCEPTION_MAX) {
  826 + errno = MODBUS_ENOBASE + exception_code;
791 } else { 827 } else {
792 - /* The chances are low to hit this  
793 - case but it can avoid a vicious  
794 - segfault */  
795 - char *s_error = malloc(64 * sizeof(char));  
796 - sprintf(s_error,  
797 - "Invalid exception code %d",  
798 - response[offset + 1]);  
799 - error_treat(mb_param, INVALID_EXCEPTION_CODE,  
800 - s_error);  
801 - free(s_error);  
802 - return INVALID_EXCEPTION_CODE; 828 + errno = EMBBADEXC;
803 } 829 }
  830 + error_print(mb_param, NULL);
  831 + return -1;
804 } 832 }
805 - } else {  
806 - /* Other errors */  
807 - error_treat(mb_param, ret, "receive_msg");  
808 } 833 }
809 834
810 - return ret; 835 + return rc;
811 } 836 }
812 837
813 static int response_io_status(int address, int nb, 838 static int response_io_status(int address, int nb,
@@ -845,7 +870,7 @@ static int response_exception(modbus_param_t *mb_param, sft_t *sft, @@ -845,7 +870,7 @@ static int response_exception(modbus_param_t *mb_param, sft_t *sft,
845 response_length = build_response_basis(mb_param, sft, response); 870 response_length = build_response_basis(mb_param, sft, response);
846 871
847 /* Positive exception code */ 872 /* Positive exception code */
848 - response[response_length++] = -exception_code; 873 + response[response_length++] = exception_code;
849 874
850 return response_length; 875 return response_length;
851 } 876 }
@@ -856,8 +881,8 @@ static int response_exception(modbus_param_t *mb_param, sft_t *sft, @@ -856,8 +881,8 @@ static int response_exception(modbus_param_t *mb_param, sft_t *sft,
856 If an error occurs, this function construct the response 881 If an error occurs, this function construct the response
857 accordingly. 882 accordingly.
858 */ 883 */
859 -void modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query,  
860 - int query_length, modbus_mapping_t *mb_mapping) 884 +int modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query,
  885 + int query_length, modbus_mapping_t *mb_mapping)
861 { 886 {
862 int offset = TAB_HEADER_LENGTH[mb_param->type_com]; 887 int offset = TAB_HEADER_LENGTH[mb_param->type_com];
863 int slave = query[offset - 1]; 888 int slave = query[offset - 1];
@@ -873,7 +898,7 @@ void modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query, @@ -873,7 +898,7 @@ void modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query,
873 printf("Request for slave %d ignored (not %d)\n", 898 printf("Request for slave %d ignored (not %d)\n",
874 slave, mb_param->slave); 899 slave, mb_param->slave);
875 } 900 }
876 - return; 901 + return 0;
877 } 902 }
878 903
879 sft.slave = slave; 904 sft.slave = slave;
@@ -890,10 +915,13 @@ void modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query, @@ -890,10 +915,13 @@ void modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query,
890 int nb = (query[offset + 3] << 8) + query[offset + 4]; 915 int nb = (query[offset + 3] << 8) + query[offset + 4];
891 916
892 if ((address + nb) > mb_mapping->nb_coil_status) { 917 if ((address + nb) > mb_mapping->nb_coil_status) {
893 - printf("Illegal data address %0X in read_coil_status\n",  
894 - address + nb);  
895 - resp_length = response_exception(mb_param, &sft,  
896 - ILLEGAL_DATA_ADDRESS, response); 918 + if (mb_param->debug) {
  919 + fprintf(stderr, "Illegal data address %0X in read_coil_status\n",
  920 + address + nb);
  921 + }
  922 + resp_length = response_exception(
  923 + mb_param, &sft,
  924 + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);
897 } else { 925 } else {
898 resp_length = build_response_basis(mb_param, &sft, response); 926 resp_length = build_response_basis(mb_param, &sft, response);
899 response[resp_length++] = (nb / 8) + ((nb % 8) ? 1 : 0); 927 response[resp_length++] = (nb / 8) + ((nb % 8) ? 1 : 0);
@@ -909,10 +937,13 @@ void modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query, @@ -909,10 +937,13 @@ void modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query,
909 int nb = (query[offset + 3] << 8) + query[offset + 4]; 937 int nb = (query[offset + 3] << 8) + query[offset + 4];
910 938
911 if ((address + nb) > mb_mapping->nb_input_status) { 939 if ((address + nb) > mb_mapping->nb_input_status) {
912 - printf("Illegal data address %0X in read_input_status\n",  
913 - address + nb);  
914 - resp_length = response_exception(mb_param, &sft,  
915 - ILLEGAL_DATA_ADDRESS, response); 940 + if (mb_param->debug) {
  941 + fprintf(stderr, "Illegal data address %0X in read_input_status\n",
  942 + address + nb);
  943 + }
  944 + resp_length = response_exception(
  945 + mb_param, &sft,
  946 + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);
916 } else { 947 } else {
917 resp_length = build_response_basis(mb_param, &sft, response); 948 resp_length = build_response_basis(mb_param, &sft, response);
918 response[resp_length++] = (nb / 8) + ((nb % 8) ? 1 : 0); 949 response[resp_length++] = (nb / 8) + ((nb % 8) ? 1 : 0);
@@ -926,10 +957,13 @@ void modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query, @@ -926,10 +957,13 @@ void modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query,
926 int nb = (query[offset + 3] << 8) + query[offset + 4]; 957 int nb = (query[offset + 3] << 8) + query[offset + 4];
927 958
928 if ((address + nb) > mb_mapping->nb_holding_registers) { 959 if ((address + nb) > mb_mapping->nb_holding_registers) {
929 - printf("Illegal data address %0X in read_holding_registers\n",  
930 - address + nb);  
931 - resp_length = response_exception(mb_param, &sft,  
932 - ILLEGAL_DATA_ADDRESS, response); 960 + if (mb_param->debug) {
  961 + fprintf(stderr, "Illegal data address %0X in read_holding_registers\n",
  962 + address + nb);
  963 + }
  964 + resp_length = response_exception(
  965 + mb_param, &sft,
  966 + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);
933 } else { 967 } else {
934 int i; 968 int i;
935 969
@@ -948,10 +982,13 @@ void modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query, @@ -948,10 +982,13 @@ void modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query,
948 int nb = (query[offset + 3] << 8) + query[offset + 4]; 982 int nb = (query[offset + 3] << 8) + query[offset + 4];
949 983
950 if ((address + nb) > mb_mapping->nb_input_registers) { 984 if ((address + nb) > mb_mapping->nb_input_registers) {
951 - printf("Illegal data address %0X in read_input_registers\n",  
952 - address + nb);  
953 - resp_length = response_exception(mb_param, &sft,  
954 - ILLEGAL_DATA_ADDRESS, response); 985 + if (mb_param->debug) {
  986 + fprintf(stderr, "Illegal data address %0X in read_input_registers\n",
  987 + address + nb);
  988 + }
  989 + resp_length = response_exception(
  990 + mb_param, &sft,
  991 + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);
955 } else { 992 } else {
956 int i; 993 int i;
957 994
@@ -966,9 +1003,13 @@ void modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query, @@ -966,9 +1003,13 @@ void modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query,
966 break; 1003 break;
967 case FC_FORCE_SINGLE_COIL: 1004 case FC_FORCE_SINGLE_COIL:
968 if (address >= mb_mapping->nb_coil_status) { 1005 if (address >= mb_mapping->nb_coil_status) {
969 - printf("Illegal data address %0X in force_singe_coil\n", address);  
970 - resp_length = response_exception(mb_param, &sft,  
971 - ILLEGAL_DATA_ADDRESS, response); 1006 + if (mb_param->debug) {
  1007 + fprintf(stderr, "Illegal data address %0X in force_singe_coil\n",
  1008 + address);
  1009 + }
  1010 + resp_length = response_exception(
  1011 + mb_param, &sft,
  1012 + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);
972 } else { 1013 } else {
973 int data = (query[offset + 3] << 8) + query[offset + 4]; 1014 int data = (query[offset + 3] << 8) + query[offset + 4];
974 1015
@@ -982,18 +1023,25 @@ void modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query, @@ -982,18 +1023,25 @@ void modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query,
982 memcpy(response, query, query_length); 1023 memcpy(response, query, query_length);
983 resp_length = query_length; 1024 resp_length = query_length;
984 } else { 1025 } else {
985 - printf("Illegal data value %0X in force_single_coil request at address %0X\n",  
986 - data, address);  
987 - resp_length = response_exception(mb_param, &sft,  
988 - ILLEGAL_DATA_VALUE, response); 1026 + if (mb_param->debug) {
  1027 + fprintf(stderr, "Illegal data value %0X in force_single_coil request at address %0X\n",
  1028 + data, address);
  1029 + }
  1030 + resp_length = response_exception(
  1031 + mb_param, &sft,
  1032 + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, response);
989 } 1033 }
990 } 1034 }
991 break; 1035 break;
992 case FC_PRESET_SINGLE_REGISTER: 1036 case FC_PRESET_SINGLE_REGISTER:
993 if (address >= mb_mapping->nb_holding_registers) { 1037 if (address >= mb_mapping->nb_holding_registers) {
994 - printf("Illegal data address %0X in preset_holding_register\n", address);  
995 - resp_length = response_exception(mb_param, &sft,  
996 - ILLEGAL_DATA_ADDRESS, response); 1038 + if (mb_param->debug) {
  1039 + fprintf(stderr, "Illegal data address %0X in preset_holding_register\n",
  1040 + address);
  1041 + }
  1042 + resp_length = response_exception(
  1043 + mb_param, &sft,
  1044 + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);
997 } else { 1045 } else {
998 int data = (query[offset + 3] << 8) + query[offset + 4]; 1046 int data = (query[offset + 3] << 8) + query[offset + 4];
999 1047
@@ -1006,10 +1054,13 @@ void modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query, @@ -1006,10 +1054,13 @@ void modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query,
1006 int nb = (query[offset + 3] << 8) + query[offset + 4]; 1054 int nb = (query[offset + 3] << 8) + query[offset + 4];
1007 1055
1008 if ((address + nb) > mb_mapping->nb_coil_status) { 1056 if ((address + nb) > mb_mapping->nb_coil_status) {
1009 - printf("Illegal data address %0X in force_multiple_coils\n",  
1010 - address + nb);  
1011 - resp_length = response_exception(mb_param, &sft,  
1012 - ILLEGAL_DATA_ADDRESS, response); 1057 + if (mb_param->debug) {
  1058 + fprintf(stderr, "Illegal data address %0X in force_multiple_coils\n",
  1059 + address + nb);
  1060 + }
  1061 + resp_length = response_exception(
  1062 + mb_param, &sft,
  1063 + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);
1013 } else { 1064 } else {
1014 /* 6 = byte count */ 1065 /* 6 = byte count */
1015 set_bits_from_bytes(mb_mapping->tab_coil_status, address, nb, &query[offset + 6]); 1066 set_bits_from_bytes(mb_mapping->tab_coil_status, address, nb, &query[offset + 6]);
@@ -1025,10 +1076,13 @@ void modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query, @@ -1025,10 +1076,13 @@ void modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query,
1025 int nb = (query[offset + 3] << 8) + query[offset + 4]; 1076 int nb = (query[offset + 3] << 8) + query[offset + 4];
1026 1077
1027 if ((address + nb) > mb_mapping->nb_holding_registers) { 1078 if ((address + nb) > mb_mapping->nb_holding_registers) {
1028 - printf("Illegal data address %0X in preset_multiple_registers\n",  
1029 - address + nb);  
1030 - resp_length = response_exception(mb_param, &sft,  
1031 - ILLEGAL_DATA_ADDRESS, response); 1079 + if (mb_param->debug) {
  1080 + fprintf(stderr, "Illegal data address %0X in preset_multiple_registers\n",
  1081 + address + nb);
  1082 + }
  1083 + resp_length = response_exception(
  1084 + mb_param, &sft,
  1085 + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);
1032 } else { 1086 } else {
1033 int i, j; 1087 int i, j;
1034 for (i = address, j = 6; i < address + nb; i++, j += 2) { 1088 for (i = address, j = 6; i < address + nb; i++, j += 2) {
@@ -1046,18 +1100,25 @@ void modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query, @@ -1046,18 +1100,25 @@ void modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query,
1046 break; 1100 break;
1047 case FC_READ_EXCEPTION_STATUS: 1101 case FC_READ_EXCEPTION_STATUS:
1048 case FC_REPORT_SLAVE_ID: 1102 case FC_REPORT_SLAVE_ID:
1049 - printf("Not implemented\n"); 1103 + if (mb_param->debug) {
  1104 + fprintf(stderr, "FIXME Not implemented\n");
  1105 + }
  1106 + errno = ENOPROTOOPT;
  1107 + return -1;
  1108 + break;
  1109 + default:
  1110 + /* FIXME Invalid function exception */
1050 break; 1111 break;
1051 } 1112 }
1052 1113
1053 - modbus_send(mb_param, response, resp_length); 1114 + return modbus_send(mb_param, response, resp_length);
1054 } 1115 }
1055 1116
1056 /* Reads IO status */ 1117 /* Reads IO status */
1057 static int read_io_status(modbus_param_t *mb_param, int function, 1118 static int read_io_status(modbus_param_t *mb_param, int function,
1058 int start_addr, int nb, uint8_t *data_dest) 1119 int start_addr, int nb, uint8_t *data_dest)
1059 { 1120 {
1060 - int ret; 1121 + int rc;
1061 int query_length; 1122 int query_length;
1062 1123
1063 uint8_t query[MIN_QUERY_LENGTH]; 1124 uint8_t query[MIN_QUERY_LENGTH];
@@ -1066,19 +1127,19 @@ static int read_io_status(modbus_param_t *mb_param, int function, @@ -1066,19 +1127,19 @@ static int read_io_status(modbus_param_t *mb_param, int function,
1066 query_length = build_query_basis(mb_param, function, 1127 query_length = build_query_basis(mb_param, function,
1067 start_addr, nb, query); 1128 start_addr, nb, query);
1068 1129
1069 - ret = modbus_send(mb_param, query, query_length);  
1070 - if (ret > 0) { 1130 + rc = modbus_send(mb_param, query, query_length);
  1131 + if (rc > 0) {
1071 int i, temp, bit; 1132 int i, temp, bit;
1072 int pos = 0; 1133 int pos = 0;
1073 int offset; 1134 int offset;
1074 int offset_end; 1135 int offset_end;
1075 1136
1076 - ret = modbus_receive(mb_param, query, response);  
1077 - if (ret < 0)  
1078 - return ret; 1137 + rc = modbus_receive(mb_param, query, response);
  1138 + if (rc == -1)
  1139 + return -1;
1079 1140
1080 offset = TAB_HEADER_LENGTH[mb_param->type_com]; 1141 offset = TAB_HEADER_LENGTH[mb_param->type_com];
1081 - offset_end = offset + ret; 1142 + offset_end = offset + rc;
1082 for (i = offset; i < offset_end; i++) { 1143 for (i = offset; i < offset_end; i++) {
1083 /* Shift reg hi_byte to temp */ 1144 /* Shift reg hi_byte to temp */
1084 temp = response[i + 2]; 1145 temp = response[i + 2];
@@ -1091,7 +1152,7 @@ static int read_io_status(modbus_param_t *mb_param, int function, @@ -1091,7 +1152,7 @@ static int read_io_status(modbus_param_t *mb_param, int function,
1091 } 1152 }
1092 } 1153 }
1093 1154
1094 - return ret; 1155 + return rc;
1095 } 1156 }
1096 1157
1097 /* Reads the boolean status of coils and sets the array elements 1158 /* Reads the boolean status of coils and sets the array elements
@@ -1099,22 +1160,25 @@ static int read_io_status(modbus_param_t *mb_param, int function, @@ -1099,22 +1160,25 @@ static int read_io_status(modbus_param_t *mb_param, int function,
1099 int read_coil_status(modbus_param_t *mb_param, int start_addr, 1160 int read_coil_status(modbus_param_t *mb_param, int start_addr,
1100 int nb, uint8_t *data_dest) 1161 int nb, uint8_t *data_dest)
1101 { 1162 {
1102 - int status; 1163 + int rc;
1103 1164
1104 if (nb > MAX_STATUS) { 1165 if (nb > MAX_STATUS) {
1105 - fprintf(stderr,  
1106 - "ERROR Too many coils status requested (%d > %d)\n",  
1107 - nb, MAX_STATUS);  
1108 - return INVALID_DATA; 1166 + if (mb_param->debug) {
  1167 + fprintf(stderr,
  1168 + "ERROR Too many coils status requested (%d > %d)\n",
  1169 + nb, MAX_STATUS);
  1170 + }
  1171 + errno = EMBMDATA;
  1172 + return -1;
1109 } 1173 }
1110 1174
1111 - status = read_io_status(mb_param, FC_READ_COIL_STATUS,  
1112 - start_addr, nb, data_dest);  
1113 -  
1114 - if (status > 0)  
1115 - status = nb; 1175 + rc = read_io_status(mb_param, FC_READ_COIL_STATUS, start_addr, nb,
  1176 + data_dest);
1116 1177
1117 - return status; 1178 + if (rc == -1)
  1179 + return -1;
  1180 + else
  1181 + return nb;
1118 } 1182 }
1119 1183
1120 1184
@@ -1122,61 +1186,67 @@ int read_coil_status(modbus_param_t *mb_param, int start_addr, @@ -1122,61 +1186,67 @@ int read_coil_status(modbus_param_t *mb_param, int start_addr,
1122 int read_input_status(modbus_param_t *mb_param, int start_addr, 1186 int read_input_status(modbus_param_t *mb_param, int start_addr,
1123 int nb, uint8_t *data_dest) 1187 int nb, uint8_t *data_dest)
1124 { 1188 {
1125 - int status; 1189 + int rc;
1126 1190
1127 if (nb > MAX_STATUS) { 1191 if (nb > MAX_STATUS) {
1128 - fprintf(stderr,  
1129 - "ERROR Too many input status requested (%d > %d)\n",  
1130 - nb, MAX_STATUS);  
1131 - return INVALID_DATA; 1192 + if (mb_param->debug) {
  1193 + fprintf(stderr,
  1194 + "ERROR Too many input status requested (%d > %d)\n",
  1195 + nb, MAX_STATUS);
  1196 + }
  1197 + errno = EMBMDATA;
  1198 + return -1;
1132 } 1199 }
1133 1200
1134 - status = read_io_status(mb_param, FC_READ_INPUT_STATUS,  
1135 - start_addr, nb, data_dest); 1201 + rc = read_io_status(mb_param, FC_READ_INPUT_STATUS, start_addr,
  1202 + nb, data_dest);
1136 1203
1137 - if (status > 0)  
1138 - status = nb;  
1139 -  
1140 - return status; 1204 + if (rc == -1)
  1205 + return -1;
  1206 + else
  1207 + return nb;
1141 } 1208 }
1142 1209
1143 /* Reads the data from a modbus slave and put that data into an array */ 1210 /* Reads the data from a modbus slave and put that data into an array */
1144 static int read_registers(modbus_param_t *mb_param, int function, 1211 static int read_registers(modbus_param_t *mb_param, int function,
1145 int start_addr, int nb, uint16_t *data_dest) 1212 int start_addr, int nb, uint16_t *data_dest)
1146 { 1213 {
1147 - int ret; 1214 + int rc;
1148 int query_length; 1215 int query_length;
1149 uint8_t query[MIN_QUERY_LENGTH]; 1216 uint8_t query[MIN_QUERY_LENGTH];
1150 uint8_t response[MAX_MESSAGE_LENGTH]; 1217 uint8_t response[MAX_MESSAGE_LENGTH];
1151 1218
1152 if (nb > MAX_REGISTERS) { 1219 if (nb > MAX_REGISTERS) {
1153 - fprintf(stderr,  
1154 - "ERROR Too many holding registers requested (%d > %d)\n",  
1155 - nb, MAX_REGISTERS);  
1156 - return INVALID_DATA; 1220 + if (mb_param->debug) {
  1221 + fprintf(stderr,
  1222 + "ERROR Too many holding registers requested (%d > %d)\n",
  1223 + nb, MAX_REGISTERS);
  1224 + }
  1225 + errno = EMBMDATA;
  1226 + return -1;
1157 } 1227 }
1158 1228
1159 query_length = build_query_basis(mb_param, function, 1229 query_length = build_query_basis(mb_param, function,
1160 start_addr, nb, query); 1230 start_addr, nb, query);
1161 1231
1162 - ret = modbus_send(mb_param, query, query_length);  
1163 - if (ret > 0) { 1232 + rc = modbus_send(mb_param, query, query_length);
  1233 + if (rc > 0) {
1164 int offset; 1234 int offset;
1165 int i; 1235 int i;
1166 1236
1167 - ret = modbus_receive(mb_param, query, response); 1237 + rc = modbus_receive(mb_param, query, response);
1168 1238
1169 offset = TAB_HEADER_LENGTH[mb_param->type_com]; 1239 offset = TAB_HEADER_LENGTH[mb_param->type_com];
1170 1240
1171 - /* If ret is negative, the loop is jumped ! */  
1172 - for (i = 0; i < ret; i++) { 1241 + /* If rc is negative, the loop is jumped ! */
  1242 + for (i = 0; i < rc; i++) {
1173 /* shift reg hi_byte to temp OR with lo_byte */ 1243 /* shift reg hi_byte to temp OR with lo_byte */
1174 data_dest[i] = (response[offset + 2 + (i << 1)] << 8) | 1244 data_dest[i] = (response[offset + 2 + (i << 1)] << 8) |
1175 response[offset + 3 + (i << 1)]; 1245 response[offset + 3 + (i << 1)];
1176 } 1246 }
1177 } 1247 }
1178 1248
1179 - return ret; 1249 + return rc;
1180 } 1250 }
1181 1251
1182 /* Reads the holding registers in a slave and put the data into an 1252 /* Reads the holding registers in a slave and put the data into an
@@ -1187,10 +1257,13 @@ int read_holding_registers(modbus_param_t *mb_param, @@ -1187,10 +1257,13 @@ int read_holding_registers(modbus_param_t *mb_param,
1187 int status; 1257 int status;
1188 1258
1189 if (nb > MAX_REGISTERS) { 1259 if (nb > MAX_REGISTERS) {
1190 - fprintf(stderr,  
1191 - "ERROR Too many holding registers requested (%d > %d)\n",  
1192 - nb, MAX_REGISTERS);  
1193 - return INVALID_DATA; 1260 + if (mb_param->debug) {
  1261 + fprintf(stderr,
  1262 + "ERROR Too many holding registers requested (%d > %d)\n",
  1263 + nb, MAX_REGISTERS);
  1264 + }
  1265 + errno = EMBMDATA;
  1266 + return -1;
1194 } 1267 }
1195 1268
1196 status = read_registers(mb_param, FC_READ_HOLDING_REGISTERS, 1269 status = read_registers(mb_param, FC_READ_HOLDING_REGISTERS,
@@ -1209,7 +1282,8 @@ int read_input_registers(modbus_param_t *mb_param, int start_addr, int nb, @@ -1209,7 +1282,8 @@ int read_input_registers(modbus_param_t *mb_param, int start_addr, int nb,
1209 fprintf(stderr, 1282 fprintf(stderr,
1210 "ERROR Too many input registers requested (%d > %d)\n", 1283 "ERROR Too many input registers requested (%d > %d)\n",
1211 nb, MAX_REGISTERS); 1284 nb, MAX_REGISTERS);
1212 - return INVALID_DATA; 1285 + errno = EMBMDATA;
  1286 + return -1;
1213 } 1287 }
1214 1288
1215 status = read_registers(mb_param, FC_READ_INPUT_REGISTERS, 1289 status = read_registers(mb_param, FC_READ_INPUT_REGISTERS,
@@ -1223,22 +1297,22 @@ int read_input_registers(modbus_param_t *mb_param, int start_addr, int nb, @@ -1223,22 +1297,22 @@ int read_input_registers(modbus_param_t *mb_param, int start_addr, int nb,
1223 static int set_single(modbus_param_t *mb_param, int function, 1297 static int set_single(modbus_param_t *mb_param, int function,
1224 int addr, int value) 1298 int addr, int value)
1225 { 1299 {
1226 - int ret; 1300 + int rc;
1227 int query_length; 1301 int query_length;
1228 uint8_t query[MIN_QUERY_LENGTH]; 1302 uint8_t query[MIN_QUERY_LENGTH];
1229 1303
1230 query_length = build_query_basis(mb_param, function, 1304 query_length = build_query_basis(mb_param, function,
1231 addr, value, query); 1305 addr, value, query);
1232 1306
1233 - ret = modbus_send(mb_param, query, query_length);  
1234 - if (ret > 0) { 1307 + rc = modbus_send(mb_param, query, query_length);
  1308 + if (rc > 0) {
1235 /* Used by force_single_coil and 1309 /* Used by force_single_coil and
1236 * preset_single_register */ 1310 * preset_single_register */
1237 uint8_t response[MIN_QUERY_LENGTH]; 1311 uint8_t response[MIN_QUERY_LENGTH];
1238 - ret = modbus_receive(mb_param, query, response); 1312 + rc = modbus_receive(mb_param, query, response);
1239 } 1313 }
1240 1314
1241 - return ret; 1315 + return rc;
1242 } 1316 }
1243 1317
1244 /* Turns ON or OFF a single coil in the slave device */ 1318 /* Turns ON or OFF a single coil in the slave device */
@@ -1270,7 +1344,7 @@ int preset_single_register(modbus_param_t *mb_param, int reg_addr, int value) @@ -1270,7 +1344,7 @@ int preset_single_register(modbus_param_t *mb_param, int reg_addr, int value)
1270 int force_multiple_coils(modbus_param_t *mb_param, int start_addr, int nb, 1344 int force_multiple_coils(modbus_param_t *mb_param, int start_addr, int nb,
1271 const uint8_t *data_src) 1345 const uint8_t *data_src)
1272 { 1346 {
1273 - int ret; 1347 + int rc;
1274 int i; 1348 int i;
1275 int byte_count; 1349 int byte_count;
1276 int query_length; 1350 int query_length;
@@ -1280,9 +1354,12 @@ int force_multiple_coils(modbus_param_t *mb_param, int start_addr, int nb, @@ -1280,9 +1354,12 @@ int force_multiple_coils(modbus_param_t *mb_param, int start_addr, int nb,
1280 uint8_t query[MAX_MESSAGE_LENGTH]; 1354 uint8_t query[MAX_MESSAGE_LENGTH];
1281 1355
1282 if (nb > MAX_STATUS) { 1356 if (nb > MAX_STATUS) {
1283 - fprintf(stderr, "ERROR Writing to too many coils (%d > %d)\n",  
1284 - nb, MAX_STATUS);  
1285 - return INVALID_DATA; 1357 + if (mb_param->debug) {
  1358 + fprintf(stderr, "ERROR Writing to too many coils (%d > %d)\n",
  1359 + nb, MAX_STATUS);
  1360 + }
  1361 + errno = EMBMDATA;
  1362 + return -1;
1286 } 1363 }
1287 1364
1288 query_length = build_query_basis(mb_param, FC_FORCE_MULTIPLE_COILS, 1365 query_length = build_query_basis(mb_param, FC_FORCE_MULTIPLE_COILS,
@@ -1307,21 +1384,21 @@ int force_multiple_coils(modbus_param_t *mb_param, int start_addr, int nb, @@ -1307,21 +1384,21 @@ int force_multiple_coils(modbus_param_t *mb_param, int start_addr, int nb,
1307 query_length++; 1384 query_length++;
1308 } 1385 }
1309 1386
1310 - ret = modbus_send(mb_param, query, query_length);  
1311 - if (ret > 0) { 1387 + rc = modbus_send(mb_param, query, query_length);
  1388 + if (rc > 0) {
1312 uint8_t response[MAX_MESSAGE_LENGTH]; 1389 uint8_t response[MAX_MESSAGE_LENGTH];
1313 - ret = modbus_receive(mb_param, query, response); 1390 + rc = modbus_receive(mb_param, query, response);
1314 } 1391 }
1315 1392
1316 1393
1317 - return ret; 1394 + return rc;
1318 } 1395 }
1319 1396
1320 /* Copies the values in the slave from the array given in argument */ 1397 /* Copies the values in the slave from the array given in argument */
1321 int preset_multiple_registers(modbus_param_t *mb_param, int start_addr, int nb, 1398 int preset_multiple_registers(modbus_param_t *mb_param, int start_addr, int nb,
1322 const uint16_t *data_src) 1399 const uint16_t *data_src)
1323 { 1400 {
1324 - int ret; 1401 + int rc;
1325 int i; 1402 int i;
1326 int query_length; 1403 int query_length;
1327 int byte_count; 1404 int byte_count;
@@ -1329,10 +1406,13 @@ int preset_multiple_registers(modbus_param_t *mb_param, int start_addr, int nb, @@ -1329,10 +1406,13 @@ int preset_multiple_registers(modbus_param_t *mb_param, int start_addr, int nb,
1329 uint8_t query[MAX_MESSAGE_LENGTH]; 1406 uint8_t query[MAX_MESSAGE_LENGTH];
1330 1407
1331 if (nb > MAX_REGISTERS) { 1408 if (nb > MAX_REGISTERS) {
1332 - fprintf(stderr,  
1333 - "ERROR Trying to write to too many registers (%d > %d)\n",  
1334 - nb, MAX_REGISTERS);  
1335 - return INVALID_DATA; 1409 + if (mb_param->debug) {
  1410 + fprintf(stderr,
  1411 + "ERROR Trying to write to too many registers (%d > %d)\n",
  1412 + nb, MAX_REGISTERS);
  1413 + }
  1414 + errno = EMBMDATA;
  1415 + return -1;
1336 } 1416 }
1337 1417
1338 query_length = build_query_basis(mb_param, FC_PRESET_MULTIPLE_REGISTERS, 1418 query_length = build_query_basis(mb_param, FC_PRESET_MULTIPLE_REGISTERS,
@@ -1345,19 +1425,19 @@ int preset_multiple_registers(modbus_param_t *mb_param, int start_addr, int nb, @@ -1345,19 +1425,19 @@ int preset_multiple_registers(modbus_param_t *mb_param, int start_addr, int nb,
1345 query[query_length++] = data_src[i] & 0x00FF; 1425 query[query_length++] = data_src[i] & 0x00FF;
1346 } 1426 }
1347 1427
1348 - ret = modbus_send(mb_param, query, query_length);  
1349 - if (ret > 0) { 1428 + rc = modbus_send(mb_param, query, query_length);
  1429 + if (rc > 0) {
1350 uint8_t response[MAX_MESSAGE_LENGTH]; 1430 uint8_t response[MAX_MESSAGE_LENGTH];
1351 - ret = modbus_receive(mb_param, query, response); 1431 + rc = modbus_receive(mb_param, query, response);
1352 } 1432 }
1353 1433
1354 - return ret; 1434 + return rc;
1355 } 1435 }
1356 1436
1357 /* Returns the slave id! */ 1437 /* Returns the slave id! */
1358 int report_slave_id(modbus_param_t *mb_param, uint8_t *data_dest) 1438 int report_slave_id(modbus_param_t *mb_param, uint8_t *data_dest)
1359 { 1439 {
1360 - int ret; 1440 + int rc;
1361 int query_length; 1441 int query_length;
1362 uint8_t query[MIN_QUERY_LENGTH]; 1442 uint8_t query[MIN_QUERY_LENGTH];
1363 1443
@@ -1366,8 +1446,8 @@ int report_slave_id(modbus_param_t *mb_param, uint8_t *data_dest) @@ -1366,8 +1446,8 @@ int report_slave_id(modbus_param_t *mb_param, uint8_t *data_dest)
1366 /* HACKISH, start_addr and count are not used */ 1446 /* HACKISH, start_addr and count are not used */
1367 query_length -= 4; 1447 query_length -= 4;
1368 1448
1369 - ret = modbus_send(mb_param, query, query_length);  
1370 - if (ret > 0) { 1449 + rc = modbus_send(mb_param, query, query_length);
  1450 + if (rc > 0) {
1371 int i; 1451 int i;
1372 int offset; 1452 int offset;
1373 int offset_end; 1453 int offset_end;
@@ -1375,18 +1455,18 @@ int report_slave_id(modbus_param_t *mb_param, uint8_t *data_dest) @@ -1375,18 +1455,18 @@ int report_slave_id(modbus_param_t *mb_param, uint8_t *data_dest)
1375 1455
1376 /* Byte count, slave id, run indicator status, 1456 /* Byte count, slave id, run indicator status,
1377 additional data */ 1457 additional data */
1378 - ret = modbus_receive(mb_param, query, response);  
1379 - if (ret < 0)  
1380 - return ret; 1458 + rc = modbus_receive(mb_param, query, response);
  1459 + if (rc == -1)
  1460 + return rc;
1381 1461
1382 offset = TAB_HEADER_LENGTH[mb_param->type_com] - 1; 1462 offset = TAB_HEADER_LENGTH[mb_param->type_com] - 1;
1383 - offset_end = offset + ret; 1463 + offset_end = offset + rc;
1384 1464
1385 for (i = offset; i < offset_end; i++) 1465 for (i = offset; i < offset_end; i++)
1386 data_dest[i] = response[i]; 1466 data_dest[i] = response[i];
1387 } 1467 }
1388 1468
1389 - return ret; 1469 + return rc;
1390 } 1470 }
1391 1471
1392 /* Initializes the modbus_param_t structure for RTU 1472 /* Initializes the modbus_param_t structure for RTU
@@ -1408,7 +1488,7 @@ void modbus_init_rtu(modbus_param_t *mb_param, const char *device, @@ -1408,7 +1488,7 @@ void modbus_init_rtu(modbus_param_t *mb_param, const char *device,
1408 mb_param->data_bit = data_bit; 1488 mb_param->data_bit = data_bit;
1409 mb_param->stop_bit = stop_bit; 1489 mb_param->stop_bit = stop_bit;
1410 mb_param->type_com = RTU; 1490 mb_param->type_com = RTU;
1411 - mb_param->error_handling = FLUSH_OR_CONNECT_ON_ERROR; 1491 + mb_param->error_recovery = FALSE;
1412 mb_param->slave = slave; 1492 mb_param->slave = slave;
1413 } 1493 }
1414 1494
@@ -1427,7 +1507,7 @@ void modbus_init_tcp(modbus_param_t *mb_param, const char *ip, int port, int sla @@ -1427,7 +1507,7 @@ void modbus_init_tcp(modbus_param_t *mb_param, const char *ip, int port, int sla
1427 strncpy(mb_param->ip, ip, sizeof(char)*16); 1507 strncpy(mb_param->ip, ip, sizeof(char)*16);
1428 mb_param->port = port; 1508 mb_param->port = port;
1429 mb_param->type_com = TCP; 1509 mb_param->type_com = TCP;
1430 - mb_param->error_handling = FLUSH_OR_CONNECT_ON_ERROR; 1510 + mb_param->error_recovery = FALSE;
1431 mb_param->slave = slave; 1511 mb_param->slave = slave;
1432 } 1512 }
1433 1513
@@ -1438,27 +1518,30 @@ void modbus_set_slave(modbus_param_t *mb_param, int slave) @@ -1438,27 +1518,30 @@ void modbus_set_slave(modbus_param_t *mb_param, int slave)
1438 mb_param->slave = slave; 1518 mb_param->slave = slave;
1439 } 1519 }
1440 1520
1441 -/* By default, the error handling mode used is FLUSH_OR_CONNECT_ON_ERROR. 1521 +/*
  1522 + When disabled (default), it is expected that the application will check for error
  1523 + returns and deal with them as necessary.
1442 1524
1443 - With FLUSH_OR_CONNECT_ON_ERROR, the library will attempt an immediate  
1444 - reconnection which may hang for several seconds if the network to  
1445 - the remote target unit is down. 1525 + It's not recommanded to enable error recovery for slave/server.
1446 1526
1447 - With NOP_ON_ERROR, it is expected that the application will  
1448 - check for error returns and deal with them as necessary. 1527 + When enabled, the library will attempt an immediate reconnection which may
  1528 + hang for several seconds if the network to the remote target unit is down.
  1529 + The write will try a infinite close/connect loop until to be successful and
  1530 + the select/read calls will just try to retablish the connection one time
  1531 + then will return an error (if the connecton was down, the values to read are
  1532 + certainly not available anymore after reconnection, except for slave/server).
1449 */ 1533 */
1450 -void modbus_set_error_handling(modbus_param_t *mb_param,  
1451 - error_handling_t error_handling) 1534 +int modbus_set_error_recovery(modbus_param_t *mb_param, int enabled)
1452 { 1535 {
1453 - if (error_handling == FLUSH_OR_CONNECT_ON_ERROR ||  
1454 - error_handling == NOP_ON_ERROR) {  
1455 - mb_param->error_handling = error_handling; 1536 + if (enabled == TRUE || enabled == FALSE) {
  1537 + mb_param->error_recovery = (uint8_t) enabled;
1456 } else { 1538 } else {
1457 - fprintf(stderr,  
1458 - "Invalid setting for error handling (not changed)\n"); 1539 + errno = EINVAL;
  1540 + return -1;
1459 } 1541 }
1460 -}  
1461 1542
  1543 + return 0;
  1544 +}
1462 1545
1463 /* Sets up a serial port for RTU communications */ 1546 /* Sets up a serial port for RTU communications */
1464 static int modbus_connect_rtu(modbus_param_t *mb_param) 1547 static int modbus_connect_rtu(modbus_param_t *mb_param)
@@ -1467,8 +1550,8 @@ static int modbus_connect_rtu(modbus_param_t *mb_param) @@ -1467,8 +1550,8 @@ static int modbus_connect_rtu(modbus_param_t *mb_param)
1467 speed_t speed; 1550 speed_t speed;
1468 1551
1469 if (mb_param->debug) { 1552 if (mb_param->debug) {
1470 - fprintf(stderr, "Opening %s at %d bauds (%s)\n",  
1471 - mb_param->device, mb_param->baud, mb_param->parity); 1553 + printf("Opening %s at %d bauds (%s)\n",
  1554 + mb_param->device, mb_param->baud, mb_param->parity);
1472 } 1555 }
1473 1556
1474 /* The O_NOCTTY flag tells UNIX that this program doesn't want 1557 /* The O_NOCTTY flag tells UNIX that this program doesn't want
@@ -1479,7 +1562,7 @@ static int modbus_connect_rtu(modbus_param_t *mb_param) @@ -1479,7 +1562,7 @@ static int modbus_connect_rtu(modbus_param_t *mb_param)
1479 Timeouts are ignored in canonical input mode or when the 1562 Timeouts are ignored in canonical input mode or when the
1480 NDELAY option is set on the file via open or fcntl */ 1563 NDELAY option is set on the file via open or fcntl */
1481 mb_param->fd = open(mb_param->device, O_RDWR | O_NOCTTY | O_NDELAY | O_EXCL); 1564 mb_param->fd = open(mb_param->device, O_RDWR | O_NOCTTY | O_NDELAY | O_EXCL);
1482 - if (mb_param->fd < 0) { 1565 + if (mb_param->fd == -1) {
1483 fprintf(stderr, "ERROR Can't open the device %s (%s)\n", 1566 fprintf(stderr, "ERROR Can't open the device %s (%s)\n",
1484 mb_param->device, strerror(errno)); 1567 mb_param->device, strerror(errno));
1485 return -1; 1568 return -1;
@@ -1529,15 +1612,16 @@ static int modbus_connect_rtu(modbus_param_t *mb_param) @@ -1529,15 +1612,16 @@ static int modbus_connect_rtu(modbus_param_t *mb_param)
1529 break; 1612 break;
1530 default: 1613 default:
1531 speed = B9600; 1614 speed = B9600;
1532 - fprintf(stderr,  
1533 - "WARNING Unknown baud rate %d for %s (B9600 used)\n",  
1534 - mb_param->baud, mb_param->device); 1615 + if (mb_param->debug) {
  1616 + fprintf(stderr,
  1617 + "WARNING Unknown baud rate %d for %s (B9600 used)\n",
  1618 + mb_param->baud, mb_param->device);
  1619 + }
1535 } 1620 }
1536 1621
1537 /* Set the baud rate */ 1622 /* Set the baud rate */
1538 if ((cfsetispeed(&tios, speed) < 0) || 1623 if ((cfsetispeed(&tios, speed) < 0) ||
1539 (cfsetospeed(&tios, speed) < 0)) { 1624 (cfsetospeed(&tios, speed) < 0)) {
1540 - perror("cfsetispeed/cfsetospeed\n");  
1541 return -1; 1625 return -1;
1542 } 1626 }
1543 1627
@@ -1707,7 +1791,6 @@ static int modbus_connect_rtu(modbus_param_t *mb_param) @@ -1707,7 +1791,6 @@ static int modbus_connect_rtu(modbus_param_t *mb_param)
1707 tios.c_cc[VTIME] = 0; 1791 tios.c_cc[VTIME] = 0;
1708 1792
1709 if (tcsetattr(mb_param->fd, TCSANOW, &tios) < 0) { 1793 if (tcsetattr(mb_param->fd, TCSANOW, &tios) < 0) {
1710 - perror("tcsetattr\n");  
1711 return -1; 1794 return -1;
1712 } 1795 }
1713 1796
@@ -1717,24 +1800,23 @@ static int modbus_connect_rtu(modbus_param_t *mb_param) @@ -1717,24 +1800,23 @@ static int modbus_connect_rtu(modbus_param_t *mb_param)
1717 /* Establishes a modbus TCP connection with a modbus slave */ 1800 /* Establishes a modbus TCP connection with a modbus slave */
1718 static int modbus_connect_tcp(modbus_param_t *mb_param) 1801 static int modbus_connect_tcp(modbus_param_t *mb_param)
1719 { 1802 {
1720 - int ret; 1803 + int rc;
1721 int option; 1804 int option;
1722 struct sockaddr_in addr; 1805 struct sockaddr_in addr;
1723 1806
1724 mb_param->fd = socket(PF_INET, SOCK_STREAM, 0); 1807 mb_param->fd = socket(PF_INET, SOCK_STREAM, 0);
1725 - if (mb_param->fd < 0) {  
1726 - return mb_param->fd; 1808 + if (mb_param->fd == -1) {
  1809 + return -1;
1727 } 1810 }
1728 1811
1729 /* Set the TCP no delay flag */ 1812 /* Set the TCP no delay flag */
1730 /* SOL_TCP = IPPROTO_TCP */ 1813 /* SOL_TCP = IPPROTO_TCP */
1731 option = 1; 1814 option = 1;
1732 - ret = setsockopt(mb_param->fd, IPPROTO_TCP, TCP_NODELAY, 1815 + rc = setsockopt(mb_param->fd, IPPROTO_TCP, TCP_NODELAY,
1733 (const void *)&option, sizeof(int)); 1816 (const void *)&option, sizeof(int));
1734 - if (ret < 0) {  
1735 - perror("setsockopt TCP_NODELAY"); 1817 + if (rc == -1) {
1736 close(mb_param->fd); 1818 close(mb_param->fd);
1737 - return ret; 1819 + return -1;
1738 } 1820 }
1739 1821
1740 #if (!HAVE_DECL___CYGWIN__) 1822 #if (!HAVE_DECL___CYGWIN__)
@@ -1744,12 +1826,11 @@ static int modbus_connect_tcp(modbus_param_t *mb_param) @@ -1744,12 +1826,11 @@ static int modbus_connect_tcp(modbus_param_t *mb_param)
1744 **/ 1826 **/
1745 /* Set the IP low delay option */ 1827 /* Set the IP low delay option */
1746 option = IPTOS_LOWDELAY; 1828 option = IPTOS_LOWDELAY;
1747 - ret = setsockopt(mb_param->fd, IPPROTO_IP, IP_TOS, 1829 + rc = setsockopt(mb_param->fd, IPPROTO_IP, IP_TOS,
1748 (const void *)&option, sizeof(int)); 1830 (const void *)&option, sizeof(int));
1749 - if (ret < 0) {  
1750 - perror("setsockopt IP_TOS"); 1831 + if (rc == -1) {
1751 close(mb_param->fd); 1832 close(mb_param->fd);
1752 - return ret; 1833 + return -1;
1753 } 1834 }
1754 #endif 1835 #endif
1755 1836
@@ -1760,12 +1841,11 @@ static int modbus_connect_tcp(modbus_param_t *mb_param) @@ -1760,12 +1841,11 @@ static int modbus_connect_tcp(modbus_param_t *mb_param)
1760 addr.sin_family = AF_INET; 1841 addr.sin_family = AF_INET;
1761 addr.sin_port = htons(mb_param->port); 1842 addr.sin_port = htons(mb_param->port);
1762 addr.sin_addr.s_addr = inet_addr(mb_param->ip); 1843 addr.sin_addr.s_addr = inet_addr(mb_param->ip);
1763 - ret = connect(mb_param->fd, (struct sockaddr *)&addr, 1844 + rc = connect(mb_param->fd, (struct sockaddr *)&addr,
1764 sizeof(struct sockaddr_in)); 1845 sizeof(struct sockaddr_in));
1765 - if (ret < 0) {  
1766 - perror("connect"); 1846 + if (rc == -1) {
1767 close(mb_param->fd); 1847 close(mb_param->fd);
1768 - return ret; 1848 + return -1;
1769 } 1849 }
1770 1850
1771 return 0; 1851 return 0;
@@ -1775,22 +1855,20 @@ static int modbus_connect_tcp(modbus_param_t *mb_param) @@ -1775,22 +1855,20 @@ static int modbus_connect_tcp(modbus_param_t *mb_param)
1775 Returns 0 on success or -1 on failure. */ 1855 Returns 0 on success or -1 on failure. */
1776 int modbus_connect(modbus_param_t *mb_param) 1856 int modbus_connect(modbus_param_t *mb_param)
1777 { 1857 {
1778 - int ret; 1858 + int rc;
1779 1859
1780 if (mb_param->type_com == RTU) 1860 if (mb_param->type_com == RTU)
1781 - ret = modbus_connect_rtu(mb_param); 1861 + rc = modbus_connect_rtu(mb_param);
1782 else 1862 else
1783 - ret = modbus_connect_tcp(mb_param); 1863 + rc = modbus_connect_tcp(mb_param);
1784 1864
1785 - return ret; 1865 + return rc;
1786 } 1866 }
1787 1867
1788 /* Closes the file descriptor in RTU mode */ 1868 /* Closes the file descriptor in RTU mode */
1789 static void modbus_close_rtu(modbus_param_t *mb_param) 1869 static void modbus_close_rtu(modbus_param_t *mb_param)
1790 { 1870 {
1791 - if (tcsetattr(mb_param->fd, TCSANOW, &(mb_param->old_tios)) < 0)  
1792 - perror("tcsetattr");  
1793 - 1871 + tcsetattr(mb_param->fd, TCSANOW, &(mb_param->old_tios));
1794 close(mb_param->fd); 1872 close(mb_param->fd);
1795 } 1873 }
1796 1874
@@ -1819,7 +1897,8 @@ void modbus_set_debug(modbus_param_t *mb_param, int boolean) @@ -1819,7 +1897,8 @@ void modbus_set_debug(modbus_param_t *mb_param, int boolean)
1819 /* Allocates 4 arrays to store coils, input status, input registers and 1897 /* Allocates 4 arrays to store coils, input status, input registers and
1820 holding registers. The pointers are stored in modbus_mapping structure. 1898 holding registers. The pointers are stored in modbus_mapping structure.
1821 1899
1822 - Returns 0 on success and -1 on failure. 1900 + The modbus_mapping_new() function shall return 0 if successful. Otherwise it
  1901 + shall return -1 and set errno to ENOMEM.
1823 */ 1902 */
1824 int modbus_mapping_new(modbus_mapping_t *mb_mapping, 1903 int modbus_mapping_new(modbus_mapping_t *mb_mapping,
1825 int nb_coil_status, int nb_input_status, 1904 int nb_coil_status, int nb_input_status,
@@ -1829,46 +1908,51 @@ int modbus_mapping_new(modbus_mapping_t *mb_mapping, @@ -1829,46 +1908,51 @@ int modbus_mapping_new(modbus_mapping_t *mb_mapping,
1829 mb_mapping->nb_coil_status = nb_coil_status; 1908 mb_mapping->nb_coil_status = nb_coil_status;
1830 mb_mapping->tab_coil_status = 1909 mb_mapping->tab_coil_status =
1831 (uint8_t *) malloc(nb_coil_status * sizeof(uint8_t)); 1910 (uint8_t *) malloc(nb_coil_status * sizeof(uint8_t));
  1911 + if (mb_mapping->tab_coil_status == NULL) {
  1912 + errno = ENOMEM;
  1913 + return -1;
  1914 + }
1832 memset(mb_mapping->tab_coil_status, 0, 1915 memset(mb_mapping->tab_coil_status, 0,
1833 nb_coil_status * sizeof(uint8_t)); 1916 nb_coil_status * sizeof(uint8_t));
1834 - if (mb_mapping->tab_coil_status == NULL)  
1835 - return -1;  
1836 1917
1837 /* 1X */ 1918 /* 1X */
1838 mb_mapping->nb_input_status = nb_input_status; 1919 mb_mapping->nb_input_status = nb_input_status;
1839 mb_mapping->tab_input_status = 1920 mb_mapping->tab_input_status =
1840 (uint8_t *) malloc(nb_input_status * sizeof(uint8_t)); 1921 (uint8_t *) malloc(nb_input_status * sizeof(uint8_t));
1841 - memset(mb_mapping->tab_input_status, 0,  
1842 - nb_input_status * sizeof(uint8_t));  
1843 if (mb_mapping->tab_input_status == NULL) { 1922 if (mb_mapping->tab_input_status == NULL) {
1844 free(mb_mapping->tab_coil_status); 1923 free(mb_mapping->tab_coil_status);
  1924 + errno = ENOMEM;
1845 return -1; 1925 return -1;
1846 } 1926 }
  1927 + memset(mb_mapping->tab_input_status, 0,
  1928 + nb_input_status * sizeof(uint8_t));
1847 1929
1848 /* 4X */ 1930 /* 4X */
1849 mb_mapping->nb_holding_registers = nb_holding_registers; 1931 mb_mapping->nb_holding_registers = nb_holding_registers;
1850 mb_mapping->tab_holding_registers = 1932 mb_mapping->tab_holding_registers =
1851 (uint16_t *) malloc(nb_holding_registers * sizeof(uint16_t)); 1933 (uint16_t *) malloc(nb_holding_registers * sizeof(uint16_t));
1852 - memset(mb_mapping->tab_holding_registers, 0,  
1853 - nb_holding_registers * sizeof(uint16_t));  
1854 if (mb_mapping->tab_holding_registers == NULL) { 1934 if (mb_mapping->tab_holding_registers == NULL) {
1855 free(mb_mapping->tab_coil_status); 1935 free(mb_mapping->tab_coil_status);
1856 free(mb_mapping->tab_input_status); 1936 free(mb_mapping->tab_input_status);
  1937 + errno = ENOMEM;
1857 return -1; 1938 return -1;
1858 } 1939 }
  1940 + memset(mb_mapping->tab_holding_registers, 0,
  1941 + nb_holding_registers * sizeof(uint16_t));
1859 1942
1860 /* 3X */ 1943 /* 3X */
1861 mb_mapping->nb_input_registers = nb_input_registers; 1944 mb_mapping->nb_input_registers = nb_input_registers;
1862 mb_mapping->tab_input_registers = 1945 mb_mapping->tab_input_registers =
1863 (uint16_t *) malloc(nb_input_registers * sizeof(uint16_t)); 1946 (uint16_t *) malloc(nb_input_registers * sizeof(uint16_t));
1864 - memset(mb_mapping->tab_input_registers, 0,  
1865 - nb_input_registers * sizeof(uint16_t));  
1866 if (mb_mapping->tab_input_registers == NULL) { 1947 if (mb_mapping->tab_input_registers == NULL) {
1867 free(mb_mapping->tab_coil_status); 1948 free(mb_mapping->tab_coil_status);
1868 free(mb_mapping->tab_input_status); 1949 free(mb_mapping->tab_input_status);
1869 free(mb_mapping->tab_holding_registers); 1950 free(mb_mapping->tab_holding_registers);
  1951 + errno = ENOMEM;
1870 return -1; 1952 return -1;
1871 } 1953 }
  1954 + memset(mb_mapping->tab_input_registers, 0,
  1955 + nb_input_registers * sizeof(uint16_t));
1872 1956
1873 return 0; 1957 return 0;
1874 } 1958 }
@@ -1890,15 +1974,13 @@ int modbus_slave_listen_tcp(modbus_param_t *mb_param, int nb_connection) @@ -1890,15 +1974,13 @@ int modbus_slave_listen_tcp(modbus_param_t *mb_param, int nb_connection)
1890 struct sockaddr_in addr; 1974 struct sockaddr_in addr;
1891 1975
1892 new_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 1976 new_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
1893 - if (new_socket < 0) {  
1894 - perror("socket"); 1977 + if (new_socket == -1) {
1895 return -1; 1978 return -1;
1896 } 1979 }
1897 1980
1898 yes = 1; 1981 yes = 1;
1899 if (setsockopt(new_socket, SOL_SOCKET, SO_REUSEADDR, 1982 if (setsockopt(new_socket, SOL_SOCKET, SO_REUSEADDR,
1900 - (char *) &yes, sizeof(yes)) < 0) {  
1901 - perror("setsockopt"); 1983 + (char *) &yes, sizeof(yes)) == -1) {
1902 close(new_socket); 1984 close(new_socket);
1903 return -1; 1985 return -1;
1904 } 1986 }
@@ -1908,14 +1990,12 @@ int modbus_slave_listen_tcp(modbus_param_t *mb_param, int nb_connection) @@ -1908,14 +1990,12 @@ int modbus_slave_listen_tcp(modbus_param_t *mb_param, int nb_connection)
1908 /* If the modbus port is < to 1024, we need the setuid root. */ 1990 /* If the modbus port is < to 1024, we need the setuid root. */
1909 addr.sin_port = htons(mb_param->port); 1991 addr.sin_port = htons(mb_param->port);
1910 addr.sin_addr.s_addr = INADDR_ANY; 1992 addr.sin_addr.s_addr = INADDR_ANY;
1911 - if (bind(new_socket, (struct sockaddr *)&addr, sizeof(addr)) < 0) {  
1912 - perror("bind"); 1993 + if (bind(new_socket, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
1913 close(new_socket); 1994 close(new_socket);
1914 return -1; 1995 return -1;
1915 } 1996 }
1916 1997
1917 - if (listen(new_socket, nb_connection) < 0) {  
1918 - perror("listen"); 1998 + if (listen(new_socket, nb_connection) == -1) {
1919 close(new_socket); 1999 close(new_socket);
1920 return -1; 2000 return -1;
1921 } 2001 }
@@ -1923,6 +2003,9 @@ int modbus_slave_listen_tcp(modbus_param_t *mb_param, int nb_connection) @@ -1923,6 +2003,9 @@ int modbus_slave_listen_tcp(modbus_param_t *mb_param, int nb_connection)
1923 return new_socket; 2003 return new_socket;
1924 } 2004 }
1925 2005
  2006 +/* On success, the function return a non-negative integer that is a descriptor
  2007 + for the accepted socket. On error, -1 is returned, and errno is set
  2008 + appropriately. */
1926 int modbus_slave_accept_tcp(modbus_param_t *mb_param, int *socket) 2009 int modbus_slave_accept_tcp(modbus_param_t *mb_param, int *socket)
1927 { 2010 {
1928 struct sockaddr_in addr; 2011 struct sockaddr_in addr;
@@ -1930,11 +2013,13 @@ int modbus_slave_accept_tcp(modbus_param_t *mb_param, int *socket) @@ -1930,11 +2013,13 @@ int modbus_slave_accept_tcp(modbus_param_t *mb_param, int *socket)
1930 2013
1931 addrlen = sizeof(struct sockaddr_in); 2014 addrlen = sizeof(struct sockaddr_in);
1932 mb_param->fd = accept(*socket, (struct sockaddr *)&addr, &addrlen); 2015 mb_param->fd = accept(*socket, (struct sockaddr *)&addr, &addrlen);
1933 - if (mb_param->fd < 0) {  
1934 - perror("accept"); 2016 + if (mb_param->fd == -1) {
1935 close(*socket); 2017 close(*socket);
1936 *socket = 0; 2018 *socket = 0;
1937 - } else { 2019 + return -1;
  2020 + }
  2021 +
  2022 + if (mb_param->debug) {
1938 printf("The client %s is connected\n", 2023 printf("The client %s is connected\n",
1939 inet_ntoa(addr.sin_addr)); 2024 inet_ntoa(addr.sin_addr));
1940 } 2025 }
@@ -1964,7 +2049,7 @@ void set_bits_from_byte(uint8_t *dest, int address, const uint8_t value) @@ -1964,7 +2049,7 @@ void set_bits_from_byte(uint8_t *dest, int address, const uint8_t value)
1964 2049
1965 /* Sets many input/coil status from a table of bytes (only the bits 2050 /* Sets many input/coil status from a table of bytes (only the bits
1966 between address and address + nb_bits are set) */ 2051 between address and address + nb_bits are set) */
1967 -void set_bits_from_bytes(uint8_t *dest, int address, int nb_bits, 2052 +void set_bits_from_bytes(uint8_t *dest, int address, unsigned int nb_bits,
1968 const uint8_t tab_byte[]) 2053 const uint8_t tab_byte[])
1969 { 2054 {
1970 int i; 2055 int i;
@@ -1980,13 +2065,13 @@ void set_bits_from_bytes(uint8_t *dest, int address, int nb_bits, @@ -1980,13 +2065,13 @@ void set_bits_from_bytes(uint8_t *dest, int address, int nb_bits,
1980 2065
1981 /* Gets the byte value from many input/coil status. 2066 /* Gets the byte value from many input/coil status.
1982 To obtain a full byte, set nb_bits to 8. */ 2067 To obtain a full byte, set nb_bits to 8. */
1983 -uint8_t get_byte_from_bits(const uint8_t *src, int address, int nb_bits) 2068 +uint8_t get_byte_from_bits(const uint8_t *src, int address, unsigned int nb_bits)
1984 { 2069 {
1985 int i; 2070 int i;
1986 uint8_t value = 0; 2071 uint8_t value = 0;
1987 2072
1988 if (nb_bits > 8) { 2073 if (nb_bits > 8) {
1989 - fprintf(stderr, "ERROR nb_bits is too big\n"); 2074 + assert(nb_bits < 8);
1990 nb_bits = 8; 2075 nb_bits = 8;
1991 } 2076 }
1992 2077
modbus/modbus.h
@@ -120,36 +120,47 @@ extern &quot;C&quot; { @@ -120,36 +120,47 @@ extern &quot;C&quot; {
120 #define FC_PRESET_MULTIPLE_REGISTERS 0x10 120 #define FC_PRESET_MULTIPLE_REGISTERS 0x10
121 #define FC_REPORT_SLAVE_ID 0x11 121 #define FC_REPORT_SLAVE_ID 0x11
122 122
  123 +/* Random number to avoid errno conflicts */
  124 +#define MODBUS_ENOBASE 112345678
  125 +
123 /* Protocol exceptions */ 126 /* Protocol exceptions */
124 -#define ILLEGAL_FUNCTION -0x01  
125 -#define ILLEGAL_DATA_ADDRESS -0x02  
126 -#define ILLEGAL_DATA_VALUE -0x03  
127 -#define SLAVE_DEVICE_FAILURE -0x04  
128 -#define SERVER_FAILURE -0x04  
129 -#define ACKNOWLEDGE -0x05  
130 -#define SLAVE_DEVICE_BUSY -0x06  
131 -#define SERVER_BUSY -0x06  
132 -#define NEGATIVE_ACKNOWLEDGE -0x07  
133 -#define MEMORY_PARITY_ERROR -0x08  
134 -#define GATEWAY_PROBLEM_PATH -0x0A  
135 -#define GATEWAY_PROBLEM_TARGET -0x0B  
136 -  
137 -/* Local */  
138 -#define INVALID_DATA -0x10  
139 -#define INVALID_CRC -0x11  
140 -#define INVALID_EXCEPTION_CODE -0x12  
141 -  
142 -#define SELECT_TIMEOUT -0x13  
143 -#define SELECT_FAILURE -0x14  
144 -#define SOCKET_FAILURE -0x15  
145 -#define CONNECTION_CLOSED -0x16  
146 -#define MB_EXCEPTION -0x17 127 +enum {
  128 + MODBUS_EXCEPTION_ILLEGAL_FUNCTION = 0x01,
  129 + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS,
  130 + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
  131 + MODBUS_EXCEPTION_SLAVE_OR_SERVER_FAILURE,
  132 + MODBUS_EXCEPTION_ACKNOWLEDGE,
  133 + MODBUS_EXCEPTION_SLAVE_OR_SERVER_BUSY,
  134 + MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE,
  135 + MODBUS_EXCEPTION_MEMORY_PARITY,
  136 + MODBUS_EXCEPTION_NOT_DEFINED,
  137 + MODBUS_EXCEPTION_GATEWAY_PATH,
  138 + MODBUS_EXCEPTION_GATEWAY_TARGET,
  139 + MODBUS_EXCEPTION_MAX
  140 +};
  141 +
  142 +#define EMBXILFUN (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_FUNCTION)
  143 +#define EMBXILADD (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS)
  144 +#define EMBXILVAL (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE)
  145 +#define EMBXSFAIL (MODBUS_ENOBASE + MODBUS_EXCEPTION_SLAVE_OR_SERVER_FAILURE)
  146 +#define EMBXACK (MODBUS_ENOBASE + MODBUS_EXCEPTION_ACKNOWLEDGE)
  147 +#define EMBXSBUSY (MODBUS_ENOBASE + MODBUS_EXCEPTION_SLAVE_OR_SERVER_BUSY)
  148 +#define EMBXNACK (MODBUS_ENOBASE + MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE)
  149 +#define EMBXMEMPAR (MODBUS_ENOBASE + MODBUS_EXCEPTION_MEMORY_PARITY)
  150 +#define EMBXGPATH (MODBUS_ENOBASE + MODBUS_EXCEPTION_GATEWAY_PATH)
  151 +#define EMBXGTAR (MODBUS_ENOBASE + MODBUS_EXCEPTION_GATEWAY_TARGET)
  152 +
  153 +/* Native libmodbus error codes */
  154 +#define EMBBADCRC (EMBXGTAR + 1)
  155 +#define EMBBADDATA (EMBXGTAR + 2)
  156 +#define EMBBADEXC (EMBXGTAR + 3)
  157 +#define EMBUNKEXC (EMBXGTAR + 4)
  158 +#define EMBMDATA (EMBXGTAR + 5)
147 159
148 /* Internal using */ 160 /* Internal using */
149 #define MSG_LENGTH_UNDEFINED -1 161 #define MSG_LENGTH_UNDEFINED -1
150 162
151 typedef enum { RTU=0, TCP } type_com_t; 163 typedef enum { RTU=0, TCP } type_com_t;
152 -typedef enum { FLUSH_OR_CONNECT_ON_ERROR, NOP_ON_ERROR } error_handling_t;  
153 164
154 /* This structure is byte-aligned */ 165 /* This structure is byte-aligned */
155 typedef struct { 166 typedef struct {
@@ -183,7 +194,7 @@ typedef struct { @@ -183,7 +194,7 @@ typedef struct {
183 /* Parity: "even", "odd", "none" */ 194 /* Parity: "even", "odd", "none" */
184 char parity[5]; 195 char parity[5];
185 /* In error_treat with TCP, do a reconnect or just dump the error */ 196 /* In error_treat with TCP, do a reconnect or just dump the error */
186 - uint8_t error_handling; 197 + uint8_t error_recovery;
187 /* IP address */ 198 /* IP address */
188 char ip[16]; 199 char ip[16];
189 /* Save old termios settings */ 200 /* Save old termios settings */
@@ -201,171 +212,60 @@ typedef struct { @@ -201,171 +212,60 @@ typedef struct {
201 uint16_t *tab_holding_registers; 212 uint16_t *tab_holding_registers;
202 } modbus_mapping_t; 213 } modbus_mapping_t;
203 214
  215 +void modbus_init_rtu(modbus_param_t *mb_param, const char *device,
  216 + int baud, const char *parity, int data_bit,
  217 + int stop_bit, int slave);
  218 +void modbus_init_tcp(modbus_param_t *mb_param, const char *ip_address, int port,
  219 + int slave);
  220 +void modbus_set_slave(modbus_param_t *mb_param, int slave);
  221 +int modbus_set_error_recovery(modbus_param_t *mb_param, int enabled);
204 222
205 -/* All functions used for sending or receiving data return:  
206 - - the numbers of values (bits or word) if success (0 or more)  
207 - - less than 0 for exceptions errors  
208 -*/ 223 +int modbus_connect(modbus_param_t *mb_param);
  224 +void modbus_close(modbus_param_t *mb_param);
  225 +
  226 +int modbus_flush(modbus_param_t *mb_param);
  227 +void modbus_set_debug(modbus_param_t *mb_param, int boolean);
  228 +
  229 +const char *modbus_strerror(int errnum);
209 230
210 -/* Reads the boolean status of coils and sets the array elements in  
211 - the destination to TRUE or FALSE */  
212 int read_coil_status(modbus_param_t *mb_param, int start_addr, int nb, 231 int read_coil_status(modbus_param_t *mb_param, int start_addr, int nb,
213 uint8_t *dest); 232 uint8_t *dest);
214 -  
215 -/* Same as read_coil_status but reads the slaves input table */  
216 int read_input_status(modbus_param_t *mb_param, int start_addr, int nb, 233 int read_input_status(modbus_param_t *mb_param, int start_addr, int nb,
217 uint8_t *dest); 234 uint8_t *dest);
218 -  
219 -/* Reads the holding registers in a slave and put the data into an  
220 - array */  
221 int read_holding_registers(modbus_param_t *mb_param, int start_addr, int nb, 235 int read_holding_registers(modbus_param_t *mb_param, int start_addr, int nb,
222 uint16_t *dest); 236 uint16_t *dest);
223 -  
224 -/* Reads the input registers in a slave and put the data into an  
225 - array */  
226 int read_input_registers(modbus_param_t *mb_param, int start_addr, int nb, 237 int read_input_registers(modbus_param_t *mb_param, int start_addr, int nb,
227 uint16_t *dest); 238 uint16_t *dest);
228 -  
229 -/* Turns ON or OFF a single coil in the slave device */  
230 int force_single_coil(modbus_param_t *mb_param, int coil_addr, int state); 239 int force_single_coil(modbus_param_t *mb_param, int coil_addr, int state);
231 240
232 -/* Sets a value in one holding register in the slave device */  
233 int preset_single_register(modbus_param_t *mb_param, int reg_addr, int value); 241 int preset_single_register(modbus_param_t *mb_param, int reg_addr, int value);
234 -  
235 -/* Sets/resets the coils in the slave from an array in argument */  
236 int force_multiple_coils(modbus_param_t *mb_param, int start_addr, int nb, 242 int force_multiple_coils(modbus_param_t *mb_param, int start_addr, int nb,
237 const uint8_t *data); 243 const uint8_t *data);
238 -  
239 -/* Copies the values in the slave from the array given in argument */  
240 int preset_multiple_registers(modbus_param_t *mb_param, int start_addr, int nb, 244 int preset_multiple_registers(modbus_param_t *mb_param, int start_addr, int nb,
241 const uint16_t *data); 245 const uint16_t *data);
242 -  
243 -/* Returns the slave id! */  
244 int report_slave_id(modbus_param_t *mb_param, uint8_t *dest); 246 int report_slave_id(modbus_param_t *mb_param, uint8_t *dest);
245 247
246 -/* Initializes the modbus_param_t structure for RTU.  
247 - - device: "/dev/ttyS0"  
248 - - baud: 9600, 19200, 57600, 115200, etc  
249 - - parity: "even", "odd" or "none"  
250 - - data_bits: 5, 6, 7, 8  
251 - - stop_bits: 1, 2  
252 -*/  
253 -void modbus_init_rtu(modbus_param_t *mb_param, const char *device,  
254 - int baud, const char *parity, int data_bit,  
255 - int stop_bit, int slave);  
256 -  
257 -/* Initializes the modbus_param_t structure for TCP.  
258 - - ip: "192.168.0.5"  
259 - - port: 1099  
260 - - slave: 5  
261 -  
262 - Set the port to MODBUS_TCP_DEFAULT_PORT to use the default one  
263 - (502). It's convenient to use a port number greater than or equal  
264 - to 1024 because it's not necessary to be root to use this port  
265 - number.  
266 -*/  
267 -void modbus_init_tcp(modbus_param_t *mb_param, const char *ip_address, int port,  
268 - int slave);  
269 -  
270 -/* Define the slave number.  
271 - The special value MODBUS_BROADCAST_ADDRESS can be used. */  
272 -void modbus_set_slave(modbus_param_t *mb_param, int slave);  
273 -  
274 -/* By default, the error handling mode used is CONNECT_ON_ERROR.  
275 -  
276 - With FLUSH_OR_CONNECT_ON_ERROR, the library will attempt an immediate  
277 - reconnection which may hang for several seconds if the network to  
278 - the remote target unit is down.  
279 -  
280 - With NOP_ON_ERROR, it is expected that the application will  
281 - check for network error returns and deal with them as necessary.  
282 -  
283 - This function is only useful in TCP mode.  
284 - */  
285 -void modbus_set_error_handling(modbus_param_t *mb_param, error_handling_t error_handling);  
286 -  
287 -/* Establishes a modbus connexion.  
288 - Returns 0 on success or -1 on failure. */  
289 -int modbus_connect(modbus_param_t *mb_param);  
290 -  
291 -/* Closes a modbus connection */  
292 -void modbus_close(modbus_param_t *mb_param);  
293 -  
294 -/* Flush the pending request */  
295 -void modbus_flush(modbus_param_t *mb_param);  
296 -  
297 -/* Activates the debug messages */  
298 -void modbus_set_debug(modbus_param_t *mb_param, int boolean);  
299 -  
300 -/**  
301 - * SLAVE/CLIENT FUNCTIONS  
302 - **/  
303 -  
304 -/* Allocates 4 arrays to store coils, input status, input registers and  
305 - holding registers. The pointers are stored in modbus_mapping structure.  
306 -  
307 - Returns 0 on success and -1 on failure  
308 - */  
309 int modbus_mapping_new(modbus_mapping_t *mb_mapping, 248 int modbus_mapping_new(modbus_mapping_t *mb_mapping,
310 int nb_coil_status, int nb_input_status, 249 int nb_coil_status, int nb_input_status,
311 int nb_holding_registers, int nb_input_registers); 250 int nb_holding_registers, int nb_input_registers);
312 -  
313 -/* Frees the 4 arrays */  
314 void modbus_mapping_free(modbus_mapping_t *mb_mapping); 251 void modbus_mapping_free(modbus_mapping_t *mb_mapping);
315 252
316 -/* Listens for any query from one or many modbus masters in TCP.  
317 -  
318 - Returns: socket  
319 - */  
320 int modbus_slave_listen_tcp(modbus_param_t *mb_param, int nb_connection); 253 int modbus_slave_listen_tcp(modbus_param_t *mb_param, int nb_connection);
321 -  
322 -/* Waits for a connection */  
323 int modbus_slave_accept_tcp(modbus_param_t *mb_param, int *socket); 254 int modbus_slave_accept_tcp(modbus_param_t *mb_param, int *socket);
324 -  
325 -/* Listens for any query from a modbus master in TCP, requires the socket file  
326 - descriptor etablished with the master device in argument or -1 to use the  
327 - internal one of modbus_param_t.  
328 -  
329 - Returns:  
330 - - byte length of the message on success, or a negative error number if the  
331 - request fails  
332 - - query, message received  
333 -*/  
334 int modbus_slave_receive(modbus_param_t *mb_param, int sockfd, uint8_t *query); 255 int modbus_slave_receive(modbus_param_t *mb_param, int sockfd, uint8_t *query);
335 -  
336 -/* Manages the received query.  
337 - Analyses the query and constructs a response.  
338 -  
339 - If an error occurs, this function construct the response  
340 - accordingly.  
341 -*/  
342 -void modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query,  
343 - int query_length, modbus_mapping_t *mb_mapping);  
344 -  
345 -/* Closes a TCP socket */ 256 +int modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query,
  257 + int query_length, modbus_mapping_t *mb_mapping);
346 void modbus_slave_close_tcp(int socket); 258 void modbus_slave_close_tcp(int socket);
347 259
348 /** 260 /**
349 * UTILS FUNCTIONS 261 * UTILS FUNCTIONS
350 **/ 262 **/
351 263
352 -/* Sets many input/coil status from a single byte value (all 8 bits of  
353 - the byte value are set) */  
354 void set_bits_from_byte(uint8_t *dest, int address, const uint8_t value); 264 void set_bits_from_byte(uint8_t *dest, int address, const uint8_t value);
355 -  
356 -/* Sets many input/coil status from a table of bytes (only the bits  
357 - between address and address + nb_bits are set) */  
358 -void set_bits_from_bytes(uint8_t *dest, int address, int nb_bits, 265 +void set_bits_from_bytes(uint8_t *dest, int address, unsigned int nb_bits,
359 const uint8_t *tab_byte); 266 const uint8_t *tab_byte);
360 -  
361 -/* Gets the byte value from many input/coil status.  
362 - To obtain a full byte, set nb_bits to 8. */  
363 -uint8_t get_byte_from_bits(const uint8_t *src, int address, int nb_bits);  
364 -  
365 -/* Read a float from 4 bytes in Modbus format */ 267 +uint8_t get_byte_from_bits(const uint8_t *src, int address, unsigned int nb_bits);
366 float modbus_read_float(const uint16_t *src); 268 float modbus_read_float(const uint16_t *src);
367 -  
368 -/* Write a float to 4 bytes in Modbus format */  
369 void modbus_write_float(float real, uint16_t *dest); 269 void modbus_write_float(float real, uint16_t *dest);
370 270
371 #ifdef __cplusplus 271 #ifdef __cplusplus
tests/bandwidth-master.c
@@ -21,6 +21,7 @@ @@ -21,6 +21,7 @@
21 #include <stdlib.h> 21 #include <stdlib.h>
22 #include <time.h> 22 #include <time.h>
23 #include <sys/time.h> 23 #include <sys/time.h>
  24 +#include <errno.h>
24 25
25 #include <modbus/modbus.h> 26 #include <modbus/modbus.h>
26 27
@@ -44,18 +45,21 @@ int main(void) @@ -44,18 +45,21 @@ int main(void)
44 uint16_t *tab_rp_registers; 45 uint16_t *tab_rp_registers;
45 modbus_param_t mb_param; 46 modbus_param_t mb_param;
46 int i; 47 int i;
47 - int ret;  
48 int nb_points; 48 int nb_points;
49 double elapsed; 49 double elapsed;
50 uint32_t start; 50 uint32_t start;
51 uint32_t end; 51 uint32_t end;
52 uint32_t bytes; 52 uint32_t bytes;
53 uint32_t rate; 53 uint32_t rate;
  54 + int rc;
54 55
55 /* TCP */ 56 /* TCP */
56 modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE); 57 modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE);
57 - if (modbus_connect(&mb_param) == -1) {  
58 - exit(1); 58 + rc = modbus_connect(&mb_param);
  59 + if (rc == -1) {
  60 + fprintf(stderr, "Connexion failed: %s\n",
  61 + modbus_strerror(errno));
  62 + return -1;
59 } 63 }
60 64
61 /* Allocate and initialize the memory to store the status */ 65 /* Allocate and initialize the memory to store the status */
@@ -71,7 +75,11 @@ int main(void) @@ -71,7 +75,11 @@ int main(void)
71 nb_points = MAX_STATUS; 75 nb_points = MAX_STATUS;
72 start = gettime_ms(); 76 start = gettime_ms();
73 for (i=0; i<NB_LOOPS; i++) { 77 for (i=0; i<NB_LOOPS; i++) {
74 - ret = read_coil_status(&mb_param, 0, nb_points, tab_rp_status); 78 + rc = read_coil_status(&mb_param, 0, nb_points, tab_rp_status);
  79 + if (rc == -1) {
  80 + fprintf(stderr, modbus_strerror(errno));
  81 + return -1;
  82 + }
75 } 83 }
76 end = gettime_ms(); 84 end = gettime_ms();
77 elapsed = end - start; 85 elapsed = end - start;
@@ -104,7 +112,11 @@ int main(void) @@ -104,7 +112,11 @@ int main(void)
104 nb_points = MAX_REGISTERS; 112 nb_points = MAX_REGISTERS;
105 start = gettime_ms(); 113 start = gettime_ms();
106 for (i=0; i<NB_LOOPS; i++) { 114 for (i=0; i<NB_LOOPS; i++) {
107 - ret = read_holding_registers(&mb_param, 0, nb_points, tab_rp_registers); 115 + rc = read_holding_registers(&mb_param, 0, nb_points, tab_rp_registers);
  116 + if (rc == -1) {
  117 + fprintf(stderr, modbus_strerror(errno));
  118 + return -1;
  119 + }
108 } 120 }
109 end = gettime_ms(); 121 end = gettime_ms();
110 elapsed = end - start; 122 elapsed = end - start;
tests/bandwidth-slave-many-up.c
@@ -42,7 +42,7 @@ int main(void) @@ -42,7 +42,7 @@ int main(void)
42 { 42 {
43 int master_socket; 43 int master_socket;
44 modbus_param_t mb_param; 44 modbus_param_t mb_param;
45 - int ret; 45 + int rc;
46 fd_set refset; 46 fd_set refset;
47 fd_set rdset; 47 fd_set rdset;
48 48
@@ -51,10 +51,11 @@ int main(void) @@ -51,10 +51,11 @@ int main(void)
51 51
52 modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE); 52 modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE);
53 53
54 - ret = modbus_mapping_new(&mb_mapping, MAX_STATUS, 0, MAX_REGISTERS, 0);  
55 - if (ret < 0) {  
56 - fprintf(stderr, "Memory allocation failure\n");  
57 - exit(1); 54 + rc = modbus_mapping_new(&mb_mapping, MAX_STATUS, 0, MAX_REGISTERS, 0);
  55 + if (rc == -1) {
  56 + fprintf(stderr, "Failed to allocate the mapping: %s\n",
  57 + modbus_strerror(errno));
  58 + return -1;
58 } 59 }
59 60
60 slave_socket = modbus_slave_listen_tcp(&mb_param, NB_CONNECTION); 61 slave_socket = modbus_slave_listen_tcp(&mb_param, NB_CONNECTION);
@@ -107,9 +108,9 @@ int main(void) @@ -107,9 +108,9 @@ int main(void)
107 /* An already connected master has sent a new query */ 108 /* An already connected master has sent a new query */
108 uint8_t query[MAX_MESSAGE_LENGTH]; 109 uint8_t query[MAX_MESSAGE_LENGTH];
109 110
110 - ret = modbus_slave_receive(&mb_param, master_socket, query);  
111 - if (ret >= 0) {  
112 - modbus_slave_manage(&mb_param, query, ret, &mb_mapping); 111 + rc = modbus_slave_receive(&mb_param, master_socket, query);
  112 + if (rc != -1) {
  113 + modbus_slave_manage(&mb_param, query, rc, &mb_mapping);
113 } else { 114 } else {
114 /* Connection closed by the client, end of server */ 115 /* Connection closed by the client, end of server */
115 printf("Connection closed on socket %d\n", master_socket); 116 printf("Connection closed on socket %d\n", master_socket);
tests/bandwidth-slave-one.c
@@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
19 #include <unistd.h> 19 #include <unistd.h>
20 #include <string.h> 20 #include <string.h>
21 #include <stdlib.h> 21 #include <stdlib.h>
  22 +#include <errno.h>
22 23
23 #include <modbus/modbus.h> 24 #include <modbus/modbus.h>
24 25
@@ -29,33 +30,34 @@ int main(void) @@ -29,33 +30,34 @@ int main(void)
29 int socket; 30 int socket;
30 modbus_param_t mb_param; 31 modbus_param_t mb_param;
31 modbus_mapping_t mb_mapping; 32 modbus_mapping_t mb_mapping;
32 - int ret; 33 + int rc;
33 34
34 modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE); 35 modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE);
35 36
36 - ret = modbus_mapping_new(&mb_mapping, MAX_STATUS, 0, MAX_REGISTERS, 0);  
37 - if (ret < 0) {  
38 - fprintf(stderr, "Memory allocation failed\n");  
39 - exit(1); 37 + rc = modbus_mapping_new(&mb_mapping, MAX_STATUS, 0, MAX_REGISTERS, 0);
  38 + if (rc == -1) {
  39 + fprintf(stderr, "Failed to allocate the mapping: %s\n",
  40 + modbus_strerror(errno));
  41 + return -1;
40 } 42 }
41 43
42 socket = modbus_slave_listen_tcp(&mb_param, 1); 44 socket = modbus_slave_listen_tcp(&mb_param, 1);
43 modbus_slave_accept_tcp(&mb_param, &socket); 45 modbus_slave_accept_tcp(&mb_param, &socket);
44 46
45 - while (1) { 47 + for(;;) {
46 uint8_t query[MAX_MESSAGE_LENGTH]; 48 uint8_t query[MAX_MESSAGE_LENGTH];
47 49
48 - ret = modbus_slave_receive(&mb_param, -1, query);  
49 - if (ret >= 0) {  
50 - modbus_slave_manage(&mb_param, query, ret, &mb_mapping);  
51 - } else if (ret == CONNECTION_CLOSED) {  
52 - /* Connection closed by the client, end of server */  
53 - break; 50 + rc = modbus_slave_receive(&mb_param, -1, query);
  51 + if (rc >= 0) {
  52 + modbus_slave_manage(&mb_param, query, rc, &mb_mapping);
54 } else { 53 } else {
55 - fprintf(stderr, "Error in modbus_listen (%d)\n", ret); 54 + /* Connection closed by the client or server */
  55 + break;
56 } 56 }
57 } 57 }
58 58
  59 + printf("Quit the loop: %s\n", modbus_strerror(errno));
  60 +
59 close(socket); 61 close(socket);
60 modbus_mapping_free(&mb_mapping); 62 modbus_mapping_free(&mb_mapping);
61 modbus_close(&mb_param); 63 modbus_close(&mb_param);
tests/random-test-master.c
@@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
19 #include <unistd.h> 19 #include <unistd.h>
20 #include <string.h> 20 #include <string.h>
21 #include <stdlib.h> 21 #include <stdlib.h>
  22 +#include <errno.h>
22 23
23 #include <modbus/modbus.h> 24 #include <modbus/modbus.h>
24 25
@@ -45,7 +46,7 @@ @@ -45,7 +46,7 @@
45 */ 46 */
46 int main(void) 47 int main(void)
47 { 48 {
48 - int ret; 49 + int rc;
49 int nb_fail; 50 int nb_fail;
50 int nb_loop; 51 int nb_loop;
51 int addr; 52 int addr;
@@ -63,7 +64,9 @@ int main(void) @@ -63,7 +64,9 @@ int main(void)
63 modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE); 64 modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE);
64 modbus_set_debug(&mb_param, TRUE); 65 modbus_set_debug(&mb_param, TRUE);
65 if (modbus_connect(&mb_param) == -1) { 66 if (modbus_connect(&mb_param) == -1) {
66 - exit(1); 67 + fprintf(stderr, "Connection failed: %s\n",
  68 + modbus_strerror(errno));
  69 + return -1;
67 } 70 }
68 71
69 /* Allocate and initialize the different memory spaces */ 72 /* Allocate and initialize the different memory spaces */
@@ -94,16 +97,16 @@ int main(void) @@ -94,16 +97,16 @@ int main(void)
94 nb = ADDRESS_END - addr; 97 nb = ADDRESS_END - addr;
95 98
96 /* SINGLE COIL */ 99 /* SINGLE COIL */
97 - ret = force_single_coil(&mb_param, addr, tab_rq_status[0]);  
98 - if (ret != 1) {  
99 - printf("ERROR force_single_coil (%d)\n", ret); 100 + rc = force_single_coil(&mb_param, addr, tab_rq_status[0]);
  101 + if (rc != 1) {
  102 + printf("ERROR force_single_coil (%d)\n", rc);
100 printf("Slave = %d, address = %d, value = %d\n", 103 printf("Slave = %d, address = %d, value = %d\n",
101 SLAVE, addr, tab_rq_status[0]); 104 SLAVE, addr, tab_rq_status[0]);
102 nb_fail++; 105 nb_fail++;
103 } else { 106 } else {
104 - ret = read_coil_status(&mb_param, addr, 1, tab_rp_status);  
105 - if (ret != 1 || tab_rq_status[0] != tab_rp_status[0]) {  
106 - printf("ERROR read_coil_status single (%d)\n", ret); 107 + rc = read_coil_status(&mb_param, addr, 1, tab_rp_status);
  108 + if (rc != 1 || tab_rq_status[0] != tab_rp_status[0]) {
  109 + printf("ERROR read_coil_status single (%d)\n", rc);
107 printf("Slave = %d, address = %d\n", 110 printf("Slave = %d, address = %d\n",
108 SLAVE, addr); 111 SLAVE, addr);
109 nb_fail++; 112 nb_fail++;
@@ -111,15 +114,15 @@ int main(void) @@ -111,15 +114,15 @@ int main(void)
111 } 114 }
112 115
113 /* MULTIPLE COILS */ 116 /* MULTIPLE COILS */
114 - ret = force_multiple_coils(&mb_param, addr, nb, tab_rq_status);  
115 - if (ret != nb) {  
116 - printf("ERROR force_multiple_coils (%d)\n", ret); 117 + rc = force_multiple_coils(&mb_param, addr, nb, tab_rq_status);
  118 + if (rc != nb) {
  119 + printf("ERROR force_multiple_coils (%d)\n", rc);
117 printf("Slave = %d, address = %d, nb = %d\n", 120 printf("Slave = %d, address = %d, nb = %d\n",
118 SLAVE, addr, nb); 121 SLAVE, addr, nb);
119 nb_fail++; 122 nb_fail++;
120 } else { 123 } else {
121 - ret = read_coil_status(&mb_param, addr, nb, tab_rp_status);  
122 - if (ret != nb) { 124 + rc = read_coil_status(&mb_param, addr, nb, tab_rp_status);
  125 + if (rc != nb) {
123 printf("ERROR read_coil_status\n"); 126 printf("ERROR read_coil_status\n");
124 printf("Slave = %d, address = %d, nb = %d\n", 127 printf("Slave = %d, address = %d, nb = %d\n",
125 SLAVE, addr, nb); 128 SLAVE, addr, nb);
@@ -139,16 +142,16 @@ int main(void) @@ -139,16 +142,16 @@ int main(void)
139 } 142 }
140 143
141 /* SINGLE REGISTER */ 144 /* SINGLE REGISTER */
142 - ret = preset_single_register(&mb_param, addr, tab_rq_registers[0]);  
143 - if (ret != 1) {  
144 - printf("ERROR preset_single_register (%d)\n", ret); 145 + rc = preset_single_register(&mb_param, addr, tab_rq_registers[0]);
  146 + if (rc != 1) {
  147 + printf("ERROR preset_single_register (%d)\n", rc);
145 printf("Slave = %d, address = %d, value = %d (0x%X)\n", 148 printf("Slave = %d, address = %d, value = %d (0x%X)\n",
146 SLAVE, addr, tab_rq_registers[0], tab_rq_registers[0]); 149 SLAVE, addr, tab_rq_registers[0], tab_rq_registers[0]);
147 nb_fail++; 150 nb_fail++;
148 } else { 151 } else {
149 - ret = read_holding_registers(&mb_param, addr, 1, tab_rp_registers);  
150 - if (ret != 1) {  
151 - printf("ERROR read_holding_registers single (%d)\n", ret); 152 + rc = read_holding_registers(&mb_param, addr, 1, tab_rp_registers);
  153 + if (rc != 1) {
  154 + printf("ERROR read_holding_registers single (%d)\n", rc);
152 printf("Slave = %d, address = %d\n", 155 printf("Slave = %d, address = %d\n",
153 SLAVE, addr); 156 SLAVE, addr);
154 nb_fail++; 157 nb_fail++;
@@ -165,18 +168,18 @@ int main(void) @@ -165,18 +168,18 @@ int main(void)
165 } 168 }
166 169
167 /* MULTIPLE REGISTERS */ 170 /* MULTIPLE REGISTERS */
168 - ret = preset_multiple_registers(&mb_param, addr, nb, 171 + rc = preset_multiple_registers(&mb_param, addr, nb,
169 tab_rq_registers); 172 tab_rq_registers);
170 - if (ret != nb) {  
171 - printf("ERROR preset_multiple_registers (%d)\n", ret); 173 + if (rc != nb) {
  174 + printf("ERROR preset_multiple_registers (%d)\n", rc);
172 printf("Slave = %d, address = %d, nb = %d\n", 175 printf("Slave = %d, address = %d, nb = %d\n",
173 SLAVE, addr, nb); 176 SLAVE, addr, nb);
174 nb_fail++; 177 nb_fail++;
175 } else { 178 } else {
176 - ret = read_holding_registers(&mb_param, addr, nb, 179 + rc = read_holding_registers(&mb_param, addr, nb,
177 tab_rp_registers); 180 tab_rp_registers);
178 - if (ret != nb) {  
179 - printf("ERROR read_holding_registers (%d)\n", ret); 181 + if (rc != nb) {
  182 + printf("ERROR read_holding_registers (%d)\n", rc);
180 printf("Slave = %d, address = %d, nb = %d\n", 183 printf("Slave = %d, address = %d, nb = %d\n",
181 SLAVE, addr, nb); 184 SLAVE, addr, nb);
182 nb_fail++; 185 nb_fail++;
tests/random-test-slave.c
@@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
18 #include <stdio.h> 18 #include <stdio.h>
19 #include <unistd.h> 19 #include <unistd.h>
20 #include <stdlib.h> 20 #include <stdlib.h>
  21 +#include <errno.h>
21 22
22 #include <modbus/modbus.h> 23 #include <modbus/modbus.h>
23 24
@@ -28,36 +29,37 @@ int main(void) @@ -28,36 +29,37 @@ int main(void)
28 int socket; 29 int socket;
29 modbus_param_t mb_param; 30 modbus_param_t mb_param;
30 modbus_mapping_t mb_mapping; 31 modbus_mapping_t mb_mapping;
31 - int ret; 32 + int rc;
32 33
33 modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE); 34 modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE);
34 /* modbus_set_debug(&mb_param, TRUE); */ 35 /* modbus_set_debug(&mb_param, TRUE); */
35 36
36 - ret = modbus_mapping_new(&mb_mapping, 500, 500, 500, 500);  
37 - if (ret < 0) {  
38 - fprintf(stderr, "Memory allocation failed\n");  
39 - exit(1); 37 + rc = modbus_mapping_new(&mb_mapping, 500, 500, 500, 500);
  38 + if (rc == -1) {
  39 + fprintf(stderr, "Failed to allocate the mapping: %s\n",
  40 + modbus_strerror(errno));
  41 + return -1;
40 } 42 }
41 43
42 socket = modbus_slave_listen_tcp(&mb_param, 1); 44 socket = modbus_slave_listen_tcp(&mb_param, 1);
43 modbus_slave_accept_tcp(&mb_param, &socket); 45 modbus_slave_accept_tcp(&mb_param, &socket);
44 46
45 - while (1) { 47 + for (;;) {
46 uint8_t query[MAX_MESSAGE_LENGTH]; 48 uint8_t query[MAX_MESSAGE_LENGTH];
47 - int ret; 49 + int rc;
48 50
49 - ret = modbus_slave_receive(&mb_param, -1, query);  
50 - if (ret >= 0) {  
51 - /* ret is the query size */  
52 - modbus_slave_manage(&mb_param, query, ret, &mb_mapping);  
53 - } else if (ret == CONNECTION_CLOSED) {  
54 - /* Connection closed by the client, end of server */  
55 - break; 51 + rc = modbus_slave_receive(&mb_param, -1, query);
  52 + if (rc != -1) {
  53 + /* rc is the query size */
  54 + modbus_slave_manage(&mb_param, query, rc, &mb_mapping);
56 } else { 55 } else {
57 - fprintf(stderr, "Error in modbus_listen (%d)\n", ret); 56 + /* Connection closed by the client or error */
  57 + break;
58 } 58 }
59 } 59 }
60 60
  61 + printf("Quit the loop: %s\n", modbus_strerror(errno));
  62 +
61 close(socket); 63 close(socket);
62 modbus_mapping_free(&mb_mapping); 64 modbus_mapping_free(&mb_mapping);
63 modbus_close(&mb_param); 65 modbus_close(&mb_param);
tests/unit-test-master.c
@@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
19 #include <unistd.h> 19 #include <unistd.h>
20 #include <string.h> 20 #include <string.h>
21 #include <stdlib.h> 21 #include <stdlib.h>
  22 +#include <errno.h>
22 23
23 #include <modbus/modbus.h> 24 #include <modbus/modbus.h>
24 #include "unit-test.h" 25 #include "unit-test.h"
@@ -36,7 +37,7 @@ int main(void) @@ -36,7 +37,7 @@ int main(void)
36 uint8_t value; 37 uint8_t value;
37 int address; 38 int address;
38 int nb_points; 39 int nb_points;
39 - int ret; 40 + int rc;
40 float real; 41 float real;
41 42
42 /* RTU parity : none, even, odd */ 43 /* RTU parity : none, even, odd */
@@ -44,10 +45,12 @@ int main(void) @@ -44,10 +45,12 @@ int main(void)
44 45
45 /* TCP */ 46 /* TCP */
46 modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE); 47 modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE);
47 -/* modbus_set_debug(&mb_param, TRUE); */ 48 + modbus_set_debug(&mb_param, TRUE);
48 49
49 if (modbus_connect(&mb_param) == -1) { 50 if (modbus_connect(&mb_param) == -1) {
50 - exit(1); 51 + fprintf(stderr, "Connection failed: %s\n",
  52 + modbus_strerror(errno));
  53 + return -1;
51 } 54 }
52 55
53 /* Allocate and initialize the memory to store the status */ 56 /* Allocate and initialize the memory to store the status */
@@ -70,20 +73,20 @@ int main(void) @@ -70,20 +73,20 @@ int main(void)
70 /** COIL STATUS **/ 73 /** COIL STATUS **/
71 74
72 /* Single */ 75 /* Single */
73 - ret = force_single_coil(&mb_param, UT_COIL_STATUS_ADDRESS, ON); 76 + rc = force_single_coil(&mb_param, UT_COIL_STATUS_ADDRESS, ON);
74 printf("1/2 force_single_coil: "); 77 printf("1/2 force_single_coil: ");
75 - if (ret == 1) { 78 + if (rc == 1) {
76 printf("OK\n"); 79 printf("OK\n");
77 } else { 80 } else {
78 printf("FAILED\n"); 81 printf("FAILED\n");
79 goto close; 82 goto close;
80 } 83 }
81 84
82 - ret = read_coil_status(&mb_param, UT_COIL_STATUS_ADDRESS, 1,  
83 - tab_rp_status); 85 + rc = read_coil_status(&mb_param, UT_COIL_STATUS_ADDRESS, 1,
  86 + tab_rp_status);
84 printf("2/2 read_coil_status: "); 87 printf("2/2 read_coil_status: ");
85 - if (ret != 1) {  
86 - printf("FAILED (nb points %d)\n", ret); 88 + if (rc != 1) {
  89 + printf("FAILED (nb points %d)\n", rc);
87 goto close; 90 goto close;
88 } 91 }
89 92
@@ -100,12 +103,12 @@ int main(void) @@ -100,12 +103,12 @@ int main(void)
100 103
101 set_bits_from_bytes(tab_value, 0, UT_COIL_STATUS_NB_POINTS, 104 set_bits_from_bytes(tab_value, 0, UT_COIL_STATUS_NB_POINTS,
102 UT_COIL_STATUS_TAB); 105 UT_COIL_STATUS_TAB);
103 - ret = force_multiple_coils(&mb_param,  
104 - UT_COIL_STATUS_ADDRESS,  
105 - UT_COIL_STATUS_NB_POINTS,  
106 - tab_value); 106 + rc = force_multiple_coils(&mb_param,
  107 + UT_COIL_STATUS_ADDRESS,
  108 + UT_COIL_STATUS_NB_POINTS,
  109 + tab_value);
107 printf("1/2 force_multiple_coils: "); 110 printf("1/2 force_multiple_coils: ");
108 - if (ret == UT_COIL_STATUS_NB_POINTS) { 111 + if (rc == UT_COIL_STATUS_NB_POINTS) {
109 printf("OK\n"); 112 printf("OK\n");
110 } else { 113 } else {
111 printf("FAILED\n"); 114 printf("FAILED\n");
@@ -113,11 +116,11 @@ int main(void) @@ -113,11 +116,11 @@ int main(void)
113 } 116 }
114 } 117 }
115 118
116 - ret = read_coil_status(&mb_param, UT_COIL_STATUS_ADDRESS,  
117 - UT_COIL_STATUS_NB_POINTS, tab_rp_status); 119 + rc = read_coil_status(&mb_param, UT_COIL_STATUS_ADDRESS,
  120 + UT_COIL_STATUS_NB_POINTS, tab_rp_status);
118 printf("2/2 read_coil_status: "); 121 printf("2/2 read_coil_status: ");
119 - if (ret != UT_COIL_STATUS_NB_POINTS) {  
120 - printf("FAILED (nb points %d)\n", ret); 122 + if (rc != UT_COIL_STATUS_NB_POINTS) {
  123 + printf("FAILED (nb points %d)\n", rc);
121 goto close; 124 goto close;
122 } 125 }
123 126
@@ -141,12 +144,12 @@ int main(void) @@ -141,12 +144,12 @@ int main(void)
141 /* End of multiple coils */ 144 /* End of multiple coils */
142 145
143 /** INPUT STATUS **/ 146 /** INPUT STATUS **/
144 - ret = read_input_status(&mb_param, UT_INPUT_STATUS_ADDRESS,  
145 - UT_INPUT_STATUS_NB_POINTS, tab_rp_status); 147 + rc = read_input_status(&mb_param, UT_INPUT_STATUS_ADDRESS,
  148 + UT_INPUT_STATUS_NB_POINTS, tab_rp_status);
146 printf("1/1 read_input_status: "); 149 printf("1/1 read_input_status: ");
147 150
148 - if (ret != UT_INPUT_STATUS_NB_POINTS) {  
149 - printf("FAILED (nb points %d)\n", ret); 151 + if (rc != UT_INPUT_STATUS_NB_POINTS) {
  152 + printf("FAILED (nb points %d)\n", rc);
150 goto close; 153 goto close;
151 } 154 }
152 155
@@ -171,22 +174,22 @@ int main(void) @@ -171,22 +174,22 @@ int main(void)
171 /** HOLDING REGISTERS **/ 174 /** HOLDING REGISTERS **/
172 175
173 /* Single register */ 176 /* Single register */
174 - ret = preset_single_register(&mb_param,  
175 - UT_HOLDING_REGISTERS_ADDRESS, 0x1234); 177 + rc = preset_single_register(&mb_param,
  178 + UT_HOLDING_REGISTERS_ADDRESS, 0x1234);
176 printf("1/2 preset_single_register: "); 179 printf("1/2 preset_single_register: ");
177 - if (ret == 1) { 180 + if (rc == 1) {
178 printf("OK\n"); 181 printf("OK\n");
179 } else { 182 } else {
180 printf("FAILED\n"); 183 printf("FAILED\n");
181 goto close; 184 goto close;
182 } 185 }
183 186
184 - ret = read_holding_registers(&mb_param,  
185 - UT_HOLDING_REGISTERS_ADDRESS,  
186 - 1, tab_rp_registers); 187 + rc = read_holding_registers(&mb_param,
  188 + UT_HOLDING_REGISTERS_ADDRESS,
  189 + 1, tab_rp_registers);
187 printf("2/2 read_holding_registers: "); 190 printf("2/2 read_holding_registers: ");
188 - if (ret != 1) {  
189 - printf("FAILED (nb points %d)\n", ret); 191 + if (rc != 1) {
  192 + printf("FAILED (nb points %d)\n", rc);
190 goto close; 193 goto close;
191 } 194 }
192 195
@@ -199,25 +202,25 @@ int main(void) @@ -199,25 +202,25 @@ int main(void)
199 /* End of single register */ 202 /* End of single register */
200 203
201 /* Many registers */ 204 /* Many registers */
202 - ret = preset_multiple_registers(&mb_param,  
203 - UT_HOLDING_REGISTERS_ADDRESS,  
204 - UT_HOLDING_REGISTERS_NB_POINTS,  
205 - UT_HOLDING_REGISTERS_TAB); 205 + rc = preset_multiple_registers(&mb_param,
  206 + UT_HOLDING_REGISTERS_ADDRESS,
  207 + UT_HOLDING_REGISTERS_NB_POINTS,
  208 + UT_HOLDING_REGISTERS_TAB);
206 printf("1/2 preset_multiple_registers: "); 209 printf("1/2 preset_multiple_registers: ");
207 - if (ret == UT_HOLDING_REGISTERS_NB_POINTS) { 210 + if (rc == UT_HOLDING_REGISTERS_NB_POINTS) {
208 printf("OK\n"); 211 printf("OK\n");
209 } else { 212 } else {
210 printf("FAILED\n"); 213 printf("FAILED\n");
211 goto close; 214 goto close;
212 } 215 }
213 216
214 - ret = read_holding_registers(&mb_param,  
215 - UT_HOLDING_REGISTERS_ADDRESS,  
216 - UT_HOLDING_REGISTERS_NB_POINTS,  
217 - tab_rp_registers); 217 + rc = read_holding_registers(&mb_param,
  218 + UT_HOLDING_REGISTERS_ADDRESS,
  219 + UT_HOLDING_REGISTERS_NB_POINTS,
  220 + tab_rp_registers);
218 printf("2/2 read_holding_registers: "); 221 printf("2/2 read_holding_registers: ");
219 - if (ret != UT_HOLDING_REGISTERS_NB_POINTS) {  
220 - printf("FAILED (nb points %d)\n", ret); 222 + if (rc != UT_HOLDING_REGISTERS_NB_POINTS) {
  223 + printf("FAILED (nb points %d)\n", rc);
221 goto close; 224 goto close;
222 } 225 }
223 226
@@ -234,13 +237,13 @@ int main(void) @@ -234,13 +237,13 @@ int main(void)
234 237
235 238
236 /** INPUT REGISTERS **/ 239 /** INPUT REGISTERS **/
237 - ret = read_input_registers(&mb_param,  
238 - UT_INPUT_REGISTERS_ADDRESS,  
239 - UT_INPUT_REGISTERS_NB_POINTS,  
240 - tab_rp_registers); 240 + rc = read_input_registers(&mb_param,
  241 + UT_INPUT_REGISTERS_ADDRESS,
  242 + UT_INPUT_REGISTERS_NB_POINTS,
  243 + tab_rp_registers);
241 printf("1/1 read_input_registers: "); 244 printf("1/1 read_input_registers: ");
242 - if (ret != UT_INPUT_REGISTERS_NB_POINTS) {  
243 - printf("FAILED (nb points %d)\n", ret); 245 + if (rc != UT_INPUT_REGISTERS_NB_POINTS) {
  246 + printf("FAILED (nb points %d)\n", rc);
244 goto close; 247 goto close;
245 } 248 }
246 249
@@ -284,83 +287,83 @@ int main(void) @@ -284,83 +287,83 @@ int main(void)
284 /* The mapping begins at 0 and ending at address + nb_points so 287 /* The mapping begins at 0 and ending at address + nb_points so
285 * the addresses below are not valid. */ 288 * the addresses below are not valid. */
286 289
287 - ret = read_coil_status(&mb_param,  
288 - UT_COIL_STATUS_ADDRESS,  
289 - UT_COIL_STATUS_NB_POINTS + 1,  
290 - tab_rp_status); 290 + rc = read_coil_status(&mb_param,
  291 + UT_COIL_STATUS_ADDRESS,
  292 + UT_COIL_STATUS_NB_POINTS + 1,
  293 + tab_rp_status);
291 printf("* read_coil_status: "); 294 printf("* read_coil_status: ");
292 - if (ret == ILLEGAL_DATA_ADDRESS) 295 + if (rc == -1 && errno == EMBXILADD)
293 printf("OK\n"); 296 printf("OK\n");
294 else { 297 else {
295 printf("FAILED\n"); 298 printf("FAILED\n");
296 goto close; 299 goto close;
297 } 300 }
298 301
299 - ret = read_input_status(&mb_param,  
300 - UT_INPUT_STATUS_ADDRESS,  
301 - UT_INPUT_STATUS_NB_POINTS + 1,  
302 - tab_rp_status); 302 + rc = read_input_status(&mb_param,
  303 + UT_INPUT_STATUS_ADDRESS,
  304 + UT_INPUT_STATUS_NB_POINTS + 1,
  305 + tab_rp_status);
303 printf("* read_input_status: "); 306 printf("* read_input_status: ");
304 - if (ret == ILLEGAL_DATA_ADDRESS) 307 + if (rc == -1 && errno == EMBXILADD)
305 printf("OK\n"); 308 printf("OK\n");
306 else { 309 else {
307 printf("FAILED\n"); 310 printf("FAILED\n");
308 goto close; 311 goto close;
309 } 312 }
310 313
311 - ret = read_holding_registers(&mb_param,  
312 - UT_HOLDING_REGISTERS_ADDRESS,  
313 - UT_HOLDING_REGISTERS_NB_POINTS + 1,  
314 - tab_rp_registers); 314 + rc = read_holding_registers(&mb_param,
  315 + UT_HOLDING_REGISTERS_ADDRESS,
  316 + UT_HOLDING_REGISTERS_NB_POINTS + 1,
  317 + tab_rp_registers);
315 printf("* read_holding_registers: "); 318 printf("* read_holding_registers: ");
316 - if (ret == ILLEGAL_DATA_ADDRESS) 319 + if (rc == -1 && errno == EMBXILADD)
317 printf("OK\n"); 320 printf("OK\n");
318 else { 321 else {
319 printf("FAILED\n"); 322 printf("FAILED\n");
320 goto close; 323 goto close;
321 } 324 }
322 325
323 - ret = read_input_registers(&mb_param,  
324 - UT_INPUT_REGISTERS_ADDRESS,  
325 - UT_INPUT_REGISTERS_NB_POINTS + 1,  
326 - tab_rp_registers); 326 + rc = read_input_registers(&mb_param,
  327 + UT_INPUT_REGISTERS_ADDRESS,
  328 + UT_INPUT_REGISTERS_NB_POINTS + 1,
  329 + tab_rp_registers);
327 printf("* read_input_registers: "); 330 printf("* read_input_registers: ");
328 - if (ret == ILLEGAL_DATA_ADDRESS) 331 + if (rc == -1 && errno == EMBXILADD)
329 printf("OK\n"); 332 printf("OK\n");
330 else { 333 else {
331 printf("FAILED\n"); 334 printf("FAILED\n");
332 goto close; 335 goto close;
333 } 336 }
334 337
335 - ret = force_single_coil(&mb_param,  
336 - UT_COIL_STATUS_ADDRESS + UT_COIL_STATUS_NB_POINTS,  
337 - ON); 338 + rc = force_single_coil(&mb_param,
  339 + UT_COIL_STATUS_ADDRESS + UT_COIL_STATUS_NB_POINTS,
  340 + ON);
338 printf("* force_single_coil: "); 341 printf("* force_single_coil: ");
339 - if (ret == ILLEGAL_DATA_ADDRESS) { 342 + if (rc == -1 && errno == EMBXILADD) {
340 printf("OK\n"); 343 printf("OK\n");
341 } else { 344 } else {
342 printf("FAILED\n"); 345 printf("FAILED\n");
343 goto close; 346 goto close;
344 } 347 }
345 348
346 - ret = force_multiple_coils(&mb_param,  
347 - UT_COIL_STATUS_ADDRESS + UT_COIL_STATUS_NB_POINTS,  
348 - UT_COIL_STATUS_NB_POINTS,  
349 - tab_rp_status); 349 + rc = force_multiple_coils(&mb_param,
  350 + UT_COIL_STATUS_ADDRESS + UT_COIL_STATUS_NB_POINTS,
  351 + UT_COIL_STATUS_NB_POINTS,
  352 + tab_rp_status);
350 printf("* force_multiple_coils: "); 353 printf("* force_multiple_coils: ");
351 - if (ret == ILLEGAL_DATA_ADDRESS) { 354 + if (rc == -1 && errno == EMBXILADD) {
352 printf("OK\n"); 355 printf("OK\n");
353 } else { 356 } else {
354 printf("FAILED\n"); 357 printf("FAILED\n");
355 goto close; 358 goto close;
356 } 359 }
357 360
358 - ret = preset_multiple_registers(&mb_param,  
359 - UT_HOLDING_REGISTERS_ADDRESS + UT_HOLDING_REGISTERS_NB_POINTS,  
360 - UT_HOLDING_REGISTERS_NB_POINTS,  
361 - tab_rp_registers); 361 + rc = preset_multiple_registers(&mb_param,
  362 + UT_HOLDING_REGISTERS_ADDRESS + UT_HOLDING_REGISTERS_NB_POINTS,
  363 + UT_HOLDING_REGISTERS_NB_POINTS,
  364 + tab_rp_registers);
362 printf("* preset_multiple_registers: "); 365 printf("* preset_multiple_registers: ");
363 - if (ret == ILLEGAL_DATA_ADDRESS) { 366 + if (rc == -1 && errno == EMBXILADD) {
364 printf("OK\n"); 367 printf("OK\n");
365 } else { 368 } else {
366 printf("FAILED\n"); 369 printf("FAILED\n");
@@ -371,72 +374,72 @@ int main(void) @@ -371,72 +374,72 @@ int main(void)
371 /** TOO MANY DATA **/ 374 /** TOO MANY DATA **/
372 printf("\nTEST TOO MANY DATA ERROR:\n"); 375 printf("\nTEST TOO MANY DATA ERROR:\n");
373 376
374 - ret = read_coil_status(&mb_param,  
375 - UT_COIL_STATUS_ADDRESS,  
376 - MAX_STATUS + 1,  
377 - tab_rp_status); 377 + rc = read_coil_status(&mb_param,
  378 + UT_COIL_STATUS_ADDRESS,
  379 + MAX_STATUS + 1,
  380 + tab_rp_status);
378 printf("* read_coil_status: "); 381 printf("* read_coil_status: ");
379 - if (ret == INVALID_DATA) { 382 + if (rc == -1 && errno == EMBMDATA) {
380 printf("OK\n"); 383 printf("OK\n");
381 } else { 384 } else {
382 printf("FAILED\n"); 385 printf("FAILED\n");
383 goto close; 386 goto close;
384 } 387 }
385 388
386 - ret = read_input_status(&mb_param,  
387 - UT_INPUT_STATUS_ADDRESS,  
388 - MAX_STATUS + 1,  
389 - tab_rp_status); 389 + rc = read_input_status(&mb_param,
  390 + UT_INPUT_STATUS_ADDRESS,
  391 + MAX_STATUS + 1,
  392 + tab_rp_status);
390 printf("* read_input_status: "); 393 printf("* read_input_status: ");
391 - if (ret == INVALID_DATA) { 394 + if (rc == -1 && errno == EMBMDATA) {
392 printf("OK\n"); 395 printf("OK\n");
393 } else { 396 } else {
394 printf("FAILED\n"); 397 printf("FAILED\n");
395 goto close; 398 goto close;
396 } 399 }
397 400
398 - ret = read_holding_registers(&mb_param,  
399 - UT_HOLDING_REGISTERS_ADDRESS,  
400 - MAX_REGISTERS + 1,  
401 - tab_rp_registers); 401 + rc = read_holding_registers(&mb_param,
  402 + UT_HOLDING_REGISTERS_ADDRESS,
  403 + MAX_REGISTERS + 1,
  404 + tab_rp_registers);
402 printf("* read_holding_registers: "); 405 printf("* read_holding_registers: ");
403 - if (ret == INVALID_DATA) { 406 + if (rc == -1 && errno == EMBMDATA) {
404 printf("OK\n"); 407 printf("OK\n");
405 } else { 408 } else {
406 printf("FAILED\n"); 409 printf("FAILED\n");
407 goto close; 410 goto close;
408 } 411 }
409 412
410 - ret = read_input_registers(&mb_param,  
411 - UT_INPUT_REGISTERS_ADDRESS,  
412 - MAX_REGISTERS + 1,  
413 - tab_rp_registers); 413 + rc = read_input_registers(&mb_param,
  414 + UT_INPUT_REGISTERS_ADDRESS,
  415 + MAX_REGISTERS + 1,
  416 + tab_rp_registers);
414 printf("* read_input_registers: "); 417 printf("* read_input_registers: ");
415 - if (ret == INVALID_DATA) { 418 + if (rc == -1 && errno == EMBMDATA) {
416 printf("OK\n"); 419 printf("OK\n");
417 } else { 420 } else {
418 printf("FAILED\n"); 421 printf("FAILED\n");
419 goto close; 422 goto close;
420 } 423 }
421 424
422 - ret = force_multiple_coils(&mb_param,  
423 - UT_COIL_STATUS_ADDRESS,  
424 - MAX_STATUS + 1,  
425 - tab_rp_status); 425 + rc = force_multiple_coils(&mb_param,
  426 + UT_COIL_STATUS_ADDRESS,
  427 + MAX_STATUS + 1,
  428 + tab_rp_status);
426 printf("* force_multiple_coils: "); 429 printf("* force_multiple_coils: ");
427 - if (ret == INVALID_DATA) { 430 + if (rc == -1 && errno == EMBMDATA) {
428 printf("OK\n"); 431 printf("OK\n");
429 } else { 432 } else {
430 goto close; 433 goto close;
431 printf("FAILED\n"); 434 printf("FAILED\n");
432 } 435 }
433 436
434 - ret = preset_multiple_registers(&mb_param,  
435 - UT_HOLDING_REGISTERS_ADDRESS,  
436 - MAX_REGISTERS + 1,  
437 - tab_rp_registers); 437 + rc = preset_multiple_registers(&mb_param,
  438 + UT_HOLDING_REGISTERS_ADDRESS,
  439 + MAX_REGISTERS + 1,
  440 + tab_rp_registers);
438 printf("* preset_multiple_registers: "); 441 printf("* preset_multiple_registers: ");
439 - if (ret == INVALID_DATA) { 442 + if (rc == -1 && errno == EMBMDATA) {
440 printf("OK\n"); 443 printf("OK\n");
441 } else { 444 } else {
442 printf("FAILED\n"); 445 printf("FAILED\n");
@@ -446,12 +449,12 @@ int main(void) @@ -446,12 +449,12 @@ int main(void)
446 /** SLAVE REPLY **/ 449 /** SLAVE REPLY **/
447 printf("\nTEST SLAVE REPLY:\n"); 450 printf("\nTEST SLAVE REPLY:\n");
448 modbus_set_slave(&mb_param, 18); 451 modbus_set_slave(&mb_param, 18);
449 - ret = read_holding_registers(&mb_param,  
450 - UT_HOLDING_REGISTERS_ADDRESS+1,  
451 - UT_HOLDING_REGISTERS_NB_POINTS,  
452 - tab_rp_registers); 452 + rc = read_holding_registers(&mb_param,
  453 + UT_HOLDING_REGISTERS_ADDRESS+1,
  454 + UT_HOLDING_REGISTERS_NB_POINTS,
  455 + tab_rp_registers);
453 printf("1/2 No reply from slave %d: ", mb_param.slave); 456 printf("1/2 No reply from slave %d: ", mb_param.slave);
454 - if (ret == SELECT_TIMEOUT) { 457 + if (rc == -1 && errno == ETIMEDOUT) {
455 printf("OK\n"); 458 printf("OK\n");
456 } else { 459 } else {
457 printf("FAILED\n"); 460 printf("FAILED\n");
@@ -459,12 +462,12 @@ int main(void) @@ -459,12 +462,12 @@ int main(void)
459 } 462 }
460 463
461 modbus_set_slave(&mb_param, MODBUS_BROADCAST_ADDRESS); 464 modbus_set_slave(&mb_param, MODBUS_BROADCAST_ADDRESS);
462 - ret = read_holding_registers(&mb_param,  
463 - UT_HOLDING_REGISTERS_ADDRESS,  
464 - UT_HOLDING_REGISTERS_NB_POINTS,  
465 - tab_rp_registers); 465 + rc = read_holding_registers(&mb_param,
  466 + UT_HOLDING_REGISTERS_ADDRESS,
  467 + UT_HOLDING_REGISTERS_NB_POINTS,
  468 + tab_rp_registers);
466 printf("2/2 Reply after a broadcast query: "); 469 printf("2/2 Reply after a broadcast query: ");
467 - if (ret == UT_HOLDING_REGISTERS_NB_POINTS) { 470 + if (rc == UT_HOLDING_REGISTERS_NB_POINTS) {
468 printf("OK\n"); 471 printf("OK\n");
469 } else { 472 } else {
470 goto close; 473 goto close;
@@ -477,12 +480,12 @@ int main(void) @@ -477,12 +480,12 @@ int main(void)
477 /* Allocate only the required space */ 480 /* Allocate only the required space */
478 tab_rp_registers_bad = (uint16_t *) malloc( 481 tab_rp_registers_bad = (uint16_t *) malloc(
479 UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL * sizeof(uint16_t)); 482 UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL * sizeof(uint16_t));
480 - ret = read_holding_registers(&mb_param,  
481 - UT_HOLDING_REGISTERS_ADDRESS,  
482 - UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL,  
483 - tab_rp_registers_bad); 483 + rc = read_holding_registers(&mb_param,
  484 + UT_HOLDING_REGISTERS_ADDRESS,
  485 + UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL,
  486 + tab_rp_registers_bad);
484 printf("* read_holding_registers: "); 487 printf("* read_holding_registers: ");
485 - if (ret == INVALID_DATA) { 488 + if (rc == -1 && errno == EMBBADDATA) {
486 printf("OK\n"); 489 printf("OK\n");
487 } else { 490 } else {
488 printf("FAILED\n"); 491 printf("FAILED\n");
tests/unit-test-slave.c
@@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
19 #include <unistd.h> 19 #include <unistd.h>
20 #include <string.h> 20 #include <string.h>
21 #include <stdlib.h> 21 #include <stdlib.h>
  22 +#include <errno.h>
22 23
23 #include <modbus/modbus.h> 24 #include <modbus/modbus.h>
24 #include "unit-test.h" 25 #include "unit-test.h"
@@ -28,20 +29,22 @@ int main(void) @@ -28,20 +29,22 @@ int main(void)
28 int socket; 29 int socket;
29 modbus_param_t mb_param; 30 modbus_param_t mb_param;
30 modbus_mapping_t mb_mapping; 31 modbus_mapping_t mb_mapping;
31 - int ret; 32 + int rc;
32 int i; 33 int i;
33 34
34 modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE); 35 modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE);
35 modbus_set_debug(&mb_param, TRUE); 36 modbus_set_debug(&mb_param, TRUE);
  37 + modbus_set_error_recovery(&mb_param, TRUE);
36 38
37 - ret = modbus_mapping_new(&mb_mapping, 39 + rc = modbus_mapping_new(&mb_mapping,
38 UT_COIL_STATUS_ADDRESS + UT_COIL_STATUS_NB_POINTS, 40 UT_COIL_STATUS_ADDRESS + UT_COIL_STATUS_NB_POINTS,
39 UT_INPUT_STATUS_ADDRESS + UT_INPUT_STATUS_NB_POINTS, 41 UT_INPUT_STATUS_ADDRESS + UT_INPUT_STATUS_NB_POINTS,
40 UT_HOLDING_REGISTERS_ADDRESS + UT_HOLDING_REGISTERS_NB_POINTS, 42 UT_HOLDING_REGISTERS_ADDRESS + UT_HOLDING_REGISTERS_NB_POINTS,
41 UT_INPUT_REGISTERS_ADDRESS + UT_INPUT_REGISTERS_NB_POINTS); 43 UT_INPUT_REGISTERS_ADDRESS + UT_INPUT_REGISTERS_NB_POINTS);
42 - if (ret < 0) {  
43 - printf("Memory allocation failed\n");  
44 - exit(1); 44 + if (rc == -1) {
  45 + fprintf(stderr, "Failed to allocate the mapping: %s\n",
  46 + modbus_strerror(errno));
  47 + return -1;
45 } 48 }
46 49
47 /* Examples from PI_MODBUS_300.pdf. 50 /* Examples from PI_MODBUS_300.pdf.
@@ -61,11 +64,11 @@ int main(void) @@ -61,11 +64,11 @@ int main(void)
61 socket = modbus_slave_listen_tcp(&mb_param, 1); 64 socket = modbus_slave_listen_tcp(&mb_param, 1);
62 modbus_slave_accept_tcp(&mb_param, &socket); 65 modbus_slave_accept_tcp(&mb_param, &socket);
63 66
64 - while (1) { 67 + for (;;) {
65 uint8_t query[MAX_MESSAGE_LENGTH]; 68 uint8_t query[MAX_MESSAGE_LENGTH];
66 69
67 - ret = modbus_slave_receive(&mb_param, -1, query);  
68 - if (ret >= 0) { 70 + rc = modbus_slave_receive(&mb_param, -1, query);
  71 + if (rc > 0) {
69 if (((query[HEADER_LENGTH_TCP + 3] << 8) + query[HEADER_LENGTH_TCP + 4]) 72 if (((query[HEADER_LENGTH_TCP + 3] << 8) + query[HEADER_LENGTH_TCP + 4])
70 == UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL) { 73 == UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL) {
71 /* Change the number of values (offset 74 /* Change the number of values (offset
@@ -74,15 +77,18 @@ int main(void) @@ -74,15 +77,18 @@ int main(void)
74 query[HEADER_LENGTH_TCP + 4] = UT_HOLDING_REGISTERS_NB_POINTS; 77 query[HEADER_LENGTH_TCP + 4] = UT_HOLDING_REGISTERS_NB_POINTS;
75 } 78 }
76 79
77 - modbus_slave_manage(&mb_param, query, ret, &mb_mapping);  
78 - } else if (ret == CONNECTION_CLOSED) {  
79 - /* Connection closed by the client, end of server */  
80 - break; 80 + rc = modbus_slave_manage(&mb_param, query, rc, &mb_mapping);
  81 + if (rc == -1) {
  82 + return -1;
  83 + }
81 } else { 84 } else {
82 - fprintf(stderr, "Error in modbus_listen (%d)\n", ret); 85 + /* Connection closed by the client or error */
  86 + break;
83 } 87 }
84 } 88 }
85 89
  90 + printf("Quit the loop: %s\n", modbus_strerror(errno));
  91 +
86 close(socket); 92 close(socket);
87 modbus_mapping_free(&mb_mapping); 93 modbus_mapping_free(&mb_mapping);
88 modbus_close(&mb_param); 94 modbus_close(&mb_param);