Commit a8676b785a487470e7a03675846e90cdabebade7
Committed by
Stéphane Raimbault
1 parent
6c1ef13d
Add support for user defined RTS toggle function
Showing
5 changed files
with
80 additions
and
4 deletions
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 |