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 41 #include <sys/time.h>
42 42 #include <unistd.h>
43 43 #include <errno.h>
  44 +#include <assert.h>
44 45 #include <limits.h>
45 46 #include <fcntl.h>
46 47  
... ... @@ -61,9 +62,8 @@
61 62 #endif
62 63  
63 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 68 /* Exported version */
69 69 const unsigned int mb_version_major = MB_VERSION_MAJOR;
... ... @@ -78,22 +78,6 @@ typedef struct {
78 78 int t_id;
79 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 81 /* Table of CRC values for high-order byte */
98 82 static uint8_t table_crc_hi[] = {
99 83 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
... ... @@ -169,42 +153,65 @@ static const int TAB_MAX_ADU_LENGTH[2] = {
169 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 207 if (mb_param->type_com == RTU) {
200   - tcflush(mb_param->fd, TCIOFLUSH);
  208 + rc = tcflush(mb_param->fd, TCIOFLUSH);
201 209 } else {
202   - int ret;
203 210 do {
204 211 /* Extract the garbage from the socket */
205 212 char devnull[MAX_ADU_LENGTH_TCP];
206 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 215 #else
209 216 /* On Cygwin, it's a bit more complicated to not wait */
210 217 fd_set rfds;
... ... @@ -214,19 +221,17 @@ void modbus_flush(modbus_param_t *mb_param)
214 221 tv.tv_usec = 0;
215 222 FD_ZERO(&rfds);
216 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 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 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 301 static uint16_t t_id = 0;
298 302  
299 303 /* Transaction ID */
... ... @@ -309,7 +313,7 @@ static int build_query_basis_tcp(int slave, int function,
309 313 query[3] = 0;
310 314  
311 315 /* Length will be defined later by set_query_length_tcp at offsets 4
312   - * and 5 */
  316 + and 5 */
313 317  
314 318 query[6] = slave;
315 319 query[7] = function;
... ... @@ -400,38 +404,39 @@ static uint16_t crc16(uint8_t *buffer, uint16_t buffer_length)
400 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 409 static int check_crc16(modbus_param_t *mb_param,
405 410 uint8_t *msg,
406 411 const int msg_length)
407 412 {
408   - int ret;
409   - uint16_t crc_calc;
  413 + uint16_t crc_calculated;
410 414 uint16_t crc_received;
411 415  
412   - crc_calc = crc16(msg, msg_length - 2);
  416 + crc_calculated = crc16(msg, msg_length - 2);
413 417 crc_received = (msg[msg_length - 2] << 8) | msg[msg_length - 1];
414 418  
415 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 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 435 /* Sends a query/response over a serial or a TCP communication */
431 436 static int modbus_send(modbus_param_t *mb_param, uint8_t *query,
432 437 int query_length)
433 438 {
434   - int ret;
  439 + int rc;
435 440 uint16_t s_crc;
436 441 int i;
437 442  
... ... @@ -449,19 +454,35 @@ static int modbus_send(modbus_param_t *mb_param, uint8_t *query,
449 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 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 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 569 /* Waits a reply from a modbus slave or a query from a modbus master.
537 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 584 static int receive_msg(modbus_param_t *mb_param,
549 585 int msg_length_computed,
550 586 uint8_t *msg)
551 587 {
552   - int select_ret;
553   - int read_ret;
  588 + int s_rc;
  589 + int read_rc;
554 590 fd_set rfds;
555 591 struct timeval tv;
556 592 int length_to_read;
... ... @@ -591,32 +627,41 @@ static int receive_msg(modbus_param_t *mb_param,
591 627  
592 628 length_to_read = msg_length_computed;
593 629  
594   - select_ret = 0;
  630 + s_rc = 0;
595 631 WAIT_DATA();
596 632  
597 633 p_msg = msg;
598   - while (select_ret) {
  634 + while (s_rc) {
599 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 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 658 /* Sums bytes received */
614   - msg_length += read_ret;
  659 + msg_length += read_rc;
615 660  
616 661 /* Display the hex code of each character received */
617 662 if (mb_param->debug) {
618 663 int i;
619   - for (i=0; i < read_ret; i++)
  664 + for (i=0; i < read_rc; i++)
620 665 printf("<%.2X>", p_msg[i]);
621 666 }
622 667  
... ... @@ -639,8 +684,9 @@ static int receive_msg(modbus_param_t *mb_param,
639 684 length_to_read = compute_query_length_data(mb_param, msg);
640 685 msg_length_computed += length_to_read;
641 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 691 state = COMPLETE;
646 692 break;
... ... @@ -651,7 +697,7 @@ static int receive_msg(modbus_param_t *mb_param,
651 697 }
652 698  
653 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 702 if (length_to_read > 0) {
657 703 /* If no character at the buffer wait
... ... @@ -662,7 +708,7 @@ static int receive_msg(modbus_param_t *mb_param,
662 708 WAIT_DATA();
663 709 } else {
664 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 729 descriptor etablished with the master device in argument or -1 to use the
684 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 734 int modbus_slave_receive(modbus_param_t *mb_param, int sockfd, uint8_t *query)
692 735 {
693 736 if (sockfd != -1) {
... ... @@ -700,10 +743,8 @@ int modbus_slave_receive(modbus_param_t *mb_param, int sockfd, uint8_t *query)
700 743  
701 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 749 Note: all functions used to send or receive data with modbus return
709 750 these values. */
... ... @@ -711,13 +752,13 @@ static int modbus_receive(modbus_param_t *mb_param,
711 752 uint8_t *query,
712 753 uint8_t *response)
713 754 {
714   - int ret;
  755 + int rc;
715 756 int response_length_computed;
716 757 int offset = TAB_HEADER_LENGTH[mb_param->type_com];
717 758  
718 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 762 /* GOOD RESPONSE */
722 763 int query_nb_value;
723 764 int response_nb_value;
... ... @@ -748,7 +789,7 @@ static int modbus_receive(modbus_param_t *mb_param,
748 789 break;
749 790 case FC_REPORT_SLAVE_ID:
750 791 /* Report slave ID (bytes received) */
751   - query_nb_value = response_nb_value = ret;
  792 + query_nb_value = response_nb_value = rc;
752 793 break;
753 794 default:
754 795 /* 1 Write functions & others */
... ... @@ -756,58 +797,42 @@ static int modbus_receive(modbus_param_t *mb_param,
756 797 }
757 798  
758 799 if (query_nb_value == response_nb_value) {
759   - ret = response_nb_value;
  800 + rc = response_nb_value;
760 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 811 /* EXCEPTION CODE RECEIVED */
770 812  
771 813 /* CRC must be checked here (not done in receive_msg) */
772 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 820 /* Check for exception response.
779 821 0x80 + function is stored in the exception
780 822 response. */
781 823 if (0x80 + query[offset] == response[offset]) {
782   -
783 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 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 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 870 response_length = build_response_basis(mb_param, sft, response);
846 871  
847 872 /* Positive exception code */
848   - response[response_length++] = -exception_code;
  873 + response[response_length++] = exception_code;
849 874  
850 875 return response_length;
851 876 }
... ... @@ -856,8 +881,8 @@ static int response_exception(modbus_param_t *mb_param, sft_t *sft,
856 881 If an error occurs, this function construct the response
857 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 887 int offset = TAB_HEADER_LENGTH[mb_param->type_com];
863 888 int slave = query[offset - 1];
... ... @@ -873,7 +898,7 @@ void modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query,
873 898 printf("Request for slave %d ignored (not %d)\n",
874 899 slave, mb_param->slave);
875 900 }
876   - return;
  901 + return 0;
877 902 }
878 903  
879 904 sft.slave = slave;
... ... @@ -890,10 +915,13 @@ void modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query,
890 915 int nb = (query[offset + 3] << 8) + query[offset + 4];
891 916  
892 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 925 } else {
898 926 resp_length = build_response_basis(mb_param, &sft, response);
899 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 937 int nb = (query[offset + 3] << 8) + query[offset + 4];
910 938  
911 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 947 } else {
917 948 resp_length = build_response_basis(mb_param, &sft, response);
918 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 957 int nb = (query[offset + 3] << 8) + query[offset + 4];
927 958  
928 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 967 } else {
934 968 int i;
935 969  
... ... @@ -948,10 +982,13 @@ void modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query,
948 982 int nb = (query[offset + 3] << 8) + query[offset + 4];
949 983  
950 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 992 } else {
956 993 int i;
957 994  
... ... @@ -966,9 +1003,13 @@ void modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query,
966 1003 break;
967 1004 case FC_FORCE_SINGLE_COIL:
968 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 1013 } else {
973 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 1023 memcpy(response, query, query_length);
983 1024 resp_length = query_length;
984 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 1035 break;
992 1036 case FC_PRESET_SINGLE_REGISTER:
993 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 1045 } else {
998 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 1054 int nb = (query[offset + 3] << 8) + query[offset + 4];
1007 1055  
1008 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 1064 } else {
1014 1065 /* 6 = byte count */
1015 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 1076 int nb = (query[offset + 3] << 8) + query[offset + 4];
1026 1077  
1027 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 1086 } else {
1033 1087 int i, j;
1034 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 1100 break;
1047 1101 case FC_READ_EXCEPTION_STATUS:
1048 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 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 1117 /* Reads IO status */
1057 1118 static int read_io_status(modbus_param_t *mb_param, int function,
1058 1119 int start_addr, int nb, uint8_t *data_dest)
1059 1120 {
1060   - int ret;
  1121 + int rc;
1061 1122 int query_length;
1062 1123  
1063 1124 uint8_t query[MIN_QUERY_LENGTH];
... ... @@ -1066,19 +1127,19 @@ static int read_io_status(modbus_param_t *mb_param, int function,
1066 1127 query_length = build_query_basis(mb_param, function,
1067 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 1132 int i, temp, bit;
1072 1133 int pos = 0;
1073 1134 int offset;
1074 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 1141 offset = TAB_HEADER_LENGTH[mb_param->type_com];
1081   - offset_end = offset + ret;
  1142 + offset_end = offset + rc;
1082 1143 for (i = offset; i < offset_end; i++) {
1083 1144 /* Shift reg hi_byte to temp */
1084 1145 temp = response[i + 2];
... ... @@ -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 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 1160 int read_coil_status(modbus_param_t *mb_param, int start_addr,
1100 1161 int nb, uint8_t *data_dest)
1101 1162 {
1102   - int status;
  1163 + int rc;
1103 1164  
1104 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 1186 int read_input_status(modbus_param_t *mb_param, int start_addr,
1123 1187 int nb, uint8_t *data_dest)
1124 1188 {
1125   - int status;
  1189 + int rc;
1126 1190  
1127 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 1210 /* Reads the data from a modbus slave and put that data into an array */
1144 1211 static int read_registers(modbus_param_t *mb_param, int function,
1145 1212 int start_addr, int nb, uint16_t *data_dest)
1146 1213 {
1147   - int ret;
  1214 + int rc;
1148 1215 int query_length;
1149 1216 uint8_t query[MIN_QUERY_LENGTH];
1150 1217 uint8_t response[MAX_MESSAGE_LENGTH];
1151 1218  
1152 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 1229 query_length = build_query_basis(mb_param, function,
1160 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 1234 int offset;
1165 1235 int i;
1166 1236  
1167   - ret = modbus_receive(mb_param, query, response);
  1237 + rc = modbus_receive(mb_param, query, response);
1168 1238  
1169 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 1243 /* shift reg hi_byte to temp OR with lo_byte */
1174 1244 data_dest[i] = (response[offset + 2 + (i << 1)] << 8) |
1175 1245 response[offset + 3 + (i << 1)];
1176 1246 }
1177 1247 }
1178 1248  
1179   - return ret;
  1249 + return rc;
1180 1250 }
1181 1251  
1182 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 1257 int status;
1188 1258  
1189 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 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 1282 fprintf(stderr,
1210 1283 "ERROR Too many input registers requested (%d > %d)\n",
1211 1284 nb, MAX_REGISTERS);
1212   - return INVALID_DATA;
  1285 + errno = EMBMDATA;
  1286 + return -1;
1213 1287 }
1214 1288  
1215 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 1297 static int set_single(modbus_param_t *mb_param, int function,
1224 1298 int addr, int value)
1225 1299 {
1226   - int ret;
  1300 + int rc;
1227 1301 int query_length;
1228 1302 uint8_t query[MIN_QUERY_LENGTH];
1229 1303  
1230 1304 query_length = build_query_basis(mb_param, function,
1231 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 1309 /* Used by force_single_coil and
1236 1310 * preset_single_register */
1237 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 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 1344 int force_multiple_coils(modbus_param_t *mb_param, int start_addr, int nb,
1271 1345 const uint8_t *data_src)
1272 1346 {
1273   - int ret;
  1347 + int rc;
1274 1348 int i;
1275 1349 int byte_count;
1276 1350 int query_length;
... ... @@ -1280,9 +1354,12 @@ int force_multiple_coils(modbus_param_t *mb_param, int start_addr, int nb,
1280 1354 uint8_t query[MAX_MESSAGE_LENGTH];
1281 1355  
1282 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 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 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 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 1397 /* Copies the values in the slave from the array given in argument */
1321 1398 int preset_multiple_registers(modbus_param_t *mb_param, int start_addr, int nb,
1322 1399 const uint16_t *data_src)
1323 1400 {
1324   - int ret;
  1401 + int rc;
1325 1402 int i;
1326 1403 int query_length;
1327 1404 int byte_count;
... ... @@ -1329,10 +1406,13 @@ int preset_multiple_registers(modbus_param_t *mb_param, int start_addr, int nb,
1329 1406 uint8_t query[MAX_MESSAGE_LENGTH];
1330 1407  
1331 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 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 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 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 1437 /* Returns the slave id! */
1358 1438 int report_slave_id(modbus_param_t *mb_param, uint8_t *data_dest)
1359 1439 {
1360   - int ret;
  1440 + int rc;
1361 1441 int query_length;
1362 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 1446 /* HACKISH, start_addr and count are not used */
1367 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 1451 int i;
1372 1452 int offset;
1373 1453 int offset_end;
... ... @@ -1375,18 +1455,18 @@ int report_slave_id(modbus_param_t *mb_param, uint8_t *data_dest)
1375 1455  
1376 1456 /* Byte count, slave id, run indicator status,
1377 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 1462 offset = TAB_HEADER_LENGTH[mb_param->type_com] - 1;
1383   - offset_end = offset + ret;
  1463 + offset_end = offset + rc;
1384 1464  
1385 1465 for (i = offset; i < offset_end; i++)
1386 1466 data_dest[i] = response[i];
1387 1467 }
1388 1468  
1389   - return ret;
  1469 + return rc;
1390 1470 }
1391 1471  
1392 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 1488 mb_param->data_bit = data_bit;
1409 1489 mb_param->stop_bit = stop_bit;
1410 1490 mb_param->type_com = RTU;
1411   - mb_param->error_handling = FLUSH_OR_CONNECT_ON_ERROR;
  1491 + mb_param->error_recovery = FALSE;
1412 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 1507 strncpy(mb_param->ip, ip, sizeof(char)*16);
1428 1508 mb_param->port = port;
1429 1509 mb_param->type_com = TCP;
1430   - mb_param->error_handling = FLUSH_OR_CONNECT_ON_ERROR;
  1510 + mb_param->error_recovery = FALSE;
1431 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 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 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 1546 /* Sets up a serial port for RTU communications */
1464 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 1550 speed_t speed;
1468 1551  
1469 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 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 1562 Timeouts are ignored in canonical input mode or when the
1480 1563 NDELAY option is set on the file via open or fcntl */
1481 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 1566 fprintf(stderr, "ERROR Can't open the device %s (%s)\n",
1484 1567 mb_param->device, strerror(errno));
1485 1568 return -1;
... ... @@ -1529,15 +1612,16 @@ static int modbus_connect_rtu(modbus_param_t *mb_param)
1529 1612 break;
1530 1613 default:
1531 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 1622 /* Set the baud rate */
1538 1623 if ((cfsetispeed(&tios, speed) < 0) ||
1539 1624 (cfsetospeed(&tios, speed) < 0)) {
1540   - perror("cfsetispeed/cfsetospeed\n");
1541 1625 return -1;
1542 1626 }
1543 1627  
... ... @@ -1707,7 +1791,6 @@ static int modbus_connect_rtu(modbus_param_t *mb_param)
1707 1791 tios.c_cc[VTIME] = 0;
1708 1792  
1709 1793 if (tcsetattr(mb_param->fd, TCSANOW, &tios) < 0) {
1710   - perror("tcsetattr\n");
1711 1794 return -1;
1712 1795 }
1713 1796  
... ... @@ -1717,24 +1800,23 @@ static int modbus_connect_rtu(modbus_param_t *mb_param)
1717 1800 /* Establishes a modbus TCP connection with a modbus slave */
1718 1801 static int modbus_connect_tcp(modbus_param_t *mb_param)
1719 1802 {
1720   - int ret;
  1803 + int rc;
1721 1804 int option;
1722 1805 struct sockaddr_in addr;
1723 1806  
1724 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 1812 /* Set the TCP no delay flag */
1730 1813 /* SOL_TCP = IPPROTO_TCP */
1731 1814 option = 1;
1732   - ret = setsockopt(mb_param->fd, IPPROTO_TCP, TCP_NODELAY,
  1815 + rc = setsockopt(mb_param->fd, IPPROTO_TCP, TCP_NODELAY,
1733 1816 (const void *)&option, sizeof(int));
1734   - if (ret < 0) {
1735   - perror("setsockopt TCP_NODELAY");
  1817 + if (rc == -1) {
1736 1818 close(mb_param->fd);
1737   - return ret;
  1819 + return -1;
1738 1820 }
1739 1821  
1740 1822 #if (!HAVE_DECL___CYGWIN__)
... ... @@ -1744,12 +1826,11 @@ static int modbus_connect_tcp(modbus_param_t *mb_param)
1744 1826 **/
1745 1827 /* Set the IP low delay option */
1746 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 1830 (const void *)&option, sizeof(int));
1749   - if (ret < 0) {
1750   - perror("setsockopt IP_TOS");
  1831 + if (rc == -1) {
1751 1832 close(mb_param->fd);
1752   - return ret;
  1833 + return -1;
1753 1834 }
1754 1835 #endif
1755 1836  
... ... @@ -1760,12 +1841,11 @@ static int modbus_connect_tcp(modbus_param_t *mb_param)
1760 1841 addr.sin_family = AF_INET;
1761 1842 addr.sin_port = htons(mb_param->port);
1762 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 1845 sizeof(struct sockaddr_in));
1765   - if (ret < 0) {
1766   - perror("connect");
  1846 + if (rc == -1) {
1767 1847 close(mb_param->fd);
1768   - return ret;
  1848 + return -1;
1769 1849 }
1770 1850  
1771 1851 return 0;
... ... @@ -1775,22 +1855,20 @@ static int modbus_connect_tcp(modbus_param_t *mb_param)
1775 1855 Returns 0 on success or -1 on failure. */
1776 1856 int modbus_connect(modbus_param_t *mb_param)
1777 1857 {
1778   - int ret;
  1858 + int rc;
1779 1859  
1780 1860 if (mb_param->type_com == RTU)
1781   - ret = modbus_connect_rtu(mb_param);
  1861 + rc = modbus_connect_rtu(mb_param);
1782 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 1868 /* Closes the file descriptor in RTU mode */
1789 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 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 1897 /* Allocates 4 arrays to store coils, input status, input registers and
1820 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 1903 int modbus_mapping_new(modbus_mapping_t *mb_mapping,
1825 1904 int nb_coil_status, int nb_input_status,
... ... @@ -1829,46 +1908,51 @@ int modbus_mapping_new(modbus_mapping_t *mb_mapping,
1829 1908 mb_mapping->nb_coil_status = nb_coil_status;
1830 1909 mb_mapping->tab_coil_status =
1831 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 1915 memset(mb_mapping->tab_coil_status, 0,
1833 1916 nb_coil_status * sizeof(uint8_t));
1834   - if (mb_mapping->tab_coil_status == NULL)
1835   - return -1;
1836 1917  
1837 1918 /* 1X */
1838 1919 mb_mapping->nb_input_status = nb_input_status;
1839 1920 mb_mapping->tab_input_status =
1840 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 1922 if (mb_mapping->tab_input_status == NULL) {
1844 1923 free(mb_mapping->tab_coil_status);
  1924 + errno = ENOMEM;
1845 1925 return -1;
1846 1926 }
  1927 + memset(mb_mapping->tab_input_status, 0,
  1928 + nb_input_status * sizeof(uint8_t));
1847 1929  
1848 1930 /* 4X */
1849 1931 mb_mapping->nb_holding_registers = nb_holding_registers;
1850 1932 mb_mapping->tab_holding_registers =
1851 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 1934 if (mb_mapping->tab_holding_registers == NULL) {
1855 1935 free(mb_mapping->tab_coil_status);
1856 1936 free(mb_mapping->tab_input_status);
  1937 + errno = ENOMEM;
1857 1938 return -1;
1858 1939 }
  1940 + memset(mb_mapping->tab_holding_registers, 0,
  1941 + nb_holding_registers * sizeof(uint16_t));
1859 1942  
1860 1943 /* 3X */
1861 1944 mb_mapping->nb_input_registers = nb_input_registers;
1862 1945 mb_mapping->tab_input_registers =
1863 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 1947 if (mb_mapping->tab_input_registers == NULL) {
1867 1948 free(mb_mapping->tab_coil_status);
1868 1949 free(mb_mapping->tab_input_status);
1869 1950 free(mb_mapping->tab_holding_registers);
  1951 + errno = ENOMEM;
1870 1952 return -1;
1871 1953 }
  1954 + memset(mb_mapping->tab_input_registers, 0,
  1955 + nb_input_registers * sizeof(uint16_t));
1872 1956  
1873 1957 return 0;
1874 1958 }
... ... @@ -1890,15 +1974,13 @@ int modbus_slave_listen_tcp(modbus_param_t *mb_param, int nb_connection)
1890 1974 struct sockaddr_in addr;
1891 1975  
1892 1976 new_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
1893   - if (new_socket < 0) {
1894   - perror("socket");
  1977 + if (new_socket == -1) {
1895 1978 return -1;
1896 1979 }
1897 1980  
1898 1981 yes = 1;
1899 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 1984 close(new_socket);
1903 1985 return -1;
1904 1986 }
... ... @@ -1908,14 +1990,12 @@ int modbus_slave_listen_tcp(modbus_param_t *mb_param, int nb_connection)
1908 1990 /* If the modbus port is < to 1024, we need the setuid root. */
1909 1991 addr.sin_port = htons(mb_param->port);
1910 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 1994 close(new_socket);
1914 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 1999 close(new_socket);
1920 2000 return -1;
1921 2001 }
... ... @@ -1923,6 +2003,9 @@ int modbus_slave_listen_tcp(modbus_param_t *mb_param, int nb_connection)
1923 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 2009 int modbus_slave_accept_tcp(modbus_param_t *mb_param, int *socket)
1927 2010 {
1928 2011 struct sockaddr_in addr;
... ... @@ -1930,11 +2013,13 @@ int modbus_slave_accept_tcp(modbus_param_t *mb_param, int *socket)
1930 2013  
1931 2014 addrlen = sizeof(struct sockaddr_in);
1932 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 2017 close(*socket);
1936 2018 *socket = 0;
1937   - } else {
  2019 + return -1;
  2020 + }
  2021 +
  2022 + if (mb_param->debug) {
1938 2023 printf("The client %s is connected\n",
1939 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 2049  
1965 2050 /* Sets many input/coil status from a table of bytes (only the bits
1966 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 2053 const uint8_t tab_byte[])
1969 2054 {
1970 2055 int i;
... ... @@ -1980,13 +2065,13 @@ void set_bits_from_bytes(uint8_t *dest, int address, int nb_bits,
1980 2065  
1981 2066 /* Gets the byte value from many input/coil status.
1982 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 2070 int i;
1986 2071 uint8_t value = 0;
1987 2072  
1988 2073 if (nb_bits > 8) {
1989   - fprintf(stderr, "ERROR nb_bits is too big\n");
  2074 + assert(nb_bits < 8);
1990 2075 nb_bits = 8;
1991 2076 }
1992 2077  
... ...
modbus/modbus.h
... ... @@ -120,36 +120,47 @@ extern &quot;C&quot; {
120 120 #define FC_PRESET_MULTIPLE_REGISTERS 0x10
121 121 #define FC_REPORT_SLAVE_ID 0x11
122 122  
  123 +/* Random number to avoid errno conflicts */
  124 +#define MODBUS_ENOBASE 112345678
  125 +
123 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 160 /* Internal using */
149 161 #define MSG_LENGTH_UNDEFINED -1
150 162  
151 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 165 /* This structure is byte-aligned */
155 166 typedef struct {
... ... @@ -183,7 +194,7 @@ typedef struct {
183 194 /* Parity: "even", "odd", "none" */
184 195 char parity[5];
185 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 198 /* IP address */
188 199 char ip[16];
189 200 /* Save old termios settings */
... ... @@ -201,171 +212,60 @@ typedef struct {
201 212 uint16_t *tab_holding_registers;
202 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 231 int read_coil_status(modbus_param_t *mb_param, int start_addr, int nb,
213 232 uint8_t *dest);
214   -
215   -/* Same as read_coil_status but reads the slaves input table */
216 233 int read_input_status(modbus_param_t *mb_param, int start_addr, int nb,
217 234 uint8_t *dest);
218   -
219   -/* Reads the holding registers in a slave and put the data into an
220   - array */
221 235 int read_holding_registers(modbus_param_t *mb_param, int start_addr, int nb,
222 236 uint16_t *dest);
223   -
224   -/* Reads the input registers in a slave and put the data into an
225   - array */
226 237 int read_input_registers(modbus_param_t *mb_param, int start_addr, int nb,
227 238 uint16_t *dest);
228   -
229   -/* Turns ON or OFF a single coil in the slave device */
230 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 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 242 int force_multiple_coils(modbus_param_t *mb_param, int start_addr, int nb,
237 243 const uint8_t *data);
238   -
239   -/* Copies the values in the slave from the array given in argument */
240 244 int preset_multiple_registers(modbus_param_t *mb_param, int start_addr, int nb,
241 245 const uint16_t *data);
242   -
243   -/* Returns the slave id! */
244 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 248 int modbus_mapping_new(modbus_mapping_t *mb_mapping,
310 249 int nb_coil_status, int nb_input_status,
311 250 int nb_holding_registers, int nb_input_registers);
312   -
313   -/* Frees the 4 arrays */
314 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 253 int modbus_slave_listen_tcp(modbus_param_t *mb_param, int nb_connection);
321   -
322   -/* Waits for a connection */
323 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 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 258 void modbus_slave_close_tcp(int socket);
347 259  
348 260 /**
349 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 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 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 268 float modbus_read_float(const uint16_t *src);
367   -
368   -/* Write a float to 4 bytes in Modbus format */
369 269 void modbus_write_float(float real, uint16_t *dest);
370 270  
371 271 #ifdef __cplusplus
... ...
tests/bandwidth-master.c
... ... @@ -21,6 +21,7 @@
21 21 #include <stdlib.h>
22 22 #include <time.h>
23 23 #include <sys/time.h>
  24 +#include <errno.h>
24 25  
25 26 #include <modbus/modbus.h>
26 27  
... ... @@ -44,18 +45,21 @@ int main(void)
44 45 uint16_t *tab_rp_registers;
45 46 modbus_param_t mb_param;
46 47 int i;
47   - int ret;
48 48 int nb_points;
49 49 double elapsed;
50 50 uint32_t start;
51 51 uint32_t end;
52 52 uint32_t bytes;
53 53 uint32_t rate;
  54 + int rc;
54 55  
55 56 /* TCP */
56 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 65 /* Allocate and initialize the memory to store the status */
... ... @@ -71,7 +75,11 @@ int main(void)
71 75 nb_points = MAX_STATUS;
72 76 start = gettime_ms();
73 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 84 end = gettime_ms();
77 85 elapsed = end - start;
... ... @@ -104,7 +112,11 @@ int main(void)
104 112 nb_points = MAX_REGISTERS;
105 113 start = gettime_ms();
106 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 121 end = gettime_ms();
110 122 elapsed = end - start;
... ...
tests/bandwidth-slave-many-up.c
... ... @@ -42,7 +42,7 @@ int main(void)
42 42 {
43 43 int master_socket;
44 44 modbus_param_t mb_param;
45   - int ret;
  45 + int rc;
46 46 fd_set refset;
47 47 fd_set rdset;
48 48  
... ... @@ -51,10 +51,11 @@ int main(void)
51 51  
52 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 61 slave_socket = modbus_slave_listen_tcp(&mb_param, NB_CONNECTION);
... ... @@ -107,9 +108,9 @@ int main(void)
107 108 /* An already connected master has sent a new query */
108 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 114 } else {
114 115 /* Connection closed by the client, end of server */
115 116 printf("Connection closed on socket %d\n", master_socket);
... ...
tests/bandwidth-slave-one.c
... ... @@ -19,6 +19,7 @@
19 19 #include <unistd.h>
20 20 #include <string.h>
21 21 #include <stdlib.h>
  22 +#include <errno.h>
22 23  
23 24 #include <modbus/modbus.h>
24 25  
... ... @@ -29,33 +30,34 @@ int main(void)
29 30 int socket;
30 31 modbus_param_t mb_param;
31 32 modbus_mapping_t mb_mapping;
32   - int ret;
  33 + int rc;
33 34  
34 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 44 socket = modbus_slave_listen_tcp(&mb_param, 1);
43 45 modbus_slave_accept_tcp(&mb_param, &socket);
44 46  
45   - while (1) {
  47 + for(;;) {
46 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 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 61 close(socket);
60 62 modbus_mapping_free(&mb_mapping);
61 63 modbus_close(&mb_param);
... ...
tests/random-test-master.c
... ... @@ -19,6 +19,7 @@
19 19 #include <unistd.h>
20 20 #include <string.h>
21 21 #include <stdlib.h>
  22 +#include <errno.h>
22 23  
23 24 #include <modbus/modbus.h>
24 25  
... ... @@ -45,7 +46,7 @@
45 46 */
46 47 int main(void)
47 48 {
48   - int ret;
  49 + int rc;
49 50 int nb_fail;
50 51 int nb_loop;
51 52 int addr;
... ... @@ -63,7 +64,9 @@ int main(void)
63 64 modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE);
64 65 modbus_set_debug(&mb_param, TRUE);
65 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 72 /* Allocate and initialize the different memory spaces */
... ... @@ -94,16 +97,16 @@ int main(void)
94 97 nb = ADDRESS_END - addr;
95 98  
96 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 103 printf("Slave = %d, address = %d, value = %d\n",
101 104 SLAVE, addr, tab_rq_status[0]);
102 105 nb_fail++;
103 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 110 printf("Slave = %d, address = %d\n",
108 111 SLAVE, addr);
109 112 nb_fail++;
... ... @@ -111,15 +114,15 @@ int main(void)
111 114 }
112 115  
113 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 120 printf("Slave = %d, address = %d, nb = %d\n",
118 121 SLAVE, addr, nb);
119 122 nb_fail++;
120 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 126 printf("ERROR read_coil_status\n");
124 127 printf("Slave = %d, address = %d, nb = %d\n",
125 128 SLAVE, addr, nb);
... ... @@ -139,16 +142,16 @@ int main(void)
139 142 }
140 143  
141 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 148 printf("Slave = %d, address = %d, value = %d (0x%X)\n",
146 149 SLAVE, addr, tab_rq_registers[0], tab_rq_registers[0]);
147 150 nb_fail++;
148 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 155 printf("Slave = %d, address = %d\n",
153 156 SLAVE, addr);
154 157 nb_fail++;
... ... @@ -165,18 +168,18 @@ int main(void)
165 168 }
166 169  
167 170 /* MULTIPLE REGISTERS */
168   - ret = preset_multiple_registers(&mb_param, addr, nb,
  171 + rc = preset_multiple_registers(&mb_param, addr, nb,
169 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 175 printf("Slave = %d, address = %d, nb = %d\n",
173 176 SLAVE, addr, nb);
174 177 nb_fail++;
175 178 } else {
176   - ret = read_holding_registers(&mb_param, addr, nb,
  179 + rc = read_holding_registers(&mb_param, addr, nb,
177 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 183 printf("Slave = %d, address = %d, nb = %d\n",
181 184 SLAVE, addr, nb);
182 185 nb_fail++;
... ...
tests/random-test-slave.c
... ... @@ -18,6 +18,7 @@
18 18 #include <stdio.h>
19 19 #include <unistd.h>
20 20 #include <stdlib.h>
  21 +#include <errno.h>
21 22  
22 23 #include <modbus/modbus.h>
23 24  
... ... @@ -28,36 +29,37 @@ int main(void)
28 29 int socket;
29 30 modbus_param_t mb_param;
30 31 modbus_mapping_t mb_mapping;
31   - int ret;
  32 + int rc;
32 33  
33 34 modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE);
34 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 44 socket = modbus_slave_listen_tcp(&mb_param, 1);
43 45 modbus_slave_accept_tcp(&mb_param, &socket);
44 46  
45   - while (1) {
  47 + for (;;) {
46 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 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 63 close(socket);
62 64 modbus_mapping_free(&mb_mapping);
63 65 modbus_close(&mb_param);
... ...
tests/unit-test-master.c
... ... @@ -19,6 +19,7 @@
19 19 #include <unistd.h>
20 20 #include <string.h>
21 21 #include <stdlib.h>
  22 +#include <errno.h>
22 23  
23 24 #include <modbus/modbus.h>
24 25 #include "unit-test.h"
... ... @@ -36,7 +37,7 @@ int main(void)
36 37 uint8_t value;
37 38 int address;
38 39 int nb_points;
39   - int ret;
  40 + int rc;
40 41 float real;
41 42  
42 43 /* RTU parity : none, even, odd */
... ... @@ -44,10 +45,12 @@ int main(void)
44 45  
45 46 /* TCP */
46 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 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 56 /* Allocate and initialize the memory to store the status */
... ... @@ -70,20 +73,20 @@ int main(void)
70 73 /** COIL STATUS **/
71 74  
72 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 77 printf("1/2 force_single_coil: ");
75   - if (ret == 1) {
  78 + if (rc == 1) {
76 79 printf("OK\n");
77 80 } else {
78 81 printf("FAILED\n");
79 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 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 90 goto close;
88 91 }
89 92  
... ... @@ -100,12 +103,12 @@ int main(void)
100 103  
101 104 set_bits_from_bytes(tab_value, 0, UT_COIL_STATUS_NB_POINTS,
102 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 110 printf("1/2 force_multiple_coils: ");
108   - if (ret == UT_COIL_STATUS_NB_POINTS) {
  111 + if (rc == UT_COIL_STATUS_NB_POINTS) {
109 112 printf("OK\n");
110 113 } else {
111 114 printf("FAILED\n");
... ... @@ -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 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 124 goto close;
122 125 }
123 126  
... ... @@ -141,12 +144,12 @@ int main(void)
141 144 /* End of multiple coils */
142 145  
143 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 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 153 goto close;
151 154 }
152 155  
... ... @@ -171,22 +174,22 @@ int main(void)
171 174 /** HOLDING REGISTERS **/
172 175  
173 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 179 printf("1/2 preset_single_register: ");
177   - if (ret == 1) {
  180 + if (rc == 1) {
178 181 printf("OK\n");
179 182 } else {
180 183 printf("FAILED\n");
181 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 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 193 goto close;
191 194 }
192 195  
... ... @@ -199,25 +202,25 @@ int main(void)
199 202 /* End of single register */
200 203  
201 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 209 printf("1/2 preset_multiple_registers: ");
207   - if (ret == UT_HOLDING_REGISTERS_NB_POINTS) {
  210 + if (rc == UT_HOLDING_REGISTERS_NB_POINTS) {
208 211 printf("OK\n");
209 212 } else {
210 213 printf("FAILED\n");
211 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 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 224 goto close;
222 225 }
223 226  
... ... @@ -234,13 +237,13 @@ int main(void)
234 237  
235 238  
236 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 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 247 goto close;
245 248 }
246 249  
... ... @@ -284,83 +287,83 @@ int main(void)
284 287 /* The mapping begins at 0 and ending at address + nb_points so
285 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 294 printf("* read_coil_status: ");
292   - if (ret == ILLEGAL_DATA_ADDRESS)
  295 + if (rc == -1 && errno == EMBXILADD)
293 296 printf("OK\n");
294 297 else {
295 298 printf("FAILED\n");
296 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 306 printf("* read_input_status: ");
304   - if (ret == ILLEGAL_DATA_ADDRESS)
  307 + if (rc == -1 && errno == EMBXILADD)
305 308 printf("OK\n");
306 309 else {
307 310 printf("FAILED\n");
308 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 318 printf("* read_holding_registers: ");
316   - if (ret == ILLEGAL_DATA_ADDRESS)
  319 + if (rc == -1 && errno == EMBXILADD)
317 320 printf("OK\n");
318 321 else {
319 322 printf("FAILED\n");
320 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 330 printf("* read_input_registers: ");
328   - if (ret == ILLEGAL_DATA_ADDRESS)
  331 + if (rc == -1 && errno == EMBXILADD)
329 332 printf("OK\n");
330 333 else {
331 334 printf("FAILED\n");
332 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 341 printf("* force_single_coil: ");
339   - if (ret == ILLEGAL_DATA_ADDRESS) {
  342 + if (rc == -1 && errno == EMBXILADD) {
340 343 printf("OK\n");
341 344 } else {
342 345 printf("FAILED\n");
343 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 353 printf("* force_multiple_coils: ");
351   - if (ret == ILLEGAL_DATA_ADDRESS) {
  354 + if (rc == -1 && errno == EMBXILADD) {
352 355 printf("OK\n");
353 356 } else {
354 357 printf("FAILED\n");
355 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 365 printf("* preset_multiple_registers: ");
363   - if (ret == ILLEGAL_DATA_ADDRESS) {
  366 + if (rc == -1 && errno == EMBXILADD) {
364 367 printf("OK\n");
365 368 } else {
366 369 printf("FAILED\n");
... ... @@ -371,72 +374,72 @@ int main(void)
371 374 /** TOO MANY DATA **/
372 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 381 printf("* read_coil_status: ");
379   - if (ret == INVALID_DATA) {
  382 + if (rc == -1 && errno == EMBMDATA) {
380 383 printf("OK\n");
381 384 } else {
382 385 printf("FAILED\n");
383 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 393 printf("* read_input_status: ");
391   - if (ret == INVALID_DATA) {
  394 + if (rc == -1 && errno == EMBMDATA) {
392 395 printf("OK\n");
393 396 } else {
394 397 printf("FAILED\n");
395 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 405 printf("* read_holding_registers: ");
403   - if (ret == INVALID_DATA) {
  406 + if (rc == -1 && errno == EMBMDATA) {
404 407 printf("OK\n");
405 408 } else {
406 409 printf("FAILED\n");
407 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 417 printf("* read_input_registers: ");
415   - if (ret == INVALID_DATA) {
  418 + if (rc == -1 && errno == EMBMDATA) {
416 419 printf("OK\n");
417 420 } else {
418 421 printf("FAILED\n");
419 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 429 printf("* force_multiple_coils: ");
427   - if (ret == INVALID_DATA) {
  430 + if (rc == -1 && errno == EMBMDATA) {
428 431 printf("OK\n");
429 432 } else {
430 433 goto close;
431 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 441 printf("* preset_multiple_registers: ");
439   - if (ret == INVALID_DATA) {
  442 + if (rc == -1 && errno == EMBMDATA) {
440 443 printf("OK\n");
441 444 } else {
442 445 printf("FAILED\n");
... ... @@ -446,12 +449,12 @@ int main(void)
446 449 /** SLAVE REPLY **/
447 450 printf("\nTEST SLAVE REPLY:\n");
448 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 456 printf("1/2 No reply from slave %d: ", mb_param.slave);
454   - if (ret == SELECT_TIMEOUT) {
  457 + if (rc == -1 && errno == ETIMEDOUT) {
455 458 printf("OK\n");
456 459 } else {
457 460 printf("FAILED\n");
... ... @@ -459,12 +462,12 @@ int main(void)
459 462 }
460 463  
461 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 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 471 printf("OK\n");
469 472 } else {
470 473 goto close;
... ... @@ -477,12 +480,12 @@ int main(void)
477 480 /* Allocate only the required space */
478 481 tab_rp_registers_bad = (uint16_t *) malloc(
479 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 487 printf("* read_holding_registers: ");
485   - if (ret == INVALID_DATA) {
  488 + if (rc == -1 && errno == EMBBADDATA) {
486 489 printf("OK\n");
487 490 } else {
488 491 printf("FAILED\n");
... ...
tests/unit-test-slave.c
... ... @@ -19,6 +19,7 @@
19 19 #include <unistd.h>
20 20 #include <string.h>
21 21 #include <stdlib.h>
  22 +#include <errno.h>
22 23  
23 24 #include <modbus/modbus.h>
24 25 #include "unit-test.h"
... ... @@ -28,20 +29,22 @@ int main(void)
28 29 int socket;
29 30 modbus_param_t mb_param;
30 31 modbus_mapping_t mb_mapping;
31   - int ret;
  32 + int rc;
32 33 int i;
33 34  
34 35 modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE);
35 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 40 UT_COIL_STATUS_ADDRESS + UT_COIL_STATUS_NB_POINTS,
39 41 UT_INPUT_STATUS_ADDRESS + UT_INPUT_STATUS_NB_POINTS,
40 42 UT_HOLDING_REGISTERS_ADDRESS + UT_HOLDING_REGISTERS_NB_POINTS,
41 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 50 /* Examples from PI_MODBUS_300.pdf.
... ... @@ -61,11 +64,11 @@ int main(void)
61 64 socket = modbus_slave_listen_tcp(&mb_param, 1);
62 65 modbus_slave_accept_tcp(&mb_param, &socket);
63 66  
64   - while (1) {
  67 + for (;;) {
65 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 72 if (((query[HEADER_LENGTH_TCP + 3] << 8) + query[HEADER_LENGTH_TCP + 4])
70 73 == UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL) {
71 74 /* Change the number of values (offset
... ... @@ -74,15 +77,18 @@ int main(void)
74 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 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 92 close(socket);
87 93 modbus_mapping_free(&mb_mapping);
88 94 modbus_close(&mb_param);
... ...