Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
45 changes: 45 additions & 0 deletions doc/modbus_rtu_set_custom_rts.txt
Original file line number Diff line number Diff line change
@@ -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 <jimmy@ekontroll.com>

The libmodbus documentation was written by Stéphane Raimbault
<stephane.raimbault@gmail.com>
1 change: 1 addition & 0 deletions src/modbus-rtu-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
36 changes: 32 additions & 4 deletions src/modbus-rtu.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions src/modbus-rtu.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */