2 * Copyright © 2001-2011 Stéphane Raimbault <stephane.raimbault@gmail.com>
4 * SPDX-License-Identifier: LGPL-2.1+
6 * This library implements the Modbus protocol.
7 * http://libmodbus.org/
24 #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
) {
47 return "Illegal function";
49 return "Illegal data address";
51 return "Illegal data value";
53 return "Slave device or server failure";
57 return "Slave device or server is busy";
59 return "Negative acknowledge";
61 return "Memory parity error";
63 return "Gateway path unavailable";
65 return "Target device failed to respond";
69 return "Invalid data";
71 return "Invalid exception code";
73 return "Too many data";
75 return "Response not from requested slave";
77 return strerror(errnum
);
81 void _error_print(modbus_t
*ctx
, const char *context
)
84 fprintf(stderr
, "ERROR %s", modbus_strerror(errno
));
85 if (context
!= NULL
) {
86 fprintf(stderr
, ": %s\n", context
);
88 fprintf(stderr
, "\n");
93 static void _sleep_response_timeout(modbus_t
*ctx
)
95 /* Response timeout is always positive */
97 /* usleep doesn't exist on Windows */
98 Sleep((ctx
->response_timeout
.tv_sec
* 1000) +
99 (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);
142 case MODBUS_FC_WRITE_AND_READ_REGISTERS
:
143 case MODBUS_FC_READ_HOLDING_REGISTERS
:
144 case MODBUS_FC_READ_INPUT_REGISTERS
:
145 /* Header + 2 * nb values */
146 length
= 2 + 2 * (req
[offset
+ 3] << 8 | req
[offset
+ 4]);
148 case MODBUS_FC_READ_EXCEPTION_STATUS
:
151 case MODBUS_FC_REPORT_SLAVE_ID
:
152 /* The response is device specific (the header provides the
154 return MSG_LENGTH_UNDEFINED
;
155 case MODBUS_FC_MASK_WRITE_REGISTER
:
162 return offset
+ length
+ ctx
->backend
->checksum_length
;
165 /* Sends a request/response */
166 static int send_msg(modbus_t
*ctx
, uint8_t *msg
, int msg_length
)
171 msg_length
= ctx
->backend
->send_msg_pre(msg
, msg_length
);
174 for (i
= 0; i
< msg_length
; i
++)
175 printf("[%.2X]", msg
[i
]);
179 /* In recovery mode, the write command will be issued until to be
180 successful! Disabled by default. */
182 rc
= ctx
->backend
->send(ctx
, msg
, msg_length
);
184 _error_print(ctx
, NULL
);
185 if (ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_LINK
) {
186 int saved_errno
= errno
;
188 if ((errno
== EBADF
|| errno
== ECONNRESET
|| errno
== EPIPE
)) {
190 _sleep_response_timeout(ctx
);
193 _sleep_response_timeout(ctx
);
199 } while ((ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_LINK
) &&
202 if (rc
> 0 && rc
!= msg_length
) {
210 int modbus_send_raw_request(modbus_t
*ctx
, uint8_t *raw_req
, int raw_req_length
)
213 uint8_t req
[MAX_MESSAGE_LENGTH
];
221 if (raw_req_length
< 2 || raw_req_length
> (MODBUS_MAX_PDU_LENGTH
+ 1)) {
222 /* The raw request must contain function and slave at least and
223 must not be longer than the maximum pdu length plus the slave
229 sft
.slave
= raw_req
[0];
230 sft
.function
= raw_req
[1];
231 /* The t_id is left to zero */
233 /* This response function only set the header so it's convenient here */
234 req_length
= ctx
->backend
->build_response_basis(&sft
, req
);
236 if (raw_req_length
> 2) {
237 /* Copy data after function code */
238 memcpy(req
+ req_length
, raw_req
+ 2, raw_req_length
- 2);
239 req_length
+= raw_req_length
- 2;
242 return send_msg(ctx
, req
, req_length
);
246 * ---------- Request Indication ----------
247 * | Client | ---------------------->| Server |
248 * ---------- Confirmation Response ----------
251 /* Computes the length to read after the function received */
252 static uint8_t compute_meta_length_after_function(int function
,
257 if (msg_type
== MSG_INDICATION
) {
258 if (function
<= MODBUS_FC_WRITE_SINGLE_REGISTER
) {
260 } else if (function
== MODBUS_FC_WRITE_MULTIPLE_COILS
||
261 function
== MODBUS_FC_WRITE_MULTIPLE_REGISTERS
) {
263 } else if (function
== MODBUS_FC_MASK_WRITE_REGISTER
) {
265 } else if (function
== MODBUS_FC_WRITE_AND_READ_REGISTERS
) {
268 /* MODBUS_FC_READ_EXCEPTION_STATUS, MODBUS_FC_REPORT_SLAVE_ID */
272 /* MSG_CONFIRMATION */
274 case MODBUS_FC_WRITE_SINGLE_COIL
:
275 case MODBUS_FC_WRITE_SINGLE_REGISTER
:
276 case MODBUS_FC_WRITE_MULTIPLE_COILS
:
277 case MODBUS_FC_WRITE_MULTIPLE_REGISTERS
:
280 case MODBUS_FC_MASK_WRITE_REGISTER
:
291 /* Computes the length to read after the meta information (address, count, etc) */
292 static int compute_data_length_after_meta(modbus_t
*ctx
, uint8_t *msg
,
295 int function
= msg
[ctx
->backend
->header_length
];
298 if (msg_type
== MSG_INDICATION
) {
300 case MODBUS_FC_WRITE_MULTIPLE_COILS
:
301 case MODBUS_FC_WRITE_MULTIPLE_REGISTERS
:
302 length
= msg
[ctx
->backend
->header_length
+ 5];
304 case MODBUS_FC_WRITE_AND_READ_REGISTERS
:
305 length
= msg
[ctx
->backend
->header_length
+ 9];
311 /* MSG_CONFIRMATION */
312 if (function
<= MODBUS_FC_READ_INPUT_REGISTERS
||
313 function
== MODBUS_FC_REPORT_SLAVE_ID
||
314 function
== MODBUS_FC_WRITE_AND_READ_REGISTERS
) {
315 length
= msg
[ctx
->backend
->header_length
+ 1];
321 length
+= ctx
->backend
->checksum_length
;
327 /* Waits a response from a modbus server or a request from a modbus client.
328 This function blocks if there is no replies (3 timeouts).
330 The function shall return the number of received characters and the received
331 message in an array of uint8_t if successful. Otherwise it shall return -1
332 and errno is set to one of the values defined below:
337 - read() or recv() error codes
340 int _modbus_receive_msg(modbus_t
*ctx
, uint8_t *msg
, msg_type_t msg_type
)
345 struct timeval
*p_tv
;
351 if (msg_type
== MSG_INDICATION
) {
352 printf("Waiting for a indication...\n");
354 printf("Waiting for a confirmation...\n");
358 /* Add a file descriptor to the set */
360 FD_SET(ctx
->s
, &rset
);
362 /* We need to analyse the message step by step. At the first step, we want
363 * to reach the function code because all packets contain this
365 step
= _STEP_FUNCTION
;
366 length_to_read
= ctx
->backend
->header_length
+ 1;
368 if (msg_type
== MSG_INDICATION
) {
369 /* Wait for a message, we don't know when the message will be
373 tv
.tv_sec
= ctx
->response_timeout
.tv_sec
;
374 tv
.tv_usec
= ctx
->response_timeout
.tv_usec
;
378 while (length_to_read
!= 0) {
379 rc
= ctx
->backend
->select(ctx
, &rset
, p_tv
, length_to_read
);
381 _error_print(ctx
, "select");
382 if (ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_LINK
) {
383 int saved_errno
= errno
;
385 if (errno
== ETIMEDOUT
) {
386 _sleep_response_timeout(ctx
);
388 } else if (errno
== EBADF
) {
397 rc
= ctx
->backend
->recv(ctx
, msg
+ msg_length
, length_to_read
);
404 _error_print(ctx
, "read");
405 if ((ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_LINK
) &&
406 (errno
== ECONNRESET
|| errno
== ECONNREFUSED
||
408 int saved_errno
= errno
;
411 /* Could be removed by previous calls */
417 /* Display the hex code of each character received */
420 for (i
=0; i
< rc
; i
++)
421 printf("<%.2X>", msg
[msg_length
+ i
]);
424 /* Sums bytes received */
426 /* Computes remaining bytes */
427 length_to_read
-= rc
;
429 if (length_to_read
== 0) {
432 /* Function code position */
433 length_to_read
= compute_meta_length_after_function(
434 msg
[ctx
->backend
->header_length
],
436 if (length_to_read
!= 0) {
439 } /* else switches straight to the next step */
441 length_to_read
= compute_data_length_after_meta(
443 if ((msg_length
+ length_to_read
) > (int)ctx
->backend
->max_adu_length
) {
445 _error_print(ctx
, "too many data");
455 if (length_to_read
> 0 &&
456 (ctx
->byte_timeout
.tv_sec
> 0 || ctx
->byte_timeout
.tv_usec
> 0)) {
457 /* If there is no character in the buffer, the allowed timeout
458 interval between two consecutive bytes is defined by
460 tv
.tv_sec
= ctx
->byte_timeout
.tv_sec
;
461 tv
.tv_usec
= ctx
->byte_timeout
.tv_usec
;
464 /* else timeout isn't set again, the full response must be read before
465 expiration of response timeout (for CONFIRMATION only) */
471 return ctx
->backend
->check_integrity(ctx
, msg
, msg_length
);
474 /* Receive the request from a modbus master */
475 int modbus_receive(modbus_t
*ctx
, uint8_t *req
)
482 return ctx
->backend
->receive(ctx
, req
);
485 /* Receives the confirmation.
487 The function shall store the read response in rsp and return the number of
488 values (bits or words). Otherwise, its shall return -1 and errno is set.
490 The function doesn't check the confirmation is the expected response to the
493 int modbus_receive_confirmation(modbus_t
*ctx
, uint8_t *rsp
)
500 return _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
503 static int check_confirmation(modbus_t
*ctx
, uint8_t *req
,
504 uint8_t *rsp
, int rsp_length
)
507 int rsp_length_computed
;
508 const int offset
= ctx
->backend
->header_length
;
509 const int function
= rsp
[offset
];
511 if (ctx
->backend
->pre_check_confirmation
) {
512 rc
= ctx
->backend
->pre_check_confirmation(ctx
, req
, rsp
, rsp_length
);
514 if (ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_PROTOCOL
) {
515 _sleep_response_timeout(ctx
);
522 rsp_length_computed
= compute_response_length_from_request(ctx
, req
);
525 if (function
>= 0x80) {
526 if (rsp_length
== (offset
+ 2 + (int)ctx
->backend
->checksum_length
) &&
527 req
[offset
] == (rsp
[offset
] - 0x80)) {
528 /* Valid exception code received */
530 int exception_code
= rsp
[offset
+ 1];
531 if (exception_code
< MODBUS_EXCEPTION_MAX
) {
532 errno
= MODBUS_ENOBASE
+ exception_code
;
536 _error_print(ctx
, NULL
);
540 _error_print(ctx
, NULL
);
546 if ((rsp_length
== rsp_length_computed
||
547 rsp_length_computed
== MSG_LENGTH_UNDEFINED
) &&
552 /* Check function code */
553 if (function
!= req
[offset
]) {
556 "Received function not corresponding to the request (0x%X != 0x%X)\n",
557 function
, req
[offset
]);
559 if (ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_PROTOCOL
) {
560 _sleep_response_timeout(ctx
);
567 /* Check the number of values is corresponding to the request */
569 case MODBUS_FC_READ_COILS
:
570 case MODBUS_FC_READ_DISCRETE_INPUTS
:
571 /* Read functions, 8 values in a byte (nb
572 * of values in the request and byte count in
574 req_nb_value
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
575 req_nb_value
= (req_nb_value
/ 8) + ((req_nb_value
% 8) ? 1 : 0);
576 rsp_nb_value
= rsp
[offset
+ 1];
578 case MODBUS_FC_WRITE_AND_READ_REGISTERS
:
579 case MODBUS_FC_READ_HOLDING_REGISTERS
:
580 case MODBUS_FC_READ_INPUT_REGISTERS
:
581 /* Read functions 1 value = 2 bytes */
582 req_nb_value
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
583 rsp_nb_value
= (rsp
[offset
+ 1] / 2);
585 case MODBUS_FC_WRITE_MULTIPLE_COILS
:
586 case MODBUS_FC_WRITE_MULTIPLE_REGISTERS
:
587 /* N Write functions */
588 req_nb_value
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
589 rsp_nb_value
= (rsp
[offset
+ 3] << 8) | rsp
[offset
+ 4];
591 case MODBUS_FC_REPORT_SLAVE_ID
:
592 /* Report slave ID (bytes received) */
593 req_nb_value
= rsp_nb_value
= rsp
[offset
+ 1];
596 /* 1 Write functions & others */
597 req_nb_value
= rsp_nb_value
= 1;
600 if (req_nb_value
== rsp_nb_value
) {
605 "Quantity not corresponding to the request (%d != %d)\n",
606 rsp_nb_value
, req_nb_value
);
609 if (ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_PROTOCOL
) {
610 _sleep_response_timeout(ctx
);
620 "Message length not corresponding to the computed length (%d != %d)\n",
621 rsp_length
, rsp_length_computed
);
623 if (ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_PROTOCOL
) {
624 _sleep_response_timeout(ctx
);
634 static int response_io_status(uint8_t *tab_io_status
,
636 uint8_t *rsp
, int offset
)
639 /* Instead of byte (not allowed in Win32) */
643 for (i
= address
; i
< address
+ nb
; i
++) {
644 one_byte
|= tab_io_status
[i
] << shift
;
647 rsp
[offset
++] = one_byte
;
648 one_byte
= shift
= 0;
655 rsp
[offset
++] = one_byte
;
660 /* Build the exception response */
661 static int response_exception(modbus_t
*ctx
, sft_t
*sft
,
662 int exception_code
, uint8_t *rsp
,
663 unsigned int to_flush
,
664 const char* template, ...)
668 /* Print debug message */
672 va_start(ap
, template);
673 vfprintf(stderr
, template, ap
);
677 /* Flush if required */
679 _sleep_response_timeout(ctx
);
683 /* Build exception response */
684 sft
->function
= sft
->function
+ 0x80;
685 rsp_length
= ctx
->backend
->build_response_basis(sft
, rsp
);
686 rsp
[rsp_length
++] = exception_code
;
691 /* Send a response to the received request.
692 Analyses the request and constructs a response.
694 If an error occurs, this function construct the response
697 int modbus_reply(modbus_t
*ctx
, const uint8_t *req
,
698 int req_length
, modbus_mapping_t
*mb_mapping
)
704 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
713 offset
= ctx
->backend
->header_length
;
714 slave
= req
[offset
- 1];
715 function
= req
[offset
];
716 address
= (req
[offset
+ 1] << 8) + req
[offset
+ 2];
719 sft
.function
= function
;
720 sft
.t_id
= ctx
->backend
->prepare_response_tid(req
, &req_length
);
722 /* Data are flushed on illegal number of values errors. */
724 case MODBUS_FC_READ_COILS
: {
725 int nb
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
726 /* The mapping can be shifted to reduce memory consumption and it
727 doesn't always start at address zero. */
728 int mapping_address
= address
- mb_mapping
->start_bits
;
730 if (nb
< 1 || MODBUS_MAX_READ_BITS
< nb
) {
731 rsp_length
= response_exception(
732 ctx
, &sft
, MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
, rsp
, TRUE
,
733 "Illegal nb of values %d in read_bits (max %d)\n",
734 nb
, MODBUS_MAX_READ_BITS
);
735 } else if (mapping_address
< 0 ||
736 (mapping_address
+ nb
) > mb_mapping
->nb_bits
) {
737 rsp_length
= response_exception(
739 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
, rsp
, FALSE
,
740 "Illegal data address 0x%0X in read_bits\n",
741 mapping_address
< 0 ? address
: address
+ nb
);
743 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
744 rsp
[rsp_length
++] = (nb
/ 8) + ((nb
% 8) ? 1 : 0);
745 rsp_length
= response_io_status(mb_mapping
->tab_bits
,
751 case MODBUS_FC_READ_DISCRETE_INPUTS
: {
752 /* Similar to coil status (but too many arguments to use a
754 int nb
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
755 int mapping_address
= address
- mb_mapping
->start_input_bits
;
757 if (nb
< 1 || MODBUS_MAX_READ_BITS
< nb
) {
758 rsp_length
= response_exception(
759 ctx
, &sft
, MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
, rsp
, TRUE
,
760 "Illegal nb of values %d in read_input_bits (max %d)\n",
761 nb
, MODBUS_MAX_READ_BITS
);
762 } else if (mapping_address
< 0 ||
763 (mapping_address
+ nb
) > mb_mapping
->nb_input_bits
) {
764 rsp_length
= response_exception(
766 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
, rsp
, FALSE
,
767 "Illegal data address 0x%0X in read_input_bits\n",
768 mapping_address
< 0 ? address
: address
+ nb
);
770 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
771 rsp
[rsp_length
++] = (nb
/ 8) + ((nb
% 8) ? 1 : 0);
772 rsp_length
= response_io_status(mb_mapping
->tab_input_bits
,
778 case MODBUS_FC_READ_HOLDING_REGISTERS
: {
779 int nb
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
780 int mapping_address
= address
- mb_mapping
->start_registers
;
782 if (nb
< 1 || MODBUS_MAX_READ_REGISTERS
< nb
) {
783 rsp_length
= response_exception(
784 ctx
, &sft
, MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
, rsp
, TRUE
,
785 "Illegal nb of values %d in read_holding_registers (max %d)\n",
786 nb
, MODBUS_MAX_READ_REGISTERS
);
787 } else if (mapping_address
< 0 ||
788 (mapping_address
+ nb
) > mb_mapping
->nb_registers
) {
789 rsp_length
= response_exception(
790 ctx
, &sft
, MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
, rsp
, FALSE
,
791 "Illegal data address 0x%0X in read_registers\n",
792 mapping_address
< 0 ? address
: address
+ nb
);
796 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
797 rsp
[rsp_length
++] = nb
<< 1;
798 for (i
= mapping_address
; i
< mapping_address
+ nb
; i
++) {
799 rsp
[rsp_length
++] = mb_mapping
->tab_registers
[i
] >> 8;
800 rsp
[rsp_length
++] = mb_mapping
->tab_registers
[i
] & 0xFF;
805 case MODBUS_FC_READ_INPUT_REGISTERS
: {
806 /* Similar to holding registers (but too many arguments to use a
808 int nb
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
809 int mapping_address
= address
- mb_mapping
->start_input_registers
;
811 if (nb
< 1 || MODBUS_MAX_READ_REGISTERS
< nb
) {
812 rsp_length
= response_exception(
813 ctx
, &sft
, MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
, rsp
, TRUE
,
814 "Illegal number of values %d in read_input_registers (max %d)\n",
815 nb
, MODBUS_MAX_READ_REGISTERS
);
816 } else if (mapping_address
< 0 ||
817 (mapping_address
+ nb
) > mb_mapping
->nb_input_registers
) {
818 rsp_length
= response_exception(
819 ctx
, &sft
, MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
, rsp
, FALSE
,
820 "Illegal data address 0x%0X in read_input_registers\n",
821 mapping_address
< 0 ? address
: address
+ nb
);
825 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
826 rsp
[rsp_length
++] = nb
<< 1;
827 for (i
= mapping_address
; i
< mapping_address
+ nb
; i
++) {
828 rsp
[rsp_length
++] = mb_mapping
->tab_input_registers
[i
] >> 8;
829 rsp
[rsp_length
++] = mb_mapping
->tab_input_registers
[i
] & 0xFF;
834 case MODBUS_FC_WRITE_SINGLE_COIL
: {
835 int mapping_address
= address
- mb_mapping
->start_bits
;
837 if (mapping_address
< 0 || mapping_address
>= mb_mapping
->nb_bits
) {
838 rsp_length
= response_exception(
839 ctx
, &sft
, MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
, rsp
, FALSE
,
840 "Illegal data address 0x%0X in write_bit\n",
843 int data
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
845 if (data
== 0xFF00 || data
== 0x0) {
846 mb_mapping
->tab_bits
[mapping_address
] = data
? ON
: OFF
;
847 memcpy(rsp
, req
, req_length
);
848 rsp_length
= req_length
;
850 rsp_length
= response_exception(
852 MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
, rsp
, FALSE
,
853 "Illegal data value 0x%0X in write_bit request at address %0X\n",
859 case MODBUS_FC_WRITE_SINGLE_REGISTER
: {
860 int mapping_address
= address
- mb_mapping
->start_registers
;
862 if (mapping_address
< 0 || mapping_address
>= mb_mapping
->nb_registers
) {
863 rsp_length
= response_exception(
865 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
, rsp
, FALSE
,
866 "Illegal data address 0x%0X in write_register\n",
869 int data
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
871 mb_mapping
->tab_registers
[mapping_address
] = data
;
872 memcpy(rsp
, req
, req_length
);
873 rsp_length
= req_length
;
877 case MODBUS_FC_WRITE_MULTIPLE_COILS
: {
878 int nb
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
879 int mapping_address
= address
- mb_mapping
->start_bits
;
881 if (nb
< 1 || MODBUS_MAX_WRITE_BITS
< nb
) {
882 /* May be the indication has been truncated on reading because of
883 * invalid address (eg. nb is 0 but the request contains values to
884 * write) so it's necessary to flush. */
885 rsp_length
= response_exception(
886 ctx
, &sft
, MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
, rsp
, TRUE
,
887 "Illegal number of values %d in write_bits (max %d)\n",
888 nb
, MODBUS_MAX_WRITE_BITS
);
889 } else if (mapping_address
< 0 ||
890 (mapping_address
+ nb
) > mb_mapping
->nb_bits
) {
891 rsp_length
= response_exception(
893 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
, rsp
, FALSE
,
894 "Illegal data address 0x%0X in write_bits\n",
895 mapping_address
< 0 ? address
: address
+ nb
);
898 modbus_set_bits_from_bytes(mb_mapping
->tab_bits
, mapping_address
, nb
,
901 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
902 /* 4 to copy the bit address (2) and the quantity of bits */
903 memcpy(rsp
+ rsp_length
, req
+ rsp_length
, 4);
908 case MODBUS_FC_WRITE_MULTIPLE_REGISTERS
: {
909 int nb
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
910 int mapping_address
= address
- mb_mapping
->start_registers
;
912 if (nb
< 1 || MODBUS_MAX_WRITE_REGISTERS
< nb
) {
913 rsp_length
= response_exception(
914 ctx
, &sft
, MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
, rsp
, TRUE
,
915 "Illegal number of values %d in write_registers (max %d)\n",
916 nb
, MODBUS_MAX_WRITE_REGISTERS
);
917 } else if (mapping_address
< 0 ||
918 (mapping_address
+ nb
) > mb_mapping
->nb_registers
) {
919 rsp_length
= response_exception(
920 ctx
, &sft
, MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
, rsp
, FALSE
,
921 "Illegal data address 0x%0X in write_registers\n",
922 mapping_address
< 0 ? address
: address
+ nb
);
925 for (i
= mapping_address
, j
= 6; i
< mapping_address
+ nb
; i
++, j
+= 2) {
926 /* 6 and 7 = first value */
927 mb_mapping
->tab_registers
[i
] =
928 (req
[offset
+ j
] << 8) + req
[offset
+ j
+ 1];
931 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
932 /* 4 to copy the address (2) and the no. of registers */
933 memcpy(rsp
+ rsp_length
, req
+ rsp_length
, 4);
938 case MODBUS_FC_REPORT_SLAVE_ID
: {
942 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
943 /* Skip byte count for now */
944 byte_count_pos
= rsp_length
++;
945 rsp
[rsp_length
++] = _REPORT_SLAVE_ID
;
946 /* Run indicator status to ON */
947 rsp
[rsp_length
++] = 0xFF;
948 /* LMB + length of LIBMODBUS_VERSION_STRING */
949 str_len
= 3 + strlen(LIBMODBUS_VERSION_STRING
);
950 memcpy(rsp
+ rsp_length
, "LMB" LIBMODBUS_VERSION_STRING
, str_len
);
951 rsp_length
+= str_len
;
952 rsp
[byte_count_pos
] = rsp_length
- byte_count_pos
- 1;
955 case MODBUS_FC_READ_EXCEPTION_STATUS
:
957 fprintf(stderr
, "FIXME Not implemented\n");
962 case MODBUS_FC_MASK_WRITE_REGISTER
: {
963 int mapping_address
= address
- mb_mapping
->start_registers
;
965 if (mapping_address
< 0 || mapping_address
>= mb_mapping
->nb_registers
) {
966 rsp_length
= response_exception(
967 ctx
, &sft
, MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
, rsp
, FALSE
,
968 "Illegal data address 0x%0X in write_register\n",
971 uint16_t data
= mb_mapping
->tab_registers
[mapping_address
];
972 uint16_t and = (req
[offset
+ 3] << 8) + req
[offset
+ 4];
973 uint16_t or = (req
[offset
+ 5] << 8) + req
[offset
+ 6];
975 data
= (data
& and) | (or & (~and));
976 mb_mapping
->tab_registers
[mapping_address
] = data
;
977 memcpy(rsp
, req
, req_length
);
978 rsp_length
= req_length
;
982 case MODBUS_FC_WRITE_AND_READ_REGISTERS
: {
983 int nb
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
984 uint16_t address_write
= (req
[offset
+ 5] << 8) + req
[offset
+ 6];
985 int nb_write
= (req
[offset
+ 7] << 8) + req
[offset
+ 8];
986 int nb_write_bytes
= req
[offset
+ 9];
987 int mapping_address
= address
- mb_mapping
->start_registers
;
988 int mapping_address_write
= address_write
- mb_mapping
->start_registers
;
990 if (nb_write
< 1 || MODBUS_MAX_WR_WRITE_REGISTERS
< nb_write
||
991 nb
< 1 || MODBUS_MAX_WR_READ_REGISTERS
< nb
||
992 nb_write_bytes
!= nb_write
* 2) {
993 rsp_length
= response_exception(
994 ctx
, &sft
, MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
, rsp
, TRUE
,
995 "Illegal nb of values (W%d, R%d) in write_and_read_registers (max W%d, R%d)\n",
996 nb_write
, nb
, MODBUS_MAX_WR_WRITE_REGISTERS
, MODBUS_MAX_WR_READ_REGISTERS
);
997 } else if (mapping_address
< 0 ||
998 (mapping_address
+ nb
) > mb_mapping
->nb_registers
||
999 mapping_address
< 0 ||
1000 (mapping_address_write
+ nb_write
) > mb_mapping
->nb_registers
) {
1001 rsp_length
= response_exception(
1002 ctx
, &sft
, MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
, rsp
, FALSE
,
1003 "Illegal data read address 0x%0X or write address 0x%0X write_and_read_registers\n",
1004 mapping_address
< 0 ? address
: address
+ nb
,
1005 mapping_address_write
< 0 ? address_write
: address_write
+ nb_write
);
1008 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
1009 rsp
[rsp_length
++] = nb
<< 1;
1012 10 and 11 are the offset of the first values to write */
1013 for (i
= mapping_address_write
, j
= 10;
1014 i
< mapping_address_write
+ nb_write
; i
++, j
+= 2) {
1015 mb_mapping
->tab_registers
[i
] =
1016 (req
[offset
+ j
] << 8) + req
[offset
+ j
+ 1];
1019 /* and read the data for the response */
1020 for (i
= mapping_address
; i
< mapping_address
+ nb
; i
++) {
1021 rsp
[rsp_length
++] = mb_mapping
->tab_registers
[i
] >> 8;
1022 rsp
[rsp_length
++] = mb_mapping
->tab_registers
[i
] & 0xFF;
1029 rsp_length
= response_exception(
1030 ctx
, &sft
, MODBUS_EXCEPTION_ILLEGAL_FUNCTION
, rsp
, FALSE
, "");
1034 /* Suppress any responses when the request was a broadcast */
1035 return (slave
== MODBUS_BROADCAST_ADDRESS
) ? 0 : send_msg(ctx
, rsp
, rsp_length
);
1038 int modbus_reply_exception(modbus_t
*ctx
, const uint8_t *req
,
1039 unsigned int exception_code
)
1044 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1046 int dummy_length
= 99;
1054 offset
= ctx
->backend
->header_length
;
1055 slave
= req
[offset
- 1];
1056 function
= req
[offset
];
1059 sft
.function
= function
+ 0x80;;
1060 sft
.t_id
= ctx
->backend
->prepare_response_tid(req
, &dummy_length
);
1061 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
1063 /* Positive exception code */
1064 if (exception_code
< MODBUS_EXCEPTION_MAX
) {
1065 rsp
[rsp_length
++] = exception_code
;
1066 return send_msg(ctx
, rsp
, rsp_length
);
1073 /* Reads IO status */
1074 static int read_io_status(modbus_t
*ctx
, int function
,
1075 int addr
, int nb
, uint8_t *dest
)
1080 uint8_t req
[_MIN_REQ_LENGTH
];
1081 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1083 req_length
= ctx
->backend
->build_request_basis(ctx
, function
, addr
, nb
, req
);
1085 rc
= send_msg(ctx
, req
, req_length
);
1092 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1096 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1100 offset
= ctx
->backend
->header_length
+ 2;
1101 offset_end
= offset
+ rc
;
1102 for (i
= offset
; i
< offset_end
; i
++) {
1103 /* Shift reg hi_byte to temp */
1106 for (bit
= 0x01; (bit
& 0xff) && (pos
< nb
);) {
1107 dest
[pos
++] = (temp
& bit
) ? TRUE
: FALSE
;
1117 /* Reads the boolean status of bits and sets the array elements
1118 in the destination to TRUE or FALSE (single bits). */
1119 int modbus_read_bits(modbus_t
*ctx
, int addr
, int nb
, uint8_t *dest
)
1128 if (nb
> MODBUS_MAX_READ_BITS
) {
1131 "ERROR Too many bits requested (%d > %d)\n",
1132 nb
, MODBUS_MAX_READ_BITS
);
1138 rc
= read_io_status(ctx
, MODBUS_FC_READ_COILS
, addr
, nb
, dest
);
1147 /* Same as modbus_read_bits but reads the remote device input table */
1148 int modbus_read_input_bits(modbus_t
*ctx
, int addr
, int nb
, uint8_t *dest
)
1157 if (nb
> MODBUS_MAX_READ_BITS
) {
1160 "ERROR Too many discrete inputs requested (%d > %d)\n",
1161 nb
, MODBUS_MAX_READ_BITS
);
1167 rc
= read_io_status(ctx
, MODBUS_FC_READ_DISCRETE_INPUTS
, addr
, nb
, dest
);
1175 /* Reads the data from a remove device and put that data into an array */
1176 static int read_registers(modbus_t
*ctx
, int function
, int addr
, int nb
,
1181 uint8_t req
[_MIN_REQ_LENGTH
];
1182 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1184 if (nb
> MODBUS_MAX_READ_REGISTERS
) {
1187 "ERROR Too many registers requested (%d > %d)\n",
1188 nb
, MODBUS_MAX_READ_REGISTERS
);
1194 req_length
= ctx
->backend
->build_request_basis(ctx
, function
, addr
, nb
, req
);
1196 rc
= send_msg(ctx
, req
, req_length
);
1201 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1205 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1209 offset
= ctx
->backend
->header_length
;
1211 for (i
= 0; i
< rc
; i
++) {
1212 /* shift reg hi_byte to temp OR with lo_byte */
1213 dest
[i
] = (rsp
[offset
+ 2 + (i
<< 1)] << 8) |
1214 rsp
[offset
+ 3 + (i
<< 1)];
1221 /* Reads the holding registers of remote device and put the data into an
1223 int modbus_read_registers(modbus_t
*ctx
, int addr
, int nb
, uint16_t *dest
)
1232 if (nb
> MODBUS_MAX_READ_REGISTERS
) {
1235 "ERROR Too many registers requested (%d > %d)\n",
1236 nb
, MODBUS_MAX_READ_REGISTERS
);
1242 status
= read_registers(ctx
, MODBUS_FC_READ_HOLDING_REGISTERS
,
1247 /* Reads the input registers of remote device and put the data into an array */
1248 int modbus_read_input_registers(modbus_t
*ctx
, int addr
, int nb
,
1258 if (nb
> MODBUS_MAX_READ_REGISTERS
) {
1260 "ERROR Too many input registers requested (%d > %d)\n",
1261 nb
, MODBUS_MAX_READ_REGISTERS
);
1266 status
= read_registers(ctx
, MODBUS_FC_READ_INPUT_REGISTERS
,
1272 /* Write a value to the specified register of the remote device.
1273 Used by write_bit and write_register */
1274 static int write_single(modbus_t
*ctx
, int function
, int addr
, int value
)
1278 uint8_t req
[_MIN_REQ_LENGTH
];
1285 req_length
= ctx
->backend
->build_request_basis(ctx
, function
, addr
, value
, req
);
1287 rc
= send_msg(ctx
, req
, req_length
);
1289 /* Used by write_bit and write_register */
1290 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1292 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1296 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1302 /* Turns ON or OFF a single bit of the remote device */
1303 int modbus_write_bit(modbus_t
*ctx
, int addr
, int status
)
1310 return write_single(ctx
, MODBUS_FC_WRITE_SINGLE_COIL
, addr
,
1311 status
? 0xFF00 : 0);
1314 /* Writes a value in one register of the remote device */
1315 int modbus_write_register(modbus_t
*ctx
, int addr
, int value
)
1322 return write_single(ctx
, MODBUS_FC_WRITE_SINGLE_REGISTER
, addr
, value
);
1325 /* Write the bits of the array in the remote device */
1326 int modbus_write_bits(modbus_t
*ctx
, int addr
, int nb
, const uint8_t *src
)
1334 uint8_t req
[MAX_MESSAGE_LENGTH
];
1341 if (nb
> MODBUS_MAX_WRITE_BITS
) {
1343 fprintf(stderr
, "ERROR Writing too many bits (%d > %d)\n",
1344 nb
, MODBUS_MAX_WRITE_BITS
);
1350 req_length
= ctx
->backend
->build_request_basis(ctx
,
1351 MODBUS_FC_WRITE_MULTIPLE_COILS
,
1353 byte_count
= (nb
/ 8) + ((nb
% 8) ? 1 : 0);
1354 req
[req_length
++] = byte_count
;
1356 for (i
= 0; i
< byte_count
; i
++) {
1360 req
[req_length
] = 0;
1362 while ((bit
& 0xFF) && (bit_check
++ < nb
)) {
1364 req
[req_length
] |= bit
;
1366 req
[req_length
] &=~ bit
;
1373 rc
= send_msg(ctx
, req
, req_length
);
1375 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1377 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1381 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1388 /* Write the values from the array to the registers of the remote device */
1389 int modbus_write_registers(modbus_t
*ctx
, int addr
, int nb
, const uint16_t *src
)
1395 uint8_t req
[MAX_MESSAGE_LENGTH
];
1402 if (nb
> MODBUS_MAX_WRITE_REGISTERS
) {
1405 "ERROR Trying to write to too many registers (%d > %d)\n",
1406 nb
, MODBUS_MAX_WRITE_REGISTERS
);
1412 req_length
= ctx
->backend
->build_request_basis(ctx
,
1413 MODBUS_FC_WRITE_MULTIPLE_REGISTERS
,
1415 byte_count
= nb
* 2;
1416 req
[req_length
++] = byte_count
;
1418 for (i
= 0; i
< nb
; i
++) {
1419 req
[req_length
++] = src
[i
] >> 8;
1420 req
[req_length
++] = src
[i
] & 0x00FF;
1423 rc
= send_msg(ctx
, req
, req_length
);
1425 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1427 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1431 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1437 int modbus_mask_write_register(modbus_t
*ctx
, int addr
, uint16_t and_mask
, uint16_t or_mask
)
1441 /* The request length can not exceed _MIN_REQ_LENGTH - 2 and 4 bytes to
1442 * store the masks. The ugly substraction is there to remove the 'nb' value
1443 * (2 bytes) which is not used. */
1444 uint8_t req
[_MIN_REQ_LENGTH
+ 2];
1446 req_length
= ctx
->backend
->build_request_basis(ctx
,
1447 MODBUS_FC_MASK_WRITE_REGISTER
,
1450 /* HACKISH, count is not used */
1453 req
[req_length
++] = and_mask
>> 8;
1454 req
[req_length
++] = and_mask
& 0x00ff;
1455 req
[req_length
++] = or_mask
>> 8;
1456 req
[req_length
++] = or_mask
& 0x00ff;
1458 rc
= send_msg(ctx
, req
, req_length
);
1460 /* Used by write_bit and write_register */
1461 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1463 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1467 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1473 /* Write multiple registers from src array to remote device and read multiple
1474 registers from remote device to dest array. */
1475 int modbus_write_and_read_registers(modbus_t
*ctx
,
1476 int write_addr
, int write_nb
,
1477 const uint16_t *src
,
1478 int read_addr
, int read_nb
,
1486 uint8_t req
[MAX_MESSAGE_LENGTH
];
1487 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1494 if (write_nb
> MODBUS_MAX_WR_WRITE_REGISTERS
) {
1497 "ERROR Too many registers to write (%d > %d)\n",
1498 write_nb
, MODBUS_MAX_WR_WRITE_REGISTERS
);
1504 if (read_nb
> MODBUS_MAX_WR_READ_REGISTERS
) {
1507 "ERROR Too many registers requested (%d > %d)\n",
1508 read_nb
, MODBUS_MAX_WR_READ_REGISTERS
);
1513 req_length
= ctx
->backend
->build_request_basis(ctx
,
1514 MODBUS_FC_WRITE_AND_READ_REGISTERS
,
1515 read_addr
, read_nb
, req
);
1517 req
[req_length
++] = write_addr
>> 8;
1518 req
[req_length
++] = write_addr
& 0x00ff;
1519 req
[req_length
++] = write_nb
>> 8;
1520 req
[req_length
++] = write_nb
& 0x00ff;
1521 byte_count
= write_nb
* 2;
1522 req
[req_length
++] = byte_count
;
1524 for (i
= 0; i
< write_nb
; i
++) {
1525 req
[req_length
++] = src
[i
] >> 8;
1526 req
[req_length
++] = src
[i
] & 0x00FF;
1529 rc
= send_msg(ctx
, req
, req_length
);
1533 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1537 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1541 offset
= ctx
->backend
->header_length
;
1542 for (i
= 0; i
< rc
; i
++) {
1543 /* shift reg hi_byte to temp OR with lo_byte */
1544 dest
[i
] = (rsp
[offset
+ 2 + (i
<< 1)] << 8) |
1545 rsp
[offset
+ 3 + (i
<< 1)];
1552 /* Send a request to get the slave ID of the device (only available in serial
1554 int modbus_report_slave_id(modbus_t
*ctx
, int max_dest
, uint8_t *dest
)
1558 uint8_t req
[_MIN_REQ_LENGTH
];
1560 if (ctx
== NULL
|| max_dest
<= 0) {
1565 req_length
= ctx
->backend
->build_request_basis(ctx
, MODBUS_FC_REPORT_SLAVE_ID
,
1568 /* HACKISH, addr and count are not used */
1571 rc
= send_msg(ctx
, req
, req_length
);
1575 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1577 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1581 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1585 offset
= ctx
->backend
->header_length
+ 2;
1587 /* Byte count, slave id, run indicator status and
1588 additional data. Truncate copy to max_dest. */
1589 for (i
=0; i
< rc
&& i
< max_dest
; i
++) {
1590 dest
[i
] = rsp
[offset
+ i
];
1597 void _modbus_init_common(modbus_t
*ctx
)
1599 /* Slave and socket are initialized to -1 */
1604 ctx
->error_recovery
= MODBUS_ERROR_RECOVERY_NONE
;
1606 ctx
->response_timeout
.tv_sec
= 0;
1607 ctx
->response_timeout
.tv_usec
= _RESPONSE_TIMEOUT
;
1609 ctx
->byte_timeout
.tv_sec
= 0;
1610 ctx
->byte_timeout
.tv_usec
= _BYTE_TIMEOUT
;
1613 /* Define the slave number */
1614 int modbus_set_slave(modbus_t
*ctx
, int slave
)
1621 return ctx
->backend
->set_slave(ctx
, slave
);
1624 int modbus_set_error_recovery(modbus_t
*ctx
,
1625 modbus_error_recovery_mode error_recovery
)
1632 /* The type of modbus_error_recovery_mode is unsigned enum */
1633 ctx
->error_recovery
= (uint8_t) error_recovery
;
1637 int modbus_set_socket(modbus_t
*ctx
, int s
)
1648 int modbus_get_socket(modbus_t
*ctx
)
1658 /* Get the timeout interval used to wait for a response */
1659 int modbus_get_response_timeout(modbus_t
*ctx
, uint32_t *to_sec
, uint32_t *to_usec
)
1666 *to_sec
= ctx
->response_timeout
.tv_sec
;
1667 *to_usec
= ctx
->response_timeout
.tv_usec
;
1671 int modbus_set_response_timeout(modbus_t
*ctx
, uint32_t to_sec
, uint32_t to_usec
)
1674 (to_sec
== 0 && to_usec
== 0) || to_usec
> 999999) {
1679 ctx
->response_timeout
.tv_sec
= to_sec
;
1680 ctx
->response_timeout
.tv_usec
= to_usec
;
1684 /* Get the timeout interval between two consecutive bytes of a message */
1685 int modbus_get_byte_timeout(modbus_t
*ctx
, uint32_t *to_sec
, uint32_t *to_usec
)
1692 *to_sec
= ctx
->byte_timeout
.tv_sec
;
1693 *to_usec
= ctx
->byte_timeout
.tv_usec
;
1697 int modbus_set_byte_timeout(modbus_t
*ctx
, uint32_t to_sec
, uint32_t to_usec
)
1699 /* Byte timeout can be disabled when both values are zero */
1700 if (ctx
== NULL
|| to_usec
> 999999) {
1705 ctx
->byte_timeout
.tv_sec
= to_sec
;
1706 ctx
->byte_timeout
.tv_usec
= to_usec
;
1710 int modbus_get_header_length(modbus_t
*ctx
)
1717 return ctx
->backend
->header_length
;
1720 int modbus_connect(modbus_t
*ctx
)
1727 return ctx
->backend
->connect(ctx
);
1730 void modbus_close(modbus_t
*ctx
)
1735 ctx
->backend
->close(ctx
);
1738 void modbus_free(modbus_t
*ctx
)
1743 ctx
->backend
->free(ctx
);
1746 int modbus_set_debug(modbus_t
*ctx
, int flag
)
1757 /* Allocates 4 arrays to store bits, input bits, registers and inputs
1758 registers. The pointers are stored in modbus_mapping structure.
1760 The modbus_mapping_new_ranges() function shall return the new allocated
1761 structure if successful. Otherwise it shall return NULL and set errno to
1763 modbus_mapping_t
* modbus_mapping_new_start_address(
1764 unsigned int start_bits
, unsigned int nb_bits
,
1765 unsigned int start_input_bits
, unsigned int nb_input_bits
,
1766 unsigned int start_registers
, unsigned int nb_registers
,
1767 unsigned int start_input_registers
, unsigned int nb_input_registers
)
1769 modbus_mapping_t
*mb_mapping
;
1771 mb_mapping
= (modbus_mapping_t
*)malloc(sizeof(modbus_mapping_t
));
1772 if (mb_mapping
== NULL
) {
1777 mb_mapping
->nb_bits
= nb_bits
;
1778 mb_mapping
->start_bits
= start_bits
;
1780 mb_mapping
->tab_bits
= NULL
;
1782 /* Negative number raises a POSIX error */
1783 mb_mapping
->tab_bits
=
1784 (uint8_t *) malloc(nb_bits
* sizeof(uint8_t));
1785 if (mb_mapping
->tab_bits
== NULL
) {
1789 memset(mb_mapping
->tab_bits
, 0, nb_bits
* sizeof(uint8_t));
1793 mb_mapping
->nb_input_bits
= nb_input_bits
;
1794 mb_mapping
->start_input_bits
= start_input_bits
;
1795 if (nb_input_bits
== 0) {
1796 mb_mapping
->tab_input_bits
= NULL
;
1798 mb_mapping
->tab_input_bits
=
1799 (uint8_t *) malloc(nb_input_bits
* sizeof(uint8_t));
1800 if (mb_mapping
->tab_input_bits
== NULL
) {
1801 free(mb_mapping
->tab_bits
);
1805 memset(mb_mapping
->tab_input_bits
, 0, nb_input_bits
* sizeof(uint8_t));
1809 mb_mapping
->nb_registers
= nb_registers
;
1810 mb_mapping
->start_registers
= start_registers
;
1811 if (nb_registers
== 0) {
1812 mb_mapping
->tab_registers
= NULL
;
1814 mb_mapping
->tab_registers
=
1815 (uint16_t *) malloc(nb_registers
* sizeof(uint16_t));
1816 if (mb_mapping
->tab_registers
== NULL
) {
1817 free(mb_mapping
->tab_input_bits
);
1818 free(mb_mapping
->tab_bits
);
1822 memset(mb_mapping
->tab_registers
, 0, nb_registers
* sizeof(uint16_t));
1826 mb_mapping
->nb_input_registers
= nb_input_registers
;
1827 mb_mapping
->start_input_registers
= start_input_registers
;
1828 if (nb_input_registers
== 0) {
1829 mb_mapping
->tab_input_registers
= NULL
;
1831 mb_mapping
->tab_input_registers
=
1832 (uint16_t *) malloc(nb_input_registers
* sizeof(uint16_t));
1833 if (mb_mapping
->tab_input_registers
== NULL
) {
1834 free(mb_mapping
->tab_registers
);
1835 free(mb_mapping
->tab_input_bits
);
1836 free(mb_mapping
->tab_bits
);
1840 memset(mb_mapping
->tab_input_registers
, 0,
1841 nb_input_registers
* sizeof(uint16_t));
1847 modbus_mapping_t
* modbus_mapping_new(int nb_bits
, int nb_input_bits
,
1848 int nb_registers
, int nb_input_registers
)
1850 return modbus_mapping_new_start_address(
1851 0, nb_bits
, 0, nb_input_bits
, 0, nb_registers
, 0, nb_input_registers
);
1854 /* Frees the 4 arrays */
1855 void modbus_mapping_free(modbus_mapping_t
*mb_mapping
)
1857 if (mb_mapping
== NULL
) {
1861 free(mb_mapping
->tab_input_registers
);
1862 free(mb_mapping
->tab_registers
);
1863 free(mb_mapping
->tab_input_bits
);
1864 free(mb_mapping
->tab_bits
);
1868 #ifndef HAVE_STRLCPY
1870 * Function strlcpy was originally developed by
1871 * Todd C. Miller <Todd.Miller@courtesan.com> to simplify writing secure code.
1872 * See ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/strlcpy.3
1873 * for more information.
1875 * Thank you Ulrich Drepper... not!
1877 * Copy src to string dest of size dest_size. At most dest_size-1 characters
1878 * will be copied. Always NUL terminates (unless dest_size == 0). Returns
1879 * strlen(src); if retval >= dest_size, truncation occurred.
1881 size_t strlcpy(char *dest
, const char *src
, size_t dest_size
)
1883 register char *d
= dest
;
1884 register const char *s
= src
;
1885 register size_t n
= dest_size
;
1887 /* Copy as many bytes as will fit */
1888 if (n
!= 0 && --n
!= 0) {
1890 if ((*d
++ = *s
++) == 0)
1895 /* Not enough room in dest, add NUL and traverse rest of src */
1898 *d
= '\0'; /* NUL-terminate dest */
1903 return (s
- src
- 1); /* count does not include NUL */