Skip to content

Commit 2a0057a

Browse files
philj56stephane
authored andcommitted
Add termios2 support (allows custom baud rates)
1 parent ef5cb9e commit 2a0057a

3 files changed

Lines changed: 58 additions & 4 deletions

File tree

configure.ac

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ fi
150150
AC_CHECK_DECLS([TIOCSRS485], [], [], [[#include <sys/ioctl.h>]])
151151
# Check for RTS flags
152152
AC_CHECK_DECLS([TIOCM_RTS], [], [], [[#include <sys/ioctl.h>]])
153+
# Check for termios2 support
154+
AC_CHECK_TYPES([struct termios2], [], [], [[#include <asm/termbits.h>]])
153155

154156
WARNING_CFLAGS="-Wall \
155157
-Wmissing-declarations -Wmissing-prototypes \

src/modbus-rtu-private.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@
1616
#if defined(_WIN32)
1717
#include <windows.h>
1818
#else
19+
#if defined(HAVE_STRUCT_TERMIOS2)
20+
/* Prevent duplicate definitions of "struct termios"
21+
* when including <asm/termbits.h> and <termios.h>. */
22+
#define termios
23+
#include <asm/termbits.h>
24+
#undef termios
25+
#endif
1926
#include <termios.h>
2027
#endif
2128

@@ -57,6 +64,9 @@ typedef struct _modbus_rtu {
5764
#if defined(_WIN32)
5865
struct win32_ser w_ser;
5966
DCB old_dcb;
67+
#elif defined(HAVE_STRUCT_TERMIOS2)
68+
/* Save old termios settings */
69+
struct termios2 old_tios;
6070
#else
6171
/* Save old termios settings */
6272
struct termios old_tios;

src/modbus-rtu.c

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
#ifndef _MSC_VER
1313
#include <unistd.h>
1414
#endif
15+
#if defined(HAVE_STRUCT_TERMIOS2)
16+
#include <sys/ioctl.h>
17+
#endif
1518
#include "modbus-private.h"
1619
#include <assert.h>
1720

@@ -503,6 +506,7 @@ static int _modbus_rtu_connect(modbus_t *ctx)
503506
}
504507
#else
505508

509+
#ifndef HAVE_STRUCT_TERMIOS2
506510
static speed_t _get_termios_speed(int baud, int debug)
507511
{
508512
speed_t speed;
@@ -614,13 +618,18 @@ static speed_t _get_termios_speed(int baud, int debug)
614618

615619
return speed;
616620
}
621+
#endif
617622

618623
/* POSIX */
619624
static int _modbus_rtu_connect(modbus_t *ctx)
620625
{
626+
#ifdef HAVE_STRUCT_TERMIOS2
627+
struct termios2 tios;
628+
#else
629+
speed_t speed;
621630
struct termios tios;
631+
#endif
622632
int flags;
623-
speed_t speed;
624633
modbus_rtu_t *ctx_rtu = ctx->backend_data;
625634

626635
if (ctx->debug) {
@@ -656,21 +665,30 @@ static int _modbus_rtu_connect(modbus_t *ctx)
656665
}
657666

658667
/* Save */
668+
#ifdef HAVE_STRUCT_TERMIOS2
669+
ioctl(ctx->s, TCGETS2, &ctx_rtu->old_tios);
670+
#else
659671
tcgetattr(ctx->s, &ctx_rtu->old_tios);
672+
#endif
660673

661-
memset(&tios, 0, sizeof(struct termios));
674+
memset(&tios, 0, sizeof(tios));
662675

663676
/* C_ISPEED Input baud (new interface)
664677
C_OSPEED Output baud (new interface)
665678
*/
666679

667680
/* Set the baud rate */
668681

682+
#ifdef HAVE_STRUCT_TERMIOS2
683+
tios.c_cflag |= BOTHER; /* Allow custom baud rate. */
684+
tios.c_ispeed = ctx_rtu->baud; /* Set input baud rate. */
685+
tios.c_ospeed = ctx_rtu->baud; /* Set output baud rate. */
686+
#else
669687
/*
670688
On MacOS, constants of baud rates are equal to the integer in argument but
671689
that's not the case under Linux so we have to find the corresponding
672-
constant. Until the code is upgraded to termios2, the list of possible
673-
values is limited (no 14400 for example).
690+
constant. Without termios2, the list of possible values is limited
691+
(no 14400 for example).
674692
*/
675693
if (9600 == B9600) {
676694
speed = ctx_rtu->baud;
@@ -683,6 +701,7 @@ static int _modbus_rtu_connect(modbus_t *ctx)
683701
ctx->s = -1;
684702
return -1;
685703
}
704+
#endif
686705

687706
/* C_CFLAG Control options
688707
CLOCAL Local line - do not change "owner" of port
@@ -852,11 +871,28 @@ static int _modbus_rtu_connect(modbus_t *ctx)
852871
tios.c_cc[VMIN] = 0;
853872
tios.c_cc[VTIME] = 0;
854873

874+
#ifdef HAVE_STRUCT_TERMIOS2
875+
if (ioctl(ctx->s, TCSETS2, &tios) < 0) {
876+
close(ctx->s);
877+
ctx->s = -1;
878+
return -1;
879+
}
880+
if (ctx->debug) {
881+
ioctl(ctx->s, TCGETS2, &tios);
882+
if (tios.c_ispeed != (unsigned int)ctx_rtu->baud) {
883+
fprintf(stderr,
884+
"WARNING Failed to set baud rate %d (%d used)\n",
885+
ctx_rtu->baud,
886+
tios.c_ispeed);
887+
}
888+
}
889+
#else
855890
if (tcsetattr(ctx->s, TCSANOW, &tios) < 0) {
856891
close(ctx->s);
857892
ctx->s = -1;
858893
return -1;
859894
}
895+
#endif
860896

861897
return 0;
862898
}
@@ -1107,6 +1143,12 @@ static void _modbus_rtu_close(modbus_t *ctx)
11071143
"ERROR Error while closing handle (LastError %d)\n",
11081144
(int) GetLastError());
11091145
}
1146+
#elif defined(HAVE_STRUCT_TERMIOS2)
1147+
if (ctx->s >= 0) {
1148+
ioctl(ctx->s, TCSETS2, &ctx_rtu->old_tios);
1149+
close(ctx->s);
1150+
ctx->s = -1;
1151+
}
11101152
#else
11111153
if (ctx->s >= 0) {
11121154
tcsetattr(ctx->s, TCSANOW, &ctx_rtu->old_tios);

0 commit comments

Comments
 (0)