2 * Copyright © Stéphane Raimbault <stephane.raimbault@gmail.com>
4 * SPDX-License-Identifier: LGPL-2.1-or-later
15 #include "modbus-private.h"
18 #include "modbus-rtu-private.h"
19 #include "modbus-rtu.h"
21 #if HAVE_DECL_TIOCSRS485 || HAVE_DECL_TIOCM_RTS
22 #include <sys/ioctl.h>
25 #if HAVE_DECL_TIOCSRS485
26 #include <linux/serial.h>
29 /* Table of CRC values for high-order byte */
30 static const uint8_t table_crc_hi
[] = {
31 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
32 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
33 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1,
34 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
35 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
36 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
37 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1,
38 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
39 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
40 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
41 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
42 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
43 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
44 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
45 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
46 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
47 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
48 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
49 0x00, 0xC1, 0x81, 0x40};
51 /* Table of CRC values for low-order byte */
52 static const uint8_t table_crc_lo
[] = {
53 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5,
54 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B,
55 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE,
56 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6,
57 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
58 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D,
59 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8,
60 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C,
61 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21,
62 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
63 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A,
64 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,
65 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7,
66 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51,
67 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
68 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98,
69 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D,
70 0x4C, 0x8C, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,
71 0x41, 0x81, 0x80, 0x40};
73 /* Define the slave ID of the remote device to talk in master mode or set the
74 * internal slave ID in slave mode */
75 static int _modbus_set_slave(modbus_t
*ctx
, int slave
)
77 int max_slave
= (ctx
->quirks
& MODBUS_QUIRK_MAX_SLAVE
) ? 255 : 247;
79 /* Broadcast address is 0 (MODBUS_BROADCAST_ADDRESS) */
80 if (slave
>= 0 && slave
<= max_slave
) {
90 /* Builds a RTU request header */
91 static int _modbus_rtu_build_request_basis(
92 modbus_t
*ctx
, int function
, int addr
, int nb
, uint8_t *req
)
94 assert(ctx
->slave
!= -1);
98 req
[3] = addr
& 0x00ff;
100 req
[5] = nb
& 0x00ff;
102 return _MODBUS_RTU_PRESET_REQ_LENGTH
;
105 /* Builds a RTU response header */
106 static int _modbus_rtu_build_response_basis(sft_t
*sft
, uint8_t *rsp
)
108 /* In this case, the slave is certainly valid because a check is already
109 * done in _modbus_rtu_listen */
111 rsp
[1] = sft
->function
;
113 return _MODBUS_RTU_PRESET_RSP_LENGTH
;
116 static uint16_t crc16(uint8_t *buffer
, uint16_t buffer_length
)
118 uint8_t crc_hi
= 0xFF; /* high CRC byte initialized */
119 uint8_t crc_lo
= 0xFF; /* low CRC byte initialized */
120 unsigned int i
; /* will index into CRC lookup */
122 /* pass through message buffer */
123 while (buffer_length
--) {
124 i
= crc_lo
^ *buffer
++; /* calculate the CRC */
125 crc_lo
= crc_hi
^ table_crc_hi
[i
];
126 crc_hi
= table_crc_lo
[i
];
129 return (crc_hi
<< 8 | crc_lo
);
132 static int _modbus_rtu_get_response_tid(const uint8_t *req
)
138 static int _modbus_rtu_send_msg_pre(uint8_t *req
, int req_length
)
140 uint16_t crc
= crc16(req
, req_length
);
142 /* According to the MODBUS specs (p. 14), the low order byte of the CRC comes
143 * first in the RTU message */
144 req
[req_length
++] = crc
& 0x00FF;
145 req
[req_length
++] = crc
>> 8;
152 /* This simple implementation is sort of a substitute of the select() call,
153 * working this way: the win32_ser_select() call tries to read some data from
154 * the serial port, setting the timeout as the select() call would. Data read is
155 * stored into the receive buffer, that is then consumed by the win32_ser_read()
156 * call. So win32_ser_select() does both the event waiting and the reading,
157 * while win32_ser_read() only consumes the receive buffer.
160 static void win32_ser_init(struct win32_ser
*ws
)
162 /* Clear everything */
163 memset(ws
, 0x00, sizeof(struct win32_ser
));
165 /* Set file handle to invalid */
166 ws
->fd
= INVALID_HANDLE_VALUE
;
169 /* FIXME Try to remove length_to_read -> max_len argument, only used by win32 */
170 static int win32_ser_select(struct win32_ser
*ws
, int max_len
, const struct timeval
*tv
)
172 COMMTIMEOUTS comm_to
;
173 unsigned int msec
= 0;
175 /* Check if some data still in the buffer to be consumed */
176 if (ws
->n_bytes
> 0) {
180 /* Setup timeouts like select() would do.
181 FIXME Please someone on Windows can look at this?
182 Does it possible to use WaitCommEvent?
183 When tv is NULL, MAXDWORD isn't infinite!
188 msec
= tv
->tv_sec
* 1000 + tv
->tv_usec
/ 1000;
193 comm_to
.ReadIntervalTimeout
= msec
;
194 comm_to
.ReadTotalTimeoutMultiplier
= 0;
195 comm_to
.ReadTotalTimeoutConstant
= msec
;
196 comm_to
.WriteTotalTimeoutMultiplier
= 0;
197 comm_to
.WriteTotalTimeoutConstant
= 1000;
198 SetCommTimeouts(ws
->fd
, &comm_to
);
200 /* Read some bytes */
201 if ((max_len
> PY_BUF_SIZE
) || (max_len
< 0)) {
202 max_len
= PY_BUF_SIZE
;
205 if (ReadFile(ws
->fd
, &ws
->buf
, max_len
, &ws
->n_bytes
, NULL
)) {
206 /* Check if some bytes available */
207 if (ws
->n_bytes
> 0) {
208 /* Some bytes read */
215 /* Some kind of error */
220 static int win32_ser_read(struct win32_ser
*ws
, uint8_t *p_msg
, unsigned int max_len
)
222 unsigned int n
= ws
->n_bytes
;
229 memcpy(p_msg
, ws
->buf
, n
);
238 #if HAVE_DECL_TIOCM_RTS
239 static void _modbus_rtu_ioctl_rts(modbus_t
*ctx
, int on
)
244 ioctl(fd
, TIOCMGET
, &flags
);
250 ioctl(fd
, TIOCMSET
, &flags
);
254 static ssize_t
_modbus_rtu_send(modbus_t
*ctx
, const uint8_t *req
, int req_length
)
257 modbus_rtu_t
*ctx_rtu
= ctx
->backend_data
;
259 return (WriteFile(ctx_rtu
->w_ser
.fd
, req
, req_length
, &n_bytes
, NULL
))
263 #if HAVE_DECL_TIOCM_RTS
264 modbus_rtu_t
*ctx_rtu
= ctx
->backend_data
;
265 if (ctx_rtu
->rts
!= MODBUS_RTU_RTS_NONE
) {
269 fprintf(stderr
, "Sending request using RTS signal\n");
272 ctx_rtu
->set_rts(ctx
, ctx_rtu
->rts
== MODBUS_RTU_RTS_UP
);
273 usleep(ctx_rtu
->rts_delay
);
275 size
= write(ctx
->s
, req
, req_length
);
277 usleep(ctx_rtu
->onebyte_time
* req_length
+ ctx_rtu
->rts_delay
);
278 ctx_rtu
->set_rts(ctx
, ctx_rtu
->rts
!= MODBUS_RTU_RTS_UP
);
283 return write(ctx
->s
, req
, req_length
);
284 #if HAVE_DECL_TIOCM_RTS
290 static int _modbus_rtu_receive(modbus_t
*ctx
, uint8_t *req
)
293 modbus_rtu_t
*ctx_rtu
= ctx
->backend_data
;
295 if (ctx_rtu
->confirmation_to_ignore
) {
296 _modbus_receive_msg(ctx
, req
, MSG_CONFIRMATION
);
297 /* Ignore errors and reset the flag */
298 ctx_rtu
->confirmation_to_ignore
= FALSE
;
301 printf("Confirmation to ignore\n");
304 rc
= _modbus_receive_msg(ctx
, req
, MSG_INDICATION
);
306 /* The next expected message is a confirmation to ignore */
307 ctx_rtu
->confirmation_to_ignore
= TRUE
;
313 static ssize_t
_modbus_rtu_recv(modbus_t
*ctx
, uint8_t *rsp
, int rsp_length
)
316 return win32_ser_read(&((modbus_rtu_t
*) ctx
->backend_data
)->w_ser
, rsp
, rsp_length
);
318 return read(ctx
->s
, rsp
, rsp_length
);
322 static int _modbus_rtu_flush(modbus_t
*);
324 static int _modbus_rtu_pre_check_confirmation(modbus_t
*ctx
,
329 /* Check responding slave is the slave we requested (except for broacast
331 if (req
[0] != rsp
[0] && req
[0] != MODBUS_BROADCAST_ADDRESS
) {
334 "The responding slave %d isn't the requested slave %d\n",
345 /* The check_crc16 function shall return 0 if the message is ignored and the
346 message length if the CRC is valid. Otherwise it shall return -1 and set
347 errno to EMBBADCRC. */
348 static int _modbus_rtu_check_integrity(modbus_t
*ctx
, uint8_t *msg
, const int msg_length
)
350 uint16_t crc_calculated
;
351 uint16_t crc_received
;
354 /* Filter on the Modbus unit identifier (slave) in RTU mode to avoid useless
356 if (slave
!= ctx
->slave
&& slave
!= MODBUS_BROADCAST_ADDRESS
) {
358 printf("Request for slave %d ignored (not %d)\n", slave
, ctx
->slave
);
360 /* Following call to check_confirmation handles this error */
364 crc_calculated
= crc16(msg
, msg_length
- 2);
365 crc_received
= (msg
[msg_length
- 1] << 8) | msg
[msg_length
- 2];
367 /* Check CRC of msg */
368 if (crc_calculated
== crc_received
) {
373 "ERROR CRC received 0x%0X != CRC calculated 0x%0X\n",
378 if (ctx
->error_recovery
& MODBUS_ERROR_RECOVERY_PROTOCOL
) {
379 _modbus_rtu_flush(ctx
);
386 /* Sets up a serial port for RTU communications */
388 static int _modbus_rtu_connect(modbus_t
*ctx
)
391 modbus_rtu_t
*ctx_rtu
= ctx
->backend_data
;
394 printf("Opening %s at %d bauds (%c, %d, %d)\n",
402 /* Some references here:
403 * http://msdn.microsoft.com/en-us/library/aa450602.aspx
405 win32_ser_init(&ctx_rtu
->w_ser
);
407 /* ctx_rtu->device should contain a string like "COMxx:" xx being a decimal
409 ctx_rtu
->w_ser
.fd
= CreateFileA(
410 ctx_rtu
->device
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
413 if (ctx_rtu
->w_ser
.fd
== INVALID_HANDLE_VALUE
) {
416 "ERROR Can't open the device %s (LastError %d)\n",
418 (int) GetLastError());
424 ctx_rtu
->old_dcb
.DCBlength
= sizeof(DCB
);
425 if (!GetCommState(ctx_rtu
->w_ser
.fd
, &ctx_rtu
->old_dcb
)) {
428 "ERROR Error getting configuration (LastError %d)\n",
429 (int) GetLastError());
431 CloseHandle(ctx_rtu
->w_ser
.fd
);
432 ctx_rtu
->w_ser
.fd
= INVALID_HANDLE_VALUE
;
436 /* Build new configuration (starting from current settings) */
437 dcb
= ctx_rtu
->old_dcb
;
440 dcb
.BaudRate
= ctx_rtu
->baud
;
443 switch (ctx_rtu
->data_bit
) {
460 if (ctx_rtu
->stop_bit
== 1)
461 dcb
.StopBits
= ONESTOPBIT
;
463 dcb
.StopBits
= TWOSTOPBITS
;
466 if (ctx_rtu
->parity
== 'N') {
467 dcb
.Parity
= NOPARITY
;
469 } else if (ctx_rtu
->parity
== 'E') {
470 dcb
.Parity
= EVENPARITY
;
474 dcb
.Parity
= ODDPARITY
;
478 /* Hardware handshaking left as default settings retrieved */
480 /* No software handshaking */
481 dcb
.fTXContinueOnXoff
= TRUE
;
485 /* Binary mode (it's the only supported on Windows anyway) */
488 /* Don't want errors to be blocking */
489 dcb
.fAbortOnError
= FALSE
;
492 if (!SetCommState(ctx_rtu
->w_ser
.fd
, &dcb
)) {
495 "ERROR Error setting new configuration (LastError %d)\n",
496 (int) GetLastError());
498 CloseHandle(ctx_rtu
->w_ser
.fd
);
499 ctx_rtu
->w_ser
.fd
= INVALID_HANDLE_VALUE
;
507 static speed_t
_get_termios_speed(int baud
, int debug
)
612 fprintf(stderr
, "WARNING Unknown baud rate %d (B9600 used)\n", baud
);
620 static int _modbus_rtu_connect(modbus_t
*ctx
)
625 modbus_rtu_t
*ctx_rtu
= ctx
->backend_data
;
628 printf("Opening %s at %d bauds (%c, %d, %d)\n",
636 /* The O_NOCTTY flag tells UNIX that this program doesn't want
637 to be the "controlling terminal" for that port. If you
638 don't specify this then any input (such as keyboard abort
639 signals and so forth) will affect your process
641 Timeouts are ignored in canonical input mode or when the
642 NDELAY option is set on the file via open or fcntl */
643 flags
= O_RDWR
| O_NOCTTY
| O_NDELAY
| O_EXCL
;
648 ctx
->s
= open(ctx_rtu
->device
, flags
);
652 "ERROR Can't open the device %s (%s)\n",
660 tcgetattr(ctx
->s
, &ctx_rtu
->old_tios
);
662 memset(&tios
, 0, sizeof(struct termios
));
664 /* C_ISPEED Input baud (new interface)
665 C_OSPEED Output baud (new interface)
668 /* Set the baud rate */
671 On MacOS, constants of baud rates are equal to the integer in argument but
672 that's not the case under Linux so we have to find the corresponding
673 constant. Until the code is upgraded to termios2, the list of possible
674 values is limited (no 14400 for example).
677 speed
= ctx_rtu
->baud
;
679 speed
= _get_termios_speed(ctx_rtu
->baud
, ctx
->debug
);
682 if ((cfsetispeed(&tios
, speed
) < 0) || (cfsetospeed(&tios
, speed
) < 0)) {
688 /* C_CFLAG Control options
689 CLOCAL Local line - do not change "owner" of port
690 CREAD Enable receiver
692 tios
.c_cflag
|= (CREAD
| CLOCAL
);
693 /* CSIZE, HUPCL, CRTSCTS (hardware flow control) */
695 /* Set data bits (5, 6, 7, 8 bits)
696 CSIZE Bit mask for data bits
698 tios
.c_cflag
&= ~CSIZE
;
699 switch (ctx_rtu
->data_bit
) {
715 /* Stop bit (1 or 2) */
716 if (ctx_rtu
->stop_bit
== 1)
717 tios
.c_cflag
&= ~CSTOPB
;
719 tios
.c_cflag
|= CSTOPB
;
721 /* PARENB Enable parity bit
722 PARODD Use odd parity instead of even */
723 if (ctx_rtu
->parity
== 'N') {
725 tios
.c_cflag
&= ~PARENB
;
726 } else if (ctx_rtu
->parity
== 'E') {
728 tios
.c_cflag
|= PARENB
;
729 tios
.c_cflag
&= ~PARODD
;
732 tios
.c_cflag
|= PARENB
;
733 tios
.c_cflag
|= PARODD
;
736 /* Read the man page of termios if you need more information. */
738 /* This field isn't used on POSIX systems
742 /* C_LFLAG Line options
744 ISIG Enable SIGINTR, SIGSUSP, SIGDSUSP, and SIGQUIT signals
745 ICANON Enable canonical input (else raw)
746 XCASE Map uppercase \lowercase (obsolete)
747 ECHO Enable echoing of input characters
748 ECHOE Echo erase character as BS-SP-BS
749 ECHOK Echo NL after kill character
751 NOFLSH Disable flushing of input buffers after
752 interrupt or quit characters
753 IEXTEN Enable extended functions
754 ECHOCTL Echo control characters as ^char and delete as ~?
755 ECHOPRT Echo erased character as character erased
756 ECHOKE BS-SP-BS entire line on line kill
757 FLUSHO Output being flushed
758 PENDIN Retype pending input at next read or input char
759 TOSTOP Send SIGTTOU for background output
761 Canonical input is line-oriented. Input characters are put
762 into a buffer which can be edited interactively by the user
763 until a CR (carriage return) or LF (line feed) character is
766 Raw input is unprocessed. Input characters are passed
767 through exactly as they are received, when they are
768 received. Generally you'll deselect the ICANON, ECHO,
769 ECHOE, and ISIG options when using raw input
773 tios
.c_lflag
&= ~(ICANON
| ECHO
| ECHOE
| ISIG
);
775 /* C_IFLAG Input options
778 INPCK Enable parity check
779 IGNPAR Ignore parity errors
780 PARMRK Mark parity errors
781 ISTRIP Strip parity bits
782 IXON Enable software flow control (outgoing)
783 IXOFF Enable software flow control (incoming)
784 IXANY Allow any character to start flow again
785 IGNBRK Ignore break condition
786 BRKINT Send a SIGINT when a break condition is detected
790 IUCLC Map uppercase to lowercase
791 IMAXBEL Echo BEL on input line too long
793 if (ctx_rtu
->parity
== 'N') {
795 tios
.c_iflag
&= ~INPCK
;
797 tios
.c_iflag
|= INPCK
;
800 /* Software flow control is disabled */
801 tios
.c_iflag
&= ~(IXON
| IXOFF
| IXANY
);
803 /* C_OFLAG Output options
804 OPOST Postprocess output (not set = raw output)
805 ONLCR Map NL to CR-NL
807 ONCLR ant others needs OPOST to be enabled
811 tios
.c_oflag
&= ~OPOST
;
813 /* C_CC Control characters
814 VMIN Minimum number of characters to read
815 VTIME Time to wait for data (tenths of seconds)
817 UNIX serial interface drivers provide the ability to
818 specify character and packet timeouts. Two elements of the
819 c_cc array are used for timeouts: VMIN and VTIME. Timeouts
820 are ignored in canonical input mode or when the NDELAY
821 option is set on the file via open or fcntl.
823 VMIN specifies the minimum number of characters to read. If
824 it is set to 0, then the VTIME value specifies the time to
825 wait for every character read. Note that this does not mean
826 that a read call for N bytes will wait for N characters to
827 come in. Rather, the timeout will apply to the first
828 character and the read call will return the number of
829 characters immediately available (up to the number you
832 If VMIN is non-zero, VTIME specifies the time to wait for
833 the first character read. If a character is read within the
834 time given, any read will block (wait) until all VMIN
835 characters are read. That is, once the first character is
836 read, the serial interface driver expects to receive an
837 entire packet of characters (VMIN bytes total). If no
838 character is read within the time allowed, then the call to
839 read returns 0. This method allows you to tell the serial
840 driver you need exactly N bytes and any read call will
841 return 0 or N bytes. However, the timeout only applies to
842 the first character read, so if for some reason the driver
843 misses one character inside the N byte packet then the read
844 call could block forever waiting for additional input
847 VTIME specifies the amount of time to wait for incoming
848 characters in tenths of seconds. If VTIME is set to 0 (the
849 default), reads will block (wait) indefinitely unless the
850 NDELAY option is set on the port with open or fcntl.
852 /* Unused because we use open with the NDELAY option */
854 tios
.c_cc
[VTIME
] = 0;
856 if (tcsetattr(ctx
->s
, TCSANOW
, &tios
) < 0) {
866 // FIXME Temporary solution before rewriting Windows RTU backend
867 static unsigned int _modbus_rtu_is_connected(modbus_t
*ctx
)
870 modbus_rtu_t
*ctx_rtu
= ctx
->backend_data
;
872 /* Check if file handle is valid */
873 return ctx_rtu
->w_ser
.fd
!= INVALID_HANDLE_VALUE
;
879 int modbus_rtu_set_serial_mode(modbus_t
*ctx
, int mode
)
886 if (ctx
->backend
->backend_type
== _MODBUS_BACKEND_TYPE_RTU
) {
887 #if HAVE_DECL_TIOCSRS485
888 modbus_rtu_t
*ctx_rtu
= ctx
->backend_data
;
889 struct serial_rs485 rs485conf
;
891 if (mode
== MODBUS_RTU_RS485
) {
893 if (ioctl(ctx
->s
, TIOCGRS485
, &rs485conf
) < 0) {
897 rs485conf
.flags
|= SER_RS485_ENABLED
;
898 if (ioctl(ctx
->s
, TIOCSRS485
, &rs485conf
) < 0) {
902 ctx_rtu
->serial_mode
= MODBUS_RTU_RS485
;
904 } else if (mode
== MODBUS_RTU_RS232
) {
905 /* Turn off RS485 mode only if required */
906 if (ctx_rtu
->serial_mode
== MODBUS_RTU_RS485
) {
907 /* The ioctl call is avoided because it can fail on some RS232 ports */
908 if (ioctl(ctx
->s
, TIOCGRS485
, &rs485conf
) < 0) {
911 rs485conf
.flags
&= ~SER_RS485_ENABLED
;
912 if (ioctl(ctx
->s
, TIOCSRS485
, &rs485conf
) < 0) {
916 ctx_rtu
->serial_mode
= MODBUS_RTU_RS232
;
921 fprintf(stderr
, "This function isn't supported on your platform\n");
928 /* Wrong backend and invalid mode specified */
933 int modbus_rtu_get_serial_mode(modbus_t
*ctx
)
940 if (ctx
->backend
->backend_type
== _MODBUS_BACKEND_TYPE_RTU
) {
941 #if HAVE_DECL_TIOCSRS485
942 modbus_rtu_t
*ctx_rtu
= ctx
->backend_data
;
943 return ctx_rtu
->serial_mode
;
946 fprintf(stderr
, "This function isn't supported on your platform\n");
957 int modbus_rtu_get_rts(modbus_t
*ctx
)
964 if (ctx
->backend
->backend_type
== _MODBUS_BACKEND_TYPE_RTU
) {
965 #if HAVE_DECL_TIOCM_RTS
966 modbus_rtu_t
*ctx_rtu
= ctx
->backend_data
;
970 fprintf(stderr
, "This function isn't supported on your platform\n");
981 int modbus_rtu_set_rts(modbus_t
*ctx
, int mode
)
988 if (ctx
->backend
->backend_type
== _MODBUS_BACKEND_TYPE_RTU
) {
989 #if HAVE_DECL_TIOCM_RTS
990 modbus_rtu_t
*ctx_rtu
= ctx
->backend_data
;
992 if (mode
== MODBUS_RTU_RTS_NONE
|| mode
== MODBUS_RTU_RTS_UP
||
993 mode
== MODBUS_RTU_RTS_DOWN
) {
996 /* Set the RTS bit in order to not reserve the RS485 bus */
997 ctx_rtu
->set_rts(ctx
, ctx_rtu
->rts
!= MODBUS_RTU_RTS_UP
);
1006 fprintf(stderr
, "This function isn't supported on your platform\n");
1012 /* Wrong backend or invalid mode specified */
1017 int modbus_rtu_set_custom_rts(modbus_t
*ctx
, void (*set_rts
)(modbus_t
*ctx
, int on
))
1024 if (ctx
->backend
->backend_type
== _MODBUS_BACKEND_TYPE_RTU
) {
1025 #if HAVE_DECL_TIOCM_RTS
1026 modbus_rtu_t
*ctx_rtu
= ctx
->backend_data
;
1027 ctx_rtu
->set_rts
= set_rts
;
1031 fprintf(stderr
, "This function isn't supported on your platform\n");
1042 int modbus_rtu_get_rts_delay(modbus_t
*ctx
)
1049 if (ctx
->backend
->backend_type
== _MODBUS_BACKEND_TYPE_RTU
) {
1050 #if HAVE_DECL_TIOCM_RTS
1051 modbus_rtu_t
*ctx_rtu
;
1052 ctx_rtu
= (modbus_rtu_t
*) ctx
->backend_data
;
1053 return ctx_rtu
->rts_delay
;
1056 fprintf(stderr
, "This function isn't supported on your platform\n");
1067 int modbus_rtu_set_rts_delay(modbus_t
*ctx
, int us
)
1069 if (ctx
== NULL
|| us
< 0) {
1074 if (ctx
->backend
->backend_type
== _MODBUS_BACKEND_TYPE_RTU
) {
1075 #if HAVE_DECL_TIOCM_RTS
1076 modbus_rtu_t
*ctx_rtu
;
1077 ctx_rtu
= (modbus_rtu_t
*) ctx
->backend_data
;
1078 ctx_rtu
->rts_delay
= us
;
1082 fprintf(stderr
, "This function isn't supported on your platform\n");
1093 static void _modbus_rtu_close(modbus_t
*ctx
)
1095 /* Restore line settings and close file descriptor in RTU mode */
1096 modbus_rtu_t
*ctx_rtu
= ctx
->backend_data
;
1099 /* Revert settings */
1100 if (!SetCommState(ctx_rtu
->w_ser
.fd
, &ctx_rtu
->old_dcb
) && ctx
->debug
) {
1102 "ERROR Couldn't revert to configuration (LastError %d)\n",
1103 (int) GetLastError());
1106 if (!CloseHandle(ctx_rtu
->w_ser
.fd
) && ctx
->debug
) {
1108 "ERROR Error while closing handle (LastError %d)\n",
1109 (int) GetLastError());
1113 tcsetattr(ctx
->s
, TCSANOW
, &ctx_rtu
->old_tios
);
1120 static int _modbus_rtu_flush(modbus_t
*ctx
)
1123 modbus_rtu_t
*ctx_rtu
= ctx
->backend_data
;
1124 ctx_rtu
->w_ser
.n_bytes
= 0;
1125 return (PurgeComm(ctx_rtu
->w_ser
.fd
, PURGE_RXCLEAR
) == FALSE
);
1127 return tcflush(ctx
->s
, TCIOFLUSH
);
1132 _modbus_rtu_select(modbus_t
*ctx
, fd_set
*rset
, struct timeval
*tv
, int length_to_read
)
1136 s_rc
= win32_ser_select(
1137 &((modbus_rtu_t
*) ctx
->backend_data
)->w_ser
, length_to_read
, tv
);
1147 while ((s_rc
= select(ctx
->s
+ 1, rset
, NULL
, NULL
, tv
)) == -1) {
1148 if (errno
== EINTR
) {
1150 fprintf(stderr
, "A non blocked signal was caught\n");
1152 /* Necessary after an error */
1154 FD_SET(ctx
->s
, rset
);
1170 static void _modbus_rtu_free(modbus_t
*ctx
)
1172 if (ctx
->backend_data
) {
1173 free(((modbus_rtu_t
*) ctx
->backend_data
)->device
);
1174 free(ctx
->backend_data
);
1181 const modbus_backend_t _modbus_rtu_backend
= {
1182 _MODBUS_BACKEND_TYPE_RTU
,
1183 _MODBUS_RTU_HEADER_LENGTH
,
1184 _MODBUS_RTU_CHECKSUM_LENGTH
,
1185 MODBUS_RTU_MAX_ADU_LENGTH
,
1187 _modbus_rtu_build_request_basis
,
1188 _modbus_rtu_build_response_basis
,
1189 _modbus_rtu_get_response_tid
,
1190 _modbus_rtu_send_msg_pre
,
1192 _modbus_rtu_receive
,
1194 _modbus_rtu_check_integrity
,
1195 _modbus_rtu_pre_check_confirmation
,
1196 _modbus_rtu_connect
,
1197 _modbus_rtu_is_connected
,
1207 modbus_new_rtu(const char *device
, int baud
, char parity
, int data_bit
, int stop_bit
)
1210 modbus_rtu_t
*ctx_rtu
;
1212 /* Check device argument */
1213 if (device
== NULL
|| *device
== 0) {
1214 fprintf(stderr
, "The device string is empty\n");
1219 /* Check baud argument */
1221 fprintf(stderr
, "The baud rate value must not be zero\n");
1226 ctx
= (modbus_t
*) malloc(sizeof(modbus_t
));
1231 _modbus_init_common(ctx
);
1232 ctx
->backend
= &_modbus_rtu_backend
;
1233 ctx
->backend_data
= (modbus_rtu_t
*) malloc(sizeof(modbus_rtu_t
));
1234 if (ctx
->backend_data
== NULL
) {
1239 ctx_rtu
= (modbus_rtu_t
*) ctx
->backend_data
;
1241 /* Device name and \0 */
1242 ctx_rtu
->device
= (char *) malloc((strlen(device
) + 1) * sizeof(char));
1243 if (ctx_rtu
->device
== NULL
) {
1250 strcpy_s(ctx_rtu
->device
, strlen(device
) + 1, device
);
1252 strcpy(ctx_rtu
->device
, device
);
1255 ctx_rtu
->baud
= baud
;
1256 if (parity
== 'N' || parity
== 'E' || parity
== 'O') {
1257 ctx_rtu
->parity
= parity
;
1263 ctx_rtu
->data_bit
= data_bit
;
1264 ctx_rtu
->stop_bit
= stop_bit
;
1266 #if HAVE_DECL_TIOCSRS485
1267 /* The RS232 mode has been set by default */
1268 ctx_rtu
->serial_mode
= MODBUS_RTU_RS232
;
1271 #if HAVE_DECL_TIOCM_RTS
1272 /* The RTS use has been set by default */
1273 ctx_rtu
->rts
= MODBUS_RTU_RTS_NONE
;
1275 /* Calculate estimated time in micro second to send one byte */
1276 ctx_rtu
->onebyte_time
=
1277 1000000 * (1 + data_bit
+ (parity
== 'N' ? 0 : 1) + stop_bit
) / baud
;
1279 /* The internal function is used by default to set RTS */
1280 ctx_rtu
->set_rts
= _modbus_rtu_ioctl_rts
;
1282 /* The delay before and after transmission when toggling the RTS pin */
1283 ctx_rtu
->rts_delay
= ctx_rtu
->onebyte_time
;
1286 ctx_rtu
->confirmation_to_ignore
= FALSE
;