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
;
1198 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1202 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1206 offset
= ctx
->backend
->header_length
+ 2;
1207 offset_end
= offset
+ rc
;
1208 for (i
= offset
; i
< offset_end
; i
++) {
1209 /* Shift reg hi_byte to temp */
1212 for (bit
= 0x01; (bit
& 0xff) && (pos
< nb
);) {
1213 dest
[pos
++] = (temp
& bit
) ? TRUE
: FALSE
;
1222 /* Reads the boolean status of bits and sets the array elements
1223 in the destination to TRUE or FALSE (single bits). */
1224 int modbus_read_bits(modbus_t
*ctx
, int addr
, int nb
, uint8_t *dest
)
1233 if (nb
> MODBUS_MAX_READ_BITS
) {
1236 "ERROR Too many bits requested (%d > %d)\n",
1238 MODBUS_MAX_READ_BITS
);
1244 rc
= read_io_status(ctx
, MODBUS_FC_READ_COILS
, addr
, nb
, dest
);
1252 /* Same as modbus_read_bits but reads the remote device input table */
1253 int modbus_read_input_bits(modbus_t
*ctx
, int addr
, int nb
, uint8_t *dest
)
1262 if (nb
> MODBUS_MAX_READ_BITS
) {
1265 "ERROR Too many discrete inputs requested (%d > %d)\n",
1267 MODBUS_MAX_READ_BITS
);
1273 rc
= read_io_status(ctx
, MODBUS_FC_READ_DISCRETE_INPUTS
, addr
, nb
, dest
);
1281 /* Reads the data from a remote device and put that data into an array */
1282 static int read_registers(modbus_t
*ctx
, int function
, int addr
, int nb
, uint16_t *dest
)
1286 uint8_t req
[_MIN_REQ_LENGTH
];
1287 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1289 if (nb
> MODBUS_MAX_READ_REGISTERS
) {
1292 "ERROR Too many registers requested (%d > %d)\n",
1294 MODBUS_MAX_READ_REGISTERS
);
1300 req_length
= ctx
->backend
->build_request_basis(ctx
, function
, addr
, nb
, req
);
1302 rc
= send_msg(ctx
, req
, req_length
);
1304 unsigned int offset
;
1307 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1311 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1315 offset
= ctx
->backend
->header_length
;
1317 for (i
= 0; i
< rc
; i
++) {
1318 /* shift reg hi_byte to temp OR with lo_byte */
1319 dest
[i
] = (rsp
[offset
+ 2 + (i
<< 1)] << 8) | rsp
[offset
+ 3 + (i
<< 1)];
1326 /* Reads the holding registers of remote device and put the data into an
1328 int modbus_read_registers(modbus_t
*ctx
, int addr
, int nb
, uint16_t *dest
)
1337 if (nb
> MODBUS_MAX_READ_REGISTERS
) {
1340 "ERROR Too many registers requested (%d > %d)\n",
1342 MODBUS_MAX_READ_REGISTERS
);
1348 status
= read_registers(ctx
, MODBUS_FC_READ_HOLDING_REGISTERS
, addr
, nb
, dest
);
1352 /* Reads the input registers of remote device and put the data into an array */
1353 int modbus_read_input_registers(modbus_t
*ctx
, int addr
, int nb
, uint16_t *dest
)
1362 if (nb
> MODBUS_MAX_READ_REGISTERS
) {
1365 "ERROR Too many input registers requested (%d > %d)\n",
1367 MODBUS_MAX_READ_REGISTERS
);
1373 status
= read_registers(ctx
, MODBUS_FC_READ_INPUT_REGISTERS
, addr
, nb
, dest
);
1378 /* Write a value to the specified register of the remote device.
1379 Used by write_bit and write_register */
1380 static int write_single(modbus_t
*ctx
, int function
, int addr
, const uint16_t value
)
1384 uint8_t req
[_MIN_REQ_LENGTH
];
1391 req_length
= ctx
->backend
->build_request_basis(ctx
, function
, addr
, (int) value
, req
);
1393 rc
= send_msg(ctx
, req
, req_length
);
1395 /* Used by write_bit and write_register */
1396 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1398 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1402 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1408 /* Turns ON or OFF a single bit of the remote device */
1409 int modbus_write_bit(modbus_t
*ctx
, int addr
, int status
)
1416 return write_single(ctx
, MODBUS_FC_WRITE_SINGLE_COIL
, addr
, status
? 0xFF00 : 0);
1419 /* Writes a value in one register of the remote device */
1420 int modbus_write_register(modbus_t
*ctx
, int addr
, const uint16_t value
)
1427 return write_single(ctx
, MODBUS_FC_WRITE_SINGLE_REGISTER
, addr
, value
);
1430 /* Write the bits of the array in the remote device */
1431 int modbus_write_bits(modbus_t
*ctx
, int addr
, int nb
, const uint8_t *src
)
1439 uint8_t req
[MAX_MESSAGE_LENGTH
];
1446 if (nb
> MODBUS_MAX_WRITE_BITS
) {
1449 "ERROR Writing too many bits (%d > %d)\n",
1451 MODBUS_MAX_WRITE_BITS
);
1457 req_length
= ctx
->backend
->build_request_basis(
1458 ctx
, MODBUS_FC_WRITE_MULTIPLE_COILS
, addr
, nb
, req
);
1459 byte_count
= (nb
/ 8) + ((nb
% 8) ? 1 : 0);
1460 req
[req_length
++] = byte_count
;
1462 for (i
= 0; i
< byte_count
; i
++) {
1466 req
[req_length
] = 0;
1468 while ((bit
& 0xFF) && (bit_check
++ < nb
)) {
1470 req
[req_length
] |= bit
;
1472 req
[req_length
] &= ~bit
;
1479 rc
= send_msg(ctx
, req
, req_length
);
1481 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1483 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1487 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1493 /* Write the values from the array to the registers of the remote device */
1494 int modbus_write_registers(modbus_t
*ctx
, int addr
, int nb
, const uint16_t *src
)
1500 uint8_t req
[MAX_MESSAGE_LENGTH
];
1507 if (nb
> MODBUS_MAX_WRITE_REGISTERS
) {
1510 "ERROR Trying to write to too many registers (%d > %d)\n",
1512 MODBUS_MAX_WRITE_REGISTERS
);
1518 req_length
= ctx
->backend
->build_request_basis(
1519 ctx
, MODBUS_FC_WRITE_MULTIPLE_REGISTERS
, addr
, nb
, req
);
1520 byte_count
= nb
* 2;
1521 req
[req_length
++] = byte_count
;
1523 for (i
= 0; i
< nb
; i
++) {
1524 req
[req_length
++] = src
[i
] >> 8;
1525 req
[req_length
++] = src
[i
] & 0x00FF;
1528 rc
= send_msg(ctx
, req
, req_length
);
1530 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1532 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1536 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1542 int modbus_mask_write_register(modbus_t
*ctx
,
1549 /* The request length can not exceed _MIN_REQ_LENGTH - 2 and 4 bytes to
1550 * store the masks. The ugly substraction is there to remove the 'nb' value
1551 * (2 bytes) which is not used. */
1552 uint8_t req
[_MIN_REQ_LENGTH
+ 2];
1554 req_length
= ctx
->backend
->build_request_basis(
1555 ctx
, MODBUS_FC_MASK_WRITE_REGISTER
, addr
, 0, req
);
1557 /* HACKISH, count is not used */
1560 req
[req_length
++] = and_mask
>> 8;
1561 req
[req_length
++] = and_mask
& 0x00ff;
1562 req
[req_length
++] = or_mask
>> 8;
1563 req
[req_length
++] = or_mask
& 0x00ff;
1565 rc
= send_msg(ctx
, req
, req_length
);
1567 /* Used by write_bit and write_register */
1568 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1570 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1574 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1580 /* Write multiple registers from src array to remote device and read multiple
1581 registers from remote device to dest array. */
1582 int modbus_write_and_read_registers(modbus_t
*ctx
,
1585 const uint16_t *src
,
1595 uint8_t req
[MAX_MESSAGE_LENGTH
];
1596 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1603 if (write_nb
> MODBUS_MAX_WR_WRITE_REGISTERS
) {
1606 "ERROR Too many registers to write (%d > %d)\n",
1608 MODBUS_MAX_WR_WRITE_REGISTERS
);
1614 if (read_nb
> MODBUS_MAX_WR_READ_REGISTERS
) {
1617 "ERROR Too many registers requested (%d > %d)\n",
1619 MODBUS_MAX_WR_READ_REGISTERS
);
1624 req_length
= ctx
->backend
->build_request_basis(
1625 ctx
, MODBUS_FC_WRITE_AND_READ_REGISTERS
, read_addr
, read_nb
, req
);
1627 req
[req_length
++] = write_addr
>> 8;
1628 req
[req_length
++] = write_addr
& 0x00ff;
1629 req
[req_length
++] = write_nb
>> 8;
1630 req
[req_length
++] = write_nb
& 0x00ff;
1631 byte_count
= write_nb
* 2;
1632 req
[req_length
++] = byte_count
;
1634 for (i
= 0; i
< write_nb
; i
++) {
1635 req
[req_length
++] = src
[i
] >> 8;
1636 req
[req_length
++] = src
[i
] & 0x00FF;
1639 rc
= send_msg(ctx
, req
, req_length
);
1641 unsigned int offset
;
1643 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1647 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1651 offset
= ctx
->backend
->header_length
;
1652 for (i
= 0; i
< rc
; i
++) {
1653 /* shift reg hi_byte to temp OR with lo_byte */
1654 dest
[i
] = (rsp
[offset
+ 2 + (i
<< 1)] << 8) | rsp
[offset
+ 3 + (i
<< 1)];
1661 /* Send a request to get the slave ID of the device (only available in serial
1663 int modbus_report_slave_id(modbus_t
*ctx
, int max_dest
, uint8_t *dest
)
1667 uint8_t req
[_MIN_REQ_LENGTH
];
1669 if (ctx
== NULL
|| max_dest
<= 0) {
1675 ctx
->backend
->build_request_basis(ctx
, MODBUS_FC_REPORT_SLAVE_ID
, 0, 0, req
);
1677 /* HACKISH, addr and count are not used */
1680 rc
= send_msg(ctx
, req
, req_length
);
1683 unsigned int offset
;
1684 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1686 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1690 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1694 offset
= ctx
->backend
->header_length
+ 2;
1696 /* Byte count, slave id, run indicator status and
1697 additional data. Truncate copy to max_dest. */
1698 for (i
= 0; i
< rc
&& i
< max_dest
; i
++) {
1699 dest
[i
] = rsp
[offset
+ i
];
1706 void _modbus_init_common(modbus_t
*ctx
)
1708 /* Slave and socket are initialized to -1 */
1713 ctx
->error_recovery
= MODBUS_ERROR_RECOVERY_NONE
;
1714 ctx
->quirks
= MODBUS_QUIRK_NONE
;
1716 ctx
->response_timeout
.tv_sec
= 0;
1717 ctx
->response_timeout
.tv_usec
= _RESPONSE_TIMEOUT
;
1719 ctx
->byte_timeout
.tv_sec
= 0;
1720 ctx
->byte_timeout
.tv_usec
= _BYTE_TIMEOUT
;
1722 ctx
->indication_timeout
.tv_sec
= 0;
1723 ctx
->indication_timeout
.tv_usec
= 0;
1726 /* Define the slave number */
1727 int modbus_set_slave(modbus_t
*ctx
, int slave
)
1734 return ctx
->backend
->set_slave(ctx
, slave
);
1737 int modbus_get_slave(modbus_t
*ctx
)
1747 int modbus_set_error_recovery(modbus_t
*ctx
, modbus_error_recovery_mode error_recovery
)
1754 /* The type of modbus_error_recovery_mode is unsigned enum */
1755 ctx
->error_recovery
= (uint8_t) error_recovery
;
1759 // FIXME Doesn't work under Windows RTU
1760 int modbus_set_socket(modbus_t
*ctx
, int s
)
1771 int modbus_get_socket(modbus_t
*ctx
)
1781 /* Get the timeout interval used to wait for a response */
1782 int modbus_get_response_timeout(modbus_t
*ctx
, uint32_t *to_sec
, uint32_t *to_usec
)
1789 *to_sec
= ctx
->response_timeout
.tv_sec
;
1790 *to_usec
= ctx
->response_timeout
.tv_usec
;
1794 int modbus_set_response_timeout(modbus_t
*ctx
, uint32_t to_sec
, uint32_t to_usec
)
1796 if (ctx
== NULL
|| (to_sec
== 0 && to_usec
== 0) || to_usec
> 999999) {
1801 ctx
->response_timeout
.tv_sec
= to_sec
;
1802 ctx
->response_timeout
.tv_usec
= to_usec
;
1806 /* Get the timeout interval between two consecutive bytes of a message */
1807 int modbus_get_byte_timeout(modbus_t
*ctx
, uint32_t *to_sec
, uint32_t *to_usec
)
1814 *to_sec
= ctx
->byte_timeout
.tv_sec
;
1815 *to_usec
= ctx
->byte_timeout
.tv_usec
;
1819 int modbus_set_byte_timeout(modbus_t
*ctx
, uint32_t to_sec
, uint32_t to_usec
)
1821 /* Byte timeout can be disabled when both values are zero */
1822 if (ctx
== NULL
|| to_usec
> 999999) {
1827 ctx
->byte_timeout
.tv_sec
= to_sec
;
1828 ctx
->byte_timeout
.tv_usec
= to_usec
;
1832 /* Get the timeout interval used by the server to wait for an indication from a client */
1833 int modbus_get_indication_timeout(modbus_t
*ctx
, uint32_t *to_sec
, uint32_t *to_usec
)
1840 *to_sec
= ctx
->indication_timeout
.tv_sec
;
1841 *to_usec
= ctx
->indication_timeout
.tv_usec
;
1845 int modbus_set_indication_timeout(modbus_t
*ctx
, uint32_t to_sec
, uint32_t to_usec
)
1847 /* Indication timeout can be disabled when both values are zero */
1848 if (ctx
== NULL
|| to_usec
> 999999) {
1853 ctx
->indication_timeout
.tv_sec
= to_sec
;
1854 ctx
->indication_timeout
.tv_usec
= to_usec
;
1858 int modbus_get_header_length(modbus_t
*ctx
)
1865 return ctx
->backend
->header_length
;
1868 int modbus_enable_quirks(modbus_t
*ctx
, unsigned int quirks_mask
)
1875 /* Enable quirks that have a true value at their index in the mask */
1876 ctx
->quirks
|= quirks_mask
;
1880 int modbus_disable_quirks(modbus_t
*ctx
, unsigned int quirks_mask
)
1887 /* Disable quirks that have a true value at ther index in the mask */
1888 ctx
->quirks
&= ~quirks_mask
;
1892 int modbus_connect(modbus_t
*ctx
)
1899 return ctx
->backend
->connect(ctx
);
1902 void modbus_close(modbus_t
*ctx
)
1907 ctx
->backend
->close(ctx
);
1910 void modbus_free(modbus_t
*ctx
)
1915 ctx
->backend
->free(ctx
);
1918 int modbus_set_debug(modbus_t
*ctx
, int flag
)
1929 /* Allocates 4 arrays to store bits, input bits, registers and inputs
1930 registers. The pointers are stored in modbus_mapping structure.
1932 The modbus_mapping_new_start_address() function shall return the new allocated
1933 structure if successful. Otherwise it shall return NULL and set errno to
1935 modbus_mapping_t
*modbus_mapping_new_start_address(unsigned int start_bits
,
1936 unsigned int nb_bits
,
1937 unsigned int start_input_bits
,
1938 unsigned int nb_input_bits
,
1939 unsigned int start_registers
,
1940 unsigned int nb_registers
,
1941 unsigned int start_input_registers
,
1942 unsigned int nb_input_registers
)
1944 modbus_mapping_t
*mb_mapping
;
1946 mb_mapping
= (modbus_mapping_t
*) malloc(sizeof(modbus_mapping_t
));
1947 if (mb_mapping
== NULL
) {
1952 mb_mapping
->nb_bits
= nb_bits
;
1953 mb_mapping
->start_bits
= start_bits
;
1955 mb_mapping
->tab_bits
= NULL
;
1957 /* Negative number raises a POSIX error */
1958 mb_mapping
->tab_bits
= (uint8_t *) malloc(nb_bits
* sizeof(uint8_t));
1959 if (mb_mapping
->tab_bits
== NULL
) {
1963 memset(mb_mapping
->tab_bits
, 0, nb_bits
* sizeof(uint8_t));
1967 mb_mapping
->nb_input_bits
= nb_input_bits
;
1968 mb_mapping
->start_input_bits
= start_input_bits
;
1969 if (nb_input_bits
== 0) {
1970 mb_mapping
->tab_input_bits
= NULL
;
1972 mb_mapping
->tab_input_bits
= (uint8_t *) malloc(nb_input_bits
* sizeof(uint8_t));
1973 if (mb_mapping
->tab_input_bits
== NULL
) {
1974 free(mb_mapping
->tab_bits
);
1978 memset(mb_mapping
->tab_input_bits
, 0, nb_input_bits
* sizeof(uint8_t));
1982 mb_mapping
->nb_registers
= nb_registers
;
1983 mb_mapping
->start_registers
= start_registers
;
1984 if (nb_registers
== 0) {
1985 mb_mapping
->tab_registers
= NULL
;
1987 mb_mapping
->tab_registers
= (uint16_t *) malloc(nb_registers
* sizeof(uint16_t));
1988 if (mb_mapping
->tab_registers
== NULL
) {
1989 free(mb_mapping
->tab_input_bits
);
1990 free(mb_mapping
->tab_bits
);
1994 memset(mb_mapping
->tab_registers
, 0, nb_registers
* sizeof(uint16_t));
1998 mb_mapping
->nb_input_registers
= nb_input_registers
;
1999 mb_mapping
->start_input_registers
= start_input_registers
;
2000 if (nb_input_registers
== 0) {
2001 mb_mapping
->tab_input_registers
= NULL
;
2003 mb_mapping
->tab_input_registers
=
2004 (uint16_t *) malloc(nb_input_registers
* sizeof(uint16_t));
2005 if (mb_mapping
->tab_input_registers
== NULL
) {
2006 free(mb_mapping
->tab_registers
);
2007 free(mb_mapping
->tab_input_bits
);
2008 free(mb_mapping
->tab_bits
);
2012 memset(mb_mapping
->tab_input_registers
, 0, nb_input_registers
* sizeof(uint16_t));
2018 modbus_mapping_t
*modbus_mapping_new(int nb_bits
,
2021 int nb_input_registers
)
2023 return modbus_mapping_new_start_address(
2024 0, nb_bits
, 0, nb_input_bits
, 0, nb_registers
, 0, nb_input_registers
);
2027 /* Frees the 4 arrays */
2028 void modbus_mapping_free(modbus_mapping_t
*mb_mapping
)
2030 if (mb_mapping
== NULL
) {
2034 free(mb_mapping
->tab_input_registers
);
2035 free(mb_mapping
->tab_registers
);
2036 free(mb_mapping
->tab_input_bits
);
2037 free(mb_mapping
->tab_bits
);
2041 #ifndef HAVE_STRLCPY
2043 * Function strlcpy was originally developed by
2044 * Todd C. Miller <Todd.Miller@courtesan.com> to simplify writing secure code.
2045 * See ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/strlcpy.3
2046 * for more information.
2048 * Thank you Ulrich Drepper... not!
2050 * Copy src to string dest of size dest_size. At most dest_size-1 characters
2051 * will be copied. Always NUL terminates (unless dest_size == 0). Returns
2052 * strlen(src); if retval >= dest_size, truncation occurred.
2054 size_t strlcpy(char *dest
, const char *src
, size_t dest_size
)
2056 register char *d
= dest
;
2057 register const char *s
= src
;
2058 register size_t n
= dest_size
;
2060 /* Copy as many bytes as will fit */
2061 if (n
!= 0 && --n
!= 0) {
2063 if ((*d
++ = *s
++) == 0)
2068 /* Not enough room in dest, add NUL and traverse rest of src */
2071 *d
= '\0'; /* NUL-terminate dest */
2076 return (s
- src
- 1); /* count does not include NUL */