Commit 27b39f7e45c754764db26e9b75497492067481e6
1 parent
88b2eaf3
Review of RTS flow control code
- avoid export of _modbus_rtu_set_rts and change its name to avoid confusion - namespace RTU functions and constants - use_rts is renamed rts - add missing '_' in function name - remove useless debug message in usual write - wrong message about 'not supported' - add check for TIOCM_RTS support - block RTS flow control when not available
Showing
4 changed files
with
51 additions
and
53 deletions
configure.ac
| @@ -129,6 +129,8 @@ fi | @@ -129,6 +129,8 @@ fi | ||
| 129 | 129 | ||
| 130 | # Check for RS485 support (Linux kernel version 2.6.28+) | 130 | # Check for RS485 support (Linux kernel version 2.6.28+) |
| 131 | AC_CHECK_DECLS([TIOCSRS485], [], [], [[#include <sys/ioctl.h>]]) | 131 | AC_CHECK_DECLS([TIOCSRS485], [], [], [[#include <sys/ioctl.h>]]) |
| 132 | +# Check for RTS flags | ||
| 133 | +AC_CHECK_DECLS([TIOCM_RTS], [], [], [[#include <sys/ioctl.h>]]) | ||
| 132 | 134 | ||
| 133 | AC_CONFIG_FILES([ | 135 | AC_CONFIG_FILES([ |
| 134 | Makefile | 136 | Makefile |
src/modbus-rtu-private.h
| @@ -37,6 +37,10 @@ | @@ -37,6 +37,10 @@ | ||
| 37 | 37 | ||
| 38 | #define _MODBUS_RTU_CHECKSUM_LENGTH 2 | 38 | #define _MODBUS_RTU_CHECKSUM_LENGTH 2 |
| 39 | 39 | ||
| 40 | +/* Time waited beetween the RTS switch before transmit data or after transmit | ||
| 41 | + data before to read */ | ||
| 42 | +#define _MODBUS_RTU_TIME_BETWEEN_RTS_SWITCH 10000 | ||
| 43 | + | ||
| 40 | #if defined(_WIN32) | 44 | #if defined(_WIN32) |
| 41 | #define ENOTSUP WSAEOPNOTSUPP | 45 | #define ENOTSUP WSAEOPNOTSUPP |
| 42 | 46 | ||
| @@ -80,12 +84,8 @@ typedef struct _modbus_rtu { | @@ -80,12 +84,8 @@ typedef struct _modbus_rtu { | ||
| 80 | #endif | 84 | #endif |
| 81 | #if HAVE_DECL_TIOCSRS485 | 85 | #if HAVE_DECL_TIOCSRS485 |
| 82 | int serial_mode; | 86 | int serial_mode; |
| 83 | - int use_rts; | 87 | + int rts; |
| 84 | #endif | 88 | #endif |
| 85 | } modbus_rtu_t; | 89 | } modbus_rtu_t; |
| 86 | 90 | ||
| 87 | -/* Time waited beetween the RTS switch before transmit data or after transmit data before to read */ | ||
| 88 | -#define TIME_BETWEEN_RTS_SWITCH 10000 | ||
| 89 | -void _modbus_rtu_setrts(int fd, int on); | ||
| 90 | - | ||
| 91 | #endif /* _MODBUS_RTU_PRIVATE_H_ */ | 91 | #endif /* _MODBUS_RTU_PRIVATE_H_ */ |
src/modbus-rtu.c
| @@ -257,6 +257,21 @@ static int win32_ser_read(struct win32_ser *ws, uint8_t *p_msg, | @@ -257,6 +257,21 @@ static int win32_ser_read(struct win32_ser *ws, uint8_t *p_msg, | ||
| 257 | } | 257 | } |
| 258 | #endif | 258 | #endif |
| 259 | 259 | ||
| 260 | +void _modbus_rtu_ioctl_rts(int fd, int on) | ||
| 261 | +{ | ||
| 262 | +#if HAVE_DECL_TIOCM_RTS | ||
| 263 | + int flags; | ||
| 264 | + | ||
| 265 | + ioctl(fd, TIOCMGET, &flags); | ||
| 266 | + if (on) { | ||
| 267 | + flags |= TIOCM_RTS; | ||
| 268 | + } else { | ||
| 269 | + flags &= ~TIOCM_RTS; | ||
| 270 | + } | ||
| 271 | + ioctl(fd, TIOCMSET, &flags); | ||
| 272 | +#endif | ||
| 273 | +} | ||
| 274 | + | ||
| 260 | ssize_t _modbus_rtu_send(modbus_t *ctx, const uint8_t *req, int req_length) | 275 | ssize_t _modbus_rtu_send(modbus_t *ctx, const uint8_t *req, int req_length) |
| 261 | { | 276 | { |
| 262 | #if defined(_WIN32) | 277 | #if defined(_WIN32) |
| @@ -265,25 +280,23 @@ ssize_t _modbus_rtu_send(modbus_t *ctx, const uint8_t *req, int req_length) | @@ -265,25 +280,23 @@ ssize_t _modbus_rtu_send(modbus_t *ctx, const uint8_t *req, int req_length) | ||
| 265 | return (WriteFile(ctx_rtu->w_ser.fd, req, req_length, &n_bytes, NULL)) ? n_bytes : -1; | 280 | return (WriteFile(ctx_rtu->w_ser.fd, req, req_length, &n_bytes, NULL)) ? n_bytes : -1; |
| 266 | #else | 281 | #else |
| 267 | modbus_rtu_t *ctx_rtu = ctx->backend_data; | 282 | modbus_rtu_t *ctx_rtu = ctx->backend_data; |
| 268 | - if (ctx_rtu->use_rts != MODBUS_RTS_NONE) { | 283 | + if (ctx_rtu->rts != MODBUS_RTU_RTS_NONE) { |
| 284 | + ssize_t size; | ||
| 285 | + | ||
| 269 | if (ctx->debug) { | 286 | if (ctx->debug) { |
| 270 | - fprintf(stderr, "sending request using RTS signal\n"); | 287 | + fprintf(stderr, "Sending request using RTS signal\n"); |
| 271 | } | 288 | } |
| 272 | 289 | ||
| 273 | - ssize_t size; | ||
| 274 | - | ||
| 275 | - _modbus_rtu_setrts(ctx->s, (ctx_rtu->use_rts == MODBUS_RTS_UP ? 1 : 0)); | ||
| 276 | - usleep(TIME_BETWEEN_RTS_SWITCH); | 290 | + _modbus_rtu_ioctl_rts(ctx->s, ctx_rtu->rts == MODBUS_RTU_RTS_UP); |
| 291 | + usleep(_MODBUS_RTU_TIME_BETWEEN_RTS_SWITCH); | ||
| 277 | 292 | ||
| 278 | size = write(ctx->s, req, req_length); | 293 | size = write(ctx->s, req, req_length); |
| 279 | - usleep(TIME_BETWEEN_RTS_SWITCH); | ||
| 280 | - _modbus_rtu_setrts(ctx->s, (ctx_rtu->use_rts == MODBUS_RTS_UP ? 0 : 1)); | 294 | + |
| 295 | + usleep(_MODBUS_RTU_TIME_BETWEEN_RTS_SWITCH); | ||
| 296 | + _modbus_rtu_ioctl_rts(ctx->s, ctx_rtu->rts != MODBUS_RTU_RTS_UP); | ||
| 281 | 297 | ||
| 282 | return size; | 298 | return size; |
| 283 | } else { | 299 | } else { |
| 284 | - if (ctx->debug) { | ||
| 285 | - fprintf(stderr, "sending request without RTS signal\n"); | ||
| 286 | - } | ||
| 287 | return write(ctx->s, req, req_length); | 300 | return write(ctx->s, req, req_length); |
| 288 | } | 301 | } |
| 289 | #endif | 302 | #endif |
| @@ -726,7 +739,7 @@ static int _modbus_rtu_connect(modbus_t *ctx) | @@ -726,7 +739,7 @@ static int _modbus_rtu_connect(modbus_t *ctx) | ||
| 726 | ctx_rtu->serial_mode = MODBUS_RTU_RS232; | 739 | ctx_rtu->serial_mode = MODBUS_RTU_RS232; |
| 727 | 740 | ||
| 728 | /* The RTS use has been set by default */ | 741 | /* The RTS use has been set by default */ |
| 729 | - ctx_rtu->use_rts = MODBUS_RTS_NONE; | 742 | + ctx_rtu->rts = MODBUS_RTU_RTS_NONE; |
| 730 | 743 | ||
| 731 | #endif | 744 | #endif |
| 732 | 745 | ||
| @@ -789,35 +802,32 @@ int modbus_rtu_get_serial_mode(modbus_t *ctx) { | @@ -789,35 +802,32 @@ int modbus_rtu_get_serial_mode(modbus_t *ctx) { | ||
| 789 | } | 802 | } |
| 790 | } | 803 | } |
| 791 | 804 | ||
| 792 | -int modbus_rtu_set_use_rts(modbus_t *ctx, int mode) | 805 | +int modbus_rtu_set_rts(modbus_t *ctx, int mode) |
| 793 | { | 806 | { |
| 807 | +#if HAVE_DECL_TIOCM_RTS | ||
| 794 | if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) { | 808 | if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) { |
| 795 | modbus_rtu_t *ctx_rtu = ctx->backend_data; | 809 | modbus_rtu_t *ctx_rtu = ctx->backend_data; |
| 796 | - | ||
| 797 | - if (mode == MODBUS_RTS_NONE || mode == MODBUS_RTS_UP || mode == MODBUS_RTS_DOWN) { | ||
| 798 | - ctx_rtu->use_rts = mode; | ||
| 799 | 810 | ||
| 800 | - // Set the RTS bit in order to not reserve the RS485 bus | ||
| 801 | - _modbus_rtu_setrts(ctx->s, (ctx_rtu->use_rts == MODBUS_RTS_UP ? 0 : 1)); | ||
| 802 | - return 0; | ||
| 803 | - } | 811 | + if (mode == MODBUS_RTU_RTS_NONE || mode == MODBUS_RTU_RTS_UP || |
| 812 | + mode == MODBUS_RTU_RTS_DOWN) { | ||
| 813 | + ctx_rtu->rts = mode; | ||
| 804 | 814 | ||
| 805 | - if (ctx->debug) { | ||
| 806 | - fprintf(stderr, "This function isn't supported on your platform\n"); | 815 | + /* Set the RTS bit in order to not reserve the RS485 bus */ |
| 816 | + _modbus_rtu_ioctl_rts(ctx->s, ctx_rtu->rts != MODBUS_RTU_RTS_UP); | ||
| 817 | + | ||
| 818 | + return 0; | ||
| 807 | } | 819 | } |
| 808 | - errno = ENOTSUP; | ||
| 809 | - return -1; | ||
| 810 | } | 820 | } |
| 811 | - | ||
| 812 | - /* Wrong backend and invalid mode specified */ | 821 | +#endif |
| 822 | + /* Wrong backend or invalid mode specified */ | ||
| 813 | errno = EINVAL; | 823 | errno = EINVAL; |
| 814 | return -1; | 824 | return -1; |
| 815 | } | 825 | } |
| 816 | 826 | ||
| 817 | -int modbus_rtu_get_use_rts(modbus_t *ctx) { | 827 | +int modbus_rtu_get_rts(modbus_t *ctx) { |
| 818 | if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) { | 828 | if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) { |
| 819 | modbus_rtu_t *ctx_rtu = ctx->backend_data; | 829 | modbus_rtu_t *ctx_rtu = ctx->backend_data; |
| 820 | - return ctx_rtu->use_rts; | 830 | + return ctx_rtu->rts; |
| 821 | } else { | 831 | } else { |
| 822 | errno = EINVAL; | 832 | errno = EINVAL; |
| 823 | return -1; | 833 | return -1; |
| @@ -975,17 +985,3 @@ modbus_t* modbus_new_rtu(const char *device, | @@ -975,17 +985,3 @@ modbus_t* modbus_new_rtu(const char *device, | ||
| 975 | 985 | ||
| 976 | return ctx; | 986 | return ctx; |
| 977 | } | 987 | } |
| 978 | - | ||
| 979 | -void _modbus_rtu_setrts(int fd, int on) | ||
| 980 | -{ | ||
| 981 | - int controlbits; | ||
| 982 | - | ||
| 983 | - ioctl(fd, TIOCMGET, &controlbits); | ||
| 984 | - if (on) { | ||
| 985 | - controlbits |= TIOCM_RTS; | ||
| 986 | - } else { | ||
| 987 | - controlbits &= ~TIOCM_RTS; | ||
| 988 | - } | ||
| 989 | - ioctl(fd, TIOCMSET, &controlbits); | ||
| 990 | -} | ||
| 991 | - |
src/modbus-rtu.h
| @@ -32,14 +32,14 @@ modbus_t* modbus_new_rtu(const char *device, int baud, char parity, | @@ -32,14 +32,14 @@ modbus_t* modbus_new_rtu(const char *device, int baud, char parity, | ||
| 32 | #define MODBUS_RTU_RS232 0 | 32 | #define MODBUS_RTU_RS232 0 |
| 33 | #define MODBUS_RTU_RS485 1 | 33 | #define MODBUS_RTU_RS485 1 |
| 34 | 34 | ||
| 35 | -#define MODBUS_RTS_NONE 0 | ||
| 36 | -#define MODBUS_RTS_UP 1 | ||
| 37 | -#define MODBUS_RTS_DOWN 2 | ||
| 38 | - | ||
| 39 | int modbus_rtu_set_serial_mode(modbus_t *ctx, int mode); | 35 | int modbus_rtu_set_serial_mode(modbus_t *ctx, int mode); |
| 40 | int modbus_rtu_get_serial_mode(modbus_t *ctx); | 36 | int modbus_rtu_get_serial_mode(modbus_t *ctx); |
| 41 | 37 | ||
| 42 | -int modbus_rtu_set_use_rts(modbus_t *ctx, int mode); | ||
| 43 | -int modbus_rtu_get_use_rts(modbus_t *ctx); | 38 | +#define MODBUS_RTU_RTS_NONE 0 |
| 39 | +#define MODBUS_RTU_RTS_UP 1 | ||
| 40 | +#define MODBUS_RTU_RTS_DOWN 2 | ||
| 41 | + | ||
| 42 | +int modbus_rtu_set_rts(modbus_t *ctx, int mode); | ||
| 43 | +int modbus_rtu_get_rts(modbus_t *ctx); | ||
| 44 | 44 | ||
| 45 | #endif /* _MODBUS_RTU_H_ */ | 45 | #endif /* _MODBUS_RTU_H_ */ |