Sfoglia il codice sorgente

Add support for user defined RTS toggle function

Jimmy Bergström 11 anni fa
parent
commit
a8676b785a
5 ha cambiato i file con 80 aggiunte e 4 eliminazioni
  1. 1 0
      doc/Makefile.am
  2. 45 0
      doc/modbus_rtu_set_custom_rts.txt
  3. 1 0
      src/modbus-rtu-private.h
  4. 32 4
      src/modbus-rtu.c
  5. 1 0
      src/modbus-rtu.h

+ 1 - 0
doc/Makefile.am

@@ -29,6 +29,7 @@ TXT3 = \
         modbus_rtu_set_serial_mode.txt \
         modbus_rtu_get_rts.txt \
         modbus_rtu_set_rts.txt \
+        modbus_rtu_set_custom_rts.txt \
         modbus_send_raw_request.txt \
         modbus_set_bits_from_bytes.txt \
         modbus_set_bits_from_byte.txt \

+ 45 - 0
doc/modbus_rtu_set_custom_rts.txt

@@ -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 - 0
src/modbus-rtu-private.h

@@ -70,6 +70,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;

+ 32 - 4
src/modbus-rtu.c

@@ -252,8 +252,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);
@@ -282,13 +283,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 {
@@ -983,7 +984,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 {
@@ -1027,6 +1028,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 */
@@ -1184,6 +1210,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;

+ 1 - 0
src/modbus-rtu.h

@@ -31,6 +31,7 @@ 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