Commit 0a6ea1ac033d9ae72547df6d9b78283bdb876dbf

Authored by Stéphane Raimbault
1 parent f20a1860

Remove one argument to receive_msg and modbus_slave_receive

- the return value is used to pass the message length
- remove the hack on exception check in modbus receive
- update tests
src/modbus.c
1 1 /*
2   - * Copyright © 2001-2008 Stéphane Raimbault <stephane.raimbault@gmail.com>
  2 + * Copyright © 2001-2010 Stéphane Raimbault <stephane.raimbault@gmail.com>
3 3 *
4 4 * This program is free software: you can redistribute it and/or modify
5 5 * it under the terms of the GNU Lesser Public License as published by
... ... @@ -252,6 +252,8 @@ static unsigned int compute_response_length(modbus_param_t *mb_param,
252 252 length = 3;
253 253 break;
254 254 case FC_REPORT_SLAVE_ID:
  255 + /* The response is device specific (the header provides the
  256 + length) */
255 257 return MSG_LENGTH_UNDEFINED;
256 258 default:
257 259 length = 5;
... ... @@ -393,7 +395,7 @@ static uint16_t crc16(uint8_t *buffer, uint16_t buffer_length)
393 395 return (crc_hi << 8 | crc_lo);
394 396 }
395 397  
396   -/* If CRC is correct returns 0 else returns INVALID_CRC */
  398 +/* If CRC is correct returns msg_length else returns INVALID_CRC */
397 399 static int check_crc16(modbus_param_t *mb_param,
398 400 uint8_t *msg,
399 401 const int msg_length)
... ... @@ -407,7 +409,7 @@ static int check_crc16(modbus_param_t *mb_param,
407 409  
408 410 /* Check CRC of msg */
409 411 if (crc_calc == crc_received) {
410   - ret = 0;
  412 + ret = msg_length;
411 413 } else {
412 414 char s_error[64];
413 415 sprintf(s_error,
... ... @@ -512,28 +514,35 @@ static int compute_query_length_data(modbus_param_t *mb_param, uint8_t *msg)
512 514 } \
513 515 \
514 516 if (select_ret == 0) { \
515   - /* Call to error_treat is done later to manage exceptions */ \
516   - return SELECT_TIMEOUT; \
  517 + /* Timeout */ \
  518 + if (msg_length == (TAB_HEADER_LENGTH[mb_param->type_com] + 2 + \
  519 + TAB_CHECKSUM_LENGTH[mb_param->type_com])) { \
  520 + /* Optimization allowed because exception response is \
  521 + the smallest trame in modbus protocol (3) so always \
  522 + raise a timeout error */ \
  523 + return MB_EXCEPTION; \
  524 + } else { \
  525 + /* Call to error_treat is done later to manage exceptions */ \
  526 + return SELECT_TIMEOUT; \
  527 + } \
517 528 } \
518 529 }
519 530  
520 531 /* Waits a reply from a modbus slave or a query from a modbus master.
521   - This function blocks for timeout seconds if there is no reply.
  532 + This function blocks if there is no replies (3 timeouts).
522 533  
523 534 In
524 535 - msg_length_computed must be set to MSG_LENGTH_UNDEFINED if undefined
525 536  
526 537 Out
527 538 - msg is an array of uint8_t to receive the message
528   - - p_msg_length, the variable is assigned to the number of
529   - characters received. This value won't be greater than
530   - msg_length_computed.
531 539  
532   - Returns 0 in success or a negative value if an error occured.
  540 + On success, return the number of received characters. On error, return
  541 + a negative value.
533 542 */
534 543 static int receive_msg(modbus_param_t *mb_param,
535 544 int msg_length_computed,
536   - uint8_t *msg, int *p_msg_length)
  545 + uint8_t *msg)
