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 29 modbus_rtu_set_serial_mode.txt \
30 30 modbus_rtu_get_rts.txt \
31 31 modbus_rtu_set_rts.txt \
  32 + modbus_rtu_set_custom_rts.txt \
32 33 modbus_send_raw_request.txt \
33 34 modbus_set_bits_from_bytes.txt \
34 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 70 #if HAVE_DECL_TIOCM_RTS
71 71 int rts;
72 72 int onebyte_time;
  73 + void (*set_rts) (modbus_t *ctx, int on);
73 74 #endif
74 75 /* To handle many slaves on the same link */
75 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 252 #endif
253 253  
254 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 258 int flags;
258 259  
259 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 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 287 usleep(_MODBUS_RTU_TIME_BETWEEN_RTS_SWITCH);
287 288  
288 289 size = write(ctx->s, req, req_length);
289 290  
290 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 294 return size;
294 295 } else {
... ... @@ -983,7 +984,7 @@ int modbus_rtu_set_rts(modbus_t *ctx, int mode)
983 984 ctx_rtu->rts = mode;
984 985  
985 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 989 return 0;
989 990 } else {
... ... @@ -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 1056 static void _modbus_rtu_close(modbus_t *ctx)
1031 1057 {
1032 1058 /* Restore line settings and close file descriptor in RTU mode */
... ... @@ -1184,6 +1210,8 @@ modbus_t* modbus_new_rtu(const char *device,
1184 1210  
1185 1211 /* Calculate estimated time in micro second to send one byte */
1186 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 1215 #endif
1188 1216  
1189 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 31  
32 32 MODBUS_API int modbus_rtu_set_rts(modbus_t *ctx, int mode);
33 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 36 MODBUS_END_DECLS
36 37  
... ...