Commit a8676b785a487470e7a03675846e90cdabebade7

Authored by Jimmy Bergström
Committed by Stéphane Raimbault
1 parent 6c1ef13d

Add support for user defined RTS toggle function

doc/Makefile.am
@@ -29,6 +29,7 @@ TXT3 = \ @@ -29,6 +29,7 @@ TXT3 = \
29 modbus_rtu_set_serial_mode.txt \ 29 modbus_rtu_set_serial_mode.txt \
30 modbus_rtu_get_rts.txt \ 30 modbus_rtu_get_rts.txt \
31 modbus_rtu_set_rts.txt \ 31 modbus_rtu_set_rts.txt \
  32 + modbus_rtu_set_custom_rts.txt \
32 modbus_send_raw_request.txt \ 33 modbus_send_raw_request.txt \
33 modbus_set_bits_from_bytes.txt \ 34 modbus_set_bits_from_bytes.txt \
34 modbus_set_bits_from_byte.txt \ 35 modbus_set_bits_from_byte.txt \
doc/modbus_rtu_set_custom_rts.txt 0 → 100644
  1 +modbus_rtu_set_custom_rts(3)
  2 +============================
  3 +
  4 +
  5 +NAME
  6 +----
  7 +modbus_rtu_set_custom_rts - set a function to be used for custom RTS implementation
  8 +
  9 +
  10 +SYNOPSIS
  11 +--------
  12 +*int modbus_rtu_set_custom_rts(modbus_t *'ctx', void (*'set_rts') (modbus_t *ctx, int on))*
  13 +
  14 +
  15 +DESCRIPTION
  16 +-----------
  17 +The _modbus_rtu_set_custom_rts()_ function shall set a custom function to be
  18 +called when the RTS pin is to be set before and after a transmission. By default
  19 +this is set to an internal function that toggles the RTS pin using an ioctl
  20 +call.
  21 +
  22 +Note that this function adheres to the RTS mode, the values MODBUS_RTU_RTS_UP or
  23 +MODBUS_RTU_RTS_DOWN must be used for the function to be called.
  24 +
  25 +This function can only be used with a context using a RTU backend.
  26 +
  27 +
  28 +RETURN VALUE
  29 +------------
  30 +The _modbus_rtu_set_custom_rts()_ function shall return 0 if successful.
  31 +Otherwise it shall return -1 and set errno to one of the values defined below.
  32 +
  33 +
  34 +ERRORS
  35 +------
  36 +*EINVAL*::
  37 +The libmodbus backend is not RTU.
  38 +
  39 +
  40 +AUTHORS
  41 +-------
  42 +Jimmy Bergström <jimmy@ekontroll.com>
  43 +
  44 +The libmodbus documentation was written by Stéphane Raimbault
  45 +<stephane.raimbault@gmail.com>