537 546 {
538 547 int select_ret;
539 548 int read_ret;
... ... @@ -544,9 +553,7 @@ static int receive_msg(modbus_param_t *mb_param,
544 553 enum { FUNCTION, BYTE, COMPLETE };
545 554 int state;
546 555  
547   - /* Initialize the return length before a call to WAIT_DATA because a
548   - * time out can quit the function. */
549   - (*p_msg_length) = 0;
  556 + int msg_length = 0;
550 557  
551 558 if (mb_param->debug) {
552 559 if (msg_length_computed == MSG_LENGTH_UNDEFINED)
... ... @@ -599,7 +606,7 @@ static int receive_msg(modbus_param_t *mb_param,
599 606 }
600 607  
601 608 /* Sums bytes received */
602   - (*p_msg_length) += read_ret;
  609 + msg_length += read_ret;
603 610  
604 611 /* Display the hex code of each character received */
605 612 if (mb_param->debug) {
... ... @@ -608,9 +615,9 @@ static int receive_msg(modbus_param_t *mb_param,
608 615 printf("<%.2X>", p_msg[i]);
609 616 }
610 617  
611   - if ((*p_msg_length) < msg_length_computed) {
  618 + if (msg_length < msg_length_computed) {
612 619 /* Message incomplete */
613   - length_to_read = msg_length_computed - (*p_msg_length);
  620 + length_to_read = msg_length_computed - msg_length;
614 621 } else {
615 622 switch (state) {
616 623 case FUNCTION:
... ... @@ -618,9 +625,9 @@ static int receive_msg(modbus_param_t *mb_param,
618 625 length_to_read = compute_query_length_header(
619 626 msg[TAB_HEADER_LENGTH[mb_param->type_com]]);
620 627 msg_length_computed += length_to_read;
621   - /* It's useless to check
622   - p_msg_length_computed value in this
623   - case (only defined values are used). */
  628 + /* It's useless to check the value of
  629 + msg_length_computed in this case (only
  630 + defined values are used). */
624 631 state = BYTE;
625 632 break;
626 633 case BYTE:
... ... @@ -658,10 +665,12 @@ static int receive_msg(modbus_param_t *mb_param,
658 665 printf("\n");
659 666  
660 667 if (mb_param->type_com == RTU) {
661   - return check_crc16(mb_param, msg, (*p_msg_length));
  668 + /* Returns msg_length on success and a negative value on
  669 + failure */
  670 + return check_crc16(mb_param, msg, msg_length);
662 671 } else {
663 672 /* OK */
664   - return 0;
  673 + return msg_length;
665 674 }
666 675 }
667 676  
... ... @@ -670,28 +679,24 @@ static int receive_msg(modbus_param_t *mb_param,
670 679 internal one of modbus_param_t.
671 680  
672 681 Returns:
673   - - 0 on success, or a negative error number if the request fails
  682 + - byte length of the message on success, or a negative error number if the
  683 + request fails
674 684 - query, message received
675   - - query_length, length in bytes of the message */
676   -int modbus_slave_receive(modbus_param_t *mb_param, int sockfd,
677   - uint8_t *query, int *query_length)
  685 +*/
  686 +int modbus_slave_receive(modbus_param_t *mb_param, int sockfd, uint8_t *query)
678 687 {
679   - int ret;
680   -
681 688 if (sockfd != -1) {
682 689 mb_param->fd = sockfd;
683 690 }
684 691  
685 692 /* The length of the query to receive isn't known. */
686   - ret = receive_msg(mb_param, MSG_LENGTH_UNDEFINED, query, query_length);
687   -
688   - return ret;
  693 + return receive_msg(mb_param, MSG_LENGTH_UNDEFINED, query);
689 694 }
690 695  
691 696 /* Receives the response and checks values (and checksum in RTU).
692 697  
693 698 Returns:
694   - - the number of values (bits or word) if success or the response
  699 + - the number of values (bits or words) if success or the response
695 700 length if no value is returned
696 701 - less than 0 for exception errors
697 702  
... ... @@ -702,14 +707,12 @@ static int modbus_receive(modbus_param_t *mb_param,
702 707 uint8_t *response)
703 708 {
704 709 int ret;
705   - int response_length;
706 710 int response_length_computed;
707 711 int offset = TAB_HEADER_LENGTH[mb_param->type_com];
708 712  
709 713 response_length_computed = compute_response_length(mb_param, query);
710   - ret = receive_msg(mb_param, response_length_computed,
711   - response, &response_length);
712   - if (ret == 0) {
  714 + ret = receive_msg(mb_param, response_length_computed, response);
  715 + if (ret >= 0) {
713 716 /* GOOD RESPONSE */
714 717 int query_nb_value;
715 718 int response_nb_value;
... ... @@ -740,7 +743,7 @@ static int modbus_receive(modbus_param_t *mb_param,
740 743 break;
741 744 case FC_REPORT_SLAVE_ID:
742 745 /* Report slave ID (bytes received) */
743   - query_nb_value = response_nb_value = response_length;
  746 + query_nb_value = response_nb_value = ret;
744 747 break;
745 748 default:
746 749 /* 1 Write functions & others */
... ... @@ -757,55 +760,46 @@ static int modbus_receive(modbus_param_t *mb_param,
757 760 error_treat(mb_param, ret, s_error);
758 761 free(s_error);
759 762 }
760   - } else if (ret == SELECT_TIMEOUT) {
761   -
762   - if (response_length == (offset + 2 + TAB_CHECKSUM_LENGTH[mb_param->type_com])) {
763   - /* EXCEPTION CODE RECEIVED */
764   -
765   - /* Optimization allowed because exception response is
766   - the smallest trame in modbus protocol (3) so always
767   - raise a timeout error */
768   -
769   - /* CRC must be checked here (not done in receive_msg) */
770   - if (mb_param->type_com == RTU) {
771   - ret = check_crc16(mb_param, response, response_length);
772   - if (ret != 0)
773   - return ret;
774   - }
  763 + } else if (ret == MB_EXCEPTION) {
  764 + /* EXCEPTION CODE RECEIVED */
  765 +
  766 + /* CRC must be checked here (not done in receive_msg) */
  767 + if (mb_param->type_com == RTU) {
  768 + ret = check_crc16(mb_param, response, EXCEPTION_RESPONSE_LENGTH_RTU);
  769 + if (ret < 0)
  770 + return ret;
  771 + }
775 772  
776   - /* Check for exception response.
777   - 0x80 + function is stored in the exception
778   - response. */
779   - if (0x80 + query[offset] == response[offset]) {
780   -
781   - int exception_code = response[offset + 1];
782   - // FIXME check test
783   - if (exception_code < NB_TAB_ERROR_MSG) {
784   - error_treat(mb_param, -exception_code,
785   - TAB_ERROR_MSG[response[offset + 1]]);
786   - /* RETURN THE EXCEPTION CODE */
787   - /* Modbus error code is negative */
788   - return -exception_code;
789   - } else {
790   - /* The chances are low to hit this
791   - case but it can avoid a vicious
792   - segfault */
793   - char *s_error = malloc(64 * sizeof(char));
794   - sprintf(s_error,
795   - "Invalid exception code %d",
796   - response[offset + 1]);
797   - error_treat(mb_param, INVALID_EXCEPTION_CODE,
798   - s_error);
799   - free(s_error);
800   - return INVALID_EXCEPTION_CODE;
801   - }
  773 + /* Check for exception response.
  774 + 0x80 + function is stored in the exception
  775 + response. */
  776 + if (0x80 + query[offset] == response[offset]) {
  777 +
  778 + int exception_code = response[offset + 1];
  779 + // FIXME check test
  780 + if (exception_code < NB_TAB_ERROR_MSG) {
  781 + error_treat(mb_param, -exception_code,
  782 + TAB_ERROR_MSG[response[offset + 1]]);
  783 + /* RETURN THE EXCEPTION CODE */
  784 + /* Modbus error code is negative */
  785 + return -exception_code;
  786 + } else {
  787 + /* The chances are low to hit this
  788 + case but it can avoid a vicious
  789 + segfault */
  790 + char *s_error = malloc(64 * sizeof(char));
  791 + sprintf(s_error,
  792 + "Invalid exception code %d",
  793 + response[offset + 1]);
  794 + error_treat(mb_param, INVALID_EXCEPTION_CODE,
  795 + s_error);
  796 + free(s_error);
  797 + return INVALID_EXCEPTION_CODE;
802 798 }
803   - /* If doesn't return previously, return as
804   - TIME OUT here */
805 799 }
806   -
807   - error_treat(mb_param, ret, "Select timeout");
808   - return ret;
  800 + } else {
  801 + /* Other errors */
  802 + error_treat(mb_param, ret, "receive_msg");
809 803 }
810 804  
811 805 return ret;
... ...
src/modbus.h
1 1 /*
2   - * Copyright © 2001-2009 Stéphane Raimbault <stephane.raimbault@gmail.com>
  2 + * Copyright © 2001-2010 Stéphane Raimbault <stephane.raimbault@gmail.com>
3 3 *
4 4 * This program is free software: you can redistribute it and/or modify
5 5 * it under the terms of the GNU Lesser Public License as published by
... ... @@ -72,6 +72,8 @@ extern &quot;C&quot; {
72 72 /* Kept for compatibility reasons (deprecated) */
73 73 #define MAX_MESSAGE_LENGTH 260
74 74  
  75 +#define EXCEPTION_RESPONSE_LENGTH_RTU 5
  76 +
75 77 /* Modbus_Application_Protocol_V1_1b.pdf (chapter 6 section 1 page 12)
76 78 * Quantity of Coils (2 bytes): 1 to 2000 (0x7D0)
77 79 */
... ... @@ -139,6 +141,7 @@ extern &quot;C&quot; {
139 141 #define SELECT_FAILURE -0x14
140 142 #define SOCKET_FAILURE -0x15
141 143 #define CONNECTION_CLOSED -0x16
  144 +#define MB_EXCEPTION -0x17
142 145  
143 146 /* Internal using */
144 147 #define MSG_LENGTH_UNDEFINED -1
... ... @@ -318,15 +321,15 @@ int modbus_slave_listen_tcp(modbus_param_t *mb_param, int nb_connection);
318 321 int modbus_slave_accept_tcp(modbus_param_t *mb_param, int *socket);
319 322  
320 323 /* Listens for any query from a modbus master in TCP, requires the socket file
321   - descriptor etablished with the master device in argument.
  324 + descriptor etablished with the master device in argument or -1 to use the
  325 + internal one of modbus_param_t.
322 326  
323 327 Returns:
324   - - 0 on success, or a negative error number if the request fails
  328 + - byte length of the message on success, or a negative error number if the
  329 + request fails
325 330 - query, message received
326   - - query_length, length in bytes of the message
327 331 */
328   -int modbus_slave_receive(modbus_param_t *mb_param, int sockfd,
329   - uint8_t *query, int *query_length);
  332 +int modbus_slave_receive(modbus_param_t *mb_param, int sockfd, uint8_t *query);
330 333  
331 334 /* Manages the received query.
332 335 Analyses the query and constructs a response.
... ...
tests/bandwidth-slave-many-up.c
... ... @@ -106,11 +106,10 @@ int main(void)
106 106 } else {
107 107 /* An already connected master has sent a new query */
108 108 uint8_t query[MAX_MESSAGE_LENGTH];
109   - int query_size;
110 109  
111   - ret = modbus_slave_receive(&mb_param, master_socket, query, &query_size);
112   - if (ret == 0) {
113   - modbus_slave_manage(&mb_param, query, query_size, &mb_mapping);
  110 + ret = modbus_slave_receive(&mb_param, master_socket, query);
  111 + if (ret >= 0) {
  112 + modbus_slave_manage(&mb_param, query, ret, &mb_mapping);
114 113 } else {
115 114 /* Connection closed by the client, end of server */
116 115 printf("Connection closed on socket %d\n", master_socket);
... ...
tests/bandwidth-slave-one.c
... ... @@ -44,11 +44,10 @@ int main(void)
44 44  
45 45 while (1) {
46 46 uint8_t query[MAX_MESSAGE_LENGTH];
47   - int query_size;
48 47  
49   - ret = modbus_slave_receive(&mb_param, -1, query, &query_size);
50   - if (ret == 0) {
51   - modbus_slave_manage(&mb_param, query, query_size, &mb_mapping);
  48 + ret = modbus_slave_receive(&mb_param, -1, query);
  49 + if (ret >= 0) {
  50 + modbus_slave_manage(&mb_param, query, ret, &mb_mapping);
52 51 } else if (ret == CONNECTION_CLOSED) {
53 52 /* Connection closed by the client, end of server */
54 53 break;
... ...
tests/random-test-slave.c
... ... @@ -44,11 +44,12 @@ int main(void)
44 44  
45 45 while (1) {
46 46 uint8_t query[MAX_MESSAGE_LENGTH];
47   - int query_size;
  47 + int ret;
48 48  
49   - ret = modbus_slave_receive(&mb_param, -1, query, &query_size);
50   - if (ret == 0) {
51   - modbus_slave_manage(&mb_param, query, query_size, &mb_mapping);
  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);
52 53 } else if (ret == CONNECTION_CLOSED) {
53 54 /* Connection closed by the client, end of server */
54 55 break;
... ...
tests/unit-test-slave.c
... ... @@ -63,10 +63,9 @@ int main(void)
63 63  
64 64 while (1) {
65 65 uint8_t query[MAX_MESSAGE_LENGTH];
66   - int query_size;
67 66  
68   - ret = modbus_slave_receive(&mb_param, -1, query, &query_size);
69   - if (ret == 0) {
  67 + ret = modbus_slave_receive(&mb_param, -1, query);
  68 + if (ret >= 0) {
70 69 if (((query[HEADER_LENGTH_TCP + 3] << 8) + query[HEADER_LENGTH_TCP + 4])
71 70 == UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL) {
72 71 /* Change the number of values (offset
... ... @@ -75,7 +74,7 @@ int main(void)
75 74 query[HEADER_LENGTH_TCP + 4] = UT_HOLDING_REGISTERS_NB_POINTS;
76 75 }
77 76  
78   - modbus_slave_manage(&mb_param, query, query_size, &mb_mapping);
  77 + modbus_slave_manage(&mb_param, query, ret, &mb_mapping);
79 78 } else if (ret == CONNECTION_CLOSED) {
80 79 /* Connection closed by the client, end of server */
81 80 break;
... ...