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 | 129 | |
| 130 | 130 | # Check for RS485 support (Linux kernel version 2.6.28+) |
| 131 | 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 | 135 | AC_CONFIG_FILES([ |
| 134 | 136 | Makefile | ... | ... |
src/modbus-rtu-private.h
| ... | ... | @@ -37,6 +37,10 @@ |
| 37 | 37 | |
| 38 | 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 | 44 | #if defined(_WIN32) |
| 41 | 45 | #define ENOTSUP WSAEOPNOTSUPP |
| 42 | 46 | |
| ... | ... | @@ -80,12 +84,8 @@ typedef struct _modbus_rtu { |
| 80 | 84 | #endif |
| 81 | 85 | #if HAVE_DECL_TIOCSRS485 |
| 82 | 86 | int serial_mode; |
| 83 | - int use_rts; | |
| 87 | + int rts; | |
| 84 | 88 | #endif |
| 85 | 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 | 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 | 257 | } |
| 258 | 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 | 275 | ssize_t _modbus_rtu_send(modbus_t *ctx, const uint8_t *req, int req_length) |
| 261 | 276 | { |
| 262 | 277 | #if defined(_WIN32) |
| ... | ... | @@ -265,25 +280,23 @@ ssize_t _modbus_rtu_send(modbus_t *ctx, const uint8_t *req, int req_length) |
| 265 | 280 | return (WriteFile(ctx_rtu->w_ser.fd, req, req_length, &n_bytes, NULL)) ? n_bytes : -1; |
| 266 | 281 | #else |
| 267 | 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 | 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 | 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 | 298 | return size; |
| 283 | 299 | } else { |
| 284 | - if (ctx->debug) { | |
| 285 | - fprintf(stderr, "sending request without RTS signal\n"); | |
| 286 | - } | |
| 287 | 300 | return write(ctx->s, req, req_length); |
| 288 | 301 | } |
| 289 | 302 | #endif |
| ... | ... | @@ -726,7 +739,7 @@ static int _modbus_rtu_connect(modbus_t *ctx) |
| 726 | 739 | ctx_rtu->serial_mode = MODBUS_RTU_RS232; |
| 727 | 740 | |
| 728 | 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 | 744 | #endif |
| 732 | 745 | |
| ... | ... | @@ -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 | 808 | if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) { |
| 795 | 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 | 823 | errno = EINVAL; |
| 814 | 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 | 828 | if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) { |
| 819 | 829 | modbus_rtu_t *ctx_rtu = ctx->backend_data; |
| 820 | - return ctx_rtu->use_rts; | |
| 830 | + return ctx_rtu->rts; | |
| 821 | 831 | } else { |
| 822 | 832 | errno = EINVAL; |
| 823 | 833 | return -1; |
| ... | ... | @@ -975,17 +985,3 @@ modbus_t* modbus_new_rtu(const char *device, |
| 975 | 985 | |
| 976 | 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 | 32 | #define MODBUS_RTU_RS232 0 |
| 33 | 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 | 35 | int modbus_rtu_set_serial_mode(modbus_t *ctx, int mode); |
| 40 | 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 | 45 | #endif /* _MODBUS_RTU_H_ */ | ... | ... |