src/modbus-rtu-private.h
@@ -70,6 +70,7 @@ typedef struct _modbus_rtu { @@ -70,6 +70,7 @@ typedef struct _modbus_rtu {
70 #if HAVE_DECL_TIOCM_RTS 70 #if HAVE_DECL_TIOCM_RTS
71 int rts; 71 int rts;
72 int onebyte_time; 72 int onebyte_time;
  73 + void (*set_rts) (modbus_t *ctx, int on);
73 #endif 74 #endif
74 /* To handle many slaves on the same link */ 75 /* To handle many slaves on the same link */
75 int confirmation_to_ignore; 76 int confirmation_to_ignore;
src/modbus-rtu.c
@@ -252,8 +252,9 @@ static int win32_ser_read(struct win32_ser *ws, uint8_t *p_msg, @@ -252,8 +252,9 @@ static int win32_ser_read(struct win32_ser *ws, uint8_t *p_msg,
252 #endif 252 #endif
253 253
254 #if HAVE_DECL_TIOCM_RTS 254 #if HAVE_DECL_TIOCM_RTS
255 -static void _modbus_rtu_ioctl_rts(int fd, int on) 255 +static void _modbus_rtu_ioctl_rts(modbus_t *ctx, int on)
256 { 256 {
  257 + int fd = ctx->s;
257 int flags; 258 int flags;
258 259
259 ioctl(fd, TIOCMGET, &flags); 260 ioctl(fd, TIOCMGET, &flags);
@@ -282,13 +283,13 @@ static ssize_t _modbus_rtu_send(modbus_t *ctx, const uint8_t *req, int req_lengt @@ -282,13 +283,13 @@ static ssize_t _modbus_rtu_send(modbus_t *ctx, const uint8_t *req, int req_lengt
282 fprintf(stderr, "Sending request using RTS signal\n"); 283 fprintf(stderr, "Sending request using RTS signal\n");
283 } 284 }
284 285
285 - _modbus_rtu_ioctl_rts(ctx->s, ctx_rtu->rts == MODBUS_RTU_RTS_UP); 286 + ctx_rtu->set_rts(ctx, ctx_rtu->rts == MODBUS_RTU_RTS_UP);
286 usleep(_MODBUS_RTU_TIME_BETWEEN_RTS_SWITCH); 287 usleep(_MODBUS_RTU_TIME_BETWEEN_RTS_SWITCH);
287 288
288 size = write(ctx->s, req, req_length); 289 size = write(ctx->s, req, req_length);
289 290
290 usleep(ctx_rtu->onebyte_time * req_length + _MODBUS_RTU_TIME_BETWEEN_RTS_SWITCH); 291 usleep(ctx_rtu->onebyte_time * req_length + _MODBUS_RTU_TIME_BETWEEN_RTS_SWITCH);
291 - _modbus_rtu_ioctl_rts(ctx->s, ctx_rtu->rts != MODBUS_RTU_RTS_UP); 292 + ctx_rtu->set_rts(ctx, ctx_rtu->rts != MODBUS_RTU_RTS_UP);
292 293
293 return size; 294 return size;
294 } else { 295 } else {
@@ -983,7 +984,7 @@ int modbus_rtu_set_rts(modbus_t *ctx, int mode) @@ -983,7 +984,7 @@ int modbus_rtu_set_rts(modbus_t *ctx, int mode)
983 ctx_rtu->rts = mode; 984 ctx_rtu->rts = mode;
984 985
985 /* Set the RTS bit in order to not reserve the RS485 bus */ 986 /* Set the RTS bit in order to not reserve the RS485 bus */
986 - _modbus_rtu_ioctl_rts(ctx->s, ctx_rtu->rts != MODBUS_RTU_RTS_UP); 987 + ctx_rtu->set_rts(ctx, ctx_rtu->rts != MODBUS_RTU_RTS_UP);
987 988
988 return 0; 989 return 0;
989 } else { 990 } else {
@@ -1027,6 +1028,31 @@ int modbus_rtu_get_rts(modbus_t *ctx) @@ -1027,6 +1028,31 @@ int modbus_rtu_get_rts(modbus_t *ctx)
1027 } 1028 }
1028 } 1029 }
1029 1030
  1031 +int modbus_rtu_set_custom_rts(modbus_t *ctx, void (*set_rts) (modbus_t *ctx, int on))
  1032 +{
  1033 + if (ctx == NULL) {
  1034 + errno = EINVAL;
  1035 + return -1;
  1036 + }
  1037 +
  1038 + if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) {
  1039 +#if HAVE_DECL_TIOCM_RTS
  1040 + modbus_rtu_t *ctx_rtu = ctx->backend_data;
  1041 + ctx_rtu->set_rts = set_rts;
  1042 + return 0;
  1043 +#else
  1044 + if (ctx->debug) {
  1045 + fprintf(stderr, "This function isn't supported on your platform\n");
  1046 + }
  1047 + errno = ENOTSUP;
  1048 + return -1;
  1049 +#endif
  1050 + } else {
  1051 + errno = EINVAL;
  1052 + return -1;
  1053 + }
  1054 +}
  1055 +
1030 static void _modbus_rtu_close(modbus_t *ctx) 1056 static void _modbus_rtu_close(modbus_t *ctx)
1031 { 1057 {
1032 /* Restore line settings and close file descriptor in RTU mode */ 1058 /* Restore line settings and close file descriptor in RTU mode */
@@ -1184,6 +1210,8 @@ modbus_t* modbus_new_rtu(const char *device, @@ -1184,6 +1210,8 @@ modbus_t* modbus_new_rtu(const char *device,
1184 1210
1185 /* Calculate estimated time in micro second to send one byte */ 1211 /* Calculate estimated time in micro second to send one byte */
1186 ctx_rtu->onebyte_time = (1000 * 1000) * (1 + data_bit + (parity == 'N' ? 0 : 1) + stop_bit) / baud; 1212 ctx_rtu->onebyte_time = (1000 * 1000) * (1 + data_bit + (parity == 'N' ? 0 : 1) + stop_bit) / baud;
  1213 +
  1214 + ctx_rtu->set_rts = _modbus_rtu_ioctl_rts;
1187 #endif 1215 #endif
1188 1216
1189 ctx_rtu->confirmation_to_ignore = FALSE; 1217 ctx_rtu->confirmation_to_ignore = FALSE;
src/modbus-rtu.h
@@ -31,6 +31,7 @@ MODBUS_API int modbus_rtu_get_serial_mode(modbus_t *ctx); @@ -31,6 +31,7 @@ MODBUS_API int modbus_rtu_get_serial_mode(modbus_t *ctx);
31 31
32 MODBUS_API int modbus_rtu_set_rts(modbus_t *ctx, int mode); 32 MODBUS_API int modbus_rtu_set_rts(modbus_t *ctx, int mode);
33 MODBUS_API int modbus_rtu_get_rts(modbus_t *ctx); 33 MODBUS_API int modbus_rtu_get_rts(modbus_t *ctx);
  34 +MODBUS_API int modbus_rtu_set_custom_rts(modbus_t *ctx, void (*set_rts) (modbus_t *ctx, int on));
34 35
35 MODBUS_END_DECLS 36 MODBUS_END_DECLS
36 37