2 * Copyright © Stéphane Raimbault <stephane.raimbault@gmail.com>
4 * SPDX-License-Identifier: LGPL-2.1-or-later
6 * This library implements the Modbus protocol.
7 * http://libmodbus.org/
23 #include "modbus-private.h"
27 #define MSG_LENGTH_UNDEFINED -1
29 /* Exported version */
30 const unsigned int libmodbus_version_major
= LIBMODBUS_VERSION_MAJOR
;
31 const unsigned int libmodbus_version_minor
= LIBMODBUS_VERSION_MINOR
;
32 const unsigned int libmodbus_version_micro
= LIBMODBUS_VERSION_MICRO
;
34 /* Max between RTU and TCP max adu length (so TCP) */
35 #define MAX_MESSAGE_LENGTH 260
37 /* 3 steps are used to parse the query */
44 const char *modbus_strerror(int errnum
)
48 return "Illegal function";
50 return "Illegal data address";
52 return "Illegal data value";
54 return "Slave device or server failure";
58 return "Slave device or server is busy";
60 return "Negative acknowledge";
62 return "Memory parity error";
64 return "Gateway path unavailable";
66 return "Target device failed to respond";
70 return "Invalid data";
72 return "Invalid exception code";
74 return "Too many data";
76 return "Response not from requested slave";
78 return strerror(errnum
);
82 void _error_print(modbus_t
*ctx
, const char *context
)
85 fprintf(stderr
, "ERROR %s", modbus_strerror(errno
));
86 if (context
!= NULL
) {
87 fprintf(stderr
, ": %s\n", context
);
89 fprintf(stderr
, "\n");
94 static void _sleep_response_timeout(modbus_t
*ctx
)
96 /* Response timeout is always positive */
98 /* usleep doesn't exist on Windows */
99 Sleep((ctx
->response_timeout
.tv_sec
* 1000) + (ctx
->response_timeout
.tv_usec
/ 1000));
101 /* usleep source code */
102 struct timespec request
, remaining
;
103 request
.tv_sec
= ctx
->response_timeout
.tv_sec
;
104 request
.tv_nsec
= ((long int) ctx
->response_timeout
.tv_usec
) * 1000;
105 while (nanosleep(&request
, &remaining
) == -1 && errno
== EINTR
) {
111 int modbus_flush(modbus_t
*ctx
)
120 rc
= ctx
->backend
->flush(ctx
);
121 if (rc
!= -1 && ctx
->debug
) {
122 /* Not all backends are able to return the number of bytes flushed */
123 printf("Bytes flushed (%d)\n", rc
);
128 /* Computes the length of the expected response */
129 static unsigned int compute_response_length_from_request(modbus_t
*ctx
, uint8_t *req
)
132 const int offset
= ctx
->backend
->header_length
;
134 switch (req
[offset
]) {
135 case MODBUS_FC_READ_COILS
:
136 case MODBUS_FC_READ_DISCRETE_INPUTS
: {
137 /* Header + nb values (code from write_bits) */
138 int nb
= (req
[offset
+ 3] << 8) | req
[offset
+ 4];
139 length
= 2 + (nb
/ 8) + ((nb
% 8) ? 1 : 0);
141 case MODBUS_FC_WRITE_AND_READ_REGISTERS
:
142 case MODBUS_FC_READ_HOLDING_REGISTERS
:
143 case MODBUS_FC_READ_INPUT_REGISTERS
:
144 /* Header + 2 * nb values */
145 length
= 2 + 2 * (req
[offset
+ 3] << 8 | req
[offset
+ 4]);
147 case MODBUS_FC_READ_EXCEPTION_STATUS
:
150 case MODBUS_FC_REPORT_SLAVE_ID
:
151 /* The response is device specific (the header provides the
153 return MSG_LENGTH_UNDEFINED
;
154 case MODBUS_FC_MASK_WRITE_REGISTER
:
161 return offset
+ length
+ ctx
->backend
->checksum_length
;
164 /* Sends a request/response */
165 static int send_msg(modbus_t
*ctx
, uint8_t *msg
, int msg_length
)
170 msg_length
= ctx
->backend
->send_msg_pre(msg
, msg_length
);
173 for (i
= 0; i
< msg_length
; i
++)
174 printf("[%.2X]", msg
[i
]);
178 /* In recovery mode, the write command will be issued until to be
179 successful! Disabled by default. */
181 rc
= ctx
->backend
->send(ctx
, msg
, msg_length
);
183 _error_print(ctx
, NULL
);
184 if (ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_LINK
) {
186 const int wsa_err
= WSAGetLastError();
187 if (wsa_err
== WSAENETRESET
|| wsa_err
== WSAENOTCONN
||
188 wsa_err
== WSAENOTSOCK
|| wsa_err
== WSAESHUTDOWN
||
189 wsa_err
== WSAEHOSTUNREACH
|| wsa_err
== WSAECONNABORTED
||
190 wsa_err
== WSAECONNRESET
|| wsa_err
== WSAETIMEDOUT
) {
192 _sleep_response_timeout(ctx
);
195 _sleep_response_timeout(ctx
);
199 int saved_errno
= errno
;
201 if ((errno
== EBADF
|| errno
== ECONNRESET
|| errno
== EPIPE
)) {
203 _sleep_response_timeout(ctx
);
206 _sleep_response_timeout(ctx
);
213 } while ((ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_LINK
) && rc
== -1);
215 if (rc
> 0 && rc
!= msg_length
) {
223 int modbus_send_raw_request_tid(modbus_t
*ctx
, const uint8_t *raw_req
, int raw_req_length
, int tid
)
226 uint8_t req
[MAX_MESSAGE_LENGTH
];
234 if (raw_req_length
< 2 || raw_req_length
> (MODBUS_MAX_PDU_LENGTH
+ 1)) {
235 /* The raw request must contain function and slave at least and
236 must not be longer than the maximum pdu length plus the slave
242 sft
.slave
= raw_req
[0];
243 sft
.function
= raw_req
[1];
244 /* The t_id is left to zero */
246 /* This response function only set the header so it's convenient here */
247 req_length
= ctx
->backend
->build_response_basis(&sft
, req
);
249 if (raw_req_length
> 2) {
250 /* Copy data after function code */
251 memcpy(req
+ req_length
, raw_req
+ 2, raw_req_length
- 2);
252 req_length
+= raw_req_length
- 2;
255 return send_msg(ctx
, req
, req_length
);
258 int modbus_send_raw_request(modbus_t
*ctx
, const uint8_t *raw_req
, int raw_req_length
)
260 return modbus_send_raw_request_tid(ctx
, raw_req
, raw_req_length
, 0);
264 * ---------- Request Indication ----------
265 * | Client | ---------------------->| Server |
266 * ---------- Confirmation Response ----------
269 /* Computes the length to read after the function received */
270 static uint8_t compute_meta_length_after_function(int function
, msg_type_t msg_type
)
274 if (msg_type
== MSG_INDICATION
) {
275 if (function
<= MODBUS_FC_WRITE_SINGLE_REGISTER
) {
277 } else if (function
== MODBUS_FC_WRITE_MULTIPLE_COILS
||
278 function
== MODBUS_FC_WRITE_MULTIPLE_REGISTERS
) {
280 } else if (function
== MODBUS_FC_MASK_WRITE_REGISTER
) {
282 } else if (function
== MODBUS_FC_WRITE_AND_READ_REGISTERS
) {
285 /* MODBUS_FC_READ_EXCEPTION_STATUS, MODBUS_FC_REPORT_SLAVE_ID */
289 /* MSG_CONFIRMATION */
291 case MODBUS_FC_WRITE_SINGLE_COIL
:
292 case MODBUS_FC_WRITE_SINGLE_REGISTER
:
293 case MODBUS_FC_WRITE_MULTIPLE_COILS
:
294 case MODBUS_FC_WRITE_MULTIPLE_REGISTERS
:
297 case MODBUS_FC_MASK_WRITE_REGISTER
:
308 /* Computes the length to read after the meta information (address, count, etc) */
310 compute_data_length_after_meta(modbus_t
*ctx
, uint8_t *msg
, msg_type_t msg_type
)
312 int function
= msg
[ctx
->backend
->header_length
];
315 if (msg_type
== MSG_INDICATION
) {
317 case MODBUS_FC_WRITE_MULTIPLE_COILS
:
318 case MODBUS_FC_WRITE_MULTIPLE_REGISTERS
:
319 length
= msg
[ctx
->backend
->header_length
+ 5];
321 case MODBUS_FC_WRITE_AND_READ_REGISTERS
:
322 length
= msg
[ctx
->backend
->header_length
+ 9];
328 /* MSG_CONFIRMATION */
329 if (function
<= MODBUS_FC_READ_INPUT_REGISTERS
||
330 function
== MODBUS_FC_REPORT_SLAVE_ID
||
331 function
== MODBUS_FC_WRITE_AND_READ_REGISTERS
) {
332 length
= msg
[ctx
->backend
->header_length
+ 1];
338 length
+= ctx
->backend
->checksum_length
;
343 /* Waits a response from a modbus server or a request from a modbus client.
344 This function blocks if there is no replies (3 timeouts).
346 The function shall return the number of received characters and the received
347 message in an array of uint8_t if successful. Otherwise it shall return -1
348 and errno is set to one of the values defined below:
352 - read() or recv() error codes
355 int _modbus_receive_msg(modbus_t
*ctx
, uint8_t *msg
, msg_type_t msg_type
)
360 struct timeval
*p_tv
;
361 unsigned int length_to_read
;
369 if (msg_type
== MSG_INDICATION
) {
370 printf("Waiting for an indication...\n");
372 printf("Waiting for a confirmation...\n");
376 if (!ctx
->backend
->is_connected(ctx
)) {
378 fprintf(stderr
, "ERROR The connection is not established.\n");
383 /* Add a file descriptor to the set */
385 FD_SET(ctx
->s
, &rset
);
387 /* We need to analyse the message step by step. At the first step, we want
388 * to reach the function code because all packets contain this
390 step
= _STEP_FUNCTION
;
391 length_to_read
= ctx
->backend
->header_length
+ 1;
393 if (msg_type
== MSG_INDICATION
) {
394 /* Wait for a message, we don't know when the message will be
396 if (ctx
->indication_timeout
.tv_sec
== 0 && ctx
->indication_timeout
.tv_usec
== 0) {
397 /* By default, the indication timeout isn't set */
400 /* Wait for an indication (name of a received request by a server, see schema)
402 tv
.tv_sec
= ctx
->indication_timeout
.tv_sec
;
403 tv
.tv_usec
= ctx
->indication_timeout
.tv_usec
;
407 tv
.tv_sec
= ctx
->response_timeout
.tv_sec
;
408 tv
.tv_usec
= ctx
->response_timeout
.tv_usec
;
412 while (length_to_read
!= 0) {
413 rc
= ctx
->backend
->select(ctx
, &rset
, p_tv
, length_to_read
);
415 _error_print(ctx
, "select");
416 if (ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_LINK
) {
418 wsa_err
= WSAGetLastError();
420 // no equivalent to ETIMEDOUT when select fails on Windows
421 if (wsa_err
== WSAENETDOWN
|| wsa_err
== WSAENOTSOCK
) {
426 int saved_errno
= errno
;
428 if (errno
== ETIMEDOUT
) {
429 _sleep_response_timeout(ctx
);
431 } else if (errno
== EBADF
) {
441 rc
= ctx
->backend
->recv(ctx
, msg
+ msg_length
, length_to_read
);
448 _error_print(ctx
, "read");
450 wsa_err
= WSAGetLastError();
451 if ((ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_LINK
) &&
452 (wsa_err
== WSAENOTCONN
|| wsa_err
== WSAENETRESET
||
453 wsa_err
== WSAENOTSOCK
|| wsa_err
== WSAESHUTDOWN
||
454 wsa_err
== WSAECONNABORTED
|| wsa_err
== WSAETIMEDOUT
||
455 wsa_err
== WSAECONNRESET
)) {
460 if ((ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_LINK
) &&
461 (errno
== ECONNRESET
|| errno
== ECONNREFUSED
|| errno
== EBADF
)) {
462 int saved_errno
= errno
;
465 /* Could be removed by previous calls */
472 /* Display the hex code of each character received */
475 for (i
= 0; i
< rc
; i
++)
476 printf("<%.2X>", msg
[msg_length
+ i
]);
479 /* Sums bytes received */
481 /* Computes remaining bytes */
482 length_to_read
-= rc
;
484 if (length_to_read
== 0) {
487 /* Function code position */
488 length_to_read
= compute_meta_length_after_function(
489 msg
[ctx
->backend
->header_length
], msg_type
);
490 if (length_to_read
!= 0) {
493 } /* else switches straight to the next step */
495 length_to_read
= compute_data_length_after_meta(ctx
, msg
, msg_type
);
496 if ((msg_length
+ length_to_read
) > ctx
->backend
->max_adu_length
) {
498 _error_print(ctx
, "too many data");
508 if (length_to_read
> 0 &&
509 (ctx
->byte_timeout
.tv_sec
> 0 || ctx
->byte_timeout
.tv_usec
> 0)) {
510 /* If there is no character in the buffer, the allowed timeout
511 interval between two consecutive bytes is defined by
513 tv
.tv_sec
= ctx
->byte_timeout
.tv_sec
;
514 tv
.tv_usec
= ctx
->byte_timeout
.tv_usec
;
517 /* else timeout isn't set again, the full response must be read before
518 expiration of response timeout (for CONFIRMATION only) */
524 return ctx
->backend
->check_integrity(ctx
, msg
, msg_length
);
527 /* Receive the request from a modbus master */
528 int modbus_receive(modbus_t
*ctx
, uint8_t *req
)
535 return ctx
->backend
->receive(ctx
, req
);
538 /* Receives the confirmation.
540 The function shall store the read response in rsp and return the number of
541 values (bits or words). Otherwise, its shall return -1 and errno is set.
543 The function doesn't check the confirmation is the expected response to the
546 int modbus_receive_confirmation(modbus_t
*ctx
, uint8_t *rsp
)
553 return _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
556 static int check_confirmation(modbus_t
*ctx
, uint8_t *req
, uint8_t *rsp
, int rsp_length
)
559 int rsp_length_computed
;
560 const unsigned int offset
= ctx
->backend
->header_length
;
561 const int function
= rsp
[offset
];
563 if (ctx
->backend
->pre_check_confirmation
) {
564 rc
= ctx
->backend
->pre_check_confirmation(ctx
, req
, rsp
, rsp_length
);
566 if (ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_PROTOCOL
) {
567 _sleep_response_timeout(ctx
);
574 rsp_length_computed
= compute_response_length_from_request(ctx
, req
);
577 if (function
>= 0x80) {
578 if (rsp_length
== (int) (offset
+ 2 + ctx
->backend
->checksum_length
) &&
579 req
[offset
] == (rsp
[offset
] - 0x80)) {
580 /* Valid exception code received */
582 int exception_code
= rsp
[offset
+ 1];
583 if (exception_code
< MODBUS_EXCEPTION_MAX
) {
584 errno
= MODBUS_ENOBASE
+ exception_code
;
588 _error_print(ctx
, NULL
);
592 _error_print(ctx
, NULL
);
598 if ((rsp_length
== rsp_length_computed
||
599 rsp_length_computed
== MSG_LENGTH_UNDEFINED
) &&
603 int resp_addr_ok
= TRUE
;
604 int resp_data_ok
= TRUE
;
606 /* Check function code */
607 if (function
!= req
[offset
]) {
611 "Received function not corresponding to the request (0x%X != 0x%X)\n",
615 if (ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_PROTOCOL
) {
616 _sleep_response_timeout(ctx
);
623 /* Check the number of values is corresponding to the request */
625 case MODBUS_FC_READ_COILS
:
626 case MODBUS_FC_READ_DISCRETE_INPUTS
:
627 /* Read functions, 8 values in a byte (nb
628 * of values in the request and byte count in
630 req_nb_value
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
631 req_nb_value
= (req_nb_value
/ 8) + ((req_nb_value
% 8) ? 1 : 0);
632 rsp_nb_value
= rsp
[offset
+ 1];
634 case MODBUS_FC_WRITE_AND_READ_REGISTERS
:
635 case MODBUS_FC_READ_HOLDING_REGISTERS
:
636 case MODBUS_FC_READ_INPUT_REGISTERS
:
637 /* Read functions 1 value = 2 bytes */
638 req_nb_value
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
639 rsp_nb_value
= (rsp
[offset
+ 1] / 2);
641 case MODBUS_FC_WRITE_MULTIPLE_COILS
:
642 case MODBUS_FC_WRITE_MULTIPLE_REGISTERS
:
643 /* address in request and response must be equal */
644 if ((req
[offset
+ 1] != rsp
[offset
+ 1]) ||
645 (req
[offset
+ 2] != rsp
[offset
+ 2])) {
646 resp_addr_ok
= FALSE
;
648 /* N Write functions */
649 req_nb_value
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
650 rsp_nb_value
= (rsp
[offset
+ 3] << 8) | rsp
[offset
+ 4];
652 case MODBUS_FC_REPORT_SLAVE_ID
:
653 /* Report slave ID (bytes received) */
654 req_nb_value
= rsp_nb_value
= rsp
[offset
+ 1];
656 case MODBUS_FC_WRITE_SINGLE_COIL
:
657 case MODBUS_FC_WRITE_SINGLE_REGISTER
:
658 /* address in request and response must be equal */
659 if ((req
[offset
+ 1] != rsp
[offset
+ 1]) ||
660 (req
[offset
+ 2] != rsp
[offset
+ 2])) {
661 resp_addr_ok
= FALSE
;
663 /* data in request and response must be equal */
664 if ((req
[offset
+ 3] != rsp
[offset
+ 3]) ||
665 (req
[offset
+ 4] != rsp
[offset
+ 4])) {
666 resp_data_ok
= FALSE
;
668 /* 1 Write functions & others */
669 req_nb_value
= rsp_nb_value
= 1;
672 /* 1 Write functions & others */
673 req_nb_value
= rsp_nb_value
= 1;
677 if ((req_nb_value
== rsp_nb_value
) && (resp_addr_ok
== TRUE
) &&
678 (resp_data_ok
== TRUE
)) {
683 "Received data not corresponding to the request (%d != %d)\n",
688 if (ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_PROTOCOL
) {
689 _sleep_response_timeout(ctx
);
700 "Message length not corresponding to the computed length (%d != %d)\n",
702 rsp_length_computed
);
704 if (ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_PROTOCOL
) {
705 _sleep_response_timeout(ctx
);
716 response_io_status(uint8_t *tab_io_status
, int address
, int nb
, uint8_t *rsp
, int offset
)
719 /* Instead of byte (not allowed in Win32) */
723 for (i
= address
; i
< address
+ nb
; i
++) {
724 one_byte
|= tab_io_status
[i
] << shift
;
727 rsp
[offset
++] = one_byte
;
728 one_byte
= shift
= 0;
735 rsp
[offset
++] = one_byte
;
740 /* Build the exception response */
741 static int response_exception(modbus_t
*ctx
,
745 unsigned int to_flush
,
746 const char *template,
751 /* Print debug message */
755 va_start(ap
, template);
756 vfprintf(stderr
, template, ap
);
760 /* Flush if required */
762 _sleep_response_timeout(ctx
);
766 /* Build exception response */
767 sft
->function
= sft
->function
+ 0x80;
768 rsp_length
= ctx
->backend
->build_response_basis(sft
, rsp
);
769 rsp
[rsp_length
++] = exception_code
;
774 /* Send a response to the received request.
775 Analyses the request and constructs a response.
777 If an error occurs, this function construct the response
780 int modbus_reply(modbus_t
*ctx
,
783 modbus_mapping_t
*mb_mapping
)
789 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
798 offset
= ctx
->backend
->header_length
;
799 slave
= req
[offset
- 1];
800 function
= req
[offset
];
801 address
= (req
[offset
+ 1] << 8) + req
[offset
+ 2];
804 sft
.function
= function
;
805 sft
.t_id
= ctx
->backend
->prepare_response_tid(req
, &req_length
);
807 /* Data are flushed on illegal number of values errors. */
809 case MODBUS_FC_READ_COILS
:
810 case MODBUS_FC_READ_DISCRETE_INPUTS
: {
811 unsigned int is_input
= (function
== MODBUS_FC_READ_DISCRETE_INPUTS
);
812 int start_bits
= is_input
? mb_mapping
->start_input_bits
: mb_mapping
->start_bits
;
813 int nb_bits
= is_input
? mb_mapping
->nb_input_bits
: mb_mapping
->nb_bits
;
814 uint8_t *tab_bits
= is_input
? mb_mapping
->tab_input_bits
: mb_mapping
->tab_bits
;
815 const char *const name
= is_input
? "read_input_bits" : "read_bits";
816 int nb
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
817 /* The mapping can be shifted to reduce memory consumption and it
818 doesn't always start at address zero. */
819 int mapping_address
= address
- start_bits
;
821 if (nb
< 1 || MODBUS_MAX_READ_BITS
< nb
) {
822 rsp_length
= response_exception(ctx
,
824 MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
,
827 "Illegal nb of values %d in %s (max %d)\n",
830 MODBUS_MAX_READ_BITS
);
831 } else if (mapping_address
< 0 || (mapping_address
+ nb
) > nb_bits
) {
832 rsp_length
= response_exception(ctx
,
834 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
,
837 "Illegal data address 0x%0X in %s\n",
838 mapping_address
< 0 ? address
: address
+ nb
,
841 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
842 rsp
[rsp_length
++] = (nb
/ 8) + ((nb
% 8) ? 1 : 0);
844 response_io_status(tab_bits
, mapping_address
, nb
, rsp
, rsp_length
);
847 case MODBUS_FC_READ_HOLDING_REGISTERS
:
848 case MODBUS_FC_READ_INPUT_REGISTERS
: {
849 unsigned int is_input
= (function
== MODBUS_FC_READ_INPUT_REGISTERS
);
850 int start_registers
=
851 is_input
? mb_mapping
->start_input_registers
: mb_mapping
->start_registers
;
853 is_input
? mb_mapping
->nb_input_registers
: mb_mapping
->nb_registers
;
854 uint16_t *tab_registers
=
855 is_input
? mb_mapping
->tab_input_registers
: mb_mapping
->tab_registers
;
856 const char *const name
= is_input
? "read_input_registers" : "read_registers";
857 int nb
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
858 /* The mapping can be shifted to reduce memory consumption and it
859 doesn't always start at address zero. */
860 int mapping_address
= address
- start_registers
;
862 if (nb
< 1 || MODBUS_MAX_READ_REGISTERS
< nb
) {
863 rsp_length
= response_exception(ctx
,
865 MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
,
868 "Illegal nb of values %d in %s (max %d)\n",
871 MODBUS_MAX_READ_REGISTERS
);
872 } else if (mapping_address
< 0 || (mapping_address
+ nb
) > nb_registers
) {
873 rsp_length
= response_exception(ctx
,
875 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
,
878 "Illegal data address 0x%0X in %s\n",
879 mapping_address
< 0 ? address
: address
+ nb
,
884 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
885 rsp
[rsp_length
++] = nb
<< 1;
886 for (i
= mapping_address
; i
< mapping_address
+ nb
; i
++) {
887 rsp
[rsp_length
++] = tab_registers
[i
] >> 8;
888 rsp
[rsp_length
++] = tab_registers
[i
] & 0xFF;
892 case MODBUS_FC_WRITE_SINGLE_COIL
: {
893 int mapping_address
= address
- mb_mapping
->start_bits
;
895 if (mapping_address
< 0 || mapping_address
>= mb_mapping
->nb_bits
) {
896 rsp_length
= response_exception(ctx
,
898 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
,
901 "Illegal data address 0x%0X in write_bit\n",
904 int data
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
906 if (data
== 0xFF00 || data
== 0x0) {
907 mb_mapping
->tab_bits
[mapping_address
] = data
? ON
: OFF
;
908 memcpy(rsp
, req
, req_length
);
909 rsp_length
= req_length
;
911 rsp_length
= response_exception(
914 MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
,
917 "Illegal data value 0x%0X in write_bit request at address %0X\n",
923 case MODBUS_FC_WRITE_SINGLE_REGISTER
: {
924 int mapping_address
= address
- mb_mapping
->start_registers
;
926 if (mapping_address
< 0 || mapping_address
>= mb_mapping
->nb_registers
) {
928 response_exception(ctx
,
930 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
,
933 "Illegal data address 0x%0X in write_register\n",
936 int data
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
938 mb_mapping
->tab_registers
[mapping_address
] = data
;
939 memcpy(rsp
, req
, req_length
);
940 rsp_length
= req_length
;
943 case MODBUS_FC_WRITE_MULTIPLE_COILS
: {
944 int nb
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
945 int nb_bits
= req
[offset
+ 5];
946 int mapping_address
= address
- mb_mapping
->start_bits
;
948 if (nb
< 1 || MODBUS_MAX_WRITE_BITS
< nb
|| nb_bits
* 8 < nb
) {
949 /* May be the indication has been truncated on reading because of
950 * invalid address (eg. nb is 0 but the request contains values to
951 * write) so it's necessary to flush. */
953 response_exception(ctx
,
955 MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
,
958 "Illegal number of values %d in write_bits (max %d)\n",
960 MODBUS_MAX_WRITE_BITS
);
961 } else if (mapping_address
< 0 || (mapping_address
+ nb
) > mb_mapping
->nb_bits
) {
962 rsp_length
= response_exception(ctx
,
964 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
,
967 "Illegal data address 0x%0X in write_bits\n",
968 mapping_address
< 0 ? address
: address
+ nb
);
971 modbus_set_bits_from_bytes(
972 mb_mapping
->tab_bits
, mapping_address
, nb
, &req
[offset
+ 6]);
974 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
975 /* 4 to copy the bit address (2) and the quantity of bits */
976 memcpy(rsp
+ rsp_length
, req
+ rsp_length
, 4);
980 case MODBUS_FC_WRITE_MULTIPLE_REGISTERS
: {
981 int nb
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
982 int nb_bytes
= req
[offset
+ 5];
983 int mapping_address
= address
- mb_mapping
->start_registers
;
985 if (nb
< 1 || MODBUS_MAX_WRITE_REGISTERS
< nb
|| nb_bytes
!= nb
* 2) {
986 rsp_length
= response_exception(
989 MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
,
992 "Illegal number of values %d in write_registers (max %d)\n",
994 MODBUS_MAX_WRITE_REGISTERS
);
995 } else if (mapping_address
< 0 ||
996 (mapping_address
+ nb
) > mb_mapping
->nb_registers
) {
998 response_exception(ctx
,
1000 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
,
1003 "Illegal data address 0x%0X in write_registers\n",
1004 mapping_address
< 0 ? address
: address
+ nb
);
1007 for (i
= mapping_address
, j
= 6; i
< mapping_address
+ nb
; i
++, j
+= 2) {
1008 /* 6 and 7 = first value */
1009 mb_mapping
->tab_registers
[i
] =
1010 (req
[offset
+ j
] << 8) + req
[offset
+ j
+ 1];
1013 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
1014 /* 4 to copy the address (2) and the no. of registers */
1015 memcpy(rsp
+ rsp_length
, req
+ rsp_length
, 4);
1019 case MODBUS_FC_REPORT_SLAVE_ID
: {
1023 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
1024 /* Skip byte count for now */
1025 byte_count_pos
= rsp_length
++;
1026 rsp
[rsp_length
++] = _REPORT_SLAVE_ID
;
1027 /* Run indicator status to ON */
1028 rsp
[rsp_length
++] = 0xFF;
1029 /* LMB + length of LIBMODBUS_VERSION_STRING */
1030 str_len
= 3 + strlen(LIBMODBUS_VERSION_STRING
);
1031 memcpy(rsp
+ rsp_length
, "LMB" LIBMODBUS_VERSION_STRING
, str_len
);
1032 rsp_length
+= str_len
;
1033 rsp
[byte_count_pos
] = rsp_length
- byte_count_pos
- 1;
1035 case MODBUS_FC_READ_EXCEPTION_STATUS
:
1037 fprintf(stderr
, "FIXME Not implemented\n");
1039 errno
= ENOPROTOOPT
;
1042 case MODBUS_FC_MASK_WRITE_REGISTER
: {
1043 int mapping_address
= address
- mb_mapping
->start_registers
;
1045 if (mapping_address
< 0 || mapping_address
>= mb_mapping
->nb_registers
) {
1047 response_exception(ctx
,
1049 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
,
1052 "Illegal data address 0x%0X in write_register\n",
1055 uint16_t data
= mb_mapping
->tab_registers
[mapping_address
];
1056 uint16_t and = (req
[offset
+ 3] << 8) + req
[offset
+ 4];
1057 uint16_t or = (req
[offset
+ 5] << 8) + req
[offset
+ 6];
1059 data
= (data
& and) | (or &(~and) );
1060 mb_mapping
->tab_registers
[mapping_address
] = data
;
1061 memcpy(rsp
, req
, req_length
);
1062 rsp_length
= req_length
;
1065 case MODBUS_FC_WRITE_AND_READ_REGISTERS
: {
1066 int nb
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
1067 uint16_t address_write
= (req
[offset
+ 5] << 8) + req
[offset
+ 6];
1068 int nb_write
= (req
[offset
+ 7] << 8) + req
[offset
+ 8];
1069 int nb_write_bytes
= req
[offset
+ 9];
1070 int mapping_address
= address
- mb_mapping
->start_registers
;
1071 int mapping_address_write
= address_write
- mb_mapping
->start_registers
;
1073 if (nb_write
< 1 || MODBUS_MAX_WR_WRITE_REGISTERS
< nb_write
|| nb
< 1 ||
1074 MODBUS_MAX_WR_READ_REGISTERS
< nb
|| nb_write_bytes
!= nb_write
* 2) {
1075 rsp_length
= response_exception(
1078 MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
,
1081 "Illegal nb of values (W%d, R%d) in write_and_read_registers (max W%d, "
1085 MODBUS_MAX_WR_WRITE_REGISTERS
,
1086 MODBUS_MAX_WR_READ_REGISTERS
);
1087 } else if (mapping_address
< 0 ||
1088 (mapping_address
+ nb
) > mb_mapping
->nb_registers
||
1089 mapping_address_write
< 0 ||
1090 (mapping_address_write
+ nb_write
) > mb_mapping
->nb_registers
) {
1091 rsp_length
= response_exception(
1094 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
,
1097 "Illegal data read address 0x%0X or write address 0x%0X "
1098 "write_and_read_registers\n",
1099 mapping_address
< 0 ? address
: address
+ nb
,
1100 mapping_address_write
< 0 ? address_write
: address_write
+ nb_write
);
1103 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
1104 rsp
[rsp_length
++] = nb
<< 1;
1107 10 and 11 are the offset of the first values to write */
1108 for (i
= mapping_address_write
, j
= 10; i
< mapping_address_write
+ nb_write
;
1110 mb_mapping
->tab_registers
[i
] =
1111 (req
[offset
+ j
] << 8) + req
[offset
+ j
+ 1];
1114 /* and read the data for the response */
1115 for (i
= mapping_address
; i
< mapping_address
+ nb
; i
++) {
1116 rsp
[rsp_length
++] = mb_mapping
->tab_registers
[i
] >> 8;
1117 rsp
[rsp_length
++] = mb_mapping
->tab_registers
[i
] & 0xFF;
1123 rsp_length
= response_exception(ctx
,
1125 MODBUS_EXCEPTION_ILLEGAL_FUNCTION
,
1128 "Unknown Modbus function code: 0x%0X\n",
1133 /* Suppress any responses in RTU when the request was a broadcast, excepted when quirk
1135 if (ctx
->backend
->backend_type
== _MODBUS_BACKEND_TYPE_RTU
&&
1136 slave
== MODBUS_BROADCAST_ADDRESS
&&
1137 !(ctx
->quirks
& MODBUS_QUIRK_REPLY_TO_BROADCAST
)) {
1140 return send_msg(ctx
, rsp
, rsp_length
);
1143 int modbus_reply_exception(modbus_t
*ctx
, const uint8_t *req
, unsigned int exception_code
)
1145 unsigned int offset
;
1148 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1150 int dummy_length
= 99;
1158 offset
= ctx
->backend
->header_length
;
1159 slave
= req
[offset
- 1];
1160 function
= req
[offset
];
1163 sft
.function
= function
+ 0x80;
1164 sft
.t_id
= ctx
->backend
->prepare_response_tid(req
, &dummy_length
);
1165 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
1167 /* Positive exception code */
1168 if (exception_code
< MODBUS_EXCEPTION_MAX
) {
1169 rsp
[rsp_length
++] = exception_code
;
1170 return send_msg(ctx
, rsp
, rsp_length
);
1177 /* Reads IO status */
1178 static int read_io_status(modbus_t
*ctx
, int function
, int addr
, int nb
, uint8_t *dest
)
1183 uint8_t req
[_MIN_REQ_LENGTH
];
1184 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1186 req_length
= ctx
->backend
->build_request_basis(ctx
, function
, addr
, nb
, req
);
1188 rc
= send_msg(ctx
, req
, req_length
);
1192 unsigned int offset
;
1193 unsigned int offset_end
;
1196 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1200 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1204 offset
= ctx
->backend
->header_length
+ 2;
1205 offset_end
= offset
+ rc
;
1206 for (i
= offset
; i
< offset_end
; i
++) {
1207 /* Shift reg hi_byte to temp */
1210 for (bit
= 0x01; (bit
& 0xff) && (pos
< nb
);) {
1211 dest
[pos
++] = (temp
& bit
) ? TRUE
: FALSE
;
1220 /* Reads the boolean status of bits and sets the array elements
1221 in the destination to TRUE or FALSE (single bits). */
1222 int modbus_read_bits(modbus_t
*ctx
, int addr
, int nb
, uint8_t *dest
)
1231 if (nb
> MODBUS_MAX_READ_BITS
) {
1234 "ERROR Too many bits requested (%d > %d)\n",
1236 MODBUS_MAX_READ_BITS
);
1242 rc
= read_io_status(ctx
, MODBUS_FC_READ_COILS
, addr
, nb
, dest
);
1250 /* Same as modbus_read_bits but reads the remote device input table */
1251 int modbus_read_input_bits(modbus_t
*ctx
, int addr
, int nb
, uint8_t *dest
)
1260 if (nb
> MODBUS_MAX_READ_BITS
) {
1263 "ERROR Too many discrete inputs requested (%d > %d)\n",
1265 MODBUS_MAX_READ_BITS
);
1271 rc
= read_io_status(ctx
, MODBUS_FC_READ_DISCRETE_INPUTS
, addr
, nb
, dest
);
1279 /* Reads the data from a remote device and put that data into an array */
1280 static int read_registers(modbus_t
*ctx
, int function
, int addr
, int nb
, uint16_t *dest
)
1284 uint8_t req
[_MIN_REQ_LENGTH
];
1285 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1287 if (nb
> MODBUS_MAX_READ_REGISTERS
) {
1290 "ERROR Too many registers requested (%d > %d)\n",
1292 MODBUS_MAX_READ_REGISTERS
);
1298 req_length
= ctx
->backend
->build_request_basis(ctx
, function
, addr
, nb
, req
);
1300 rc
= send_msg(ctx
, req
, req_length
);
1302 unsigned int offset
;
1305 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1309 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1313 offset
= ctx
->backend
->header_length
;
1315 for (i
= 0; i
< rc
; i
++) {
1316 /* shift reg hi_byte to temp OR with lo_byte */
1317 dest
[i
] = (rsp
[offset
+ 2 + (i
<< 1)] << 8) | rsp
[offset
+ 3 + (i
<< 1)];
1324 /* Reads the holding registers of remote device and put the data into an
1326 int modbus_read_registers(modbus_t
*ctx
, int addr
, int nb
, uint16_t *dest
)
1335 if (nb
> MODBUS_MAX_READ_REGISTERS
) {
1338 "ERROR Too many registers requested (%d > %d)\n",
1340 MODBUS_MAX_READ_REGISTERS
);
1346 status
= read_registers(ctx
, MODBUS_FC_READ_HOLDING_REGISTERS
, addr
, nb
, dest
);
1350 /* Reads the input registers of remote device and put the data into an array */
1351 int modbus_read_input_registers(modbus_t
*ctx
, int addr
, int nb
, uint16_t *dest
)
1360 if (nb
> MODBUS_MAX_READ_REGISTERS
) {
1363 "ERROR Too many input registers requested (%d > %d)\n",
1365 MODBUS_MAX_READ_REGISTERS
);
1371 status
= read_registers(ctx
, MODBUS_FC_READ_INPUT_REGISTERS
, addr
, nb
, dest
);
1376 /* Write a value to the specified register of the remote device.
1377 Used by write_bit and write_register */
1378 static int write_single(modbus_t
*ctx
, int function
, int addr
, const uint16_t value
)
1382 uint8_t req
[_MIN_REQ_LENGTH
];
1389 req_length
= ctx
->backend
->build_request_basis(ctx
, function
, addr
, (int) value
, req
);
1391 rc
= send_msg(ctx
, req
, req_length
);
1393 /* Used by write_bit and write_register */
1394 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1396 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1400 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1406 /* Turns ON or OFF a single bit of the remote device */
1407 int modbus_write_bit(modbus_t
*ctx
, int addr
, int status
)
1414 return write_single(ctx
, MODBUS_FC_WRITE_SINGLE_COIL
, addr
, status
? 0xFF00 : 0);
1417 /* Writes a value in one register of the remote device */
1418 int modbus_write_register(modbus_t
*ctx
, int addr
, const uint16_t value
)
1425 return write_single(ctx
, MODBUS_FC_WRITE_SINGLE_REGISTER
, addr
, value
);
1428 /* Write the bits of the array in the remote device */
1429 int modbus_write_bits(modbus_t
*ctx
, int addr
, int nb
, const uint8_t *src
)
1437 uint8_t req
[MAX_MESSAGE_LENGTH
];
1444 if (nb
> MODBUS_MAX_WRITE_BITS
) {
1447 "ERROR Writing too many bits (%d > %d)\n",
1449 MODBUS_MAX_WRITE_BITS
);
1455 req_length
= ctx
->backend
->build_request_basis(
1456 ctx
, MODBUS_FC_WRITE_MULTIPLE_COILS
, addr
, nb
, req
);
1457 byte_count
= (nb
/ 8) + ((nb
% 8) ? 1 : 0);
1458 req
[req_length
++] = byte_count
;
1460 for (i
= 0; i
< byte_count
; i
++) {
1464 req
[req_length
] = 0;
1466 while ((bit
& 0xFF) && (bit_check
++ < nb
)) {
1468 req
[req_length
] |= bit
;
1470 req
[req_length
] &= ~bit
;
1477 rc
= send_msg(ctx
, req
, req_length
);
1479 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1481 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1485 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1491 /* Write the values from the array to the registers of the remote device */
1492 int modbus_write_registers(modbus_t
*ctx
, int addr
, int nb
, const uint16_t *src
)
1498 uint8_t req
[MAX_MESSAGE_LENGTH
];
1505 if (nb
> MODBUS_MAX_WRITE_REGISTERS
) {
1508 "ERROR Trying to write to too many registers (%d > %d)\n",
1510 MODBUS_MAX_WRITE_REGISTERS
);
1516 req_length
= ctx
->backend
->build_request_basis(
1517 ctx
, MODBUS_FC_WRITE_MULTIPLE_REGISTERS
, addr
, nb
, req
);
1518 byte_count
= nb
* 2;
1519 req
[req_length
++] = byte_count
;
1521 for (i
= 0; i
< nb
; i
++) {
1522 req
[req_length
++] = src
[i
] >> 8;
1523 req
[req_length
++] = src
[i
] & 0x00FF;
1526 rc
= send_msg(ctx
, req
, req_length
);
1528 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1530 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1534 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1540 int modbus_mask_write_register(modbus_t
*ctx
,
1547 /* The request length can not exceed _MIN_REQ_LENGTH - 2 and 4 bytes to
1548 * store the masks. The ugly substraction is there to remove the 'nb' value
1549 * (2 bytes) which is not used. */
1550 uint8_t req
[_MIN_REQ_LENGTH
+ 2];
1552 req_length
= ctx
->backend
->build_request_basis(
1553 ctx
, MODBUS_FC_MASK_WRITE_REGISTER
, addr
, 0, req
);
1555 /* HACKISH, count is not used */
1558 req
[req_length
++] = and_mask
>> 8;
1559 req
[req_length
++] = and_mask
& 0x00ff;
1560 req
[req_length
++] = or_mask
>> 8;
1561 req
[req_length
++] = or_mask
& 0x00ff;
1563 rc
= send_msg(ctx
, req
, req_length
);
1565 /* Used by write_bit and write_register */
1566 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1568 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1572 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1578 /* Write multiple registers from src array to remote device and read multiple
1579 registers from remote device to dest array. */
1580 int modbus_write_and_read_registers(modbus_t
*ctx
,
1583 const uint16_t *src
,
1593 uint8_t req
[MAX_MESSAGE_LENGTH
];
1594 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1601 if (write_nb
> MODBUS_MAX_WR_WRITE_REGISTERS
) {
1604 "ERROR Too many registers to write (%d > %d)\n",
1606 MODBUS_MAX_WR_WRITE_REGISTERS
);
1612 if (read_nb
> MODBUS_MAX_WR_READ_REGISTERS
) {
1615 "ERROR Too many registers requested (%d > %d)\n",
1617 MODBUS_MAX_WR_READ_REGISTERS
);
1622 req_length
= ctx
->backend
->build_request_basis(
1623 ctx
, MODBUS_FC_WRITE_AND_READ_REGISTERS
, read_addr
, read_nb
, req
);
1625 req
[req_length
++] = write_addr
>> 8;
1626 req
[req_length
++] = write_addr
& 0x00ff;
1627 req
[req_length
++] = write_nb
>> 8;
1628 req
[req_length
++] = write_nb
& 0x00ff;
1629 byte_count
= write_nb
* 2;
1630 req
[req_length
++] = byte_count
;
1632 for (i
= 0; i
< write_nb
; i
++) {
1633 req
[req_length
++] = src
[i
] >> 8;
1634 req
[req_length
++] = src
[i
] & 0x00FF;
1637 rc
= send_msg(ctx
, req
, req_length
);
1639 unsigned int offset
;
1641 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1645 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1649 offset
= ctx
->backend
->header_length
;
1650 for (i
= 0; i
< rc
; i
++) {
1651 /* shift reg hi_byte to temp OR with lo_byte */
1652 dest
[i
] = (rsp
[offset
+ 2 + (i
<< 1)] << 8) | rsp
[offset
+ 3 + (i
<< 1)];
1659 /* Send a request to get the slave ID of the device (only available in serial
1661 int modbus_report_slave_id(modbus_t
*ctx
, int max_dest
, uint8_t *dest
)
1665 uint8_t req
[_MIN_REQ_LENGTH
];
1667 if (ctx
== NULL
|| max_dest
<= 0) {
1673 ctx
->backend
->build_request_basis(ctx
, MODBUS_FC_REPORT_SLAVE_ID
, 0, 0, req
);
1675 /* HACKISH, addr and count are not used */
1678 rc
= send_msg(ctx
, req
, req_length
);
1681 unsigned int offset
;
1682 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1684 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1688 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1692 offset
= ctx
->backend
->header_length
+ 2;
1694 /* Byte count, slave id, run indicator status and
1695 additional data. Truncate copy to max_dest. */
1696 for (i
= 0; i
< rc
&& i
< max_dest
; i
++) {
1697 dest
[i
] = rsp
[offset
+ i
];
1704 void _modbus_init_common(modbus_t
*ctx
)
1706 /* Slave and socket are initialized to -1 */
1711 ctx
->error_recovery
= MODBUS_ERROR_RECOVERY_NONE
;
1712 ctx
->quirks
= MODBUS_QUIRK_NONE
;
1714 ctx
->response_timeout
.tv_sec
= 0;
1715 ctx
->response_timeout
.tv_usec
= _RESPONSE_TIMEOUT
;
1717 ctx
->byte_timeout
.tv_sec
= 0;
1718 ctx
->byte_timeout
.tv_usec
= _BYTE_TIMEOUT
;
1720 ctx
->indication_timeout
.tv_sec
= 0;
1721 ctx
->indication_timeout
.tv_usec
= 0;
1724 /* Define the slave number */
1725 int modbus_set_slave(modbus_t
*ctx
, int slave
)
1732 return ctx
->backend
->set_slave(ctx
, slave
);
1735 int modbus_get_slave(modbus_t
*ctx
)
1745 int modbus_set_error_recovery(modbus_t
*ctx
, modbus_error_recovery_mode error_recovery
)
1752 /* The type of modbus_error_recovery_mode is unsigned enum */
1753 ctx
->error_recovery
= (uint8_t) error_recovery
;
1757 // FIXME Doesn't work under Windows RTU
1758 int modbus_set_socket(modbus_t
*ctx
, int s
)
1769 int modbus_get_socket(modbus_t
*ctx
)
1779 /* Get the timeout interval used to wait for a response */
1780 int modbus_get_response_timeout(modbus_t
*ctx
, uint32_t *to_sec
, uint32_t *to_usec
)
1787 *to_sec
= ctx
->response_timeout
.tv_sec
;
1788 *to_usec
= ctx
->response_timeout
.tv_usec
;
1792 int modbus_set_response_timeout(modbus_t
*ctx
, uint32_t to_sec
, uint32_t to_usec
)
1794 if (ctx
== NULL
|| (to_sec
== 0 && to_usec
== 0) || to_usec
> 999999) {
1799 ctx
->response_timeout
.tv_sec
= to_sec
;
1800 ctx
->response_timeout
.tv_usec
= to_usec
;
1804 /* Get the timeout interval between two consecutive bytes of a message */
1805 int modbus_get_byte_timeout(modbus_t
*ctx
, uint32_t *to_sec
, uint32_t *to_usec
)
1812 *to_sec
= ctx
->byte_timeout
.tv_sec
;
1813 *to_usec
= ctx
->byte_timeout
.tv_usec
;
1817 int modbus_set_byte_timeout(modbus_t
*ctx
, uint32_t to_sec
, uint32_t to_usec
)
1819 /* Byte timeout can be disabled when both values are zero */
1820 if (ctx
== NULL
|| to_usec
> 999999) {
1825 ctx
->byte_timeout
.tv_sec
= to_sec
;
1826 ctx
->byte_timeout
.tv_usec
= to_usec
;
1830 /* Get the timeout interval used by the server to wait for an indication from a client */
1831 int modbus_get_indication_timeout(modbus_t
*ctx
, uint32_t *to_sec
, uint32_t *to_usec
)
1838 *to_sec
= ctx
->indication_timeout
.tv_sec
;
1839 *to_usec
= ctx
->indication_timeout
.tv_usec
;
1843 int modbus_set_indication_timeout(modbus_t
*ctx
, uint32_t to_sec
, uint32_t to_usec
)
1845 /* Indication timeout can be disabled when both values are zero */
1846 if (ctx
== NULL
|| to_usec
> 999999) {
1851 ctx
->indication_timeout
.tv_sec
= to_sec
;
1852 ctx
->indication_timeout
.tv_usec
= to_usec
;
1856 int modbus_get_header_length(modbus_t
*ctx
)
1863 return ctx
->backend
->header_length
;
1866 int modbus_enable_quirks(modbus_t
*ctx
, unsigned int quirks_mask
)
1873 /* Enable quirks that have a true value at their index in the mask */
1874 ctx
->quirks
|= quirks_mask
;
1878 int modbus_disable_quirks(modbus_t
*ctx
, unsigned int quirks_mask
)
1885 /* Disable quirks that have a true value at ther index in the mask */
1886 ctx
->quirks
&= ~quirks_mask
;
1890 int modbus_connect(modbus_t
*ctx
)
1897 return ctx
->backend
->connect(ctx
);
1900 void modbus_close(modbus_t
*ctx
)
1905 ctx
->backend
->close(ctx
);
1908 void modbus_free(modbus_t
*ctx
)
1913 ctx
->backend
->free(ctx
);
1916 int modbus_set_debug(modbus_t
*ctx
, int flag
)
1927 /* Allocates 4 arrays to store bits, input bits, registers and inputs
1928 registers. The pointers are stored in modbus_mapping structure.
1930 The modbus_mapping_new_start_address() function shall return the new allocated
1931 structure if successful. Otherwise it shall return NULL and set errno to
1933 modbus_mapping_t
*modbus_mapping_new_start_address(unsigned int start_bits
,
1934 unsigned int nb_bits
,
1935 unsigned int start_input_bits
,
1936 unsigned int nb_input_bits
,
1937 unsigned int start_registers
,
1938 unsigned int nb_registers
,
1939 unsigned int start_input_registers
,
1940 unsigned int nb_input_registers
)
1942 modbus_mapping_t
*mb_mapping
;
1944 mb_mapping
= (modbus_mapping_t
*) malloc(sizeof(modbus_mapping_t
));
1945 if (mb_mapping
== NULL
) {
1950 mb_mapping
->nb_bits
= nb_bits
;
1951 mb_mapping
->start_bits
= start_bits
;
1953 mb_mapping
->tab_bits
= NULL
;
1955 /* Negative number raises a POSIX error */
1956 mb_mapping
->tab_bits
= (uint8_t *) malloc(nb_bits
* sizeof(uint8_t));
1957 if (mb_mapping
->tab_bits
== NULL
) {
1961 memset(mb_mapping
->tab_bits
, 0, nb_bits
* sizeof(uint8_t));
1965 mb_mapping
->nb_input_bits
= nb_input_bits
;
1966 mb_mapping
->start_input_bits
= start_input_bits
;
1967 if (nb_input_bits
== 0) {
1968 mb_mapping
->tab_input_bits
= NULL
;
1970 mb_mapping
->tab_input_bits
= (uint8_t *) malloc(nb_input_bits
* sizeof(uint8_t));
1971 if (mb_mapping
->tab_input_bits
== NULL
) {
1972 free(mb_mapping
->tab_bits
);
1976 memset(mb_mapping
->tab_input_bits
, 0, nb_input_bits
* sizeof(uint8_t));
1980 mb_mapping
->nb_registers
= nb_registers
;
1981 mb_mapping
->start_registers
= start_registers
;
1982 if (nb_registers
== 0) {
1983 mb_mapping
->tab_registers
= NULL
;
1985 mb_mapping
->tab_registers
= (uint16_t *) malloc(nb_registers
* sizeof(uint16_t));
1986 if (mb_mapping
->tab_registers
== NULL
) {
1987 free(mb_mapping
->tab_input_bits
);
1988 free(mb_mapping
->tab_bits
);
1992 memset(mb_mapping
->tab_registers
, 0, nb_registers
* sizeof(uint16_t));
1996 mb_mapping
->nb_input_registers
= nb_input_registers
;
1997 mb_mapping
->start_input_registers
= start_input_registers
;
1998 if (nb_input_registers
== 0) {
1999 mb_mapping
->tab_input_registers
= NULL
;
2001 mb_mapping
->tab_input_registers
=
2002 (uint16_t *) malloc(nb_input_registers
* sizeof(uint16_t));
2003 if (mb_mapping
->tab_input_registers
== NULL
) {
2004 free(mb_mapping
->tab_registers
);
2005 free(mb_mapping
->tab_input_bits
);
2006 free(mb_mapping
->tab_bits
);
2010 memset(mb_mapping
->tab_input_registers
, 0, nb_input_registers
* sizeof(uint16_t));
2016 modbus_mapping_t
*modbus_mapping_new(int nb_bits
,
2019 int nb_input_registers
)
2021 return modbus_mapping_new_start_address(
2022 0, nb_bits
, 0, nb_input_bits
, 0, nb_registers
, 0, nb_input_registers
);
2025 /* Frees the 4 arrays */
2026 void modbus_mapping_free(modbus_mapping_t
*mb_mapping
)
2028 if (mb_mapping
== NULL
) {
2032 free(mb_mapping
->tab_input_registers
);
2033 free(mb_mapping
->tab_registers
);
2034 free(mb_mapping
->tab_input_bits
);
2035 free(mb_mapping
->tab_bits
);
2039 #ifndef HAVE_STRLCPY
2041 * Function strlcpy was originally developed by
2042 * Todd C. Miller <Todd.Miller@courtesan.com> to simplify writing secure code.
2043 * See ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/strlcpy.3
2044 * for more information.
2046 * Thank you Ulrich Drepper... not!
2048 * Copy src to string dest of size dest_size. At most dest_size-1 characters
2049 * will be copied. Always NUL terminates (unless dest_size == 0). Returns
2050 * strlen(src); if retval >= dest_size, truncation occurred.
2052 size_t strlcpy(char *dest
, const char *src
, size_t dest_size
)
2054 register char *d
= dest
;
2055 register const char *s
= src
;
2056 register size_t n
= dest_size
;
2058 /* Copy as many bytes as will fit */
2059 if (n
!= 0 && --n
!= 0) {
2061 if ((*d
++ = *s
++) == 0)
2066 /* Not enough room in dest, add NUL and traverse rest of src */
2069 *d
= '\0'; /* NUL-terminate dest */
2074 return (s
- src
- 1); /* count does not include NUL */