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
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
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 | ... | ... |