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 including checksum */
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
,
224 const uint8_t *raw_req
,
229 uint8_t req
[MAX_MESSAGE_LENGTH
];
237 if (raw_req_length
< 2 || raw_req_length
> (MODBUS_MAX_PDU_LENGTH
+ 1)) {
238 /* The raw request must contain function and slave at least and
239 must not be longer than the maximum pdu length plus the slave
245 sft
.slave
= raw_req
[0];
246 sft
.function
= raw_req
[1];
247 /* The t_id is left to zero */
249 /* This response function only set the header so it's convenient here */
250 req_length
= ctx
->backend
->build_response_basis(&sft
, req
);
252 if (raw_req_length
> 2) {
253 /* Copy data after function code */
254 memcpy(req
+ req_length
, raw_req
+ 2, raw_req_length
- 2);
255 req_length
+= raw_req_length
- 2;
258 return send_msg(ctx
, req
, req_length
);
261 int modbus_send_raw_request(modbus_t
*ctx
, const uint8_t *raw_req
, int raw_req_length
)
263 return modbus_send_raw_request_tid(ctx
, raw_req
, raw_req_length
, 0);
267 * ---------- Request Indication ----------
268 * | Client | ---------------------->| Server |
269 * ---------- Confirmation Response ----------
272 /* Computes the length to read after the function received */
273 static uint8_t compute_meta_length_after_function(int function
, msg_type_t msg_type
)
277 if (msg_type
== MSG_INDICATION
) {
278 if (function
<= MODBUS_FC_WRITE_SINGLE_REGISTER
) {
280 } else if (function
== MODBUS_FC_WRITE_MULTIPLE_COILS
||
281 function
== MODBUS_FC_WRITE_MULTIPLE_REGISTERS
) {
283 } else if (function
== MODBUS_FC_MASK_WRITE_REGISTER
) {
285 } else if (function
== MODBUS_FC_WRITE_AND_READ_REGISTERS
) {
288 /* MODBUS_FC_READ_EXCEPTION_STATUS, MODBUS_FC_REPORT_SLAVE_ID */
292 /* MSG_CONFIRMATION */
294 case MODBUS_FC_WRITE_SINGLE_COIL
:
295 case MODBUS_FC_WRITE_SINGLE_REGISTER
:
296 case MODBUS_FC_WRITE_MULTIPLE_COILS
:
297 case MODBUS_FC_WRITE_MULTIPLE_REGISTERS
:
300 case MODBUS_FC_MASK_WRITE_REGISTER
:
311 /* Computes the length to read after the meta information (address, count, etc) */
313 compute_data_length_after_meta(modbus_t
*ctx
, uint8_t *msg
, msg_type_t msg_type
)
315 int function
= msg
[ctx
->backend
->header_length
];
318 if (msg_type
== MSG_INDICATION
) {
320 case MODBUS_FC_WRITE_MULTIPLE_COILS
:
321 case MODBUS_FC_WRITE_MULTIPLE_REGISTERS
:
322 length
= msg
[ctx
->backend
->header_length
+ 5];
324 case MODBUS_FC_WRITE_AND_READ_REGISTERS
:
325 length
= msg
[ctx
->backend
->header_length
+ 9];
331 /* MSG_CONFIRMATION */
332 if (function
<= MODBUS_FC_READ_INPUT_REGISTERS
||
333 function
== MODBUS_FC_REPORT_SLAVE_ID
||
334 function
== MODBUS_FC_WRITE_AND_READ_REGISTERS
) {
335 length
= msg
[ctx
->backend
->header_length
+ 1];
341 length
+= ctx
->backend
->checksum_length
;
346 /* Waits a response from a modbus server or a request from a modbus client.
347 This function blocks if there is no replies (3 timeouts).
349 The function shall return the number of received characters and the received
350 message in an array of uint8_t if successful. Otherwise it shall return -1
351 and errno is set to one of the values defined below:
355 - read() or recv() error codes
358 int _modbus_receive_msg(modbus_t
*ctx
, uint8_t *msg
, msg_type_t msg_type
)
363 struct timeval
*p_tv
;
364 unsigned int length_to_read
;
372 if (msg_type
== MSG_INDICATION
) {
373 printf("Waiting for an indication...\n");
375 printf("Waiting for a confirmation...\n");
379 if (!ctx
->backend
->is_connected(ctx
)) {
381 fprintf(stderr
, "ERROR The connection is not established.\n");
386 /* Add a file descriptor to the set */
388 FD_SET(ctx
->s
, &rset
);
390 /* We need to analyse the message step by step. At the first step, we want
391 * to reach the function code because all packets contain this
393 step
= _STEP_FUNCTION
;
394 length_to_read
= ctx
->backend
->header_length
+ 1;
396 if (msg_type
== MSG_INDICATION
) {
397 /* Wait for a message, we don't know when the message will be received */
398 if (ctx
->indication_timeout
.tv_sec
== 0 && ctx
->indication_timeout
.tv_usec
== 0) {
399 /* By default, the indication timeout isn't set */
402 /* Wait for an indication (name of a received request by a server, see schema)
404 tv
.tv_sec
= ctx
->indication_timeout
.tv_sec
;
405 tv
.tv_usec
= ctx
->indication_timeout
.tv_usec
;
409 tv
.tv_sec
= ctx
->response_timeout
.tv_sec
;
410 tv
.tv_usec
= ctx
->response_timeout
.tv_usec
;
414 while (length_to_read
!= 0) {
415 rc
= ctx
->backend
->select(ctx
, &rset
, p_tv
, length_to_read
);
417 _error_print(ctx
, "select");
418 if (ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_LINK
) {
420 wsa_err
= WSAGetLastError();
422 // no equivalent to ETIMEDOUT when select fails on Windows
423 if (wsa_err
== WSAENETDOWN
|| wsa_err
== WSAENOTSOCK
) {
428 int saved_errno
= errno
;
430 if (errno
== ETIMEDOUT
) {
431 _sleep_response_timeout(ctx
);
433 } else if (errno
== EBADF
) {
443 rc
= ctx
->backend
->recv(ctx
, msg
+ msg_length
, length_to_read
);
450 _error_print(ctx
, "read");
452 wsa_err
= WSAGetLastError();
453 if ((ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_LINK
) &&
454 (wsa_err
== WSAENOTCONN
|| wsa_err
== WSAENETRESET
||
455 wsa_err
== WSAENOTSOCK
|| wsa_err
== WSAESHUTDOWN
||
456 wsa_err
== WSAECONNABORTED
|| wsa_err
== WSAETIMEDOUT
||
457 wsa_err
== WSAECONNRESET
)) {
462 if ((ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_LINK
) &&
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
->get_response_tid(req
);
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",
908 /* This check is only done here to ensure using memcpy is safe. */
909 rsp_length
= compute_response_length_from_request(ctx
, (uint8_t *) req
);
910 if (rsp_length
!= req_length
) {
911 /* Bad use of modbus_reply */
912 rsp_length
= response_exception(
915 MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
,
918 "Invalid request length in modbus_reply to write bit (%d)\n",
923 /* Don't copy the CRC, if any, it will be computed later (even if identical to the
925 rsp_length
-= ctx
->backend
->checksum_length
;
927 int data
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
928 if (data
== 0xFF00 || data
== 0x0) {
929 /* Apply the change to mapping */
930 mb_mapping
->tab_bits
[mapping_address
] = data
? ON
: OFF
;
931 /* Prepare response */
932 memcpy(rsp
, req
, rsp_length
);
934 rsp_length
= response_exception(
937 MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
,
940 "Illegal data value 0x%0X in write_bit request at address %0X\n",
945 case MODBUS_FC_WRITE_SINGLE_REGISTER
: {
946 int mapping_address
= address
- mb_mapping
->start_registers
;
948 if (mapping_address
< 0 || mapping_address
>= mb_mapping
->nb_registers
) {
950 response_exception(ctx
,
952 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
,
955 "Illegal data address 0x%0X in write_register\n",
960 rsp_length
= compute_response_length_from_request(ctx
, (uint8_t *) req
);
961 if (rsp_length
!= req_length
) {
962 /* Bad use of modbus_reply */
963 rsp_length
= response_exception(
966 MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
,
969 "Invalid request length in modbus_reply to write register (%d)\n",
973 int data
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
975 mb_mapping
->tab_registers
[mapping_address
] = data
;
977 rsp_length
-= ctx
->backend
->checksum_length
;
978 memcpy(rsp
, req
, rsp_length
);
980 case MODBUS_FC_WRITE_MULTIPLE_COILS
: {
981 int nb
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
982 int nb_bits
= req
[offset
+ 5];
983 int mapping_address
= address
- mb_mapping
->start_bits
;
985 if (nb
< 1 || MODBUS_MAX_WRITE_BITS
< nb
|| nb_bits
* 8 < nb
) {
986 /* May be the indication has been truncated on reading because of
987 * invalid address (eg. nb is 0 but the request contains values to
988 * write) so it's necessary to flush. */
990 response_exception(ctx
,
992 MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
,
995 "Illegal number of values %d in write_bits (max %d)\n",
997 MODBUS_MAX_WRITE_BITS
);
998 } else if (mapping_address
< 0 || (mapping_address
+ nb
) > mb_mapping
->nb_bits
) {
999 rsp_length
= response_exception(ctx
,
1001 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
,
1004 "Illegal data address 0x%0X in write_bits\n",
1005 mapping_address
< 0 ? address
: address
+ nb
);
1007 /* 6 = byte count */
1008 modbus_set_bits_from_bytes(
1009 mb_mapping
->tab_bits
, mapping_address
, nb
, &req
[offset
+ 6]);
1011 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
1012 /* 4 to copy the bit address (2) and the quantity of bits */
1013 memcpy(rsp
+ rsp_length
, req
+ rsp_length
, 4);
1017 case MODBUS_FC_WRITE_MULTIPLE_REGISTERS
: {
1018 int nb
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
1019 int nb_bytes
= req
[offset
+ 5];
1020 int mapping_address
= address
- mb_mapping
->start_registers
;
1022 if (nb
< 1 || MODBUS_MAX_WRITE_REGISTERS
< nb
|| nb_bytes
!= nb
* 2) {
1023 rsp_length
= response_exception(
1026 MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
,
1029 "Illegal number of values %d in write_registers (max %d)\n",
1031 MODBUS_MAX_WRITE_REGISTERS
);
1032 } else if (mapping_address
< 0 ||
1033 (mapping_address
+ nb
) > mb_mapping
->nb_registers
) {
1035 response_exception(ctx
,
1037 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
,
1040 "Illegal data address 0x%0X in write_registers\n",
1041 mapping_address
< 0 ? address
: address
+ nb
);
1044 for (i
= mapping_address
, j
= 6; i
< mapping_address
+ nb
; i
++, j
+= 2) {
1045 /* 6 and 7 = first value */
1046 mb_mapping
->tab_registers
[i
] =
1047 (req
[offset
+ j
] << 8) + req
[offset
+ j
+ 1];
1050 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
1051 /* 4 to copy the address (2) and the no. of registers */
1052 memcpy(rsp
+ rsp_length
, req
+ rsp_length
, 4);
1056 case MODBUS_FC_REPORT_SLAVE_ID
: {
1060 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
1061 /* Skip byte count for now */
1062 byte_count_pos
= rsp_length
++;
1063 rsp
[rsp_length
++] = _REPORT_SLAVE_ID
;
1064 /* Run indicator status to ON */
1065 rsp
[rsp_length
++] = 0xFF;
1066 /* LMB + length of LIBMODBUS_VERSION_STRING */
1067 str_len
= 3 + strlen(LIBMODBUS_VERSION_STRING
);
1068 memcpy(rsp
+ rsp_length
, "LMB" LIBMODBUS_VERSION_STRING
, str_len
);
1069 rsp_length
+= str_len
;
1070 rsp
[byte_count_pos
] = rsp_length
- byte_count_pos
- 1;
1072 case MODBUS_FC_READ_EXCEPTION_STATUS
:
1074 fprintf(stderr
, "FIXME Not implemented\n");
1076 errno
= ENOPROTOOPT
;
1079 case MODBUS_FC_MASK_WRITE_REGISTER
: {
1080 int mapping_address
= address
- mb_mapping
->start_registers
;
1082 if (mapping_address
< 0 || mapping_address
>= mb_mapping
->nb_registers
) {
1084 response_exception(ctx
,
1086 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
,
1089 "Illegal data address 0x%0X in write_register\n",
1092 uint16_t data
= mb_mapping
->tab_registers
[mapping_address
];
1093 uint16_t and = (req
[offset
+ 3] << 8) + req
[offset
+ 4];
1094 uint16_t or = (req
[offset
+ 5] << 8) + req
[offset
+ 6];
1096 data
= (data
& and) | (or &(~and) );
1097 mb_mapping
->tab_registers
[mapping_address
] = data
;
1099 rsp_length
= compute_response_length_from_request(ctx
, (uint8_t *) req
);
1100 if (rsp_length
!= req_length
) {
1101 /* Bad use of modbus_reply */
1102 rsp_length
= response_exception(ctx
,
1104 MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
,
1107 "Invalid request length in modbus_reply "
1108 "to mask write register (%d)\n",
1113 rsp_length
-= ctx
->backend
->checksum_length
;
1114 memcpy(rsp
, req
, rsp_length
);
1117 case MODBUS_FC_WRITE_AND_READ_REGISTERS
: {
1118 int nb
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
1119 uint16_t address_write
= (req
[offset
+ 5] << 8) + req
[offset
+ 6];
1120 int nb_write
= (req
[offset
+ 7] << 8) + req
[offset
+ 8];
1121 int nb_write_bytes
= req
[offset
+ 9];
1122 int mapping_address
= address
- mb_mapping
->start_registers
;
1123 int mapping_address_write
= address_write
- mb_mapping
->start_registers
;
1125 if (nb_write
< 1 || MODBUS_MAX_WR_WRITE_REGISTERS
< nb_write
|| nb
< 1 ||
1126 MODBUS_MAX_WR_READ_REGISTERS
< nb
|| nb_write_bytes
!= nb_write
* 2) {
1127 rsp_length
= response_exception(
1130 MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
,
1133 "Illegal nb of values (W%d, R%d) in write_and_read_registers (max W%d, "
1137 MODBUS_MAX_WR_WRITE_REGISTERS
,
1138 MODBUS_MAX_WR_READ_REGISTERS
);
1139 } else if (mapping_address
< 0 ||
1140 (mapping_address
+ nb
) > mb_mapping
->nb_registers
||
1141 mapping_address_write
< 0 ||
1142 (mapping_address_write
+ nb_write
) > mb_mapping
->nb_registers
) {
1143 rsp_length
= response_exception(
1146 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
,
1149 "Illegal data read address 0x%0X or write address 0x%0X "
1150 "write_and_read_registers\n",
1151 mapping_address
< 0 ? address
: address
+ nb
,
1152 mapping_address_write
< 0 ? address_write
: address_write
+ nb_write
);
1155 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
1156 rsp
[rsp_length
++] = nb
<< 1;
1159 10 and 11 are the offset of the first values to write */
1160 for (i
= mapping_address_write
, j
= 10; i
< mapping_address_write
+ nb_write
;
1162 mb_mapping
->tab_registers
[i
] =
1163 (req
[offset
+ j
] << 8) + req
[offset
+ j
+ 1];
1166 /* and read the data for the response */
1167 for (i
= mapping_address
; i
< mapping_address
+ nb
; i
++) {
1168 rsp
[rsp_length
++] = mb_mapping
->tab_registers
[i
] >> 8;
1169 rsp
[rsp_length
++] = mb_mapping
->tab_registers
[i
] & 0xFF;
1175 rsp_length
= response_exception(ctx
,
1177 MODBUS_EXCEPTION_ILLEGAL_FUNCTION
,
1180 "Unknown Modbus function code: 0x%0X\n",
1185 /* Suppress any responses in RTU when the request was a broadcast, excepted when
1186 * quirk is enabled. */
1187 if (ctx
->backend
->backend_type
== _MODBUS_BACKEND_TYPE_RTU
&&
1188 slave
== MODBUS_BROADCAST_ADDRESS
&&
1189 !(ctx
->quirks
& MODBUS_QUIRK_REPLY_TO_BROADCAST
)) {
1192 return send_msg(ctx
, rsp
, rsp_length
);
1195 int modbus_reply_exception(modbus_t
*ctx
, const uint8_t *req
, unsigned int exception_code
)
1197 unsigned int offset
;
1200 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1209 offset
= ctx
->backend
->header_length
;
1210 slave
= req
[offset
- 1];
1211 function
= req
[offset
];
1214 sft
.function
= function
+ 0x80;
1215 sft
.t_id
= ctx
->backend
->get_response_tid(req
);
1216 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
1218 /* Positive exception code */
1219 if (exception_code
< MODBUS_EXCEPTION_MAX
) {
1220 rsp
[rsp_length
++] = exception_code
;
1221 return send_msg(ctx
, rsp
, rsp_length
);
1228 /* Reads IO status */
1229 static int read_io_status(modbus_t
*ctx
, int function
, int addr
, int nb
, uint8_t *dest
)
1234 uint8_t req
[_MIN_REQ_LENGTH
];
1235 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1237 req_length
= ctx
->backend
->build_request_basis(ctx
, function
, addr
, nb
, req
);
1239 rc
= send_msg(ctx
, req
, req_length
);
1243 unsigned int offset
;
1244 unsigned int offset_end
;
1247 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1251 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1255 offset
= ctx
->backend
->header_length
+ 2;
1256 offset_end
= offset
+ rc
;
1257 for (i
= offset
; i
< offset_end
; i
++) {
1258 /* Shift reg hi_byte to temp */
1261 for (bit
= 0x01; (bit
& 0xff) && (pos
< nb
);) {
1262 dest
[pos
++] = (temp
& bit
) ? TRUE
: FALSE
;
1271 /* Reads the boolean status of bits and sets the array elements
1272 in the destination to TRUE or FALSE (single bits). */
1273 int modbus_read_bits(modbus_t
*ctx
, int addr
, int nb
, uint8_t *dest
)
1282 if (nb
> MODBUS_MAX_READ_BITS
) {
1285 "ERROR Too many bits requested (%d > %d)\n",
1287 MODBUS_MAX_READ_BITS
);
1293 rc
= read_io_status(ctx
, MODBUS_FC_READ_COILS
, addr
, nb
, dest
);
1301 /* Same as modbus_read_bits but reads the remote device input table */
1302 int modbus_read_input_bits(modbus_t
*ctx
, int addr
, int nb
, uint8_t *dest
)
1311 if (nb
> MODBUS_MAX_READ_BITS
) {
1314 "ERROR Too many discrete inputs requested (%d > %d)\n",
1316 MODBUS_MAX_READ_BITS
);
1322 rc
= read_io_status(ctx
, MODBUS_FC_READ_DISCRETE_INPUTS
, addr
, nb
, dest
);
1330 /* Reads the data from a remote device and put that data into an array */
1331 static int read_registers(modbus_t
*ctx
, int function
, int addr
, int nb
, uint16_t *dest
)
1335 uint8_t req
[_MIN_REQ_LENGTH
];
1336 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1338 if (nb
> MODBUS_MAX_READ_REGISTERS
) {
1341 "ERROR Too many registers requested (%d > %d)\n",
1343 MODBUS_MAX_READ_REGISTERS
);
1349 req_length
= ctx
->backend
->build_request_basis(ctx
, function
, addr
, nb
, req
);
1351 rc
= send_msg(ctx
, req
, req_length
);
1353 unsigned int offset
;
1356 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1360 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1364 offset
= ctx
->backend
->header_length
;
1366 for (i
= 0; i
< rc
; i
++) {
1367 /* shift reg hi_byte to temp OR with lo_byte */
1368 dest
[i
] = (rsp
[offset
+ 2 + (i
<< 1)] << 8) | rsp
[offset
+ 3 + (i
<< 1)];
1375 /* Reads the holding registers of remote device and put the data into an
1377 int modbus_read_registers(modbus_t
*ctx
, int addr
, int nb
, uint16_t *dest
)
1386 if (nb
> MODBUS_MAX_READ_REGISTERS
) {
1389 "ERROR Too many registers requested (%d > %d)\n",
1391 MODBUS_MAX_READ_REGISTERS
);
1397 status
= read_registers(ctx
, MODBUS_FC_READ_HOLDING_REGISTERS
, addr
, nb
, dest
);
1401 /* Reads the input registers of remote device and put the data into an array */
1402 int modbus_read_input_registers(modbus_t
*ctx
, int addr
, int nb
, uint16_t *dest
)
1411 if (nb
> MODBUS_MAX_READ_REGISTERS
) {
1414 "ERROR Too many input registers requested (%d > %d)\n",
1416 MODBUS_MAX_READ_REGISTERS
);
1422 status
= read_registers(ctx
, MODBUS_FC_READ_INPUT_REGISTERS
, addr
, nb
, dest
);
1427 /* Write a value to the specified register of the remote device.
1428 Used by write_bit and write_register */
1429 static int write_single(modbus_t
*ctx
, int function
, int addr
, const uint16_t value
)
1433 uint8_t req
[_MIN_REQ_LENGTH
];
1440 req_length
= ctx
->backend
->build_request_basis(ctx
, function
, addr
, (int) value
, req
);
1442 rc
= send_msg(ctx
, req
, req_length
);
1444 /* Used by write_bit and write_register */
1445 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1447 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1451 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1457 /* Turns ON or OFF a single bit of the remote device */
1458 int modbus_write_bit(modbus_t
*ctx
, int addr
, int status
)
1465 return write_single(ctx
, MODBUS_FC_WRITE_SINGLE_COIL
, addr
, status
? 0xFF00 : 0);
1468 /* Writes a value in one register of the remote device */
1469 int modbus_write_register(modbus_t
*ctx
, int addr
, const uint16_t value
)
1476 return write_single(ctx
, MODBUS_FC_WRITE_SINGLE_REGISTER
, addr
, value
);
1479 /* Write the bits of the array in the remote device */
1480 int modbus_write_bits(modbus_t
*ctx
, int addr
, int nb
, const uint8_t *src
)
1488 uint8_t req
[MAX_MESSAGE_LENGTH
];
1495 if (nb
> MODBUS_MAX_WRITE_BITS
) {
1498 "ERROR Writing too many bits (%d > %d)\n",
1500 MODBUS_MAX_WRITE_BITS
);
1506 req_length
= ctx
->backend
->build_request_basis(
1507 ctx
, MODBUS_FC_WRITE_MULTIPLE_COILS
, addr
, nb
, req
);
1508 byte_count
= (nb
/ 8) + ((nb
% 8) ? 1 : 0);
1509 req
[req_length
++] = byte_count
;
1511 for (i
= 0; i
< byte_count
; i
++) {
1515 req
[req_length
] = 0;
1517 while ((bit
& 0xFF) && (bit_check
++ < nb
)) {
1519 req
[req_length
] |= bit
;
1521 req
[req_length
] &= ~bit
;
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 /* Write the values from the array to the registers of the remote device */
1543 int modbus_write_registers(modbus_t
*ctx
, int addr
, int nb
, const uint16_t *src
)
1549 uint8_t req
[MAX_MESSAGE_LENGTH
];
1556 if (nb
> MODBUS_MAX_WRITE_REGISTERS
) {
1559 "ERROR Trying to write to too many registers (%d > %d)\n",
1561 MODBUS_MAX_WRITE_REGISTERS
);
1567 req_length
= ctx
->backend
->build_request_basis(
1568 ctx
, MODBUS_FC_WRITE_MULTIPLE_REGISTERS
, addr
, nb
, req
);
1569 byte_count
= nb
* 2;
1570 req
[req_length
++] = byte_count
;
1572 for (i
= 0; i
< nb
; i
++) {
1573 req
[req_length
++] = src
[i
] >> 8;
1574 req
[req_length
++] = src
[i
] & 0x00FF;
1577 rc
= send_msg(ctx
, req
, req_length
);
1579 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1581 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1585 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1591 int modbus_mask_write_register(modbus_t
*ctx
,
1598 /* The request length can not exceed _MIN_REQ_LENGTH - 2 and 4 bytes to
1599 * store the masks. The ugly substraction is there to remove the 'nb' value
1600 * (2 bytes) which is not used. */
1601 uint8_t req
[_MIN_REQ_LENGTH
+ 2];
1603 req_length
= ctx
->backend
->build_request_basis(
1604 ctx
, MODBUS_FC_MASK_WRITE_REGISTER
, addr
, 0, req
);
1606 /* HACKISH, count is not used */
1609 req
[req_length
++] = and_mask
>> 8;
1610 req
[req_length
++] = and_mask
& 0x00ff;
1611 req
[req_length
++] = or_mask
>> 8;
1612 req
[req_length
++] = or_mask
& 0x00ff;
1614 rc
= send_msg(ctx
, req
, req_length
);
1616 /* Used by write_bit and write_register */
1617 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1619 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1623 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1629 /* Write multiple registers from src array to remote device and read multiple
1630 registers from remote device to dest array. */
1631 int modbus_write_and_read_registers(modbus_t
*ctx
,
1634 const uint16_t *src
,
1644 uint8_t req
[MAX_MESSAGE_LENGTH
];
1645 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1652 if (write_nb
> MODBUS_MAX_WR_WRITE_REGISTERS
) {
1655 "ERROR Too many registers to write (%d > %d)\n",
1657 MODBUS_MAX_WR_WRITE_REGISTERS
);
1663 if (read_nb
> MODBUS_MAX_WR_READ_REGISTERS
) {
1666 "ERROR Too many registers requested (%d > %d)\n",
1668 MODBUS_MAX_WR_READ_REGISTERS
);
1673 req_length
= ctx
->backend
->build_request_basis(
1674 ctx
, MODBUS_FC_WRITE_AND_READ_REGISTERS
, read_addr
, read_nb
, req
);
1676 req
[req_length
++] = write_addr
>> 8;
1677 req
[req_length
++] = write_addr
& 0x00ff;
1678 req
[req_length
++] = write_nb
>> 8;
1679 req
[req_length
++] = write_nb
& 0x00ff;
1680 byte_count
= write_nb
* 2;
1681 req
[req_length
++] = byte_count
;
1683 for (i
= 0; i
< write_nb
; i
++) {
1684 req
[req_length
++] = src
[i
] >> 8;
1685 req
[req_length
++] = src
[i
] & 0x00FF;
1688 rc
= send_msg(ctx
, req
, req_length
);
1690 unsigned int offset
;
1692 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1696 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1700 offset
= ctx
->backend
->header_length
;
1701 for (i
= 0; i
< rc
; i
++) {
1702 /* shift reg hi_byte to temp OR with lo_byte */
1703 dest
[i
] = (rsp
[offset
+ 2 + (i
<< 1)] << 8) | rsp
[offset
+ 3 + (i
<< 1)];
1710 /* Send a request to get the slave ID of the device (only available in serial
1712 int modbus_report_slave_id(modbus_t
*ctx
, int max_dest
, uint8_t *dest
)
1716 uint8_t req
[_MIN_REQ_LENGTH
];
1718 if (ctx
== NULL
|| max_dest
<= 0) {
1724 ctx
->backend
->build_request_basis(ctx
, MODBUS_FC_REPORT_SLAVE_ID
, 0, 0, req
);
1726 /* HACKISH, addr and count are not used */
1729 rc
= send_msg(ctx
, req
, req_length
);
1732 unsigned int offset
;
1733 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1735 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1739 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1743 offset
= ctx
->backend
->header_length
+ 2;
1745 /* Byte count, slave id, run indicator status and
1746 additional data. Truncate copy to max_dest. */
1747 for (i
= 0; i
< rc
&& i
< max_dest
; i
++) {
1748 dest
[i
] = rsp
[offset
+ i
];
1755 void _modbus_init_common(modbus_t
*ctx
)
1757 /* Slave and socket are initialized to -1 */
1762 ctx
->error_recovery
= MODBUS_ERROR_RECOVERY_NONE
;
1763 ctx
->quirks
= MODBUS_QUIRK_NONE
;
1765 ctx
->response_timeout
.tv_sec
= 0;
1766 ctx
->response_timeout
.tv_usec
= _RESPONSE_TIMEOUT
;
1768 ctx
->byte_timeout
.tv_sec
= 0;
1769 ctx
->byte_timeout
.tv_usec
= _BYTE_TIMEOUT
;
1771 ctx
->indication_timeout
.tv_sec
= 0;
1772 ctx
->indication_timeout
.tv_usec
= 0;
1775 /* Define the slave number */
1776 int modbus_set_slave(modbus_t
*ctx
, int slave
)
1783 return ctx
->backend
->set_slave(ctx
, slave
);
1786 int modbus_get_slave(modbus_t
*ctx
)
1796 int modbus_set_error_recovery(modbus_t
*ctx
, modbus_error_recovery_mode error_recovery
)
1803 /* The type of modbus_error_recovery_mode is unsigned enum */
1804 ctx
->error_recovery
= (uint8_t) error_recovery
;
1808 // FIXME Doesn't work under Windows RTU
1809 int modbus_set_socket(modbus_t
*ctx
, int s
)
1820 int modbus_get_socket(modbus_t
*ctx
)
1830 /* Get the timeout interval used to wait for a response */
1831 int modbus_get_response_timeout(modbus_t
*ctx
, uint32_t *to_sec
, uint32_t *to_usec
)
1838 *to_sec
= ctx
->response_timeout
.tv_sec
;
1839 *to_usec
= ctx
->response_timeout
.tv_usec
;
1843 int modbus_set_response_timeout(modbus_t
*ctx
, uint32_t to_sec
, uint32_t to_usec
)
1845 if (ctx
== NULL
|| (to_sec
== 0 && to_usec
== 0) || to_usec
> 999999) {
1850 ctx
->response_timeout
.tv_sec
= to_sec
;
1851 ctx
->response_timeout
.tv_usec
= to_usec
;
1855 /* Get the timeout interval between two consecutive bytes of a message */
1856 int modbus_get_byte_timeout(modbus_t
*ctx
, uint32_t *to_sec
, uint32_t *to_usec
)
1863 *to_sec
= ctx
->byte_timeout
.tv_sec
;
1864 *to_usec
= ctx
->byte_timeout
.tv_usec
;
1868 int modbus_set_byte_timeout(modbus_t
*ctx
, uint32_t to_sec
, uint32_t to_usec
)
1870 /* Byte timeout can be disabled when both values are zero */
1871 if (ctx
== NULL
|| to_usec
> 999999) {
1876 ctx
->byte_timeout
.tv_sec
= to_sec
;
1877 ctx
->byte_timeout
.tv_usec
= to_usec
;
1881 /* Get the timeout interval used by the server to wait for an indication from a client
1883 int modbus_get_indication_timeout(modbus_t
*ctx
, uint32_t *to_sec
, uint32_t *to_usec
)
1890 *to_sec
= ctx
->indication_timeout
.tv_sec
;
1891 *to_usec
= ctx
->indication_timeout
.tv_usec
;
1895 int modbus_set_indication_timeout(modbus_t
*ctx
, uint32_t to_sec
, uint32_t to_usec
)
1897 /* Indication timeout can be disabled when both values are zero */
1898 if (ctx
== NULL
|| to_usec
> 999999) {
1903 ctx
->indication_timeout
.tv_sec
= to_sec
;
1904 ctx
->indication_timeout
.tv_usec
= to_usec
;
1908 int modbus_get_header_length(modbus_t
*ctx
)
1915 return ctx
->backend
->header_length
;
1918 int modbus_enable_quirks(modbus_t
*ctx
, unsigned int quirks_mask
)
1925 /* Enable quirks that have a true value at their index in the mask */
1926 ctx
->quirks
|= quirks_mask
;
1930 int modbus_disable_quirks(modbus_t
*ctx
, unsigned int quirks_mask
)
1937 /* Disable quirks that have a true value at ther index in the mask */
1938 ctx
->quirks
&= ~quirks_mask
;
1942 int modbus_connect(modbus_t
*ctx
)
1949 return ctx
->backend
->connect(ctx
);
1952 void modbus_close(modbus_t
*ctx
)
1957 ctx
->backend
->close(ctx
);
1960 void modbus_free(modbus_t
*ctx
)
1965 ctx
->backend
->free(ctx
);
1968 int modbus_set_debug(modbus_t
*ctx
, int flag
)
1979 /* Allocates 4 arrays to store bits, input bits, registers and inputs
1980 registers. The pointers are stored in modbus_mapping structure.
1982 The modbus_mapping_new_start_address() function shall return the new allocated
1983 structure if successful. Otherwise it shall return NULL and set errno to
1985 modbus_mapping_t
*modbus_mapping_new_start_address(unsigned int start_bits
,
1986 unsigned int nb_bits
,
1987 unsigned int start_input_bits
,
1988 unsigned int nb_input_bits
,
1989 unsigned int start_registers
,
1990 unsigned int nb_registers
,
1991 unsigned int start_input_registers
,
1992 unsigned int nb_input_registers
)
1994 modbus_mapping_t
*mb_mapping
;
1996 mb_mapping
= (modbus_mapping_t
*) malloc(sizeof(modbus_mapping_t
));
1997 if (mb_mapping
== NULL
) {
2002 mb_mapping
->nb_bits
= nb_bits
;
2003 mb_mapping
->start_bits
= start_bits
;
2005 mb_mapping
->tab_bits
= NULL
;
2007 /* Negative number raises a POSIX error */
2008 mb_mapping
->tab_bits
= (uint8_t *) malloc(nb_bits
* sizeof(uint8_t));
2009 if (mb_mapping
->tab_bits
== NULL
) {
2013 memset(mb_mapping
->tab_bits
, 0, nb_bits
* sizeof(uint8_t));
2017 mb_mapping
->nb_input_bits
= nb_input_bits
;
2018 mb_mapping
->start_input_bits
= start_input_bits
;
2019 if (nb_input_bits
== 0) {
2020 mb_mapping
->tab_input_bits
= NULL
;
2022 mb_mapping
->tab_input_bits
= (uint8_t *) malloc(nb_input_bits
* sizeof(uint8_t));
2023 if (mb_mapping
->tab_input_bits
== NULL
) {
2024 free(mb_mapping
->tab_bits
);
2028 memset(mb_mapping
->tab_input_bits
, 0, nb_input_bits
* sizeof(uint8_t));
2032 mb_mapping
->nb_registers
= nb_registers
;
2033 mb_mapping
->start_registers
= start_registers
;
2034 if (nb_registers
== 0) {
2035 mb_mapping
->tab_registers
= NULL
;
2037 mb_mapping
->tab_registers
= (uint16_t *) malloc(nb_registers
* sizeof(uint16_t));
2038 if (mb_mapping
->tab_registers
== NULL
) {
2039 free(mb_mapping
->tab_input_bits
);
2040 free(mb_mapping
->tab_bits
);
2044 memset(mb_mapping
->tab_registers
, 0, nb_registers
* sizeof(uint16_t));
2048 mb_mapping
->nb_input_registers
= nb_input_registers
;
2049 mb_mapping
->start_input_registers
= start_input_registers
;
2050 if (nb_input_registers
== 0) {
2051 mb_mapping
->tab_input_registers
= NULL
;
2053 mb_mapping
->tab_input_registers
=
2054 (uint16_t *) malloc(nb_input_registers
* sizeof(uint16_t));
2055 if (mb_mapping
->tab_input_registers
== NULL
) {
2056 free(mb_mapping
->tab_registers
);
2057 free(mb_mapping
->tab_input_bits
);
2058 free(mb_mapping
->tab_bits
);
2062 memset(mb_mapping
->tab_input_registers
, 0, nb_input_registers
* sizeof(uint16_t));
2068 modbus_mapping_t
*modbus_mapping_new(int nb_bits
,
2071 int nb_input_registers
)
2073 return modbus_mapping_new_start_address(
2074 0, nb_bits
, 0, nb_input_bits
, 0, nb_registers
, 0, nb_input_registers
);
2077 /* Frees the 4 arrays */
2078 void modbus_mapping_free(modbus_mapping_t
*mb_mapping
)
2080 if (mb_mapping
== NULL
) {
2084 free(mb_mapping
->tab_input_registers
);
2085 free(mb_mapping
->tab_registers
);
2086 free(mb_mapping
->tab_input_bits
);
2087 free(mb_mapping
->tab_bits
);
2091 #ifndef HAVE_STRLCPY
2093 * Function strlcpy was originally developed by
2094 * Todd C. Miller <Todd.Miller@courtesan.com> to simplify writing secure code.
2095 * See ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/strlcpy.3
2096 * for more information.
2098 * Thank you Ulrich Drepper... not!
2100 * Copy src to string dest of size dest_size. At most dest_size-1 characters
2101 * will be copied. Always NUL terminates (unless dest_size == 0). Returns
2102 * strlen(src); if retval >= dest_size, truncation occurred.
2104 size_t strlcpy(char *dest
, const char *src
, size_t dest_size
)
2106 register char *d
= dest
;
2107 register const char *s
= src
;
2108 register size_t n
= dest_size
;
2110 /* Copy as many bytes as will fit */
2111 if (n
!= 0 && --n
!= 0) {
2113 if ((*d
++ = *s
++) == 0)
2118 /* Not enough room in dest, add NUL and traverse rest of src */
2121 *d
= '\0'; /* NUL-terminate dest */
2126 return (s
- src
- 1); /* count does not include NUL */