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/
23 #include "modbus-private.h"
26 #define MSG_LENGTH_UNDEFINED -1
28 /* Exported version */
29 const unsigned int libmodbus_version_major
= LIBMODBUS_VERSION_MAJOR
;
30 const unsigned int libmodbus_version_minor
= LIBMODBUS_VERSION_MINOR
;
31 const unsigned int libmodbus_version_micro
= LIBMODBUS_VERSION_MICRO
;
33 /* Max between RTU and TCP max adu length (so TCP) */
34 #define MAX_MESSAGE_LENGTH 260
36 /* 3 steps are used to parse the query */
43 const char *modbus_strerror(int errnum
) {
46 return "Illegal function";
48 return "Illegal data address";
50 return "Illegal data value";
52 return "Slave device or server failure";
56 return "Slave device or server is busy";
58 return "Negative acknowledge";
60 return "Memory parity error";
62 return "Gateway path unavailable";
64 return "Target device failed to respond";
68 return "Invalid data";
70 return "Invalid exception code";
72 return "Too many data";
74 return "Response not from requested slave";
76 return strerror(errnum
);
80 void _error_print(modbus_t
*ctx
, const char *context
)
83 fprintf(stderr
, "ERROR %s", modbus_strerror(errno
));
84 if (context
!= NULL
) {
85 fprintf(stderr
, ": %s\n", context
);
87 fprintf(stderr
, "\n");
92 static void _sleep_response_timeout(modbus_t
*ctx
)
94 /* Response timeout is always positive */
96 /* usleep doesn't exist on Windows */
97 Sleep((ctx
->response_timeout
.tv_sec
* 1000) +
98 (ctx
->response_timeout
.tv_usec
/ 1000));
100 /* usleep source code */
101 struct timespec request
, remaining
;
102 request
.tv_sec
= ctx
->response_timeout
.tv_sec
;
103 request
.tv_nsec
= ((long int)ctx
->response_timeout
.tv_usec
) * 1000;
104 while (nanosleep(&request
, &remaining
) == -1 && errno
== EINTR
) {
110 int modbus_flush(modbus_t
*ctx
)
119 rc
= ctx
->backend
->flush(ctx
);
120 if (rc
!= -1 && ctx
->debug
) {
121 /* Not all backends are able to return the number of bytes flushed */
122 printf("Bytes flushed (%d)\n", rc
);
127 /* Computes the length of the expected response */
128 static unsigned int compute_response_length_from_request(modbus_t
*ctx
, uint8_t *req
)
131 const int offset
= ctx
->backend
->header_length
;
133 switch (req
[offset
]) {
134 case MODBUS_FC_READ_COILS
:
135 case MODBUS_FC_READ_DISCRETE_INPUTS
: {
136 /* Header + nb values (code from write_bits) */
137 int nb
= (req
[offset
+ 3] << 8) | req
[offset
+ 4];
138 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
) {
185 int saved_errno
= errno
;
187 if ((errno
== EBADF
|| errno
== ECONNRESET
|| errno
== EPIPE
)) {
189 _sleep_response_timeout(ctx
);
192 _sleep_response_timeout(ctx
);
198 } while ((ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_LINK
) &&
201 if (rc
> 0 && rc
!= msg_length
) {
209 int modbus_send_raw_request(modbus_t
*ctx
, uint8_t *raw_req
, int raw_req_length
)
212 uint8_t req
[MAX_MESSAGE_LENGTH
];
220 if (raw_req_length
< 2 || raw_req_length
> (MODBUS_MAX_PDU_LENGTH
+ 1)) {
221 /* The raw request must contain function and slave at least and
222 must not be longer than the maximum pdu length plus the slave
228 sft
.slave
= raw_req
[0];
229 sft
.function
= raw_req
[1];
230 /* The t_id is left to zero */
232 /* This response function only set the header so it's convenient here */
233 req_length
= ctx
->backend
->build_response_basis(&sft
, req
);
235 if (raw_req_length
> 2) {
236 /* Copy data after function code */
237 memcpy(req
+ req_length
, raw_req
+ 2, raw_req_length
- 2);
238 req_length
+= raw_req_length
- 2;
241 return send_msg(ctx
, req
, req_length
);
245 * ---------- Request Indication ----------
246 * | Client | ---------------------->| Server |
247 * ---------- Confirmation Response ----------
250 /* Computes the length to read after the function received */
251 static uint8_t compute_meta_length_after_function(int function
,
256 if (msg_type
== MSG_INDICATION
) {
257 if (function
<= MODBUS_FC_WRITE_SINGLE_REGISTER
) {
259 } else if (function
== MODBUS_FC_WRITE_MULTIPLE_COILS
||
260 function
== MODBUS_FC_WRITE_MULTIPLE_REGISTERS
) {
262 } else if (function
== MODBUS_FC_MASK_WRITE_REGISTER
) {
264 } else if (function
== MODBUS_FC_WRITE_AND_READ_REGISTERS
) {
267 /* MODBUS_FC_READ_EXCEPTION_STATUS, MODBUS_FC_REPORT_SLAVE_ID */
271 /* MSG_CONFIRMATION */
273 case MODBUS_FC_WRITE_SINGLE_COIL
:
274 case MODBUS_FC_WRITE_SINGLE_REGISTER
:
275 case MODBUS_FC_WRITE_MULTIPLE_COILS
:
276 case MODBUS_FC_WRITE_MULTIPLE_REGISTERS
:
279 case MODBUS_FC_MASK_WRITE_REGISTER
:
290 /* Computes the length to read after the meta information (address, count, etc) */
291 static int compute_data_length_after_meta(modbus_t
*ctx
, uint8_t *msg
,
294 int function
= msg
[ctx
->backend
->header_length
];
297 if (msg_type
== MSG_INDICATION
) {
299 case MODBUS_FC_WRITE_MULTIPLE_COILS
:
300 case MODBUS_FC_WRITE_MULTIPLE_REGISTERS
:
301 length
= msg
[ctx
->backend
->header_length
+ 5];
303 case MODBUS_FC_WRITE_AND_READ_REGISTERS
:
304 length
= msg
[ctx
->backend
->header_length
+ 9];
310 /* MSG_CONFIRMATION */
311 if (function
<= MODBUS_FC_READ_INPUT_REGISTERS
||
312 function
== MODBUS_FC_REPORT_SLAVE_ID
||
313 function
== MODBUS_FC_WRITE_AND_READ_REGISTERS
) {
314 length
= msg
[ctx
->backend
->header_length
+ 1];
320 length
+= ctx
->backend
->checksum_length
;
326 /* Waits a response from a modbus server or a request from a modbus client.
327 This function blocks if there is no replies (3 timeouts).
329 The function shall return the number of received characters and the received
330 message in an array of uint8_t if successful. Otherwise it shall return -1
331 and errno is set to one of the values defined below:
336 - read() or recv() error codes
339 int _modbus_receive_msg(modbus_t
*ctx
, uint8_t *msg
, msg_type_t msg_type
)
344 struct timeval
*p_tv
;
350 if (msg_type
== MSG_INDICATION
) {
351 printf("Waiting for a indication...\n");
353 printf("Waiting for a confirmation...\n");
357 /* Add a file descriptor to the set */
359 FD_SET(ctx
->s
, &rset
);
361 /* We need to analyse the message step by step. At the first step, we want
362 * to reach the function code because all packets contain this
364 step
= _STEP_FUNCTION
;
365 length_to_read
= ctx
->backend
->header_length
+ 1;
367 if (msg_type
== MSG_INDICATION
) {
368 /* Wait for a message, we don't know when the message will be
372 tv
.tv_sec
= ctx
->response_timeout
.tv_sec
;
373 tv
.tv_usec
= ctx
->response_timeout
.tv_usec
;
377 while (length_to_read
!= 0) {
378 rc
= ctx
->backend
->select(ctx
, &rset
, p_tv
, length_to_read
);
380 _error_print(ctx
, "select");
381 if (ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_LINK
) {
382 int saved_errno
= errno
;
384 if (errno
== ETIMEDOUT
) {
385 _sleep_response_timeout(ctx
);
387 } else if (errno
== EBADF
) {
396 rc
= ctx
->backend
->recv(ctx
, msg
+ msg_length
, length_to_read
);
403 _error_print(ctx
, "read");
404 if ((ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_LINK
) &&
405 (errno
== ECONNRESET
|| errno
== ECONNREFUSED
||
407 int saved_errno
= errno
;
410 /* Could be removed by previous calls */
416 /* Display the hex code of each character received */
419 for (i
=0; i
< rc
; i
++)
420 printf("<%.2X>", msg
[msg_length
+ i
]);
423 /* Sums bytes received */
425 /* Computes remaining bytes */
426 length_to_read
-= rc
;
428 if (length_to_read
== 0) {
431 /* Function code position */
432 length_to_read
= compute_meta_length_after_function(
433 msg
[ctx
->backend
->header_length
],
435 if (length_to_read
!= 0) {
438 } /* else switches straight to the next step */
440 length_to_read
= compute_data_length_after_meta(
442 if ((msg_length
+ length_to_read
) > (int)ctx
->backend
->max_adu_length
) {
444 _error_print(ctx
, "too many data");
454 if (length_to_read
> 0 &&
455 (ctx
->byte_timeout
.tv_sec
> 0 || ctx
->byte_timeout
.tv_usec
> 0)) {
456 /* If there is no character in the buffer, the allowed timeout
457 interval between two consecutive bytes is defined by
459 tv
.tv_sec
= ctx
->byte_timeout
.tv_sec
;
460 tv
.tv_usec
= ctx
->byte_timeout
.tv_usec
;
463 /* else timeout isn't set again, the full response must be read before
464 expiration of response timeout (for CONFIRMATION only) */
470 return ctx
->backend
->check_integrity(ctx
, msg
, msg_length
);
473 /* Receive the request from a modbus master */
474 int modbus_receive(modbus_t
*ctx
, uint8_t *req
)
481 return ctx
->backend
->receive(ctx
, req
);
484 /* Receives the confirmation.
486 The function shall store the read response in rsp and return the number of
487 values (bits or words). Otherwise, its shall return -1 and errno is set.
489 The function doesn't check the confirmation is the expected response to the
492 int modbus_receive_confirmation(modbus_t
*ctx
, uint8_t *rsp
)
499 return _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
502 static int check_confirmation(modbus_t
*ctx
, uint8_t *req
,
503 uint8_t *rsp
, int rsp_length
)
506 int rsp_length_computed
;
507 const int offset
= ctx
->backend
->header_length
;
508 const int function
= rsp
[offset
];
510 if (ctx
->backend
->pre_check_confirmation
) {
511 rc
= ctx
->backend
->pre_check_confirmation(ctx
, req
, rsp
, rsp_length
);
513 if (ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_PROTOCOL
) {
514 _sleep_response_timeout(ctx
);
521 rsp_length_computed
= compute_response_length_from_request(ctx
, req
);
524 if (function
>= 0x80) {
525 if (rsp_length
== (offset
+ 2 + (int)ctx
->backend
->checksum_length
) &&
526 req
[offset
] == (rsp
[offset
] - 0x80)) {
527 /* Valid exception code received */
529 int exception_code
= rsp
[offset
+ 1];
530 if (exception_code
< MODBUS_EXCEPTION_MAX
) {
531 errno
= MODBUS_ENOBASE
+ exception_code
;
535 _error_print(ctx
, NULL
);
539 _error_print(ctx
, NULL
);
545 if ((rsp_length
== rsp_length_computed
||
546 rsp_length_computed
== MSG_LENGTH_UNDEFINED
) &&
551 /* Check function code */
552 if (function
!= req
[offset
]) {
555 "Received function not corresponding to the request (0x%X != 0x%X)\n",
556 function
, req
[offset
]);
558 if (ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_PROTOCOL
) {
559 _sleep_response_timeout(ctx
);
566 /* Check the number of values is corresponding to the request */
568 case MODBUS_FC_READ_COILS
:
569 case MODBUS_FC_READ_DISCRETE_INPUTS
:
570 /* Read functions, 8 values in a byte (nb
571 * of values in the request and byte count in
573 req_nb_value
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
574 req_nb_value
= (req_nb_value
/ 8) + ((req_nb_value
% 8) ? 1 : 0);
575 rsp_nb_value
= rsp
[offset
+ 1];
577 case MODBUS_FC_WRITE_AND_READ_REGISTERS
:
578 case MODBUS_FC_READ_HOLDING_REGISTERS
:
579 case MODBUS_FC_READ_INPUT_REGISTERS
:
580 /* Read functions 1 value = 2 bytes */
581 req_nb_value
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
582 rsp_nb_value
= (rsp
[offset
+ 1] / 2);
584 case MODBUS_FC_WRITE_MULTIPLE_COILS
:
585 case MODBUS_FC_WRITE_MULTIPLE_REGISTERS
:
586 /* N Write functions */
587 req_nb_value
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
588 rsp_nb_value
= (rsp
[offset
+ 3] << 8) | rsp
[offset
+ 4];
590 case MODBUS_FC_REPORT_SLAVE_ID
:
591 /* Report slave ID (bytes received) */
592 req_nb_value
= rsp_nb_value
= rsp
[offset
+ 1];
595 /* 1 Write functions & others */
596 req_nb_value
= rsp_nb_value
= 1;
599 if (req_nb_value
== rsp_nb_value
) {
604 "Quantity not corresponding to the request (%d != %d)\n",
605 rsp_nb_value
, req_nb_value
);
608 if (ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_PROTOCOL
) {
609 _sleep_response_timeout(ctx
);
619 "Message length not corresponding to the computed length (%d != %d)\n",
620 rsp_length
, rsp_length_computed
);
622 if (ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_PROTOCOL
) {
623 _sleep_response_timeout(ctx
);
633 static int response_io_status(uint8_t *tab_io_status
,
635 uint8_t *rsp
, int offset
)
638 /* Instead of byte (not allowed in Win32) */
642 for (i
= address
; i
< address
+ nb
; i
++) {
643 one_byte
|= tab_io_status
[i
] << shift
;
646 rsp
[offset
++] = one_byte
;
647 one_byte
= shift
= 0;
654 rsp
[offset
++] = one_byte
;
659 /* Build the exception response */
660 static int response_exception(modbus_t
*ctx
, sft_t
*sft
,
661 int exception_code
, uint8_t *rsp
)
665 sft
->function
= sft
->function
+ 0x80;
666 rsp_length
= ctx
->backend
->build_response_basis(sft
, rsp
);
668 /* Positive exception code */
669 rsp
[rsp_length
++] = exception_code
;
674 /* Send a response to the received request.
675 Analyses the request and constructs a response.
677 If an error occurs, this function construct the response
680 int modbus_reply(modbus_t
*ctx
, const uint8_t *req
,
681 int req_length
, modbus_mapping_t
*mb_mapping
)
687 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
696 offset
= ctx
->backend
->header_length
;
697 slave
= req
[offset
- 1];
698 function
= req
[offset
];
699 address
= (req
[offset
+ 1] << 8) + req
[offset
+ 2];
702 sft
.function
= function
;
703 sft
.t_id
= ctx
->backend
->prepare_response_tid(req
, &req_length
);
705 /* Data are flushed on illegal number of values errors. */
707 case MODBUS_FC_READ_COILS
: {
708 int nb
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
709 /* The mapping can be shifted to reduce memory consumption and it
710 doesn't always start at address zero. */
711 int mapping_address
= address
- mb_mapping
->start_bits
;
713 if (nb
< 1 || MODBUS_MAX_READ_BITS
< nb
) {
716 "Illegal nb of values %d in read_bits (max %d)\n",
717 nb
, MODBUS_MAX_READ_BITS
);
719 _sleep_response_timeout(ctx
);
721 rsp_length
= response_exception(
723 MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
, rsp
);
724 } else if (mapping_address
< 0 ||
725 (mapping_address
+ nb
) > mb_mapping
->nb_bits
) {
727 fprintf(stderr
, "Illegal data address 0x%0X in read_bits\n",
728 mapping_address
< 0 ? address
: address
+ nb
);
730 rsp_length
= response_exception(
732 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
, rsp
);
734 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
735 rsp
[rsp_length
++] = (nb
/ 8) + ((nb
% 8) ? 1 : 0);
736 rsp_length
= response_io_status(mb_mapping
->tab_bits
,
742 case MODBUS_FC_READ_DISCRETE_INPUTS
: {
743 /* Similar to coil status (but too many arguments to use a
745 int nb
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
746 int mapping_address
= address
- mb_mapping
->start_input_bits
;
748 if (nb
< 1 || MODBUS_MAX_READ_BITS
< nb
) {
751 "Illegal nb of values %d in read_input_bits (max %d)\n",
752 nb
, MODBUS_MAX_READ_BITS
);
754 _sleep_response_timeout(ctx
);
756 rsp_length
= response_exception(
758 MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
, rsp
);
759 } else if (mapping_address
< 0 ||
760 (mapping_address
+ nb
) > mb_mapping
->nb_input_bits
) {
762 fprintf(stderr
, "Illegal data address 0x%0X in read_input_bits\n",
763 mapping_address
< 0 ? address
: address
+ nb
);
765 rsp_length
= response_exception(
767 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
, rsp
);
769 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
770 rsp
[rsp_length
++] = (nb
/ 8) + ((nb
% 8) ? 1 : 0);
771 rsp_length
= response_io_status(mb_mapping
->tab_input_bits
,
777 case MODBUS_FC_READ_HOLDING_REGISTERS
: {
778 int nb
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
779 int mapping_address
= address
- mb_mapping
->start_registers
;
781 if (nb
< 1 || MODBUS_MAX_READ_REGISTERS
< nb
) {
784 "Illegal nb of values %d in read_holding_registers (max %d)\n",
785 nb
, MODBUS_MAX_READ_REGISTERS
);
787 _sleep_response_timeout(ctx
);
789 rsp_length
= response_exception(
791 MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
, rsp
);
792 } else if (mapping_address
< 0 ||
793 (mapping_address
+ nb
) > mb_mapping
->nb_registers
) {
795 fprintf(stderr
, "Illegal data address 0x%0X in read_registers\n",
796 mapping_address
< 0 ? address
: address
+ nb
);
798 rsp_length
= response_exception(
800 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
, rsp
);
804 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
805 rsp
[rsp_length
++] = nb
<< 1;
806 for (i
= mapping_address
; i
< mapping_address
+ nb
; i
++) {
807 rsp
[rsp_length
++] = mb_mapping
->tab_registers
[i
] >> 8;
808 rsp
[rsp_length
++] = mb_mapping
->tab_registers
[i
] & 0xFF;
813 case MODBUS_FC_READ_INPUT_REGISTERS
: {
814 /* Similar to holding registers (but too many arguments to use a
816 int nb
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
817 int mapping_address
= address
- mb_mapping
->start_input_registers
;
819 if (nb
< 1 || MODBUS_MAX_READ_REGISTERS
< nb
) {
822 "Illegal number of values %d in read_input_registers (max %d)\n",
823 nb
, MODBUS_MAX_READ_REGISTERS
);
825 _sleep_response_timeout(ctx
);
827 rsp_length
= response_exception(
829 MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
, rsp
);
830 } else if (mapping_address
< 0 ||
831 (mapping_address
+ nb
) > mb_mapping
->nb_input_registers
) {
833 fprintf(stderr
, "Illegal data address 0x%0X in read_input_registers\n",
834 mapping_address
< 0 ? address
: address
+ nb
);
836 rsp_length
= response_exception(
838 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
, rsp
);
842 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
843 rsp
[rsp_length
++] = nb
<< 1;
844 for (i
= mapping_address
; i
< mapping_address
+ nb
; i
++) {
845 rsp
[rsp_length
++] = mb_mapping
->tab_input_registers
[i
] >> 8;
846 rsp
[rsp_length
++] = mb_mapping
->tab_input_registers
[i
] & 0xFF;
851 case MODBUS_FC_WRITE_SINGLE_COIL
: {
852 int mapping_address
= address
- mb_mapping
->start_bits
;
854 if (mapping_address
< 0 || mapping_address
>= mb_mapping
->nb_bits
) {
857 "Illegal data address 0x%0X in write_bit\n",
860 rsp_length
= response_exception(
862 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
, rsp
);
864 int data
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
866 if (data
== 0xFF00 || data
== 0x0) {
867 mb_mapping
->tab_bits
[mapping_address
] = data
? ON
: OFF
;
868 memcpy(rsp
, req
, req_length
);
869 rsp_length
= req_length
;
873 "Illegal data value 0x%0X in write_bit request at address %0X\n",
876 rsp_length
= response_exception(
878 MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
, rsp
);
883 case MODBUS_FC_WRITE_SINGLE_REGISTER
: {
884 int mapping_address
= address
- mb_mapping
->start_registers
;
886 if (mapping_address
< 0 || mapping_address
>= mb_mapping
->nb_registers
) {
888 fprintf(stderr
, "Illegal data address 0x%0X in write_register\n",
891 rsp_length
= response_exception(
893 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
, rsp
);
895 int data
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
897 mb_mapping
->tab_registers
[mapping_address
] = data
;
898 memcpy(rsp
, req
, req_length
);
899 rsp_length
= req_length
;
903 case MODBUS_FC_WRITE_MULTIPLE_COILS
: {
904 int nb
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
905 int mapping_address
= address
- mb_mapping
->start_bits
;
907 if (nb
< 1 || MODBUS_MAX_WRITE_BITS
< nb
) {
910 "Illegal number of values %d in write_bits (max %d)\n",
911 nb
, MODBUS_MAX_WRITE_BITS
);
913 /* May be the indication has been truncated on reading because of
914 * invalid address (eg. nb is 0 but the request contains values to
915 * write) so it's necessary to flush. */
916 _sleep_response_timeout(ctx
);
918 rsp_length
= response_exception(
920 MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
, rsp
);
921 } else if (mapping_address
< 0 ||
922 (mapping_address
+ nb
) > mb_mapping
->nb_bits
) {
924 fprintf(stderr
, "Illegal data address 0x%0X in write_bits\n",
925 mapping_address
< 0 ? address
: address
+ nb
);
927 rsp_length
= response_exception(
929 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
, rsp
);
932 modbus_set_bits_from_bytes(mb_mapping
->tab_bits
, mapping_address
, nb
,
935 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
936 /* 4 to copy the bit address (2) and the quantity of bits */
937 memcpy(rsp
+ rsp_length
, req
+ rsp_length
, 4);
942 case MODBUS_FC_WRITE_MULTIPLE_REGISTERS
: {
943 int nb
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
944 int mapping_address
= address
- mb_mapping
->start_registers
;
946 if (nb
< 1 || MODBUS_MAX_WRITE_REGISTERS
< nb
) {
949 "Illegal number of values %d in write_registers (max %d)\n",
950 nb
, MODBUS_MAX_WRITE_REGISTERS
);
952 /* May be the indication has been truncated on reading because of
953 * invalid address (eg. nb is 0 but the request contains values to
954 * write) so it's necessary to flush. */
955 _sleep_response_timeout(ctx
);
957 rsp_length
= response_exception(
959 MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
, rsp
);
960 } else if (mapping_address
< 0 ||
961 (mapping_address
+ nb
) > mb_mapping
->nb_registers
) {
963 fprintf(stderr
, "Illegal data address 0x%0X in write_registers\n",
964 mapping_address
< 0 ? address
: address
+ nb
);
966 rsp_length
= response_exception(
968 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
, rsp
);
971 for (i
= mapping_address
, j
= 6; i
< mapping_address
+ nb
; i
++, j
+= 2) {
972 /* 6 and 7 = first value */
973 mb_mapping
->tab_registers
[i
] =
974 (req
[offset
+ j
] << 8) + req
[offset
+ j
+ 1];
977 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
978 /* 4 to copy the address (2) and the no. of registers */
979 memcpy(rsp
+ rsp_length
, req
+ rsp_length
, 4);
984 case MODBUS_FC_REPORT_SLAVE_ID
: {
988 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
989 /* Skip byte count for now */
990 byte_count_pos
= rsp_length
++;
991 rsp
[rsp_length
++] = _REPORT_SLAVE_ID
;
992 /* Run indicator status to ON */
993 rsp
[rsp_length
++] = 0xFF;
994 /* LMB + length of LIBMODBUS_VERSION_STRING */
995 str_len
= 3 + strlen(LIBMODBUS_VERSION_STRING
);
996 memcpy(rsp
+ rsp_length
, "LMB" LIBMODBUS_VERSION_STRING
, str_len
);
997 rsp_length
+= str_len
;
998 rsp
[byte_count_pos
] = rsp_length
- byte_count_pos
- 1;
1001 case MODBUS_FC_READ_EXCEPTION_STATUS
:
1003 fprintf(stderr
, "FIXME Not implemented\n");
1005 errno
= ENOPROTOOPT
;
1008 case MODBUS_FC_MASK_WRITE_REGISTER
: {
1009 int mapping_address
= address
- mb_mapping
->start_registers
;
1011 if (mapping_address
< 0 || mapping_address
>= mb_mapping
->nb_registers
) {
1013 fprintf(stderr
, "Illegal data address 0x%0X in write_register\n",
1016 rsp_length
= response_exception(
1018 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
, rsp
);
1020 uint16_t data
= mb_mapping
->tab_registers
[mapping_address
];
1021 uint16_t and = (req
[offset
+ 3] << 8) + req
[offset
+ 4];
1022 uint16_t or = (req
[offset
+ 5] << 8) + req
[offset
+ 6];
1024 data
= (data
& and) | (or & (~and));
1025 mb_mapping
->tab_registers
[mapping_address
] = data
;
1026 memcpy(rsp
, req
, req_length
);
1027 rsp_length
= req_length
;
1031 case MODBUS_FC_WRITE_AND_READ_REGISTERS
: {
1032 int nb
= (req
[offset
+ 3] << 8) + req
[offset
+ 4];
1033 uint16_t address_write
= (req
[offset
+ 5] << 8) + req
[offset
+ 6];
1034 int nb_write
= (req
[offset
+ 7] << 8) + req
[offset
+ 8];
1035 int nb_write_bytes
= req
[offset
+ 9];
1036 int mapping_address
= address
- mb_mapping
->start_registers
;
1037 int mapping_address_write
= address_write
- mb_mapping
->start_registers
;
1039 if (nb_write
< 1 || MODBUS_MAX_WR_WRITE_REGISTERS
< nb_write
||
1040 nb
< 1 || MODBUS_MAX_WR_READ_REGISTERS
< nb
||
1041 nb_write_bytes
!= nb_write
* 2) {
1044 "Illegal nb of values (W%d, R%d) in write_and_read_registers (max W%d, R%d)\n",
1046 MODBUS_MAX_WR_WRITE_REGISTERS
, MODBUS_MAX_WR_READ_REGISTERS
);
1048 _sleep_response_timeout(ctx
);
1050 rsp_length
= response_exception(
1052 MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
, rsp
);
1053 } else if (mapping_address
< 0 ||
1054 (mapping_address
+ nb
) > mb_mapping
->nb_registers
||
1055 mapping_address
< 0 ||
1056 (mapping_address_write
+ nb_write
) > mb_mapping
->nb_registers
) {
1059 "Illegal data read address 0x%0X or write address 0x%0X write_and_read_registers\n",
1060 mapping_address
< 0 ? address
: address
+ nb
,
1061 mapping_address_write
< 0 ? address_write
: address_write
+ nb_write
);
1063 rsp_length
= response_exception(ctx
, &sft
,
1064 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
, rsp
);
1067 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
1068 rsp
[rsp_length
++] = nb
<< 1;
1071 10 and 11 are the offset of the first values to write */
1072 for (i
= mapping_address_write
, j
= 10;
1073 i
< mapping_address_write
+ nb_write
; i
++, j
+= 2) {
1074 mb_mapping
->tab_registers
[i
] =
1075 (req
[offset
+ j
] << 8) + req
[offset
+ j
+ 1];
1078 /* and read the data for the response */
1079 for (i
= mapping_address
; i
< mapping_address
+ nb
; i
++) {
1080 rsp
[rsp_length
++] = mb_mapping
->tab_registers
[i
] >> 8;
1081 rsp
[rsp_length
++] = mb_mapping
->tab_registers
[i
] & 0xFF;
1088 rsp_length
= response_exception(ctx
, &sft
,
1089 MODBUS_EXCEPTION_ILLEGAL_FUNCTION
,
1094 /* Suppress any responses when the request was a broadcast */
1095 return (slave
== MODBUS_BROADCAST_ADDRESS
) ? 0 : send_msg(ctx
, rsp
, rsp_length
);
1098 int modbus_reply_exception(modbus_t
*ctx
, const uint8_t *req
,
1099 unsigned int exception_code
)
1104 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1106 int dummy_length
= 99;
1114 offset
= ctx
->backend
->header_length
;
1115 slave
= req
[offset
- 1];
1116 function
= req
[offset
];
1119 sft
.function
= function
+ 0x80;;
1120 sft
.t_id
= ctx
->backend
->prepare_response_tid(req
, &dummy_length
);
1121 rsp_length
= ctx
->backend
->build_response_basis(&sft
, rsp
);
1123 /* Positive exception code */
1124 if (exception_code
< MODBUS_EXCEPTION_MAX
) {
1125 rsp
[rsp_length
++] = exception_code
;
1126 return send_msg(ctx
, rsp
, rsp_length
);
1133 /* Reads IO status */
1134 static int read_io_status(modbus_t
*ctx
, int function
,
1135 int addr
, int nb
, uint8_t *dest
)
1140 uint8_t req
[_MIN_REQ_LENGTH
];
1141 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1143 req_length
= ctx
->backend
->build_request_basis(ctx
, function
, addr
, nb
, req
);
1145 rc
= send_msg(ctx
, req
, req_length
);
1152 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1156 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1160 offset
= ctx
->backend
->header_length
+ 2;
1161 offset_end
= offset
+ rc
;
1162 for (i
= offset
; i
< offset_end
; i
++) {
1163 /* Shift reg hi_byte to temp */
1166 for (bit
= 0x01; (bit
& 0xff) && (pos
< nb
);) {
1167 dest
[pos
++] = (temp
& bit
) ? TRUE
: FALSE
;
1177 /* Reads the boolean status of bits and sets the array elements
1178 in the destination to TRUE or FALSE (single bits). */
1179 int modbus_read_bits(modbus_t
*ctx
, int addr
, int nb
, uint8_t *dest
)
1188 if (nb
> MODBUS_MAX_READ_BITS
) {
1191 "ERROR Too many bits requested (%d > %d)\n",
1192 nb
, MODBUS_MAX_READ_BITS
);
1198 rc
= read_io_status(ctx
, MODBUS_FC_READ_COILS
, addr
, nb
, dest
);
1207 /* Same as modbus_read_bits but reads the remote device input table */
1208 int modbus_read_input_bits(modbus_t
*ctx
, int addr
, int nb
, uint8_t *dest
)
1217 if (nb
> MODBUS_MAX_READ_BITS
) {
1220 "ERROR Too many discrete inputs requested (%d > %d)\n",
1221 nb
, MODBUS_MAX_READ_BITS
);
1227 rc
= read_io_status(ctx
, MODBUS_FC_READ_DISCRETE_INPUTS
, addr
, nb
, dest
);
1235 /* Reads the data from a remove device and put that data into an array */
1236 static int read_registers(modbus_t
*ctx
, int function
, int addr
, int nb
,
1241 uint8_t req
[_MIN_REQ_LENGTH
];
1242 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1244 if (nb
> MODBUS_MAX_READ_REGISTERS
) {
1247 "ERROR Too many registers requested (%d > %d)\n",
1248 nb
, MODBUS_MAX_READ_REGISTERS
);
1254 req_length
= ctx
->backend
->build_request_basis(ctx
, function
, addr
, nb
, req
);
1256 rc
= send_msg(ctx
, req
, req_length
);
1261 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1265 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1269 offset
= ctx
->backend
->header_length
;
1271 for (i
= 0; i
< rc
; i
++) {
1272 /* shift reg hi_byte to temp OR with lo_byte */
1273 dest
[i
] = (rsp
[offset
+ 2 + (i
<< 1)] << 8) |
1274 rsp
[offset
+ 3 + (i
<< 1)];
1281 /* Reads the holding registers of remote device and put the data into an
1283 int modbus_read_registers(modbus_t
*ctx
, int addr
, int nb
, uint16_t *dest
)
1292 if (nb
> MODBUS_MAX_READ_REGISTERS
) {
1295 "ERROR Too many registers requested (%d > %d)\n",
1296 nb
, MODBUS_MAX_READ_REGISTERS
);
1302 status
= read_registers(ctx
, MODBUS_FC_READ_HOLDING_REGISTERS
,
1307 /* Reads the input registers of remote device and put the data into an array */
1308 int modbus_read_input_registers(modbus_t
*ctx
, int addr
, int nb
,
1318 if (nb
> MODBUS_MAX_READ_REGISTERS
) {
1320 "ERROR Too many input registers requested (%d > %d)\n",
1321 nb
, MODBUS_MAX_READ_REGISTERS
);
1326 status
= read_registers(ctx
, MODBUS_FC_READ_INPUT_REGISTERS
,
1332 /* Write a value to the specified register of the remote device.
1333 Used by write_bit and write_register */
1334 static int write_single(modbus_t
*ctx
, int function
, int addr
, int value
)
1338 uint8_t req
[_MIN_REQ_LENGTH
];
1345 req_length
= ctx
->backend
->build_request_basis(ctx
, function
, addr
, value
, req
);
1347 rc
= send_msg(ctx
, req
, req_length
);
1349 /* Used by write_bit and write_register */
1350 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1352 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1356 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1362 /* Turns ON or OFF a single bit of the remote device */
1363 int modbus_write_bit(modbus_t
*ctx
, int addr
, int status
)
1370 return write_single(ctx
, MODBUS_FC_WRITE_SINGLE_COIL
, addr
,
1371 status
? 0xFF00 : 0);
1374 /* Writes a value in one register of the remote device */
1375 int modbus_write_register(modbus_t
*ctx
, int addr
, int value
)
1382 return write_single(ctx
, MODBUS_FC_WRITE_SINGLE_REGISTER
, addr
, value
);
1385 /* Write the bits of the array in the remote device */
1386 int modbus_write_bits(modbus_t
*ctx
, int addr
, int nb
, const uint8_t *src
)
1394 uint8_t req
[MAX_MESSAGE_LENGTH
];
1401 if (nb
> MODBUS_MAX_WRITE_BITS
) {
1403 fprintf(stderr
, "ERROR Writing too many bits (%d > %d)\n",
1404 nb
, MODBUS_MAX_WRITE_BITS
);
1410 req_length
= ctx
->backend
->build_request_basis(ctx
,
1411 MODBUS_FC_WRITE_MULTIPLE_COILS
,
1413 byte_count
= (nb
/ 8) + ((nb
% 8) ? 1 : 0);
1414 req
[req_length
++] = byte_count
;
1416 for (i
= 0; i
< byte_count
; i
++) {
1420 req
[req_length
] = 0;
1422 while ((bit
& 0xFF) && (bit_check
++ < nb
)) {
1424 req
[req_length
] |= bit
;
1426 req
[req_length
] &=~ bit
;
1433 rc
= send_msg(ctx
, req
, req_length
);
1435 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1437 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1441 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1448 /* Write the values from the array to the registers of the remote device */
1449 int modbus_write_registers(modbus_t
*ctx
, int addr
, int nb
, const uint16_t *src
)
1455 uint8_t req
[MAX_MESSAGE_LENGTH
];
1462 if (nb
> MODBUS_MAX_WRITE_REGISTERS
) {
1465 "ERROR Trying to write to too many registers (%d > %d)\n",
1466 nb
, MODBUS_MAX_WRITE_REGISTERS
);
1472 req_length
= ctx
->backend
->build_request_basis(ctx
,
1473 MODBUS_FC_WRITE_MULTIPLE_REGISTERS
,
1475 byte_count
= nb
* 2;
1476 req
[req_length
++] = byte_count
;
1478 for (i
= 0; i
< nb
; i
++) {
1479 req
[req_length
++] = src
[i
] >> 8;
1480 req
[req_length
++] = src
[i
] & 0x00FF;
1483 rc
= send_msg(ctx
, req
, req_length
);
1485 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1487 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1491 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1497 int modbus_mask_write_register(modbus_t
*ctx
, int addr
, uint16_t and_mask
, uint16_t or_mask
)
1501 /* The request length can not exceed _MIN_REQ_LENGTH - 2 and 4 bytes to
1502 * store the masks. The ugly substraction is there to remove the 'nb' value
1503 * (2 bytes) which is not used. */
1504 uint8_t req
[_MIN_REQ_LENGTH
+ 2];
1506 req_length
= ctx
->backend
->build_request_basis(ctx
,
1507 MODBUS_FC_MASK_WRITE_REGISTER
,
1510 /* HACKISH, count is not used */
1513 req
[req_length
++] = and_mask
>> 8;
1514 req
[req_length
++] = and_mask
& 0x00ff;
1515 req
[req_length
++] = or_mask
>> 8;
1516 req
[req_length
++] = or_mask
& 0x00ff;
1518 rc
= send_msg(ctx
, req
, req_length
);
1520 /* Used by write_bit and write_register */
1521 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1523 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1527 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1533 /* Write multiple registers from src array to remote device and read multiple
1534 registers from remote device to dest array. */
1535 int modbus_write_and_read_registers(modbus_t
*ctx
,
1536 int write_addr
, int write_nb
,
1537 const uint16_t *src
,
1538 int read_addr
, int read_nb
,
1546 uint8_t req
[MAX_MESSAGE_LENGTH
];
1547 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1554 if (write_nb
> MODBUS_MAX_WR_WRITE_REGISTERS
) {
1557 "ERROR Too many registers to write (%d > %d)\n",
1558 write_nb
, MODBUS_MAX_WR_WRITE_REGISTERS
);
1564 if (read_nb
> MODBUS_MAX_WR_READ_REGISTERS
) {
1567 "ERROR Too many registers requested (%d > %d)\n",
1568 read_nb
, MODBUS_MAX_WR_READ_REGISTERS
);
1573 req_length
= ctx
->backend
->build_request_basis(ctx
,
1574 MODBUS_FC_WRITE_AND_READ_REGISTERS
,
1575 read_addr
, read_nb
, req
);
1577 req
[req_length
++] = write_addr
>> 8;
1578 req
[req_length
++] = write_addr
& 0x00ff;
1579 req
[req_length
++] = write_nb
>> 8;
1580 req
[req_length
++] = write_nb
& 0x00ff;
1581 byte_count
= write_nb
* 2;
1582 req
[req_length
++] = byte_count
;
1584 for (i
= 0; i
< write_nb
; i
++) {
1585 req
[req_length
++] = src
[i
] >> 8;
1586 req
[req_length
++] = src
[i
] & 0x00FF;
1589 rc
= send_msg(ctx
, req
, req_length
);
1593 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1597 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1601 offset
= ctx
->backend
->header_length
;
1602 for (i
= 0; i
< rc
; i
++) {
1603 /* shift reg hi_byte to temp OR with lo_byte */
1604 dest
[i
] = (rsp
[offset
+ 2 + (i
<< 1)] << 8) |
1605 rsp
[offset
+ 3 + (i
<< 1)];
1612 /* Send a request to get the slave ID of the device (only available in serial
1614 int modbus_report_slave_id(modbus_t
*ctx
, int max_dest
, uint8_t *dest
)
1618 uint8_t req
[_MIN_REQ_LENGTH
];
1620 if (ctx
== NULL
|| max_dest
<= 0) {
1625 req_length
= ctx
->backend
->build_request_basis(ctx
, MODBUS_FC_REPORT_SLAVE_ID
,
1628 /* HACKISH, addr and count are not used */
1631 rc
= send_msg(ctx
, req
, req_length
);
1635 uint8_t rsp
[MAX_MESSAGE_LENGTH
];
1637 rc
= _modbus_receive_msg(ctx
, rsp
, MSG_CONFIRMATION
);
1641 rc
= check_confirmation(ctx
, req
, rsp
, rc
);
1645 offset
= ctx
->backend
->header_length
+ 2;
1647 /* Byte count, slave id, run indicator status and
1648 additional data. Truncate copy to max_dest. */
1649 for (i
=0; i
< rc
&& i
< max_dest
; i
++) {
1650 dest
[i
] = rsp
[offset
+ i
];
1657 void _modbus_init_common(modbus_t
*ctx
)
1659 /* Slave and socket are initialized to -1 */
1664 ctx
->error_recovery
= MODBUS_ERROR_RECOVERY_NONE
;
1666 ctx
->response_timeout
.tv_sec
= 0;
1667 ctx
->response_timeout
.tv_usec
= _RESPONSE_TIMEOUT
;
1669 ctx
->byte_timeout
.tv_sec
= 0;
1670 ctx
->byte_timeout
.tv_usec
= _BYTE_TIMEOUT
;
1673 /* Define the slave number */
1674 int modbus_set_slave(modbus_t
*ctx
, int slave
)
1681 return ctx
->backend
->set_slave(ctx
, slave
);
1684 int modbus_set_error_recovery(modbus_t
*ctx
,
1685 modbus_error_recovery_mode error_recovery
)
1692 /* The type of modbus_error_recovery_mode is unsigned enum */
1693 ctx
->error_recovery
= (uint8_t) error_recovery
;
1697 int modbus_set_socket(modbus_t
*ctx
, int s
)
1708 int modbus_get_socket(modbus_t
*ctx
)
1718 /* Get the timeout interval used to wait for a response */
1719 int modbus_get_response_timeout(modbus_t
*ctx
, uint32_t *to_sec
, uint32_t *to_usec
)
1726 *to_sec
= ctx
->response_timeout
.tv_sec
;
1727 *to_usec
= ctx
->response_timeout
.tv_usec
;
1731 int modbus_set_response_timeout(modbus_t
*ctx
, uint32_t to_sec
, uint32_t to_usec
)
1734 (to_sec
== 0 && to_usec
== 0) || to_usec
> 999999) {
1739 ctx
->response_timeout
.tv_sec
= to_sec
;
1740 ctx
->response_timeout
.tv_usec
= to_usec
;
1744 /* Get the timeout interval between two consecutive bytes of a message */
1745 int modbus_get_byte_timeout(modbus_t
*ctx
, uint32_t *to_sec
, uint32_t *to_usec
)
1752 *to_sec
= ctx
->byte_timeout
.tv_sec
;
1753 *to_usec
= ctx
->byte_timeout
.tv_usec
;
1757 int modbus_set_byte_timeout(modbus_t
*ctx
, uint32_t to_sec
, uint32_t to_usec
)
1759 /* Byte timeout can be disabled when both values are zero */
1760 if (ctx
== NULL
|| to_usec
> 999999) {
1765 ctx
->byte_timeout
.tv_sec
= to_sec
;
1766 ctx
->byte_timeout
.tv_usec
= to_usec
;
1770 int modbus_get_header_length(modbus_t
*ctx
)
1777 return ctx
->backend
->header_length
;
1780 int modbus_connect(modbus_t
*ctx
)
1787 return ctx
->backend
->connect(ctx
);
1790 void modbus_close(modbus_t
*ctx
)
1795 ctx
->backend
->close(ctx
);
1798 void modbus_free(modbus_t
*ctx
)
1803 ctx
->backend
->free(ctx
);
1806 int modbus_set_debug(modbus_t
*ctx
, int flag
)
1817 /* Allocates 4 arrays to store bits, input bits, registers and inputs
1818 registers. The pointers are stored in modbus_mapping structure.
1820 The modbus_mapping_new_ranges() function shall return the new allocated
1821 structure if successful. Otherwise it shall return NULL and set errno to
1823 modbus_mapping_t
* modbus_mapping_new_start_address(
1824 unsigned int start_bits
, unsigned int nb_bits
,
1825 unsigned int start_input_bits
, unsigned int nb_input_bits
,
1826 unsigned int start_registers
, unsigned int nb_registers
,
1827 unsigned int start_input_registers
, unsigned int nb_input_registers
)
1829 modbus_mapping_t
*mb_mapping
;
1831 mb_mapping
= (modbus_mapping_t
*)malloc(sizeof(modbus_mapping_t
));
1832 if (mb_mapping
== NULL
) {
1837 mb_mapping
->nb_bits
= nb_bits
;
1838 mb_mapping
->start_bits
= start_bits
;
1840 mb_mapping
->tab_bits
= NULL
;
1842 /* Negative number raises a POSIX error */
1843 mb_mapping
->tab_bits
=
1844 (uint8_t *) malloc(nb_bits
* sizeof(uint8_t));
1845 if (mb_mapping
->tab_bits
== NULL
) {
1849 memset(mb_mapping
->tab_bits
, 0, nb_bits
* sizeof(uint8_t));
1853 mb_mapping
->nb_input_bits
= nb_input_bits
;
1854 mb_mapping
->start_input_bits
= start_input_bits
;
1855 if (nb_input_bits
== 0) {
1856 mb_mapping
->tab_input_bits
= NULL
;
1858 mb_mapping
->tab_input_bits
=
1859 (uint8_t *) malloc(nb_input_bits
* sizeof(uint8_t));
1860 if (mb_mapping
->tab_input_bits
== NULL
) {
1861 free(mb_mapping
->tab_bits
);
1865 memset(mb_mapping
->tab_input_bits
, 0, nb_input_bits
* sizeof(uint8_t));
1869 mb_mapping
->nb_registers
= nb_registers
;
1870 mb_mapping
->start_registers
= start_registers
;
1871 if (nb_registers
== 0) {
1872 mb_mapping
->tab_registers
= NULL
;
1874 mb_mapping
->tab_registers
=
1875 (uint16_t *) malloc(nb_registers
* sizeof(uint16_t));
1876 if (mb_mapping
->tab_registers
== NULL
) {
1877 free(mb_mapping
->tab_input_bits
);
1878 free(mb_mapping
->tab_bits
);
1882 memset(mb_mapping
->tab_registers
, 0, nb_registers
* sizeof(uint16_t));
1886 mb_mapping
->nb_input_registers
= nb_input_registers
;
1887 mb_mapping
->start_input_registers
= start_input_registers
;
1888 if (nb_input_registers
== 0) {
1889 mb_mapping
->tab_input_registers
= NULL
;
1891 mb_mapping
->tab_input_registers
=
1892 (uint16_t *) malloc(nb_input_registers
* sizeof(uint16_t));
1893 if (mb_mapping
->tab_input_registers
== NULL
) {
1894 free(mb_mapping
->tab_registers
);
1895 free(mb_mapping
->tab_input_bits
);
1896 free(mb_mapping
->tab_bits
);
1900 memset(mb_mapping
->tab_input_registers
, 0,
1901 nb_input_registers
* sizeof(uint16_t));
1907 modbus_mapping_t
* modbus_mapping_new(int nb_bits
, int nb_input_bits
,
1908 int nb_registers
, int nb_input_registers
)
1910 return modbus_mapping_new_start_address(
1911 0, nb_bits
, 0, nb_input_bits
, 0, nb_registers
, 0, nb_input_registers
);
1914 /* Frees the 4 arrays */
1915 void modbus_mapping_free(modbus_mapping_t
*mb_mapping
)
1917 if (mb_mapping
== NULL
) {
1921 free(mb_mapping
->tab_input_registers
);
1922 free(mb_mapping
->tab_registers
);
1923 free(mb_mapping
->tab_input_bits
);
1924 free(mb_mapping
->tab_bits
);
1928 #ifndef HAVE_STRLCPY
1930 * Function strlcpy was originally developed by
1931 * Todd C. Miller <Todd.Miller@courtesan.com> to simplify writing secure code.
1932 * See ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/strlcpy.3
1933 * for more information.
1935 * Thank you Ulrich Drepper... not!
1937 * Copy src to string dest of size dest_size. At most dest_size-1 characters
1938 * will be copied. Always NUL terminates (unless dest_size == 0). Returns
1939 * strlen(src); if retval >= dest_size, truncation occurred.
1941 size_t strlcpy(char *dest
, const char *src
, size_t dest_size
)
1943 register char *d
= dest
;
1944 register const char *s
= src
;
1945 register size_t n
= dest_size
;
1947 /* Copy as many bytes as will fit */
1948 if (n
!= 0 && --n
!= 0) {
1950 if ((*d
++ = *s
++) == 0)
1955 /* Not enough room in dest, add NUL and traverse rest of src */
1958 *d
= '\0'; /* NUL-terminate dest */
1963 return (s
- src
- 1); /* count does not include NUL */