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 (ctx
->backend
->backend_type
== _MODBUS_BACKEND_TYPE_TCP
) &&
453 (wsa_err
== WSAENOTCONN
|| wsa_err
== WSAENETRESET
||
454 wsa_err
== WSAENOTSOCK
|| wsa_err
== WSAESHUTDOWN
||
455 wsa_err
== WSAECONNABORTED
|| wsa_err
== WSAETIMEDOUT
||
456 wsa_err
== WSAECONNRESET
)) {
461 if ((ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_LINK
) &&
462 (ctx
->backend
->backend_type
== _MODBUS_BACKEND_TYPE_TCP
) &&
463 (errno
== ECONNRESET
|| errno
== ECONNREFUSED
|| errno
== EBADF
)) {
464 int saved_errno
= errno
;
467 /* Could be removed by previous calls */
474 /* Display the hex code of each character received */
477 for (i
= 0; i
< rc
; i
++)
478 printf("<%.2X>", msg
[msg_length
+ i
]);
481 /* Sums bytes received */
483 /* Computes remaining bytes */
484 length_to_read
-= rc
;
486 if (length_to_read
== 0) {
489 /* Function code position */
490 length_to_read
= compute_meta_length_after_function(
491 msg
[ctx
->backend
->header_length
], msg_type
);
492 if (length_to_read
!= 0) {
495 } /* else switches straight to the next step */
497 length_to_read
= compute_data_length_after_meta(ctx
, msg
, msg_type
);
498 if ((msg_length
+ length_to_read
) > ctx
->backend
->max_adu_length
) {
500 _error_print(ctx
, "too many data");
510 if (length_to_read
> 0 &&
511 (ctx
->byte_timeout
.tv_sec
> 0 || ctx
->byte_timeout
.tv_usec
> 0)) {
512 /* If there is no character in the buffer, the allowed timeout
513 interval between two consecutive bytes is defined by
515 tv
.tv_sec
= ctx
->byte_timeout
.tv_sec
;
516 tv
.tv_usec
= ctx
->byte_timeout
.tv_usec
;
519 /* else timeout isn't set again, the full response must be read before
520 expiration of response timeout (for CONFIRMATION only) */
526 return ctx
->backend
->check_integrity(ctx
, msg
, msg_length
);
529 /* Receive the request from a modbus master */
530 int modbus_receive(modbus_t
*ctx
, uint8_t *req
)
537 return ctx
->backend
->receive(ctx
, req
);
540 /* Receives the confirmation.
542 The function shall store the read response in rsp and return the number of
543 values (bits or words). Otherwise, its shall return -1 and errno is set.
545 The function doesn't check the confirmation is the expected response to the
548 int modbus_receive_confirmation(modbus_t
*ctx
, uint8_t *rsp
)
555 return _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
558 static int check_confirmation(modbus_t
*ctx
, uint8_t *req
, uint8_t *rsp
, int rsp_length
)
561 int rsp_length_computed
;
562 const unsigned int offset
= ctx
->backend
->header_length
;
563 const int function
= rsp
[offset
];
565 if (ctx
->backend
->pre_check_confirmation
) {
566 rc
= ctx
->backend
->pre_check_confirmation(ctx
, req
, rsp
, rsp_length
);
568 if (ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_PROTOCOL
) {
569 _sleep_response_timeout(ctx
);
576 rsp_length_computed
= compute_response_length_from_request(ctx
, req
);
579 if (function
>= 0x80) {
580 if (rsp_length
== (int) (offset
+ 2 + ctx
->backend
->checksum_length
) &&
581 req
[offset
] == (rsp
[offset
] - 0x80)) {
582 /* Valid exception code received */
584 int exception_code
= rsp
[offset
+ 1];
585 if (exception_code
< MODBUS_EXCEPTION_MAX
) {
586 errno
= MODBUS_ENOBASE
+ exception_code
;
590 _error_print(ctx
, NULL
);
594 _error_print(ctx
, NULL
);
600 if ((rsp_length
== rsp_length_computed
||
601 rsp_length_computed
== MSG_LENGTH_UNDEFINED
) &&
605 int resp_addr_ok
= TRUE
;
606 int resp_data_ok
= TRUE
;
608 /* Check function code */
609 if (function
!= req
[offset
]) {
613 "Received function not corresponding to the request (0x%X != 0x%X)\n",
617 if (ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_PROTOCOL
) {
618 _sleep_response_timeout(ctx
);
625 /* Check the number of values is corresponding to the request */
627 case MODBUS_FC_READ_COILS
:
628 case MODBUS_FC_READ_DISCRETE_INPUTS
:
629 /* Read functions, 8 values in a byte (nb
630 * of values in the request and byte count in
632 req_nb_value
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
633 req_nb_value
= (req_nb_value
/ 8) + ((req_nb_value
% 8) ? 1 : 0);
634 rsp_nb_value
= rsp
[offset
+ 1];
636 case MODBUS_FC_WRITE_AND_READ_REGISTERS
:
637 case MODBUS_FC_READ_HOLDING_REGISTERS
:
638 case MODBUS_FC_READ_INPUT_REGISTERS
:
639 /* Read functions 1 value = 2 bytes */
640 req_nb_value
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
641 rsp_nb_value
= (rsp
[offset
+ 1] / 2);
643 case MODBUS_FC_WRITE_MULTIPLE_COILS
:
644 case MODBUS_FC_WRITE_MULTIPLE_REGISTERS
:
645 /* address in request and response must be equal */
646 if ((req
[offset
+ 1] != rsp
[offset
+ 1]) ||
647 (req
[offset
+ 2] != rsp
[offset
+ 2])) {
648 resp_addr_ok
= FALSE
;
650 /* N Write functions */
651 req_nb_value
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
652 rsp_nb_value
= (rsp
[offset
+ 3] << 8) | rsp
[offset
+ 4];
654 case MODBUS_FC_REPORT_SLAVE_ID
:
655 /* Report slave ID (bytes received) */
656 req_nb_value
= rsp_nb_value
= rsp
[offset
+ 1];
658 case MODBUS_FC_WRITE_SINGLE_COIL
:
659 case MODBUS_FC_WRITE_SINGLE_REGISTER
:
660 /* address in request and response must be equal */
661 if ((req
[offset
+ 1] != rsp
[offset
+ 1]) ||
662 (req
[offset
+ 2] != rsp
[offset
+ 2])) {
663 resp_addr_ok
= FALSE
;
665 /* data in request and response must be equal */
666 if ((req
[offset
+ 3] != rsp
[offset
+ 3]) ||
667 (req
[offset
+ 4] != rsp
[offset
+ 4])) {
668 resp_data_ok
= FALSE
;
670 /* 1 Write functions & others */
671 req_nb_value
= rsp_nb_value
= 1;
674 /* 1 Write functions & others */
675 req_nb_value
= rsp_nb_value
= 1;
679 if ((req_nb_value
== rsp_nb_value
) && (resp_addr_ok
== TRUE
) &&
680 (resp_data_ok
== TRUE
)) {
685 "Received data not corresponding to the request (%d != %d)\n",
690 if (ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_PROTOCOL
) {
691 _sleep_response_timeout(ctx
);
702 "Message length not corresponding to the computed length (%d != %d)\n",
704 rsp_length_computed
);
706 if (ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_PROTOCOL
) {
707 _sleep_response_timeout(ctx
);
718 response_io_status(uint8_t *tab_io_status
, int address
, int nb
, uint8_t *rsp
, int offset
)
721 /* Instead of byte (not allowed in Win32) */
725 for (i
= address
; i
< address
+ nb
; i
++) {
726 one_byte
|= tab_io_status
[i
] << shift
;
729 rsp
[offset
++] = one_byte
;
730 one_byte
= shift
= 0;
737 rsp
[offset
++] = one_byte
;
742 /* Build the exception response */
743 static int response_exception(modbus_t
*ctx
,
747 unsigned int to_flush
,
748 const char *template,
753 /* Print debug message */
757 va_start(ap
, template);
758 vfprintf(stderr
, template, ap
);
762 /* Flush if required */
764 _sleep_response_timeout(ctx
);
768 /* Build exception response */
769 sft
->function
= sft
->function
+ 0x80;
770 rsp_length
= ctx
->backend
->build_response_basis(sft
, rsp
);
771 rsp
[rsp_length
++] = exception_code
;
776 /* Send a response to the received request.
777 Analyses the request and constructs a response.
779 If an error occurs, this function construct the response
782 int modbus_reply(modbus_t
*ctx
,
785 modbus_mapping_t
*mb_mapping
)
791 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
800 offset
= ctx
->backend
->header_length
;
801 slave
= req
[offset
- 1];
802 function
= req
[offset
];
803 address
= (req
[offset
+ 1] << 8) + req
[offset
+ 2];
806 sft
.function
= function
;
807 sft
.t_id
= ctx
->backend
->prepare_response_tid(req
, &req_length
);
809 /* Data are flushed on illegal number of values errors. */
811 case MODBUS_FC_READ_COILS
:
812 case MODBUS_FC_READ_DISCRETE_INPUTS
: {
813 unsigned int is_input
= (function
== MODBUS_FC_READ_DISCRETE_INPUTS
);
814 int start_bits
= is_input
? mb_mapping
->start_input_bits
: mb_mapping
->start_bits
;
815 int nb_bits
= is_input
? mb_mapping
->nb_input_bits
: mb_mapping
->nb_bits
;
816 uint8_t *tab_bits
= is_input
? mb_mapping
->tab_input_bits
: mb_mapping
->tab_bits
;
817 const char *const name
= is_input
? "read_input_bits" : "read_bits";
818 int nb
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
819 /* The mapping can be shifted to reduce memory consumption and it
820 doesn't always start at address zero. */
821 int mapping_address
= address
- start_bits
;
823 if (nb
< 1 || MODBUS_MAX_READ_BITS
< nb
) {
824 rsp_length
= response_exception(ctx
,
826 MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
,
829 "Illegal nb of values %d in %s (max %d)\n",
832 MODBUS_MAX_READ_BITS
);
833 } else if (mapping_address
< 0 || (mapping_address
+ nb
) > nb_bits
) {
834 rsp_length
= response_exception(ctx
,
836 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
,
839 "Illegal data address 0x%0X in %s\n",
840 mapping_address
< 0 ? address
: address
+ nb
,
843 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
844 rsp
[rsp_length
++] = (nb
/ 8) + ((nb
% 8) ? 1 : 0);
846 response_io_status(tab_bits
, mapping_address
, nb
, rsp
, rsp_length
);
849 case MODBUS_FC_READ_HOLDING_REGISTERS
:
850 case MODBUS_FC_READ_INPUT_REGISTERS
: {
851 unsigned int is_input
= (function
== MODBUS_FC_READ_INPUT_REGISTERS
);
852 int start_registers
=
853 is_input
? mb_mapping
->start_input_registers
: mb_mapping
->start_registers
;
855 is_input
? mb_mapping
->nb_input_registers
: mb_mapping
->nb_registers
;
856 uint16_t *tab_registers
=
857 is_input
? mb_mapping
->tab_input_registers
: mb_mapping
->tab_registers
;
858 const char *const name
= is_input
? "read_input_registers" : "read_registers";
859 int nb
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
860 /* The mapping can be shifted to reduce memory consumption and it
861 doesn't always start at address zero. */
862 int mapping_address
= address
- start_registers
;
864 if (nb
< 1 || MODBUS_MAX_READ_REGISTERS
< nb
) {
865 rsp_length
= response_exception(ctx
,
867 MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
,
870 "Illegal nb of values %d in %s (max %d)\n",
873 MODBUS_MAX_READ_REGISTERS
);
874 } else if (mapping_address
< 0 || (mapping_address
+ nb
) > nb_registers
) {
875 rsp_length
= response_exception(ctx
,
877 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
,
880 "Illegal data address 0x%0X in %s\n",
881 mapping_address
< 0 ? address
: address
+ nb
,
886 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
887 rsp
[rsp_length
++] = nb
<< 1;
888 for (i
= mapping_address
; i
< mapping_address
+ nb
; i
++) {
889 rsp
[rsp_length
++] = tab_registers
[i
] >> 8;
890 rsp
[rsp_length
++] = tab_registers
[i
] & 0xFF;
894 case MODBUS_FC_WRITE_SINGLE_COIL
: {
895 int mapping_address
= address
- mb_mapping
->start_bits
;
897 if (mapping_address
< 0 || mapping_address
>= mb_mapping
->nb_bits
) {
898 rsp_length
= response_exception(ctx
,
900 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
,
903 "Illegal data address 0x%0X in write_bit\n",
906 int data
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
908 if (data
== 0xFF00 || data
== 0x0) {
909 mb_mapping
->tab_bits
[mapping_address
] = data
? ON
: OFF
;
910 memcpy(rsp
, req
, req_length
);
911 rsp_length
= req_length
;
913 rsp_length
= response_exception(
916 MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
,
919 "Illegal data value 0x%0X in write_bit request at address %0X\n",
925 case MODBUS_FC_WRITE_SINGLE_REGISTER
: {
926 int mapping_address
= address
- mb_mapping
->start_registers
;
928 if (mapping_address
< 0 || mapping_address
>= mb_mapping
->nb_registers
) {
930 response_exception(ctx
,
932 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
,
935 "Illegal data address 0x%0X in write_register\n",
938 int data
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
940 mb_mapping
->tab_registers
[mapping_address
] = data
;
941 memcpy(rsp
, req
, req_length
);
942 rsp_length
= req_length
;
945 case MODBUS_FC_WRITE_MULTIPLE_COILS
: {
946 int nb
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
947 int nb_bits
= req
[offset
+ 5];
948 int mapping_address
= address
- mb_mapping
->start_bits
;
950 if (nb
< 1 || MODBUS_MAX_WRITE_BITS
< nb
|| nb_bits
* 8 < nb
) {
951 /* May be the indication has been truncated on reading because of
952 * invalid address (eg. nb is 0 but the request contains values to
953 * write) so it's necessary to flush. */
955 response_exception(ctx
,
957 MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
,
960 "Illegal number of values %d in write_bits (max %d)\n",
962 MODBUS_MAX_WRITE_BITS
);
963 } else if (mapping_address
< 0 || (mapping_address
+ nb
) > mb_mapping
->nb_bits
) {
964 rsp_length
= response_exception(ctx
,
966 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
,
969 "Illegal data address 0x%0X in write_bits\n",
970 mapping_address
< 0 ? address
: address
+ nb
);
973 modbus_set_bits_from_bytes(
974 mb_mapping
->tab_bits
, mapping_address
, nb
, &req
[offset
+ 6]);
976 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
977 /* 4 to copy the bit address (2) and the quantity of bits */
978 memcpy(rsp
+ rsp_length
, req
+ rsp_length
, 4);
982 case MODBUS_FC_WRITE_MULTIPLE_REGISTERS
: {
983 int nb
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
984 int nb_bytes
= req
[offset
+ 5];
985 int mapping_address
= address
- mb_mapping
->start_registers
;
987 if (nb
< 1 || MODBUS_MAX_WRITE_REGISTERS
< nb
|| nb_bytes
!= nb
* 2) {
988 rsp_length
= response_exception(
991 MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
,
994 "Illegal number of values %d in write_registers (max %d)\n",
996 MODBUS_MAX_WRITE_REGISTERS
);
997 } else if (mapping_address
< 0 ||
998 (mapping_address
+ nb
) > mb_mapping
->nb_registers
) {
1000 response_exception(ctx
,
1002 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
,
1005 "Illegal data address 0x%0X in write_registers\n",
1006 mapping_address
< 0 ? address
: address
+ nb
);
1009 for (i
= mapping_address
, j
= 6; i
< mapping_address
+ nb
; i
++, j
+= 2) {
1010 /* 6 and 7 = first value */
1011 mb_mapping
->tab_registers
[i
] =
1012 (req
[offset
+ j
] << 8) + req
[offset
+ j
+ 1];
1015 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
1016 /* 4 to copy the address (2) and the no. of registers */
1017 memcpy(rsp
+ rsp_length
, req
+ rsp_length
, 4);
1021 case MODBUS_FC_REPORT_SLAVE_ID
: {
1025 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
1026 /* Skip byte count for now */
1027 byte_count_pos
= rsp_length
++;
1028 rsp
[rsp_length
++] = _REPORT_SLAVE_ID
;
1029 /* Run indicator status to ON */
1030 rsp
[rsp_length
++] = 0xFF;
1031 /* LMB + length of LIBMODBUS_VERSION_STRING */
1032 str_len
= 3 + strlen(LIBMODBUS_VERSION_STRING
);
1033 memcpy(rsp
+ rsp_length
, "LMB" LIBMODBUS_VERSION_STRING
, str_len
);
1034 rsp_length
+= str_len
;
1035 rsp
[byte_count_pos
] = rsp_length
- byte_count_pos
- 1;
1037 case MODBUS_FC_READ_EXCEPTION_STATUS
:
1039 fprintf(stderr
, "FIXME Not implemented\n");
1041 errno
= ENOPROTOOPT
;
1044 case MODBUS_FC_MASK_WRITE_REGISTER
: {
1045 int mapping_address
= address
- mb_mapping
->start_registers
;
1047 if (mapping_address
< 0 || mapping_address
>= mb_mapping
->nb_registers
) {
1049 response_exception(ctx
,
1051 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
,
1054 "Illegal data address 0x%0X in write_register\n",
1057 uint16_t data
= mb_mapping
->tab_registers
[mapping_address
];
1058 uint16_t and = (req
[offset
+ 3] << 8) + req
[offset
+ 4];
1059 uint16_t or = (req
[offset
+ 5] << 8) + req
[offset
+ 6];
1061 data
= (data
& and) | (or &(~and));
1062 mb_mapping
->tab_registers
[mapping_address
] = data
;
1063 memcpy(rsp
, req
, req_length
);
1064 rsp_length
= req_length
;
1067 case MODBUS_FC_WRITE_AND_READ_REGISTERS
: {
1068 int nb
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
1069 uint16_t address_write
= (req
[offset
+ 5] << 8) + req
[offset
+ 6];
1070 int nb_write
= (req
[offset
+ 7] << 8) + req
[offset
+ 8];
1071 int nb_write_bytes
= req
[offset
+ 9];
1072 int mapping_address
= address
- mb_mapping
->start_registers
;
1073 int mapping_address_write
= address_write
- mb_mapping
->start_registers
;
1075 if (nb_write
< 1 || MODBUS_MAX_WR_WRITE_REGISTERS
< nb_write
|| nb
< 1 ||
1076 MODBUS_MAX_WR_READ_REGISTERS
< nb
|| nb_write_bytes
!= nb_write
* 2) {
1077 rsp_length
= response_exception(
1080 MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
,
1083 "Illegal nb of values (W%d, R%d) in write_and_read_registers (max W%d, "
1087 MODBUS_MAX_WR_WRITE_REGISTERS
,
1088 MODBUS_MAX_WR_READ_REGISTERS
);
1089 } else if (mapping_address
< 0 ||
1090 (mapping_address
+ nb
) > mb_mapping
->nb_registers
||
1091 mapping_address_write
< 0 ||
1092 (mapping_address_write
+ nb_write
) > mb_mapping
->nb_registers
) {
1093 rsp_length
= response_exception(
1096 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
,
1099 "Illegal data read address 0x%0X or write address 0x%0X "
1100 "write_and_read_registers\n",
1101 mapping_address
< 0 ? address
: address
+ nb
,
1102 mapping_address_write
< 0 ? address_write
: address_write
+ nb_write
);
1105 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
1106 rsp
[rsp_length
++] = nb
<< 1;
1109 10 and 11 are the offset of the first values to write */
1110 for (i
= mapping_address_write
, j
= 10; i
< mapping_address_write
+ nb_write
;
1112 mb_mapping
->tab_registers
[i
] =
1113 (req
[offset
+ j
] << 8) + req
[offset
+ j
+ 1];
1116 /* and read the data for the response */
1117 for (i
= mapping_address
; i
< mapping_address
+ nb
; i
++) {
1118 rsp
[rsp_length
++] = mb_mapping
->tab_registers
[i
] >> 8;
1119 rsp
[rsp_length
++] = mb_mapping
->tab_registers
[i
] & 0xFF;
1125 rsp_length
= response_exception(ctx
,
1127 MODBUS_EXCEPTION_ILLEGAL_FUNCTION
,
1130 "Unknown Modbus function code: 0x%0X\n",
1135 /* Suppress any responses in RTU when the request was a broadcast, excepted when quirk
1137 if (ctx
->backend
->backend_type
== _MODBUS_BACKEND_TYPE_RTU
&&
1138 slave
== MODBUS_BROADCAST_ADDRESS
&&
1139 !(ctx
->quirks
& MODBUS_QUIRK_REPLY_TO_BROADCAST
)) {
1142 return send_msg(ctx
, rsp
, rsp_length
);
1145 int modbus_reply_exception(modbus_t
*ctx
, const uint8_t *req
, unsigned int exception_code
)
1147 unsigned int offset
;
1150 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1152 int dummy_length
= 99;
1160 offset
= ctx
->backend
->header_length
;
1161 slave
= req
[offset
- 1];
1162 function
= req
[offset
];
1165 sft
.function
= function
+ 0x80;
1166 sft
.t_id
= ctx
->backend
->prepare_response_tid(req
, &dummy_length
);
1167 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
1169 /* Positive exception code */
1170 if (exception_code
< MODBUS_EXCEPTION_MAX
) {
1171 rsp
[rsp_length
++] = exception_code
;
1172 return send_msg(ctx
, rsp
, rsp_length
);
1179 /* Reads IO status */
1180 static int read_io_status(modbus_t
*ctx
, int function
, int addr
, int nb
, uint8_t *dest
)
1185 uint8_t req
[_MIN_REQ_LENGTH
];
1186 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1188 req_length
= ctx
->backend
->build_request_basis(ctx
, function
, addr
, nb
, req
);
1190 rc
= send_msg(ctx
, req
, req_length
);
1194 unsigned int offset
;
1195 unsigned int offset_end
;
1197 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1201 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1205 offset
= ctx
->backend
->header_length
+ 2;
1206 offset_end
= offset
+ rc
;
1207 for (unsigned int i
= offset
; i
< offset_end
; i
++) {
1208 /* Shift reg hi_byte to temp */
1211 for (bit
= 0x01; (bit
& 0xff) && (pos
< nb
);) {
1212 dest
[pos
++] = (temp
& bit
) ? TRUE
: FALSE
;
1221 /* Reads the boolean status of bits and sets the array elements
1222 in the destination to TRUE or FALSE (single bits). */
1223 int modbus_read_bits(modbus_t
*ctx
, int addr
, int nb
, uint8_t *dest
)
1232 if (nb
> MODBUS_MAX_READ_BITS
) {
1235 "ERROR Too many bits requested (%d > %d)\n",
1237 MODBUS_MAX_READ_BITS
);
1243 rc
= read_io_status(ctx
, MODBUS_FC_READ_COILS
, addr
, nb
, dest
);
1251 /* Same as modbus_read_bits but reads the remote device input table */
1252 int modbus_read_input_bits(modbus_t
*ctx
, int addr
, int nb
, uint8_t *dest
)
1261 if (nb
> MODBUS_MAX_READ_BITS
) {
1264 "ERROR Too many discrete inputs requested (%d > %d)\n",
1266 MODBUS_MAX_READ_BITS
);
1272 rc
= read_io_status(ctx
, MODBUS_FC_READ_DISCRETE_INPUTS
, addr
, nb
, dest
);
1280 /* Reads the data from a remote device and put that data into an array */
1281 static int read_registers(modbus_t
*ctx
, int function
, int addr
, int nb
, uint16_t *dest
)
1285 uint8_t req
[_MIN_REQ_LENGTH
];
1286 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1288 if (nb
> MODBUS_MAX_READ_REGISTERS
) {
1291 "ERROR Too many registers requested (%d > %d)\n",
1293 MODBUS_MAX_READ_REGISTERS
);
1299 req_length
= ctx
->backend
->build_request_basis(ctx
, function
, addr
, nb
, req
);
1301 rc
= send_msg(ctx
, req
, req_length
);
1303 unsigned int offset
;
1306 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1310 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1314 offset
= ctx
->backend
->header_length
;
1316 for (i
= 0; i
< rc
; i
++) {
1317 /* shift reg hi_byte to temp OR with lo_byte */
1318 dest
[i
] = (rsp
[offset
+ 2 + (i
<< 1)] << 8) | rsp
[offset
+ 3 + (i
<< 1)];
1325 /* Reads the holding registers of remote device and put the data into an
1327 int modbus_read_registers(modbus_t
*ctx
, int addr
, int nb
, uint16_t *dest
)
1336 if (nb
> MODBUS_MAX_READ_REGISTERS
) {
1339 "ERROR Too many registers requested (%d > %d)\n",
1341 MODBUS_MAX_READ_REGISTERS
);
1347 status
= read_registers(ctx
, MODBUS_FC_READ_HOLDING_REGISTERS
, addr
, nb
, dest
);
1351 /* Reads the input registers of remote device and put the data into an array */
1352 int modbus_read_input_registers(modbus_t
*ctx
, int addr
, int nb
, uint16_t *dest
)
1361 if (nb
> MODBUS_MAX_READ_REGISTERS
) {
1364 "ERROR Too many input registers requested (%d > %d)\n",
1366 MODBUS_MAX_READ_REGISTERS
);
1372 status
= read_registers(ctx
, MODBUS_FC_READ_INPUT_REGISTERS
, addr
, nb
, dest
);
1377 /* Write a value to the specified register of the remote device.
1378 Used by write_bit and write_register */
1379 static int write_single(modbus_t
*ctx
, int function
, int addr
, const uint16_t value
)
1383 uint8_t req
[_MIN_REQ_LENGTH
];
1390 req_length
= ctx
->backend
->build_request_basis(ctx
, function
, addr
, (int) value
, req
);
1392 rc
= send_msg(ctx
, req
, req_length
);
1394 /* Used by write_bit and write_register */
1395 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1397 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1401 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1407 /* Turns ON or OFF a single bit of the remote device */
1408 int modbus_write_bit(modbus_t
*ctx
, int addr
, int status
)
1415 return write_single(ctx
, MODBUS_FC_WRITE_SINGLE_COIL
, addr
, status
? 0xFF00 : 0);
1418 /* Writes a value in one register of the remote device */
1419 int modbus_write_register(modbus_t
*ctx
, int addr
, const uint16_t value
)
1426 return write_single(ctx
, MODBUS_FC_WRITE_SINGLE_REGISTER
, addr
, value
);
1429 /* Write the bits of the array in the remote device */
1430 int modbus_write_bits(modbus_t
*ctx
, int addr
, int nb
, const uint8_t *src
)
1438 uint8_t req
[MAX_MESSAGE_LENGTH
];
1445 if (nb
> MODBUS_MAX_WRITE_BITS
) {
1448 "ERROR Writing too many bits (%d > %d)\n",
1450 MODBUS_MAX_WRITE_BITS
);
1456 req_length
= ctx
->backend
->build_request_basis(
1457 ctx
, MODBUS_FC_WRITE_MULTIPLE_COILS
, addr
, nb
, req
);
1458 byte_count
= (nb
/ 8) + ((nb
% 8) ? 1 : 0);
1459 req
[req_length
++] = byte_count
;
1461 for (i
= 0; i
< byte_count
; i
++) {
1465 req
[req_length
] = 0;
1467 while ((bit
& 0xFF) && (bit_check
++ < nb
)) {
1469 req
[req_length
] |= bit
;
1471 req
[req_length
] &= ~bit
;
1478 rc
= send_msg(ctx
, req
, req_length
);
1480 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1482 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1486 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1492 /* Write the values from the array to the registers of the remote device */
1493 int modbus_write_registers(modbus_t
*ctx
, int addr
, int nb
, const uint16_t *src
)
1499 uint8_t req
[MAX_MESSAGE_LENGTH
];
1506 if (nb
> MODBUS_MAX_WRITE_REGISTERS
) {
1509 "ERROR Trying to write to too many registers (%d > %d)\n",
1511 MODBUS_MAX_WRITE_REGISTERS
);
1517 req_length
= ctx
->backend
->build_request_basis(
1518 ctx
, MODBUS_FC_WRITE_MULTIPLE_REGISTERS
, addr
, nb
, req
);
1519 byte_count
= nb
* 2;
1520 req
[req_length
++] = byte_count
;
1522 for (i
= 0; i
< nb
; i
++) {
1523 req
[req_length
++] = src
[i
] >> 8;
1524 req
[req_length
++] = src
[i
] & 0x00FF;
1527 rc
= send_msg(ctx
, req
, req_length
);
1529 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1531 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1535 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1541 int modbus_mask_write_register(modbus_t
*ctx
,
1548 /* The request length can not exceed _MIN_REQ_LENGTH - 2 and 4 bytes to
1549 * store the masks. The ugly substraction is there to remove the 'nb' value
1550 * (2 bytes) which is not used. */
1551 uint8_t req
[_MIN_REQ_LENGTH
+ 2];
1553 req_length
= ctx
->backend
->build_request_basis(
1554 ctx
, MODBUS_FC_MASK_WRITE_REGISTER
, addr
, 0, req
);
1556 /* HACKISH, count is not used */
1559 req
[req_length
++] = and_mask
>> 8;
1560 req
[req_length
++] = and_mask
& 0x00ff;
1561 req
[req_length
++] = or_mask
>> 8;
1562 req
[req_length
++] = or_mask
& 0x00ff;
1564 rc
= send_msg(ctx
, req
, req_length
);
1566 /* Used by write_bit and write_register */
1567 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1569 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1573 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1579 /* Write multiple registers from src array to remote device and read multiple
1580 registers from remote device to dest array. */
1581 int modbus_write_and_read_registers(modbus_t
*ctx
,
1584 const uint16_t *src
,
1594 uint8_t req
[MAX_MESSAGE_LENGTH
];
1595 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1602 if (write_nb
> MODBUS_MAX_WR_WRITE_REGISTERS
) {
1605 "ERROR Too many registers to write (%d > %d)\n",
1607 MODBUS_MAX_WR_WRITE_REGISTERS
);
1613 if (read_nb
> MODBUS_MAX_WR_READ_REGISTERS
) {
1616 "ERROR Too many registers requested (%d > %d)\n",
1618 MODBUS_MAX_WR_READ_REGISTERS
);
1623 req_length
= ctx
->backend
->build_request_basis(
1624 ctx
, MODBUS_FC_WRITE_AND_READ_REGISTERS
, read_addr
, read_nb
, req
);
1626 req
[req_length
++] = write_addr
>> 8;
1627 req
[req_length
++] = write_addr
& 0x00ff;
1628 req
[req_length
++] = write_nb
>> 8;
1629 req
[req_length
++] = write_nb
& 0x00ff;
1630 byte_count
= write_nb
* 2;
1631 req
[req_length
++] = byte_count
;
1633 for (i
= 0; i
< write_nb
; i
++) {
1634 req
[req_length
++] = src
[i
] >> 8;
1635 req
[req_length
++] = src
[i
] & 0x00FF;
1638 rc
= send_msg(ctx
, req
, req_length
);
1640 unsigned int offset
;
1642 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1646 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1650 offset
= ctx
->backend
->header_length
;
1651 for (i
= 0; i
< rc
; i
++) {
1652 /* shift reg hi_byte to temp OR with lo_byte */
1653 dest
[i
] = (rsp
[offset
+ 2 + (i
<< 1)] << 8) | rsp
[offset
+ 3 + (i
<< 1)];
1660 /* Send a request to get the slave ID of the device (only available in serial
1662 int modbus_report_slave_id(modbus_t
*ctx
, int max_dest
, uint8_t *dest
)
1666 uint8_t req
[_MIN_REQ_LENGTH
];
1668 if (ctx
== NULL
|| max_dest
<= 0) {
1674 ctx
->backend
->build_request_basis(ctx
, MODBUS_FC_REPORT_SLAVE_ID
, 0, 0, req
);
1676 /* HACKISH, addr and count are not used */
1679 rc
= send_msg(ctx
, req
, req_length
);
1682 unsigned int offset
;
1683 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1685 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1689 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1693 offset
= ctx
->backend
->header_length
+ 2;
1695 /* Byte count, slave id, run indicator status and
1696 additional data. Truncate copy to max_dest. */
1697 for (i
= 0; i
< rc
&& i
< max_dest
; i
++) {
1698 dest
[i
] = rsp
[offset
+ i
];
1705 void _modbus_init_common(modbus_t
*ctx
)
1707 /* Slave and socket are initialized to -1 */
1712 ctx
->error_recovery
= MODBUS_ERROR_RECOVERY_NONE
;
1713 ctx
->quirks
= MODBUS_QUIRK_NONE
;
1715 ctx
->response_timeout
.tv_sec
= 0;
1716 ctx
->response_timeout
.tv_usec
= _RESPONSE_TIMEOUT
;
1718 ctx
->byte_timeout
.tv_sec
= 0;
1719 ctx
->byte_timeout
.tv_usec
= _BYTE_TIMEOUT
;
1721 ctx
->indication_timeout
.tv_sec
= 0;
1722 ctx
->indication_timeout
.tv_usec
= 0;
1725 /* Define the slave number */
1726 int modbus_set_slave(modbus_t
*ctx
, int slave
)
1733 return ctx
->backend
->set_slave(ctx
, slave
);
1736 int modbus_get_slave(modbus_t
*ctx
)
1746 int modbus_set_error_recovery(modbus_t
*ctx
, modbus_error_recovery_mode error_recovery
)
1753 /* The type of modbus_error_recovery_mode is unsigned enum */
1754 ctx
->error_recovery
= (uint8_t) error_recovery
;
1758 // FIXME Doesn't work under Windows RTU
1759 int modbus_set_socket(modbus_t
*ctx
, int s
)
1770 int modbus_get_socket(modbus_t
*ctx
)
1780 /* Get the timeout interval used to wait for a response */
1781 int modbus_get_response_timeout(modbus_t
*ctx
, uint32_t *to_sec
, uint32_t *to_usec
)
1788 *to_sec
= ctx
->response_timeout
.tv_sec
;
1789 *to_usec
= ctx
->response_timeout
.tv_usec
;
1793 int modbus_set_response_timeout(modbus_t
*ctx
, uint32_t to_sec
, uint32_t to_usec
)
1795 if (ctx
== NULL
|| (to_sec
== 0 && to_usec
== 0) || to_usec
> 999999) {
1800 ctx
->response_timeout
.tv_sec
= to_sec
;
1801 ctx
->response_timeout
.tv_usec
= to_usec
;
1805 /* Get the timeout interval between two consecutive bytes of a message */
1806 int modbus_get_byte_timeout(modbus_t
*ctx
, uint32_t *to_sec
, uint32_t *to_usec
)
1813 *to_sec
= ctx
->byte_timeout
.tv_sec
;
1814 *to_usec
= ctx
->byte_timeout
.tv_usec
;
1818 int modbus_set_byte_timeout(modbus_t
*ctx
, uint32_t to_sec
, uint32_t to_usec
)
1820 /* Byte timeout can be disabled when both values are zero */
1821 if (ctx
== NULL
|| to_usec
> 999999) {
1826 ctx
->byte_timeout
.tv_sec
= to_sec
;
1827 ctx
->byte_timeout
.tv_usec
= to_usec
;
1831 /* Get the timeout interval used by the server to wait for an indication from a client */
1832 int modbus_get_indication_timeout(modbus_t
*ctx
, uint32_t *to_sec
, uint32_t *to_usec
)
1839 *to_sec
= ctx
->indication_timeout
.tv_sec
;
1840 *to_usec
= ctx
->indication_timeout
.tv_usec
;
1844 int modbus_set_indication_timeout(modbus_t
*ctx
, uint32_t to_sec
, uint32_t to_usec
)
1846 /* Indication timeout can be disabled when both values are zero */
1847 if (ctx
== NULL
|| to_usec
> 999999) {
1852 ctx
->indication_timeout
.tv_sec
= to_sec
;
1853 ctx
->indication_timeout
.tv_usec
= to_usec
;
1857 int modbus_get_header_length(modbus_t
*ctx
)
1864 return ctx
->backend
->header_length
;
1867 int modbus_enable_quirks(modbus_t
*ctx
, unsigned int quirks_mask
)
1874 /* Enable quirks that have a true value at their index in the mask */
1875 ctx
->quirks
|= quirks_mask
;
1879 int modbus_disable_quirks(modbus_t
*ctx
, unsigned int quirks_mask
)
1886 /* Disable quirks that have a true value at ther index in the mask */
1887 ctx
->quirks
&= ~quirks_mask
;
1891 int modbus_connect(modbus_t
*ctx
)
1898 return ctx
->backend
->connect(ctx
);
1901 void modbus_close(modbus_t
*ctx
)
1906 ctx
->backend
->close(ctx
);
1909 void modbus_free(modbus_t
*ctx
)
1914 ctx
->backend
->free(ctx
);
1917 int modbus_set_debug(modbus_t
*ctx
, int flag
)
1928 /* Allocates 4 arrays to store bits, input bits, registers and inputs
1929 registers. The pointers are stored in modbus_mapping structure.
1931 The modbus_mapping_new_start_address() function shall return the new allocated
1932 structure if successful. Otherwise it shall return NULL and set errno to
1934 modbus_mapping_t
*modbus_mapping_new_start_address(unsigned int start_bits
,
1935 unsigned int nb_bits
,
1936 unsigned int start_input_bits
,
1937 unsigned int nb_input_bits
,
1938 unsigned int start_registers
,
1939 unsigned int nb_registers
,
1940 unsigned int start_input_registers
,
1941 unsigned int nb_input_registers
)
1943 modbus_mapping_t
*mb_mapping
;
1945 mb_mapping
= (modbus_mapping_t
*) malloc(sizeof(modbus_mapping_t
));
1946 if (mb_mapping
== NULL
) {
1951 mb_mapping
->nb_bits
= nb_bits
;
1952 mb_mapping
->start_bits
= start_bits
;
1954 mb_mapping
->tab_bits
= NULL
;
1956 /* Negative number raises a POSIX error */
1957 mb_mapping
->tab_bits
= (uint8_t *) malloc(nb_bits
* sizeof(uint8_t));
1958 if (mb_mapping
->tab_bits
== NULL
) {
1962 memset(mb_mapping
->tab_bits
, 0, nb_bits
* sizeof(uint8_t));
1966 mb_mapping
->nb_input_bits
= nb_input_bits
;
1967 mb_mapping
->start_input_bits
= start_input_bits
;
1968 if (nb_input_bits
== 0) {
1969 mb_mapping
->tab_input_bits
= NULL
;
1971 mb_mapping
->tab_input_bits
= (uint8_t *) malloc(nb_input_bits
* sizeof(uint8_t));
1972 if (mb_mapping
->tab_input_bits
== NULL
) {
1973 free(mb_mapping
->tab_bits
);
1977 memset(mb_mapping
->tab_input_bits
, 0, nb_input_bits
* sizeof(uint8_t));
1981 mb_mapping
->nb_registers
= nb_registers
;
1982 mb_mapping
->start_registers
= start_registers
;
1983 if (nb_registers
== 0) {
1984 mb_mapping
->tab_registers
= NULL
;
1986 mb_mapping
->tab_registers
= (uint16_t *) malloc(nb_registers
* sizeof(uint16_t));
1987 if (mb_mapping
->tab_registers
== NULL
) {
1988 free(mb_mapping
->tab_input_bits
);
1989 free(mb_mapping
->tab_bits
);
1993 memset(mb_mapping
->tab_registers
, 0, nb_registers
* sizeof(uint16_t));
1997 mb_mapping
->nb_input_registers
= nb_input_registers
;
1998 mb_mapping
->start_input_registers
= start_input_registers
;
1999 if (nb_input_registers
== 0) {
2000 mb_mapping
->tab_input_registers
= NULL
;
2002 mb_mapping
->tab_input_registers
=
2003 (uint16_t *) malloc(nb_input_registers
* sizeof(uint16_t));
2004 if (mb_mapping
->tab_input_registers
== NULL
) {
2005 free(mb_mapping
->tab_registers
);
2006 free(mb_mapping
->tab_input_bits
);
2007 free(mb_mapping
->tab_bits
);
2011 memset(mb_mapping
->tab_input_registers
, 0, nb_input_registers
* sizeof(uint16_t));
2017 modbus_mapping_t
*modbus_mapping_new(int nb_bits
,
2020 int nb_input_registers
)
2022 return modbus_mapping_new_start_address(
2023 0, nb_bits
, 0, nb_input_bits
, 0, nb_registers
, 0, nb_input_registers
);
2026 /* Frees the 4 arrays */
2027 void modbus_mapping_free(modbus_mapping_t
*mb_mapping
)
2029 if (mb_mapping
== NULL
) {
2033 free(mb_mapping
->tab_input_registers
);
2034 free(mb_mapping
->tab_registers
);
2035 free(mb_mapping
->tab_input_bits
);
2036 free(mb_mapping
->tab_bits
);
2040 #ifndef HAVE_STRLCPY
2042 * Function strlcpy was originally developed by
2043 * Todd C. Miller <Todd.Miller@courtesan.com> to simplify writing secure code.
2044 * See ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/strlcpy.3
2045 * for more information.
2047 * Thank you Ulrich Drepper... not!
2049 * Copy src to string dest of size dest_size. At most dest_size-1 characters
2050 * will be copied. Always NUL terminates (unless dest_size == 0). Returns
2051 * strlen(src); if retval >= dest_size, truncation occurred.
2053 size_t strlcpy(char *dest
, const char *src
, size_t dest_size
)
2055 register char *d
= dest
;
2056 register const char *s
= src
;
2057 register size_t n
= dest_size
;
2059 /* Copy as many bytes as will fit */
2060 if (n
!= 0 && --n
!= 0) {
2062 if ((*d
++ = *s
++) == 0)
2067 /* Not enough room in dest, add NUL and traverse rest of src */
2070 *d
= '\0'; /* NUL-terminate dest */
2075 return (s
- src
- 1); /* count does not include NUL */