From 9bf830959754a8909a8477fdd238dfb31e3216ce Mon Sep 17 00:00:00 2001 From: Stéphane Raimbault Date: Sun, 29 May 2011 23:33:10 +0200 Subject: [PATCH] Add functions to set/get RS485 communications on Linux --- NEWS | 3 ++- configure.ac | 1 + src/modbus-rtu-private.h | 1 + src/modbus-rtu.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/modbus-rtu.h | 9 +++++++++ 5 files changed, 63 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 67fdd0e..0b35867 100644 --- a/NEWS +++ b/NEWS @@ -18,7 +18,8 @@ libmodbus 2.9.4 (2011-05-XX) * modbus_set_timeout_begin -> modbus_set_response_timeout * modbus_get_timeout_end -> modbus_get_byte_timeout * modbus_set_timeout_end -> modbus_set_byte_timeout - +- New functions modbus_set/get_serial_mode by Manfred Gruber and Stéphane + Raimbault for RS485 communications libmodbus 2.9.3 (2011-01-14) ============================ diff --git a/configure.ac b/configure.ac index 5c83973..810d5a8 100644 --- a/configure.ac +++ b/configure.ac @@ -77,6 +77,7 @@ AC_CHECK_HEADERS([ \ netinet/tcp.h \ arpa/inet.h \ netdb.h \ + linux/serial.h \ ]) # Check whether to build docs / install man pages diff --git a/src/modbus-rtu-private.h b/src/modbus-rtu-private.h index a15025c..8376878 100644 --- a/src/modbus-rtu-private.h +++ b/src/modbus-rtu-private.h @@ -74,6 +74,7 @@ typedef struct _modbus_rtu { #else /* Save old termios settings */ struct termios old_tios; + int serial_mode; #endif } modbus_rtu_t; diff --git a/src/modbus-rtu.c b/src/modbus-rtu.c index 983e9c1..0b6eeac 100644 --- a/src/modbus-rtu.c +++ b/src/modbus-rtu.c @@ -30,6 +30,11 @@ #include "modbus-rtu.h" #include "modbus-rtu-private.h" +#if defined(linux) +#include +#include +#endif + /* Table of CRC values for high-order byte */ static const uint8_t table_crc_hi[] = { 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, @@ -692,11 +697,55 @@ static int _modbus_rtu_connect(modbus_t *ctx) if (tcsetattr(ctx->s, TCSANOW, &tios) < 0) { return -1; } -#endif + /* The RS232 mode has been set by default */ + ctx_rtu->serial_mode = MODBUS_RTU_RS232; +#endif return 0; } +#if defined(linux) +int modbus_rtu_set_serial_mode(modbus_t *ctx, int mode) +{ + if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) { + modbus_rtu_t *ctx_rtu = ctx->backend_data; + struct serial_rs485 rs485conf; + memset(&rs485conf, 0x0, sizeof(struct serial_rs485)); + + if (mode == MODBUS_RTU_RS485) { + rs485conf.flags = SER_RS485_ENABLED; + if (ioctl(ctx->s, TIOCSRS485, &rs485conf) < 0) { + return -1; + } + + ctx_rtu->serial_mode |= MODBUS_RTU_RS485; + return 0; + } else if (mode == MODBUS_RTU_RS232) { + if (ioctl(ctx->s, TIOCSRS485, &rs485conf) < 0) { + return -1; + } + + ctx_rtu->serial_mode = MODBUS_RTU_RS232; + return 0; + } + } + + /* Wrong backend and invalid mode specified */ + errno = EINVAL; + return -1; +} + +int modbus_rtu_get_serial_mode(modbus_t *ctx) { + if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) { + modbus_rtu_t *ctx_rtu = ctx->backend_data; + return ctx_rtu->serial_mode; + } else { + errno = EINVAL; + return -1; + } +} +#endif + void _modbus_rtu_close(modbus_t *ctx) { /* Closes the file descriptor in RTU mode */ diff --git a/src/modbus-rtu.h b/src/modbus-rtu.h index edfcda2..4cbb375 100644 --- a/src/modbus-rtu.h +++ b/src/modbus-rtu.h @@ -28,4 +28,13 @@ modbus_t* modbus_new_rtu(const char *device, int baud, char parity, int data_bit, int stop_bit); +#if defined(linux) +/* On Linux, we can tell the kernel for RS485 communication */ +#define MODBUS_RTU_RS232 0 +#define MODBUS_RTU_RS485 1 + +int modbus_rtu_set_serial_mode(modbus_t *ctx, int mode); +int modbus_rtu_get_serial_mode(modbus_t *ctx); +#endif + #endif /* _MODBUS_RTU_H_ */ -- libgit2 0.21.4