From ba5ecf9ad913850067590d7e40aa591c4887e2a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jimmy=20Bergstr=C3=B6m?= Date: Tue, 14 Jan 2014 19:41:56 +0100 Subject: [PATCH] Add support for user defined RTS toggle function --- doc/Makefile.am | 1 + doc/modbus_rtu_set_custom_rts.txt | 45 +++++++++++++++++++++++++++++++ src/modbus-rtu-private.h | 1 + src/modbus-rtu.c | 36 ++++++++++++++++++++++--- src/modbus-rtu.h | 2 ++ 5 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 doc/modbus_rtu_set_custom_rts.txt diff --git a/doc/Makefile.am b/doc/Makefile.am index 9f7e282c9..c86889804 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -33,6 +33,7 @@ MAN3 = \ modbus_rtu_set_serial_mode.3 \ modbus_rtu_get_rts.3 \ modbus_rtu_set_rts.3 \ + modbus_rtu_set_custom_rts.3 \ modbus_send_raw_request.3 \ modbus_set_bits_from_bytes.3 \ modbus_set_bits_from_byte.3 \ diff --git a/doc/modbus_rtu_set_custom_rts.txt b/doc/modbus_rtu_set_custom_rts.txt new file mode 100644 index 000000000..c17bd3d1f --- /dev/null +++ b/doc/modbus_rtu_set_custom_rts.txt @@ -0,0 +1,45 @@ +modbus_rtu_set_custom_rts(3) +============================ + + +NAME +---- +modbus_rtu_set_custom_rts - set a function to be used for custom RTS implementation + + +SYNOPSIS +-------- +*int modbus_rtu_set_custom_rts(modbus_t *'ctx', void (*'set_rts') (modbus_t *ctx, int on))* + + +DESCRIPTION +----------- +The _modbus_rtu_set_custom_rts()_ function shall set a custom function to be +called when the RTS pin is to be set before and after a transmission. By default +this is set to an internal function that toggles the RTS pin using an ioctl +call. + +Note that this function adheres to the RTS mode, the values MODBUS_RTU_RTS_UP or +MODBUS_RTU_RTS_DOWN must be used for the function to be called. + +This function can only be used with a context using a RTU backend. + + +RETURN VALUE +------------ +The _modbus_rtu_set_custom_rts()_ function shall return 0 if successful. +Otherwise it shall return -1 and set errno to one of the values defined below. + + +ERRORS +------ +*EINVAL*:: +The libmodbus backend is not RTU. + + +AUTHORS +------- +Jimmy Bergström + +The libmodbus documentation was written by Stéphane Raimbault + diff --git a/src/modbus-rtu-private.h b/src/modbus-rtu-private.h index 41aa4f291..e06810374 100644 --- a/src/modbus-rtu-private.h +++ b/src/modbus-rtu-private.h @@ -82,6 +82,7 @@ typedef struct _modbus_rtu { #if HAVE_DECL_TIOCM_RTS int rts; int onebyte_time; + void (*set_rts) (modbus_t *ctx, int on); #endif /* To handle many slaves on the same link */ int confirmation_to_ignore; diff --git a/src/modbus-rtu.c b/src/modbus-rtu.c index 6251f7d29..4b1a0cbfb 100644 --- a/src/modbus-rtu.c +++ b/src/modbus-rtu.c @@ -261,8 +261,9 @@ static int win32_ser_read(struct win32_ser *ws, uint8_t *p_msg, #endif #if HAVE_DECL_TIOCM_RTS -static void _modbus_rtu_ioctl_rts(int fd, int on) +static void _modbus_rtu_ioctl_rts(modbus_t *ctx, int on) { + int fd = ctx->s; int flags; ioctl(fd, TIOCMGET, &flags); @@ -291,13 +292,13 @@ static ssize_t _modbus_rtu_send(modbus_t *ctx, const uint8_t *req, int req_lengt fprintf(stderr, "Sending request using RTS signal\n"); } - _modbus_rtu_ioctl_rts(ctx->s, ctx_rtu->rts == MODBUS_RTU_RTS_UP); + ctx_rtu->set_rts(ctx, ctx_rtu->rts == MODBUS_RTU_RTS_UP); usleep(_MODBUS_RTU_TIME_BETWEEN_RTS_SWITCH); size = write(ctx->s, req, req_length); usleep(ctx_rtu->onebyte_time * req_length + _MODBUS_RTU_TIME_BETWEEN_RTS_SWITCH); - _modbus_rtu_ioctl_rts(ctx->s, ctx_rtu->rts != MODBUS_RTU_RTS_UP); + ctx_rtu->set_rts(ctx, ctx_rtu->rts != MODBUS_RTU_RTS_UP); return size; } else { @@ -992,7 +993,7 @@ int modbus_rtu_set_rts(modbus_t *ctx, int mode) ctx_rtu->rts = mode; /* Set the RTS bit in order to not reserve the RS485 bus */ - _modbus_rtu_ioctl_rts(ctx->s, ctx_rtu->rts != MODBUS_RTU_RTS_UP); + ctx_rtu->set_rts(ctx, ctx_rtu->rts != MODBUS_RTU_RTS_UP); return 0; } else { @@ -1036,6 +1037,31 @@ int modbus_rtu_get_rts(modbus_t *ctx) } } +int modbus_rtu_set_custom_rts(modbus_t *ctx, void (*set_rts) (modbus_t *ctx, int on)) +{ + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) { +#if HAVE_DECL_TIOCM_RTS + modbus_rtu_t *ctx_rtu = ctx->backend_data; + ctx_rtu->set_rts = set_rts; + return 0; +#else + if (ctx->debug) { + fprintf(stderr, "This function isn't supported on your platform\n"); + } + errno = ENOTSUP; + return -1; +#endif + } else { + errno = EINVAL; + return -1; + } +} + static void _modbus_rtu_close(modbus_t *ctx) { /* Restore line settings and close file descriptor in RTU mode */ @@ -1187,6 +1213,8 @@ modbus_t* modbus_new_rtu(const char *device, /* Calculate estimated time in micro second to send one byte */ ctx_rtu->onebyte_time = (1000 * 1000) * (1 + data_bit + (parity == 'N' ? 0 : 1) + stop_bit) / baud; + + ctx_rtu->set_rts = _modbus_rtu_ioctl_rts; #endif ctx_rtu->confirmation_to_ignore = FALSE; diff --git a/src/modbus-rtu.h b/src/modbus-rtu.h index ce7619da9..010380e3d 100644 --- a/src/modbus-rtu.h +++ b/src/modbus-rtu.h @@ -44,6 +44,8 @@ MODBUS_API int modbus_rtu_get_serial_mode(modbus_t *ctx); MODBUS_API int modbus_rtu_set_rts(modbus_t *ctx, int mode); MODBUS_API int modbus_rtu_get_rts(modbus_t *ctx); +MODBUS_API int modbus_rtu_set_custom_rts(modbus_t *ctx, void (*set_rts) (modbus_t *ctx, int on)); + MODBUS_END_DECLS #endif /* MODBUS_RTU_H */