Commit 783ce3c583f4d6094ed7e9a68c41534fc2bceffd

Authored by Peter M. Groen
1 parent 0df27b07

Setting up working version

3rdparty/libmodbus/config.h
1 -/* config.h. Generated from config.h.in by configure. */  
2 -/* config.h.in. Generated from configure.ac by autoheader. */  
3 -  
4 /* Define to 1 if you have the <arpa/inet.h> header file. */ 1 /* Define to 1 if you have the <arpa/inet.h> header file. */
5 #define HAVE_ARPA_INET_H 1 2 #define HAVE_ARPA_INET_H 1
6 3
7 -/* Define to 1 if you have the declaration of `TIOCSRS485', and to 0 if you  
8 - don't. */ 4 +/* Define to 1 if you have the declaration of `TIOCSRS485', and to 0 if you don't. */
9 #define HAVE_DECL_TIOCSRS485 0 5 #define HAVE_DECL_TIOCSRS485 0
10 6
11 -/* Define to 1 if you have the declaration of `TIOCM_RTS', and to 0 if you  
12 - don't. */ 7 +/* Define to 1 if you have the declaration of `TIOCM_RTS', and to 0 if you don't. */
13 #define HAVE_DECL_TIOCM_RTS 0 8 #define HAVE_DECL_TIOCM_RTS 0
14 9
15 -/* Define to 1 if you have the declaration of `__CYGWIN__', and to 0 if you  
16 - don't. */ 10 +/* Define to 1 if you have the declaration of `__CYGWIN__', and to 0 if you don't. */
17 #define HAVE_DECL___CYGWIN__ 0 11 #define HAVE_DECL___CYGWIN__ 0
18 12
19 /* Define to 1 if you have the <dlfcn.h> header file. */ 13 /* Define to 1 if you have the <dlfcn.h> header file. */
@@ -141,13 +135,13 @@ @@ -141,13 +135,13 @@
141 #define PACKAGE_STRING "libmodbus 3.1.0-1" 135 #define PACKAGE_STRING "libmodbus 3.1.0-1"
142 136
143 /* Define to the one symbol short name of this package. */ 137 /* Define to the one symbol short name of this package. */
144 -#define PACKAGE_TARNAME "libmodbus" 138 +#define PACKAGE_TARNAME "modbus"
145 139
146 /* Define to the home page for this package. */ 140 /* Define to the home page for this package. */
147 #define PACKAGE_URL "" 141 #define PACKAGE_URL ""
148 142
149 /* Define to the version of this package. */ 143 /* Define to the version of this package. */
150 -#define PACKAGE_VERSION "3.1.0-1" 144 +#define PACKAGE_VERSION "1.0.0"
151 145
152 /* Define to 1 if you have the ANSI C header files. */ 146 /* Define to 1 if you have the ANSI C header files. */
153 #define STDC_HEADERS 1 147 #define STDC_HEADERS 1
@@ -156,7 +150,7 @@ @@ -156,7 +150,7 @@
156 #define TIME_WITH_SYS_TIME 1 150 #define TIME_WITH_SYS_TIME 1
157 151
158 /* Version number of package */ 152 /* Version number of package */
159 -#define VERSION "3.1.0-1" 153 +#define VERSION "1.0.0"
160 154
161 /* Define to empty if `const' does not conform to ANSI C. */ 155 /* Define to empty if `const' does not conform to ANSI C. */
162 /* #undef const */ 156 /* #undef const */
3rdparty/libmodbus/modbus-data.c
1 -/*  
2 - * Copyright © 2010-2014 Stéphane Raimbault <stephane.raimbault@gmail.com>  
3 - *  
4 - * SPDX-License-Identifier: LGPL-2.1+  
5 - */  
6 1
7 #include <stdlib.h> 2 #include <stdlib.h>
8 3
9 -#ifndef _MSC_VER  
10 -# include <stdint.h>  
11 -#else  
12 -# include "stdint.h"  
13 -#endif 4 +#include "stdint.h"
14 5
15 #include <string.h> 6 #include <string.h>
16 #include <assert.h> 7 #include <assert.h>
17 -  
18 -#if defined(_WIN32)  
19 -# include <winsock2.h>  
20 -#else  
21 -# include <arpa/inet.h>  
22 -#endif  
23 - 8 +#include <arpa/inet.h>
24 #include <config.h> 9 #include <config.h>
25 10
26 #include "modbus.h" 11 #include "modbus.h"
@@ -29,13 +14,6 @@ @@ -29,13 +14,6 @@
29 # include <byteswap.h> 14 # include <byteswap.h>
30 #endif 15 #endif
31 16
32 -#if defined(__APPLE__)  
33 -# include <libkern/OSByteOrder.h>  
34 -# define bswap_16 OSSwapInt16  
35 -# define bswap_32 OSSwapInt32  
36 -# define bswap_64 OSSwapInt64  
37 -#endif  
38 -  
39 #if defined(__GNUC__) 17 #if defined(__GNUC__)
40 # define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__ * 10) 18 # define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__ * 10)
41 # if GCC_VERSION >= 430 19 # if GCC_VERSION >= 430
@@ -45,13 +23,8 @@ @@ -45,13 +23,8 @@
45 # endif 23 # endif
46 #endif 24 #endif
47 25
48 -#if defined(_MSC_VER) && (_MSC_VER >= 1400)  
49 -# define bswap_32 _byteswap_ulong  
50 -# define bswap_16 _byteswap_ushort  
51 -#endif  
52 -  
53 #if !defined(__CYGWIN__) && !defined(bswap_16) 26 #if !defined(__CYGWIN__) && !defined(bswap_16)
54 -# warning "Fallback on C functions for bswap_16" 27 +#pragma message "Fallback on C functions for bswap_16"
55 static inline uint16_t bswap_16(uint16_t x) 28 static inline uint16_t bswap_16(uint16_t x)
56 { 29 {
57 return (x >> 8) | (x << 8); 30 return (x >> 8) | (x << 8);
@@ -59,7 +32,7 @@ static inline uint16_t bswap_16(uint16_t x) @@ -59,7 +32,7 @@ static inline uint16_t bswap_16(uint16_t x)
59 #endif 32 #endif
60 33
61 #if !defined(bswap_32) 34 #if !defined(bswap_32)
62 -# warning "Fallback on C functions for bswap_32" 35 +#pragma message "Fallback on C functions for bswap_32"
63 static inline uint32_t bswap_32(uint32_t x) 36 static inline uint32_t bswap_32(uint32_t x)
64 { 37 {
65 return (bswap_16(x & 0xffff) << 16) | (bswap_16(x >> 16)); 38 return (bswap_16(x & 0xffff) << 16) | (bswap_16(x >> 16));
@@ -68,24 +41,25 @@ static inline uint32_t bswap_32(uint32_t x) @@ -68,24 +41,25 @@ static inline uint32_t bswap_32(uint32_t x)
68 41
69 /* Sets many bits from a single byte value (all 8 bits of the byte value are 42 /* Sets many bits from a single byte value (all 8 bits of the byte value are
70 set) */ 43 set) */
71 -void modbus_set_bits_from_byte(uint8_t *dest, int idx, const uint8_t value) 44 +void modbus_set_bits_from_byte( uint8_t *dest, int idx, const uint8_t value )
72 { 45 {
73 int i; 46 int i;
74 47
75 - for (i=0; i < 8; i++) { 48 + for (i=0; i < 8; i++)
  49 + {
76 dest[idx+i] = (value & (1 << i)) ? 1 : 0; 50 dest[idx+i] = (value & (1 << i)) ? 1 : 0;
77 } 51 }
78 } 52 }
79 53
80 /* Sets many bits from a table of bytes (only the bits between idx and 54 /* Sets many bits from a table of bytes (only the bits between idx and
81 idx + nb_bits are set) */ 55 idx + nb_bits are set) */
82 -void modbus_set_bits_from_bytes(uint8_t *dest, int idx, unsigned int nb_bits,  
83 - const uint8_t *tab_byte) 56 +void modbus_set_bits_from_bytes( uint8_t *dest, int idx, unsigned int nb_bits, const uint8_t *tab_byte )
84 { 57 {
85 unsigned int i; 58 unsigned int i;
86 int shift = 0; 59 int shift = 0;
87 60
88 - for (i = idx; i < idx + nb_bits; i++) { 61 + for ( i = idx; i < idx + nb_bits; i++ )
  62 + {
89 dest[i] = tab_byte[(i - idx) / 8] & (1 << shift) ? 1 : 0; 63 dest[i] = tab_byte[(i - idx) / 8] & (1 << shift) ? 1 : 0;
90 /* gcc doesn't like: shift = (++shift) % 8; */ 64 /* gcc doesn't like: shift = (++shift) % 8; */
91 shift++; 65 shift++;
@@ -95,19 +69,20 @@ void modbus_set_bits_from_bytes(uint8_t *dest, int idx, unsigned int nb_bits, @@ -95,19 +69,20 @@ void modbus_set_bits_from_bytes(uint8_t *dest, int idx, unsigned int nb_bits,
95 69
96 /* Gets the byte value from many bits. 70 /* Gets the byte value from many bits.
97 To obtain a full byte, set nb_bits to 8. */ 71 To obtain a full byte, set nb_bits to 8. */
98 -uint8_t modbus_get_byte_from_bits(const uint8_t *src, int idx,  
99 - unsigned int nb_bits) 72 +uint8_t modbus_get_byte_from_bits( const uint8_t *src, int idx, unsigned int nb_bits )
100 { 73 {
101 unsigned int i; 74 unsigned int i;
102 uint8_t value = 0; 75 uint8_t value = 0;
103 76
104 - if (nb_bits > 8) { 77 + if (nb_bits > 8)
  78 + {
105 /* Assert is ignored if NDEBUG is set */ 79 /* Assert is ignored if NDEBUG is set */
106 assert(nb_bits < 8); 80 assert(nb_bits < 8);
107 nb_bits = 8; 81 nb_bits = 8;
108 } 82 }
109 83
110 - for (i=0; i < nb_bits; i++) { 84 + for (i=0; i < nb_bits; i++)
  85 + {
111 value |= (src[idx+i] << i); 86 value |= (src[idx+i] << i);
112 } 87 }
113 88
3rdparty/libmodbus/modbus-private.h
1 -/*  
2 - * Copyright © 2010-2012 Stéphane Raimbault <stephane.raimbault@gmail.com>  
3 - *  
4 - * SPDX-License-Identifier: LGPL-2.1+  
5 - */  
6 1
7 -#ifndef MODBUS_PRIVATE_H  
8 -#define MODBUS_PRIVATE_H 2 +#pragma once
9 3
10 -#ifndef _MSC_VER  
11 # include <stdint.h> 4 # include <stdint.h>
12 # include <sys/time.h> 5 # include <sys/time.h>
13 -#else  
14 -# include "stdint.h"  
15 -# include <time.h>  
16 -typedef int ssize_t;  
17 -#endif  
18 #include <sys/types.h> 6 #include <sys/types.h>
19 #include <config.h> 7 #include <config.h>
20 8
@@ -30,16 +18,15 @@ MODBUS_BEGIN_DECLS @@ -30,16 +18,15 @@ MODBUS_BEGIN_DECLS
30 * - HEADER_LENGTH_RTU (1) + function (1) + address (2) + number (2) + CRC (2) 18 * - HEADER_LENGTH_RTU (1) + function (1) + address (2) + number (2) + CRC (2)
31 */ 19 */
32 #define _MIN_REQ_LENGTH 12 20 #define _MIN_REQ_LENGTH 12
33 -  
34 #define _REPORT_SLAVE_ID 180 21 #define _REPORT_SLAVE_ID 180
35 -  
36 #define _MODBUS_EXCEPTION_RSP_LENGTH 5 22 #define _MODBUS_EXCEPTION_RSP_LENGTH 5
37 23
38 /* Timeouts in microsecond (0.5 s) */ 24 /* Timeouts in microsecond (0.5 s) */
39 #define _RESPONSE_TIMEOUT 500000 25 #define _RESPONSE_TIMEOUT 500000
40 #define _BYTE_TIMEOUT 500000 26 #define _BYTE_TIMEOUT 500000
41 27
42 -typedef enum { 28 +typedef enum
  29 +{
43 _MODBUS_BACKEND_TYPE_RTU=0, 30 _MODBUS_BACKEND_TYPE_RTU=0,
44 _MODBUS_BACKEND_TYPE_TCP 31 _MODBUS_BACKEND_TYPE_TCP
45 } modbus_backend_type_t; 32 } modbus_backend_type_t;
@@ -49,7 +36,8 @@ typedef enum { @@ -49,7 +36,8 @@ typedef enum {
49 * | Client | ---------------------->| Server | 36 * | Client | ---------------------->| Server |
50 * ---------- Confirmation Response ---------- 37 * ---------- Confirmation Response ----------
51 */ 38 */
52 -typedef enum { 39 +typedef enum
  40 +{
53 /* Request message on the server side */ 41 /* Request message on the server side */
54 MSG_INDICATION, 42 MSG_INDICATION,
55 /* Request message on the client side */ 43 /* Request message on the client side */
@@ -58,30 +46,29 @@ typedef enum { @@ -58,30 +46,29 @@ typedef enum {
58 46
59 /* This structure reduces the number of params in functions and so 47 /* This structure reduces the number of params in functions and so
60 * optimizes the speed of execution (~ 37%). */ 48 * optimizes the speed of execution (~ 37%). */
61 -typedef struct _sft { 49 +typedef struct _sft
  50 +{
62 int slave; 51 int slave;
63 int function; 52 int function;
64 int t_id; 53 int t_id;
65 } sft_t; 54 } sft_t;
66 55
67 -typedef struct _modbus_backend { 56 +typedef struct _modbus_backend
  57 +{
68 unsigned int backend_type; 58 unsigned int backend_type;
69 unsigned int header_length; 59 unsigned int header_length;
70 unsigned int checksum_length; 60 unsigned int checksum_length;
71 unsigned int max_adu_length; 61 unsigned int max_adu_length;
72 int (*set_slave) (modbus_t *ctx, int slave); 62 int (*set_slave) (modbus_t *ctx, int slave);
73 - int (*build_request_basis) (modbus_t *ctx, int function, int addr,  
74 - int nb, uint8_t *req); 63 + int (*build_request_basis) (modbus_t *ctx, int function, int addr, int nb, uint8_t *req);
75 int (*build_response_basis) (sft_t *sft, uint8_t *rsp); 64 int (*build_response_basis) (sft_t *sft, uint8_t *rsp);
76 int (*prepare_response_tid) (const uint8_t *req, int *req_length); 65 int (*prepare_response_tid) (const uint8_t *req, int *req_length);
77 int (*send_msg_pre) (uint8_t *req, int req_length); 66 int (*send_msg_pre) (uint8_t *req, int req_length);
78 ssize_t (*send) (modbus_t *ctx, const uint8_t *req, int req_length); 67 ssize_t (*send) (modbus_t *ctx, const uint8_t *req, int req_length);
79 int (*receive) (modbus_t *ctx, uint8_t *req); 68 int (*receive) (modbus_t *ctx, uint8_t *req);
80 ssize_t (*recv) (modbus_t *ctx, uint8_t *rsp, int rsp_length); 69 ssize_t (*recv) (modbus_t *ctx, uint8_t *rsp, int rsp_length);
81 - int (*check_integrity) (modbus_t *ctx, uint8_t *msg,  
82 - const int msg_length);  
83 - int (*pre_check_confirmation) (modbus_t *ctx, const uint8_t *req,  
84 - const uint8_t *rsp, int rsp_length); 70 + int (*check_integrity) (modbus_t *ctx, uint8_t *msg, const int msg_length);
  71 + int (*pre_check_confirmation) (modbus_t *ctx, const uint8_t *req, const uint8_t *rsp, int rsp_length);
85 int (*connect) (modbus_t *ctx); 72 int (*connect) (modbus_t *ctx);
86 void (*close) (modbus_t *ctx); 73 void (*close) (modbus_t *ctx);
87 int (*flush) (modbus_t *ctx); 74 int (*flush) (modbus_t *ctx);
@@ -89,7 +76,8 @@ typedef struct _modbus_backend { @@ -89,7 +76,8 @@ typedef struct _modbus_backend {
89 void (*free) (modbus_t *ctx); 76 void (*free) (modbus_t *ctx);
90 } modbus_backend_t; 77 } modbus_backend_t;
91 78
92 -struct _modbus { 79 +struct _modbus
  80 +{
93 /* Slave address */ 81 /* Slave address */
94 int slave; 82 int slave;
95 /* Socket or file descriptor */ 83 /* Socket or file descriptor */
@@ -111,5 +99,3 @@ size_t strlcpy(char *dest, const char *src, size_t dest_size); @@ -111,5 +99,3 @@ size_t strlcpy(char *dest, const char *src, size_t dest_size);
111 #endif 99 #endif
112 100
113 MODBUS_END_DECLS 101 MODBUS_END_DECLS
114 -  
115 -#endif /* MODBUS_PRIVATE_H */  
3rdparty/libmodbus/modbus-rtu-private.h
1 -/*  
2 - * Copyright © 2001-2011 Stéphane Raimbault <stephane.raimbault@gmail.com>  
3 - *  
4 - * SPDX-License-Identifier: LGPL-2.1+  
5 - */  
6 1
7 -#ifndef MODBUS_RTU_PRIVATE_H  
8 -#define MODBUS_RTU_PRIVATE_H 2 +#pragma once
9 3
10 -#ifndef _MSC_VER  
11 #include <stdint.h> 4 #include <stdint.h>
12 -#else  
13 -#include "stdint.h"  
14 -#endif  
15 -  
16 -#if defined(_WIN32)  
17 -#include <windows.h>  
18 -#else  
19 #include <termios.h> 5 #include <termios.h>
20 -#endif  
21 6
22 #define _MODBUS_RTU_HEADER_LENGTH 1 7 #define _MODBUS_RTU_HEADER_LENGTH 1
23 #define _MODBUS_RTU_PRESET_REQ_LENGTH 6 8 #define _MODBUS_RTU_PRESET_REQ_LENGTH 6
@@ -25,24 +10,8 @@ @@ -25,24 +10,8 @@
25 10
26 #define _MODBUS_RTU_CHECKSUM_LENGTH 2 11 #define _MODBUS_RTU_CHECKSUM_LENGTH 2
27 12
28 -#if defined(_WIN32)  
29 -#if !defined(ENOTSUP)  
30 -#define ENOTSUP WSAEOPNOTSUPP  
31 -#endif  
32 -  
33 -/* WIN32: struct containing serial handle and a receive buffer */  
34 -#define PY_BUF_SIZE 512  
35 -struct win32_ser {  
36 - /* File handle */  
37 - HANDLE fd;  
38 - /* Receive buffer */  
39 - uint8_t buf[PY_BUF_SIZE];  
40 - /* Received chars */  
41 - DWORD n_bytes;  
42 -};  
43 -#endif /* _WIN32 */  
44 -  
45 -typedef struct _modbus_rtu { 13 +typedef struct _modbus_rtu
  14 +{
46 /* Device: "/dev/ttyS0", "/dev/ttyUSB0" or "/dev/tty.USA19*" on Mac OS X. */ 15 /* Device: "/dev/ttyS0", "/dev/ttyUSB0" or "/dev/tty.USA19*" on Mac OS X. */
47 char *device; 16 char *device;
48 /* Bauds: 9600, 19200, 57600, 115200, etc */ 17 /* Bauds: 9600, 19200, 57600, 115200, etc */
@@ -53,25 +22,13 @@ typedef struct _modbus_rtu { @@ -53,25 +22,13 @@ typedef struct _modbus_rtu {
53 uint8_t stop_bit; 22 uint8_t stop_bit;
54 /* Parity: 'N', 'O', 'E' */ 23 /* Parity: 'N', 'O', 'E' */
55 char parity; 24 char parity;
56 -#if defined(_WIN32)  
57 - struct win32_ser w_ser;  
58 - DCB old_dcb;  
59 -#else  
60 /* Save old termios settings */ 25 /* Save old termios settings */
61 struct termios old_tios; 26 struct termios old_tios;
62 -#endif 27 +
63 #if HAVE_DECL_TIOCSRS485 28 #if HAVE_DECL_TIOCSRS485
64 int serial_mode; 29 int serial_mode;
65 #endif 30 #endif
66 -//***Not part of libmodbus - added for QModMaster***//  
67 -#if defined(_WIN32) || HAVE_DECL_TIOCM_RTS  
68 - int rts;  
69 - int rts_delay;  
70 - int onebyte_time;  
71 - void (*set_rts) (modbus_t *ctx, int on);  
72 -#endif 31 +
73 /* To handle many slaves on the same link */ 32 /* To handle many slaves on the same link */
74 int confirmation_to_ignore; 33 int confirmation_to_ignore;
75 } modbus_rtu_t; 34 } modbus_rtu_t;
76 -  
77 -#endif /* MODBUS_RTU_PRIVATE_H */  
3rdparty/libmodbus/modbus-rtu.c
1 -/*  
2 - * Copyright © 2001-2011 Stéphane Raimbault <stephane.raimbault@gmail.com>  
3 - *  
4 - * SPDX-License-Identifier: LGPL-2.1+  
5 - */  
6 1
7 #include <stdio.h> 2 #include <stdio.h>
8 #include <stdlib.h> 3 #include <stdlib.h>
9 #include <errno.h> 4 #include <errno.h>
10 #include <fcntl.h> 5 #include <fcntl.h>
11 #include <string.h> 6 #include <string.h>
12 -#ifndef _MSC_VER  
13 #include <unistd.h> 7 #include <unistd.h>
14 -#endif  
15 #include <assert.h> 8 #include <assert.h>
16 9
17 #include "modbus-private.h" 10 #include "modbus-private.h"
@@ -89,12 +82,15 @@ static const uint8_t table_crc_lo[] = { @@ -89,12 +82,15 @@ static const uint8_t table_crc_lo[] = {
89 82
90 /* Define the slave ID of the remote device to talk in master mode or set the 83 /* Define the slave ID of the remote device to talk in master mode or set the
91 * internal slave ID in slave mode */ 84 * internal slave ID in slave mode */
92 -static int _modbus_set_slave(modbus_t *ctx, int slave) 85 +static int _modbus_set_slave( modbus_t *ctx, int slave )
93 { 86 {
94 /* Broadcast address is 0 (MODBUS_BROADCAST_ADDRESS) */ 87 /* Broadcast address is 0 (MODBUS_BROADCAST_ADDRESS) */
95 - if (slave >= 0 && slave <= 247) { 88 + if (slave >= 0 && slave <= 247)
  89 + {
96 ctx->slave = slave; 90 ctx->slave = slave;
97 - } else { 91 + }
  92 + else
  93 + {
98 errno = EINVAL; 94 errno = EINVAL;
99 return -1; 95 return -1;
100 } 96 }
@@ -103,9 +99,7 @@ static int _modbus_set_slave(modbus_t *ctx, int slave) @@ -103,9 +99,7 @@ static int _modbus_set_slave(modbus_t *ctx, int slave)
103 } 99 }
104 100
105 /* Builds a RTU request header */ 101 /* Builds a RTU request header */
106 -static int _modbus_rtu_build_request_basis(modbus_t *ctx, int function,  
107 - int addr, int nb,  
108 - uint8_t *req) 102 +static int _modbus_rtu_build_request_basis( modbus_t *ctx, int function, int addr, int nb, uint8_t *req )
109 { 103 {
110 assert(ctx->slave != -1); 104 assert(ctx->slave != -1);
111 req[0] = ctx->slave; 105 req[0] = ctx->slave;
@@ -119,7 +113,7 @@ static int _modbus_rtu_build_request_basis(modbus_t *ctx, int function, @@ -119,7 +113,7 @@ static int _modbus_rtu_build_request_basis(modbus_t *ctx, int function,
119 } 113 }
120 114
121 /* Builds a RTU response header */ 115 /* Builds a RTU response header */
122 -static int _modbus_rtu_build_response_basis(sft_t *sft, uint8_t *rsp) 116 +static int _modbus_rtu_build_response_basis( sft_t *sft, uint8_t *rsp )
123 { 117 {
124 /* In this case, the slave is certainly valid because a check is already 118 /* In this case, the slave is certainly valid because a check is already
125 * done in _modbus_rtu_listen */ 119 * done in _modbus_rtu_listen */
@@ -129,11 +123,11 @@ static int _modbus_rtu_build_response_basis(sft_t *sft, uint8_t *rsp) @@ -129,11 +123,11 @@ static int _modbus_rtu_build_response_basis(sft_t *sft, uint8_t *rsp)
129 return _MODBUS_RTU_PRESET_RSP_LENGTH; 123 return _MODBUS_RTU_PRESET_RSP_LENGTH;
130 } 124 }
131 125
132 -static uint16_t crc16(uint8_t *buffer, uint16_t buffer_length) 126 +static uint16_t crc16( uint8_t *buffer, uint16_t buffer_length )
133 { 127 {
134 - uint8_t crc_hi = 0xFF; /* high CRC byte initialized */  
135 - uint8_t crc_lo = 0xFF; /* low CRC byte initialized */  
136 - unsigned int i; /* will index into CRC lookup */ 128 + uint8_t crc_hi = 0xFF; /* high CRC byte initialized */
  129 + uint8_t crc_lo = 0xFF; /* low CRC byte initialized */
  130 + unsigned int i; /* will index into CRC lookup */
137 131
138 /* pass through message buffer */ 132 /* pass through message buffer */
139 while (buffer_length--) { 133 while (buffer_length--) {
@@ -145,138 +139,47 @@ static uint16_t crc16(uint8_t *buffer, uint16_t buffer_length) @@ -145,138 +139,47 @@ static uint16_t crc16(uint8_t *buffer, uint16_t buffer_length)
145 return (crc_hi << 8 | crc_lo); 139 return (crc_hi << 8 | crc_lo);
146 } 140 }
147 141
148 -static int _modbus_rtu_prepare_response_tid(const uint8_t *req, int *req_length) 142 +static int _modbus_rtu_prepare_response_tid( const uint8_t *req, int *req_length )
149 { 143 {
150 (*req_length) -= _MODBUS_RTU_CHECKSUM_LENGTH; 144 (*req_length) -= _MODBUS_RTU_CHECKSUM_LENGTH;
151 /* No TID */ 145 /* No TID */
152 return 0; 146 return 0;
153 } 147 }
154 148
155 -static int _modbus_rtu_send_msg_pre(uint8_t *req, int req_length) 149 +static int _modbus_rtu_send_msg_pre( uint8_t *req, int req_length )
156 { 150 {
157 - uint16_t crc = crc16(req, req_length); 151 + uint16_t crc = crc16( req, req_length );
158 req[req_length++] = crc >> 8; 152 req[req_length++] = crc >> 8;
159 req[req_length++] = crc & 0x00FF; 153 req[req_length++] = crc & 0x00FF;
160 154
161 return req_length; 155 return req_length;
162 } 156 }
163 157
164 -#if defined(_WIN32)  
165 -  
166 -/* This simple implementation is sort of a substitute of the select() call,  
167 - * working this way: the win32_ser_select() call tries to read some data from  
168 - * the serial port, setting the timeout as the select() call would. Data read is  
169 - * stored into the receive buffer, that is then consumed by the win32_ser_read()  
170 - * call. So win32_ser_select() does both the event waiting and the reading,  
171 - * while win32_ser_read() only consumes the receive buffer.  
172 - */  
173 -  
174 -static void win32_ser_init(struct win32_ser *ws)  
175 -{  
176 - /* Clear everything */  
177 - memset(ws, 0x00, sizeof(struct win32_ser));  
178 -  
179 - /* Set file handle to invalid */  
180 - ws->fd = INVALID_HANDLE_VALUE;  
181 -}  
182 -  
183 -/* FIXME Try to remove length_to_read -> max_len argument, only used by win32 */  
184 -static int win32_ser_select(struct win32_ser *ws, int max_len,  
185 - const struct timeval *tv)  
186 -{  
187 - COMMTIMEOUTS comm_to;  
188 - unsigned int msec = 0;  
189 -  
190 - /* Check if some data still in the buffer to be consumed */  
191 - if (ws->n_bytes > 0) {  
192 - return 1;  
193 - }  
194 -  
195 - /* Setup timeouts like select() would do.  
196 - FIXME Please someone on Windows can look at this?  
197 - Does it possible to use WaitCommEvent?  
198 - When tv is NULL, MAXDWORD isn't infinite!  
199 - */  
200 - if (tv == NULL) {  
201 - msec = MAXDWORD;  
202 - } else {  
203 - msec = tv->tv_sec * 1000 + tv->tv_usec / 1000;  
204 - if (msec < 1)  
205 - msec = 1;  
206 - }  
207 -  
208 - comm_to.ReadIntervalTimeout = msec;  
209 - comm_to.ReadTotalTimeoutMultiplier = 0;  
210 - comm_to.ReadTotalTimeoutConstant = msec;  
211 - comm_to.WriteTotalTimeoutMultiplier = 0;  
212 - comm_to.WriteTotalTimeoutConstant = 1000;  
213 - SetCommTimeouts(ws->fd, &comm_to);  
214 -  
215 - /* Read some bytes */  
216 - if ((max_len > PY_BUF_SIZE) || (max_len < 0)) {  
217 - max_len = PY_BUF_SIZE;  
218 - }  
219 -  
220 - if (ReadFile(ws->fd, &ws->buf, max_len, &ws->n_bytes, NULL)) {  
221 - /* Check if some bytes available */  
222 - if (ws->n_bytes > 0) {  
223 - /* Some bytes read */  
224 - return 1;  
225 - } else {  
226 - /* Just timed out */  
227 - return 0;  
228 - }  
229 - } else {  
230 - /* Some kind of error */  
231 - return -1;  
232 - }  
233 -}  
234 -  
235 -static int win32_ser_read(struct win32_ser *ws, uint8_t *p_msg,  
236 - unsigned int max_len)  
237 -{  
238 - unsigned int n = ws->n_bytes;  
239 -  
240 - if (max_len < n) {  
241 - n = max_len;  
242 - }  
243 -  
244 - if (n > 0) {  
245 - memcpy(p_msg, ws->buf, n);  
246 - }  
247 -  
248 - ws->n_bytes -= n;  
249 -  
250 - return n;  
251 -}  
252 -#endif  
253 -  
254 #if HAVE_DECL_TIOCM_RTS 158 #if HAVE_DECL_TIOCM_RTS
255 -static void _modbus_rtu_ioctl_rts(modbus_t *ctx, int on) 159 +static void _modbus_rtu_ioctl_rts( modbus_t *ctx, int on )
256 { 160 {
257 int fd = ctx->s; 161 int fd = ctx->s;
258 int flags; 162 int flags;
259 163
260 ioctl(fd, TIOCMGET, &flags); 164 ioctl(fd, TIOCMGET, &flags);
261 - if (on) { 165 + if (on)
  166 + {
262 flags |= TIOCM_RTS; 167 flags |= TIOCM_RTS;
263 - } else { 168 + }
  169 + else
  170 + {
264 flags &= ~TIOCM_RTS; 171 flags &= ~TIOCM_RTS;
265 } 172 }
266 ioctl(fd, TIOCMSET, &flags); 173 ioctl(fd, TIOCMSET, &flags);
267 } 174 }
268 #endif 175 #endif
269 176
270 -static ssize_t _modbus_rtu_send(modbus_t *ctx, const uint8_t *req, int req_length) 177 +static ssize_t _modbus_rtu_send( modbus_t *ctx, const uint8_t *req, int req_length )
271 { 178 {
272 -#if defined(_WIN32)  
273 - modbus_rtu_t *ctx_rtu = ctx->backend_data;  
274 - DWORD n_bytes = 0;  
275 - return (WriteFile(ctx_rtu->w_ser.fd, req, req_length, &n_bytes, NULL)) ? (ssize_t)n_bytes : -1;  
276 -#else  
277 #if HAVE_DECL_TIOCM_RTS 179 #if HAVE_DECL_TIOCM_RTS
278 modbus_rtu_t *ctx_rtu = ctx->backend_data; 180 modbus_rtu_t *ctx_rtu = ctx->backend_data;
279 - if (ctx_rtu->rts != MODBUS_RTU_RTS_NONE) { 181 + if (ctx_rtu->rts != MODBUS_RTU_RTS_NONE)
  182 + {
280 ssize_t size; 183 ssize_t size;
281 184
282 if (ctx->debug) { 185 if (ctx->debug) {
@@ -292,31 +195,37 @@ static ssize_t _modbus_rtu_send(modbus_t *ctx, const uint8_t *req, int req_lengt @@ -292,31 +195,37 @@ static ssize_t _modbus_rtu_send(modbus_t *ctx, const uint8_t *req, int req_lengt
292 ctx_rtu->set_rts(ctx, ctx_rtu->rts != MODBUS_RTU_RTS_UP); 195 ctx_rtu->set_rts(ctx, ctx_rtu->rts != MODBUS_RTU_RTS_UP);
293 196
294 return size; 197 return size;
295 - } else { 198 + }
  199 + else
  200 + {
296 #endif 201 #endif
297 return write(ctx->s, req, req_length); 202 return write(ctx->s, req, req_length);
298 #if HAVE_DECL_TIOCM_RTS 203 #if HAVE_DECL_TIOCM_RTS
299 } 204 }
300 #endif 205 #endif
301 -#endif  
302 } 206 }
303 207
304 -static int _modbus_rtu_receive(modbus_t *ctx, uint8_t *req) 208 +static int _modbus_rtu_receive( modbus_t *ctx, uint8_t *req )
305 { 209 {
306 int rc; 210 int rc;
307 modbus_rtu_t *ctx_rtu = ctx->backend_data; 211 modbus_rtu_t *ctx_rtu = ctx->backend_data;
308 212
309 - if (ctx_rtu->confirmation_to_ignore) { 213 + if( ctx_rtu->confirmation_to_ignore )
  214 + {
310 _modbus_receive_msg(ctx, req, MSG_CONFIRMATION); 215 _modbus_receive_msg(ctx, req, MSG_CONFIRMATION);
311 /* Ignore errors and reset the flag */ 216 /* Ignore errors and reset the flag */
312 ctx_rtu->confirmation_to_ignore = FALSE; 217 ctx_rtu->confirmation_to_ignore = FALSE;
313 rc = 0; 218 rc = 0;
314 - if (ctx->debug) { 219 + if( ctx->debug )
  220 + {
315 printf("Confirmation to ignore\n"); 221 printf("Confirmation to ignore\n");
316 } 222 }
317 - } else {  
318 - rc = _modbus_receive_msg(ctx, req, MSG_INDICATION);  
319 - if (rc == 0) { 223 + }
  224 + else
  225 + {
  226 + rc = _modbus_receive_msg( ctx, req, MSG_INDICATION );
  227 + if( rc == 0 )
  228 + {
320 /* The next expected message is a confirmation to ignore */ 229 /* The next expected message is a confirmation to ignore */
321 ctx_rtu->confirmation_to_ignore = TRUE; 230 ctx_rtu->confirmation_to_ignore = TRUE;
322 } 231 }
@@ -324,40 +233,33 @@ static int _modbus_rtu_receive(modbus_t *ctx, uint8_t *req) @@ -324,40 +233,33 @@ static int _modbus_rtu_receive(modbus_t *ctx, uint8_t *req)
324 return rc; 233 return rc;
325 } 234 }
326 235
327 -static ssize_t _modbus_rtu_recv(modbus_t *ctx, uint8_t *rsp, int rsp_length) 236 +static ssize_t _modbus_rtu_recv( modbus_t *ctx, uint8_t *rsp, int rsp_length )
328 { 237 {
329 -#if defined(_WIN32)  
330 - return win32_ser_read(&((modbus_rtu_t *)ctx->backend_data)->w_ser, rsp, rsp_length);  
331 -#else  
332 return read(ctx->s, rsp, rsp_length); 238 return read(ctx->s, rsp, rsp_length);
333 -#endif  
334 } 239 }
335 240
336 static int _modbus_rtu_flush(modbus_t *); 241 static int _modbus_rtu_flush(modbus_t *);
337 242
338 -static int _modbus_rtu_pre_check_confirmation(modbus_t *ctx, const uint8_t *req,  
339 - const uint8_t *rsp, int rsp_length) 243 +static int _modbus_rtu_pre_check_confirmation(modbus_t *ctx, const uint8_t *req, const uint8_t *rsp, int rsp_length)
340 { 244 {
341 - /* Check responding slave is the slave we requested (except for broacast  
342 - * request) */  
343 - if (req[0] != rsp[0] && req[0] != MODBUS_BROADCAST_ADDRESS) {  
344 - if (ctx->debug) {  
345 - fprintf(stderr,  
346 - "The responding slave %d isn't the requested slave %d\n",  
347 - rsp[0], req[0]); 245 + /* Check responding slave is the slave we requested (except for broacast request) */
  246 + if (req[0] != rsp[0] && req[0] != MODBUS_BROADCAST_ADDRESS)
  247 + {
  248 + if (ctx->debug)
  249 + {
  250 + fprintf(stderr, "The responding slave %d isn't the requested slave %d\n", rsp[0], req[0]);
348 } 251 }
349 errno = EMBBADSLAVE; 252 errno = EMBBADSLAVE;
350 return -1; 253 return -1;
351 - } else {  
352 - return 0;  
353 - } 254 + }
  255 +
  256 + return 0;
354 } 257 }
355 258
356 /* The check_crc16 function shall return 0 is the message is ignored and the 259 /* The check_crc16 function shall return 0 is the message is ignored and the
357 message length if the CRC is valid. Otherwise it shall return -1 and set 260 message length if the CRC is valid. Otherwise it shall return -1 and set
358 errno to EMBADCRC. */ 261 errno to EMBADCRC. */
359 -static int _modbus_rtu_check_integrity(modbus_t *ctx, uint8_t *msg,  
360 - const int msg_length) 262 +static int _modbus_rtu_check_integrity(modbus_t *ctx, uint8_t *msg, const int msg_length)
361 { 263 {
362 uint16_t crc_calculated; 264 uint16_t crc_calculated;
363 uint16_t crc_received; 265 uint16_t crc_received;
@@ -365,8 +267,10 @@ static int _modbus_rtu_check_integrity(modbus_t *ctx, uint8_t *msg, @@ -365,8 +267,10 @@ static int _modbus_rtu_check_integrity(modbus_t *ctx, uint8_t *msg,
365 267
366 /* Filter on the Modbus unit identifier (slave) in RTU mode to avoid useless 268 /* Filter on the Modbus unit identifier (slave) in RTU mode to avoid useless
367 * CRC computing. */ 269 * CRC computing. */
368 - if (slave != ctx->slave && slave != MODBUS_BROADCAST_ADDRESS) {  
369 - if (ctx->debug) { 270 + if (slave != ctx->slave && slave != MODBUS_BROADCAST_ADDRESS)
  271 + {
  272 + if (ctx->debug)
  273 + {
370 printf("Request for slave %d ignored (not %d)\n", slave, ctx->slave); 274 printf("Request for slave %d ignored (not %d)\n", slave, ctx->slave);
371 } 275 }
372 /* Following call to check_confirmation handles this error */ 276 /* Following call to check_confirmation handles this error */
@@ -377,15 +281,20 @@ static int _modbus_rtu_check_integrity(modbus_t *ctx, uint8_t *msg, @@ -377,15 +281,20 @@ static int _modbus_rtu_check_integrity(modbus_t *ctx, uint8_t *msg,
377 crc_received = (msg[msg_length - 2] << 8) | msg[msg_length - 1]; 281 crc_received = (msg[msg_length - 2] << 8) | msg[msg_length - 1];
378 282
379 /* Check CRC of msg */ 283 /* Check CRC of msg */
380 - if (crc_calculated == crc_received) { 284 + if (crc_calculated == crc_received)
  285 + {
381 return msg_length; 286 return msg_length;
382 - } else {  
383 - if (ctx->debug) { 287 + }
  288 + else
  289 + {
  290 + if (ctx->debug)
  291 + {
384 fprintf(stderr, "ERROR CRC received 0x%0X != CRC calculated 0x%0X\n", 292 fprintf(stderr, "ERROR CRC received 0x%0X != CRC calculated 0x%0X\n",
385 crc_received, crc_calculated); 293 crc_received, crc_calculated);
386 } 294 }
387 295
388 - if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_PROTOCOL) { 296 + if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_PROTOCOL)
  297 + {
389 _modbus_rtu_flush(ctx); 298 _modbus_rtu_flush(ctx);
390 } 299 }
391 errno = EMBBADCRC; 300 errno = EMBBADCRC;
@@ -396,189 +305,18 @@ static int _modbus_rtu_check_integrity(modbus_t *ctx, uint8_t *msg, @@ -396,189 +305,18 @@ static int _modbus_rtu_check_integrity(modbus_t *ctx, uint8_t *msg,
396 /* Sets up a serial port for RTU communications */ 305 /* Sets up a serial port for RTU communications */
397 static int _modbus_rtu_connect(modbus_t *ctx) 306 static int _modbus_rtu_connect(modbus_t *ctx)
398 { 307 {
399 -#if defined(_WIN32)  
400 - DCB dcb;  
401 -#else  
402 struct termios tios; 308 struct termios tios;
403 speed_t speed; 309 speed_t speed;
404 int flags; 310 int flags;
405 -#endif 311 +
406 modbus_rtu_t *ctx_rtu = ctx->backend_data; 312 modbus_rtu_t *ctx_rtu = ctx->backend_data;
407 313
408 - if (ctx->debug) { 314 + if (ctx->debug)
  315 + {
409 printf("Opening %s at %d bauds (%c, %d, %d)\n", 316 printf("Opening %s at %d bauds (%c, %d, %d)\n",
410 - ctx_rtu->device, ctx_rtu->baud, ctx_rtu->parity,  
411 - ctx_rtu->data_bit, ctx_rtu->stop_bit);  
412 - }  
413 -  
414 -#if defined(_WIN32)  
415 - /* Some references here:  
416 - * http://msdn.microsoft.com/en-us/library/aa450602.aspx  
417 - */  
418 - win32_ser_init(&ctx_rtu->w_ser);  
419 -  
420 - /* ctx_rtu->device should contain a string like "COMxx:" xx being a decimal  
421 - * number */  
422 - ctx_rtu->w_ser.fd = CreateFileA(ctx_rtu->device,  
423 - GENERIC_READ | GENERIC_WRITE,  
424 - 0,  
425 - NULL,  
426 - OPEN_EXISTING,  
427 - 0,  
428 - NULL);  
429 -  
430 - /* Error checking */  
431 - if (ctx_rtu->w_ser.fd == INVALID_HANDLE_VALUE) {  
432 - if (ctx->debug) {  
433 - fprintf(stderr, "ERROR Can't open the device %s (LastError %d)\n",  
434 - ctx_rtu->device, (int)GetLastError());  
435 - }  
436 - return -1;  
437 - }  
438 -  
439 - /* Save params */  
440 - ctx_rtu->old_dcb.DCBlength = sizeof(DCB);  
441 - if (!GetCommState(ctx_rtu->w_ser.fd, &ctx_rtu->old_dcb)) {  
442 - if (ctx->debug) {  
443 - fprintf(stderr, "ERROR Error getting configuration (LastError %d)\n",  
444 - (int)GetLastError());  
445 - }  
446 - CloseHandle(ctx_rtu->w_ser.fd);  
447 - ctx_rtu->w_ser.fd = INVALID_HANDLE_VALUE;  
448 - return -1; 317 + ctx_rtu->device, ctx_rtu->baud, ctx_rtu->parity, ctx_rtu->data_bit, ctx_rtu->stop_bit);
449 } 318 }
450 319
451 - /* Build new configuration (starting from current settings) */  
452 - dcb = ctx_rtu->old_dcb;  
453 -  
454 - /* Speed setting */  
455 - switch (ctx_rtu->baud) {  
456 - case 110:  
457 - dcb.BaudRate = CBR_110;  
458 - break;  
459 - case 300:  
460 - dcb.BaudRate = CBR_300;  
461 - break;  
462 - case 600:  
463 - dcb.BaudRate = CBR_600;  
464 - break;  
465 - case 1200:  
466 - dcb.BaudRate = CBR_1200;  
467 - break;  
468 - case 2400:  
469 - dcb.BaudRate = CBR_2400;  
470 - break;  
471 - case 4800:  
472 - dcb.BaudRate = CBR_4800;  
473 - break;  
474 - case 9600:  
475 - dcb.BaudRate = CBR_9600;  
476 - break;  
477 - case 14400:  
478 - dcb.BaudRate = CBR_14400;  
479 - break;  
480 - case 19200:  
481 - dcb.BaudRate = CBR_19200;  
482 - break;  
483 - case 38400:  
484 - dcb.BaudRate = CBR_38400;  
485 - break;  
486 - case 57600:  
487 - dcb.BaudRate = CBR_57600;  
488 - break;  
489 - case 115200:  
490 - dcb.BaudRate = CBR_115200;  
491 - break;  
492 - case 230400:  
493 - /* CBR_230400 - not defined */  
494 - dcb.BaudRate = 230400;  
495 - break;  
496 - case 250000:  
497 - dcb.BaudRate = 250000;  
498 - break;  
499 - case 460800:  
500 - dcb.BaudRate = 460800;  
501 - break;  
502 - case 500000:  
503 - dcb.BaudRate = 500000;  
504 - break;  
505 - case 921600:  
506 - dcb.BaudRate = 921600;  
507 - break;  
508 - case 1000000:  
509 - dcb.BaudRate = 1000000;  
510 - break;  
511 - default:  
512 - dcb.BaudRate = CBR_9600;  
513 - if (ctx->debug) {  
514 - fprintf(stderr, "WARNING Unknown baud rate %d for %s (B9600 used)\n",  
515 - ctx_rtu->baud, ctx_rtu->device);  
516 - }  
517 - }  
518 -  
519 - /* Data bits */  
520 - switch (ctx_rtu->data_bit) {  
521 - case 5:  
522 - dcb.ByteSize = 5;  
523 - break;  
524 - case 6:  
525 - dcb.ByteSize = 6;  
526 - break;  
527 - case 7:  
528 - dcb.ByteSize = 7;  
529 - break;  
530 - case 8:  
531 - default:  
532 - dcb.ByteSize = 8;  
533 - break;  
534 - }  
535 -  
536 - /* Stop bits */  
537 - if (ctx_rtu->stop_bit == 1)  
538 - dcb.StopBits = ONESTOPBIT;  
539 - else /* 2 */  
540 - dcb.StopBits = TWOSTOPBITS;  
541 -  
542 - /* Parity */  
543 - if (ctx_rtu->parity == 'N') {  
544 - dcb.Parity = NOPARITY;  
545 - dcb.fParity = FALSE;  
546 - } else if (ctx_rtu->parity == 'E') {  
547 - dcb.Parity = EVENPARITY;  
548 - dcb.fParity = TRUE;  
549 - } else {  
550 - /* odd */  
551 - dcb.Parity = ODDPARITY;  
552 - dcb.fParity = TRUE;  
553 - }  
554 -  
555 - /* Hardware handshaking left as default settings retrieved */  
556 -  
557 - /* No software handshaking */  
558 - dcb.fTXContinueOnXoff = TRUE;  
559 - dcb.fOutX = FALSE;  
560 - dcb.fInX = FALSE;  
561 -  
562 - /* Binary mode (it's the only supported on Windows anyway) */  
563 - dcb.fBinary = TRUE;  
564 -  
565 - /* Don't want errors to be blocking */  
566 - dcb.fAbortOnError = FALSE;  
567 -  
568 - //***Not part of libmodbus - added for QModMaster***//  
569 - dcb.fRtsControl = ctx_rtu->rts;  
570 -  
571 - /* Setup port */  
572 - if (!SetCommState(ctx_rtu->w_ser.fd, &dcb)) {  
573 - if (ctx->debug) {  
574 - fprintf(stderr, "ERROR Error setting new configuration (LastError %d)\n",  
575 - (int)GetLastError());  
576 - }  
577 - CloseHandle(ctx_rtu->w_ser.fd);  
578 - ctx_rtu->w_ser.fd = INVALID_HANDLE_VALUE;  
579 - return -1;  
580 - }  
581 -#else  
582 /* The O_NOCTTY flag tells UNIX that this program doesn't want 320 /* The O_NOCTTY flag tells UNIX that this program doesn't want
583 to be the "controlling terminal" for that port. If you 321 to be the "controlling terminal" for that port. If you
584 don't specify this then any input (such as keyboard abort 322 don't specify this then any input (such as keyboard abort
@@ -608,7 +346,8 @@ static int _modbus_rtu_connect(modbus_t *ctx) @@ -608,7 +346,8 @@ static int _modbus_rtu_connect(modbus_t *ctx)
608 /* C_ISPEED Input baud (new interface) 346 /* C_ISPEED Input baud (new interface)
609 C_OSPEED Output baud (new interface) 347 C_OSPEED Output baud (new interface)
610 */ 348 */
611 - switch (ctx_rtu->baud) { 349 + switch (ctx_rtu->baud)
  350 + {
612 case 110: 351 case 110:
613 speed = B110; 352 speed = B110;
614 break; 353 break;
@@ -889,15 +628,13 @@ static int _modbus_rtu_connect(modbus_t *ctx) @@ -889,15 +628,13 @@ static int _modbus_rtu_connect(modbus_t *ctx)
889 */ 628 */
890 /* Unused because we use open with the NDELAY option */ 629 /* Unused because we use open with the NDELAY option */
891 tios.c_cc[VMIN] = 0; 630 tios.c_cc[VMIN] = 0;
892 - tios.c_cc[VTIME] = 0; 631 + tios.c_cc[VTIME] = 10; // Set per default to 1 second
893 632
894 if (tcsetattr(ctx->s, TCSANOW, &tios) < 0) { 633 if (tcsetattr(ctx->s, TCSANOW, &tios) < 0) {
895 close(ctx->s); 634 close(ctx->s);
896 ctx->s = -1; 635 ctx->s = -1;
897 return -1; 636 return -1;
898 } 637 }
899 -#endif  
900 -  
901 return 0; 638 return 0;
902 } 639 }
903 640
@@ -1112,62 +849,35 @@ static void _modbus_rtu_close(modbus_t *ctx) @@ -1112,62 +849,35 @@ static void _modbus_rtu_close(modbus_t *ctx)
1112 /* Restore line settings and close file descriptor in RTU mode */ 849 /* Restore line settings and close file descriptor in RTU mode */
1113 modbus_rtu_t *ctx_rtu = ctx->backend_data; 850 modbus_rtu_t *ctx_rtu = ctx->backend_data;
1114 851
1115 -#if defined(_WIN32)  
1116 - /* Revert settings */  
1117 - if (!SetCommState(ctx_rtu->w_ser.fd, &ctx_rtu->old_dcb) && ctx->debug) {  
1118 - fprintf(stderr, "ERROR Couldn't revert to configuration (LastError %d)\n",  
1119 - (int)GetLastError());  
1120 - }  
1121 -  
1122 - if (!CloseHandle(ctx_rtu->w_ser.fd) && ctx->debug) {  
1123 - fprintf(stderr, "ERROR Error while closing handle (LastError %d)\n",  
1124 - (int)GetLastError());  
1125 - }  
1126 -#else  
1127 if (ctx->s != -1) { 852 if (ctx->s != -1) {
1128 tcsetattr(ctx->s, TCSANOW, &ctx_rtu->old_tios); 853 tcsetattr(ctx->s, TCSANOW, &ctx_rtu->old_tios);
1129 close(ctx->s); 854 close(ctx->s);
1130 ctx->s = -1; 855 ctx->s = -1;
1131 } 856 }
1132 -#endif  
1133 } 857 }
1134 858
1135 static int _modbus_rtu_flush(modbus_t *ctx) 859 static int _modbus_rtu_flush(modbus_t *ctx)
1136 { 860 {
1137 -#if defined(_WIN32)  
1138 - modbus_rtu_t *ctx_rtu = ctx->backend_data;  
1139 - ctx_rtu->w_ser.n_bytes = 0;  
1140 - return (PurgeComm(ctx_rtu->w_ser.fd, PURGE_RXCLEAR) == FALSE);  
1141 -#else  
1142 return tcflush(ctx->s, TCIOFLUSH); 861 return tcflush(ctx->s, TCIOFLUSH);
1143 -#endif  
1144 } 862 }
1145 863
1146 -static int _modbus_rtu_select(modbus_t *ctx, fd_set *rset,  
1147 - struct timeval *tv, int length_to_read) 864 +static int _modbus_rtu_select(modbus_t *ctx, fd_set *rset, struct timeval *tv, int length_to_read)
1148 { 865 {
1149 int s_rc; 866 int s_rc;
1150 -#if defined(_WIN32)  
1151 - s_rc = win32_ser_select(&((modbus_rtu_t *)ctx->backend_data)->w_ser,  
1152 - length_to_read, tv);  
1153 - if (s_rc == 0) {  
1154 - errno = ETIMEDOUT;  
1155 - return -1;  
1156 - }  
1157 -  
1158 - if (s_rc < 0) {  
1159 - return -1;  
1160 - }  
1161 -#else  
1162 - while ((s_rc = select(ctx->s+1, rset, NULL, NULL, tv)) == -1) {  
1163 - if (errno == EINTR) {  
1164 - if (ctx->debug) { 867 + while ((s_rc = select(ctx->s+1, rset, NULL, NULL, tv)) == -1)
  868 + {
  869 + if (errno == EINTR)
  870 + {
  871 + if (ctx->debug)
  872 + {
1165 fprintf(stderr, "A non blocked signal was caught\n"); 873 fprintf(stderr, "A non blocked signal was caught\n");
1166 } 874 }
1167 /* Necessary after an error */ 875 /* Necessary after an error */
1168 FD_ZERO(rset); 876 FD_ZERO(rset);
1169 FD_SET(ctx->s, rset); 877 FD_SET(ctx->s, rset);
1170 - } else { 878 + }
  879 + else
  880 + {
1171 return -1; 881 return -1;
1172 } 882 }
1173 } 883 }
@@ -1177,7 +887,6 @@ static int _modbus_rtu_select(modbus_t *ctx, fd_set *rset, @@ -1177,7 +887,6 @@ static int _modbus_rtu_select(modbus_t *ctx, fd_set *rset,
1177 errno = ETIMEDOUT; 887 errno = ETIMEDOUT;
1178 return -1; 888 return -1;
1179 } 889 }
1180 -#endif  
1181 890
1182 return s_rc; 891 return s_rc;
1183 } 892 }
@@ -1210,10 +919,9 @@ const modbus_backend_t _modbus_rtu_backend = { @@ -1210,10 +919,9 @@ const modbus_backend_t _modbus_rtu_backend = {
1210 _modbus_rtu_free 919 _modbus_rtu_free
1211 }; 920 };
1212 921
1213 -//***Not part of libmodbus - rts param added for QModMaster***//  
1214 modbus_t* modbus_new_rtu(const char *device, 922 modbus_t* modbus_new_rtu(const char *device,
1215 int baud, char parity, int data_bit, 923 int baud, char parity, int data_bit,
1216 - int stop_bit, int rts) 924 + int stop_bit)
1217 { 925 {
1218 modbus_t *ctx; 926 modbus_t *ctx;
1219 modbus_rtu_t *ctx_rtu; 927 modbus_rtu_t *ctx_rtu;
@@ -1273,11 +981,6 @@ modbus_t* modbus_new_rtu(const char *device, @@ -1273,11 +981,6 @@ modbus_t* modbus_new_rtu(const char *device,
1273 ctx_rtu->rts_delay = ctx_rtu->onebyte_time; 981 ctx_rtu->rts_delay = ctx_rtu->onebyte_time;
1274 #endif 982 #endif
1275 983
1276 -//***Not part of libmodbus - added for QModMaster***//  
1277 -#if defined(_WIN32)  
1278 - ctx_rtu->rts = rts;  
1279 -#endif  
1280 -  
1281 ctx_rtu->confirmation_to_ignore = FALSE; 984 ctx_rtu->confirmation_to_ignore = FALSE;
1282 985
1283 return ctx; 986 return ctx;
3rdparty/libmodbus/modbus-rtu.h
1 -/*  
2 - * Copyright © 2001-2011 Stéphane Raimbault <stephane.raimbault@gmail.com>  
3 - *  
4 - * SPDX-License-Identifier: LGPL-2.1+  
5 - */  
6 1
7 -#ifndef MODBUS_RTU_H  
8 -#define MODBUS_RTU_H 2 +#pragma once
9 3
10 #include "modbus.h" 4 #include "modbus.h"
11 5
@@ -16,28 +10,25 @@ MODBUS_BEGIN_DECLS @@ -16,28 +10,25 @@ MODBUS_BEGIN_DECLS
16 */ 10 */
17 #define MODBUS_RTU_MAX_ADU_LENGTH 256 11 #define MODBUS_RTU_MAX_ADU_LENGTH 256
18 12
19 -//***Not part of libmodbus - rts param added for QModMaster***//  
20 -MODBUS_API modbus_t* modbus_new_rtu(const char *device, int baud, char parity,  
21 - int data_bit, int stop_bit, int rts); 13 +MODBUS_API modbus_t* modbus_new_rtu(const char *device, int baud, char parity, int data_bit, int stop_bit);
22 14
23 #define MODBUS_RTU_RS232 0 15 #define MODBUS_RTU_RS232 0
24 #define MODBUS_RTU_RS485 1 16 #define MODBUS_RTU_RS485 1
25 17
26 -MODBUS_API int modbus_rtu_set_serial_mode(modbus_t *ctx, int mode);  
27 -MODBUS_API int modbus_rtu_get_serial_mode(modbus_t *ctx); 18 +MODBUS_API int modbus_rtu_set_serial_mode( modbus_t *ctx, int mode );
  19 +MODBUS_API int modbus_rtu_get_serial_mode( modbus_t *ctx );
28 20
29 #define MODBUS_RTU_RTS_NONE 0 21 #define MODBUS_RTU_RTS_NONE 0
30 #define MODBUS_RTU_RTS_UP 1 22 #define MODBUS_RTU_RTS_UP 1
31 #define MODBUS_RTU_RTS_DOWN 2 23 #define MODBUS_RTU_RTS_DOWN 2
32 24
33 -MODBUS_API int modbus_rtu_set_rts(modbus_t *ctx, int mode);  
34 -MODBUS_API int modbus_rtu_get_rts(modbus_t *ctx); 25 +MODBUS_API int modbus_rtu_set_rts( modbus_t *ctx, int mode );
  26 +MODBUS_API int modbus_rtu_get_rts( modbus_t *ctx );
35 27
36 -MODBUS_API int modbus_rtu_set_custom_rts(modbus_t *ctx, void (*set_rts) (modbus_t *ctx, int on)); 28 +MODBUS_API int modbus_rtu_set_custom_rts( modbus_t *ctx, void ( *set_rts ) ( modbus_t *ctx, int on ) );
37 29
38 -MODBUS_API int modbus_rtu_set_rts_delay(modbus_t *ctx, int us);  
39 -MODBUS_API int modbus_rtu_get_rts_delay(modbus_t *ctx); 30 +MODBUS_API int modbus_rtu_set_rts_delay( modbus_t *ctx, int us );
  31 +MODBUS_API int modbus_rtu_get_rts_delay( modbus_t *ctx );
40 32
41 MODBUS_END_DECLS 33 MODBUS_END_DECLS
42 34
43 -#endif /* MODBUS_RTU_H */  
3rdparty/libmodbus/modbus-tcp-private.h
1 -/*  
2 - * Copyright © 2001-2011 Stéphane Raimbault <stephane.raimbault@gmail.com>  
3 - *  
4 - * SPDX-License-Identifier: LGPL-2.1+  
5 - */  
6 -  
7 -#ifndef MODBUS_TCP_PRIVATE_H  
8 -#define MODBUS_TCP_PRIVATE_H 1 +#pragma once
9 2
10 #define _MODBUS_TCP_HEADER_LENGTH 7 3 #define _MODBUS_TCP_HEADER_LENGTH 7
11 #define _MODBUS_TCP_PRESET_REQ_LENGTH 12 4 #define _MODBUS_TCP_PRESET_REQ_LENGTH 12
@@ -15,7 +8,8 @@ @@ -15,7 +8,8 @@
15 8
16 /* In both structures, the transaction ID must be placed on first position 9 /* In both structures, the transaction ID must be placed on first position
17 to have a quick access not dependant of the TCP backend */ 10 to have a quick access not dependant of the TCP backend */
18 -typedef struct _modbus_tcp { 11 +typedef struct _modbus_tcp
  12 +{
19 /* Extract from MODBUS Messaging on TCP/IP Implementation Guide V1.0b 13 /* Extract from MODBUS Messaging on TCP/IP Implementation Guide V1.0b
20 (page 23/46): 14 (page 23/46):
21 The transaction identifier is used to associate the future response 15 The transaction identifier is used to associate the future response
@@ -30,7 +24,8 @@ typedef struct _modbus_tcp { @@ -30,7 +24,8 @@ typedef struct _modbus_tcp {
30 #define _MODBUS_TCP_PI_NODE_LENGTH 1025 24 #define _MODBUS_TCP_PI_NODE_LENGTH 1025
31 #define _MODBUS_TCP_PI_SERVICE_LENGTH 32 25 #define _MODBUS_TCP_PI_SERVICE_LENGTH 32
32 26
33 -typedef struct _modbus_tcp_pi { 27 +typedef struct _modbus_tcp_pi
  28 +{
34 /* Transaction ID */ 29 /* Transaction ID */
35 uint16_t t_id; 30 uint16_t t_id;
36 /* TCP port */ 31 /* TCP port */
@@ -41,4 +36,4 @@ typedef struct _modbus_tcp_pi { @@ -41,4 +36,4 @@ typedef struct _modbus_tcp_pi {
41 char service[_MODBUS_TCP_PI_SERVICE_LENGTH]; 36 char service[_MODBUS_TCP_PI_SERVICE_LENGTH];
42 } modbus_tcp_pi_t; 37 } modbus_tcp_pi_t;
43 38
44 -#endif /* MODBUS_TCP_PRIVATE_H */ 39 +
3rdparty/libmodbus/modbus-tcp.c
  1 +
1 #include <stdio.h> 2 #include <stdio.h>
2 #include <stdlib.h> 3 #include <stdlib.h>
3 #include <string.h> 4 #include <string.h>
@@ -20,46 +21,30 @@ @@ -20,46 +21,30 @@
20 # include <arpa/inet.h> 21 # include <arpa/inet.h>
21 # include <netdb.h> 22 # include <netdb.h>
22 23
23 -  
24 #if !defined(MSG_NOSIGNAL) 24 #if !defined(MSG_NOSIGNAL)
25 #define MSG_NOSIGNAL 0 25 #define MSG_NOSIGNAL 0
26 #endif 26 #endif
27 27
28 -#if defined(_AIX) && !defined(MSG_DONTWAIT)  
29 -#define MSG_DONTWAIT MSG_NONBLOCK  
30 -#endif  
31 -  
32 #include "modbus-private.h" 28 #include "modbus-private.h"
33 29
34 #include "modbus-tcp.h" 30 #include "modbus-tcp.h"
35 #include "modbus-tcp-private.h" 31 #include "modbus-tcp-private.h"
36 32
37 -#ifdef OS_WIN32  
38 -static int _modbus_tcp_init_win32(void)  
39 -{  
40 - /* Initialise Windows Socket API */  
41 - WSADATA wsaData;  
42 -  
43 - if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {  
44 - fprintf(stderr, "WSAStartup() returned error code %d\n",  
45 - (unsigned int)GetLastError());  
46 - errno = EIO;  
47 - return -1;  
48 - }  
49 - return 0;  
50 -}  
51 -#endif  
52 -  
53 static int _modbus_set_slave(modbus_t *ctx, int slave) 33 static int _modbus_set_slave(modbus_t *ctx, int slave)
54 { 34 {
55 /* Broadcast address is 0 (MODBUS_BROADCAST_ADDRESS) */ 35 /* Broadcast address is 0 (MODBUS_BROADCAST_ADDRESS) */
56 - if (slave >= 0 && slave <= 247) { 36 + if ( slave >= 0 && slave <= 247)
  37 + {
57 ctx->slave = slave; 38 ctx->slave = slave;
58 - } else if (slave == MODBUS_TCP_SLAVE) { 39 + }
  40 + else if ( slave == MODBUS_TCP_SLAVE )
  41 + {
59 /* The special value MODBUS_TCP_SLAVE (0xFF) can be used in TCP mode to 42 /* The special value MODBUS_TCP_SLAVE (0xFF) can be used in TCP mode to
60 * restore the default value. */ 43 * restore the default value. */
61 ctx->slave = slave; 44 ctx->slave = slave;
62 - } else { 45 + }
  46 + else
  47 + {
63 errno = EINVAL; 48 errno = EINVAL;
64 return -1; 49 return -1;
65 } 50 }
@@ -68,9 +53,7 @@ static int _modbus_set_slave(modbus_t *ctx, int slave) @@ -68,9 +53,7 @@ static int _modbus_set_slave(modbus_t *ctx, int slave)
68 } 53 }
69 54
70 /* Builds a TCP request header */ 55 /* Builds a TCP request header */
71 -static int _modbus_tcp_build_request_basis(modbus_t *ctx, int function,  
72 - int addr, int nb,  
73 - uint8_t *req) 56 +static int _modbus_tcp_build_request_basis( modbus_t *ctx, int function, int addr, int nb, uint8_t *req )
74 { 57 {
75 modbus_tcp_t *ctx_tcp = ctx->backend_data; 58 modbus_tcp_t *ctx_tcp = ctx->backend_data;
76 59
@@ -79,6 +62,7 @@ static int _modbus_tcp_build_request_basis(modbus_t *ctx, int function, @@ -79,6 +62,7 @@ static int _modbus_tcp_build_request_basis(modbus_t *ctx, int function,
79 ctx_tcp->t_id++; 62 ctx_tcp->t_id++;
80 else 63 else
81 ctx_tcp->t_id = 0; 64 ctx_tcp->t_id = 0;
  65 +
82 req[0] = ctx_tcp->t_id >> 8; 66 req[0] = ctx_tcp->t_id >> 8;
83 req[1] = ctx_tcp->t_id & 0x00ff; 67 req[1] = ctx_tcp->t_id & 0x00ff;
84 68
@@ -100,7 +84,7 @@ static int _modbus_tcp_build_request_basis(modbus_t *ctx, int function, @@ -100,7 +84,7 @@ static int _modbus_tcp_build_request_basis(modbus_t *ctx, int function,
100 } 84 }
101 85
102 /* Builds a TCP response header */ 86 /* Builds a TCP response header */
103 -static int _modbus_tcp_build_response_basis(sft_t *sft, uint8_t *rsp) 87 +static int _modbus_tcp_build_response_basis( sft_t *sft, uint8_t *rsp )
104 { 88 {
105 /* Extract from MODBUS Messaging on TCP/IP Implementation 89 /* Extract from MODBUS Messaging on TCP/IP Implementation
106 Guide V1.0b (page 23/46): 90 Guide V1.0b (page 23/46):
@@ -123,12 +107,12 @@ static int _modbus_tcp_build_response_basis(sft_t *sft, uint8_t *rsp) @@ -123,12 +107,12 @@ static int _modbus_tcp_build_response_basis(sft_t *sft, uint8_t *rsp)
123 } 107 }
124 108
125 109
126 -static int _modbus_tcp_prepare_response_tid(const uint8_t *req, int *req_length) 110 +static int _modbus_tcp_prepare_response_tid( const uint8_t *req, int *req_length )
127 { 111 {
128 return (req[0] << 8) + req[1]; 112 return (req[0] << 8) + req[1];
129 } 113 }
130 114
131 -static int _modbus_tcp_send_msg_pre(uint8_t *req, int req_length) 115 +static int _modbus_tcp_send_msg_pre( uint8_t *req, int req_length )
132 { 116 {
133 /* Substract the header length to the message length */ 117 /* Substract the header length to the message length */
134 int mbap_length = req_length - 6; 118 int mbap_length = req_length - 6;
@@ -139,7 +123,7 @@ static int _modbus_tcp_send_msg_pre(uint8_t *req, int req_length) @@ -139,7 +123,7 @@ static int _modbus_tcp_send_msg_pre(uint8_t *req, int req_length)
139 return req_length; 123 return req_length;
140 } 124 }
141 125
142 -static ssize_t _modbus_tcp_send(modbus_t *ctx, const uint8_t *req, int req_length) 126 +static ssize_t _modbus_tcp_send( modbus_t *ctx, const uint8_t *req, int req_length )
143 { 127 {
144 /* MSG_NOSIGNAL 128 /* MSG_NOSIGNAL
145 Requests not to send SIGPIPE on errors on stream oriented 129 Requests not to send SIGPIPE on errors on stream oriented
@@ -148,25 +132,27 @@ static ssize_t _modbus_tcp_send(modbus_t *ctx, const uint8_t *req, int req_lengt @@ -148,25 +132,27 @@ static ssize_t _modbus_tcp_send(modbus_t *ctx, const uint8_t *req, int req_lengt
148 return send(ctx->s, (const char *)req, req_length, MSG_NOSIGNAL); 132 return send(ctx->s, (const char *)req, req_length, MSG_NOSIGNAL);
149 } 133 }
150 134
151 -static int _modbus_tcp_receive(modbus_t *ctx, uint8_t *req) { 135 +static int _modbus_tcp_receive(modbus_t *ctx, uint8_t *req)
  136 +{
152 return _modbus_receive_msg(ctx, req, MSG_INDICATION); 137 return _modbus_receive_msg(ctx, req, MSG_INDICATION);
153 } 138 }
154 139
155 -static ssize_t _modbus_tcp_recv(modbus_t *ctx, uint8_t *rsp, int rsp_length) {  
156 - return recv(ctx->s, (char *)rsp, rsp_length, 0); 140 +static ssize_t _modbus_tcp_recv(modbus_t *ctx, uint8_t *rsp, int rsp_length)
  141 +{
  142 + return recv( ctx->s, (char *)rsp, rsp_length, 0 );
157 } 143 }
158 144
159 -static int _modbus_tcp_check_integrity(modbus_t *ctx, uint8_t *msg, const int msg_length) 145 +static int _modbus_tcp_check_integrity( modbus_t *ctx, uint8_t *msg, const int msg_length )
160 { 146 {
161 return msg_length; 147 return msg_length;
162 } 148 }
163 149
164 -static int _modbus_tcp_pre_check_confirmation(modbus_t *ctx, const uint8_t *req,  
165 - const uint8_t *rsp, int rsp_length) 150 +static int _modbus_tcp_pre_check_confirmation( modbus_t *ctx, const uint8_t *req, const uint8_t *rsp, int rsp_length )
166 { 151 {
167 /* Check transaction ID */ 152 /* Check transaction ID */
168 if (req[0] != rsp[0] || req[1] != rsp[1]) { 153 if (req[0] != rsp[0] || req[1] != rsp[1]) {
169 - if (ctx->debug) { 154 + if (ctx->debug)
  155 + {
170 fprintf(stderr, "Invalid transaction ID received 0x%X (not 0x%X)\n", 156 fprintf(stderr, "Invalid transaction ID received 0x%X (not 0x%X)\n",
171 (rsp[0] << 8) + rsp[1], (req[0] << 8) + req[1]); 157 (rsp[0] << 8) + rsp[1], (req[0] << 8) + req[1]);
172 } 158 }
@@ -175,8 +161,10 @@ static int _modbus_tcp_pre_check_confirmation(modbus_t *ctx, const uint8_t *req, @@ -175,8 +161,10 @@ static int _modbus_tcp_pre_check_confirmation(modbus_t *ctx, const uint8_t *req,
175 } 161 }
176 162
177 /* Check protocol ID */ 163 /* Check protocol ID */
178 - if (rsp[2] != 0x0 && rsp[3] != 0x0) {  
179 - if (ctx->debug) { 164 + if (rsp[2] != 0x0 && rsp[3] != 0x0)
  165 + {
  166 + if (ctx->debug)
  167 + {
180 fprintf(stderr, "Invalid protocol ID received 0x%X (not 0x0)\n", 168 fprintf(stderr, "Invalid protocol ID received 0x%X (not 0x0)\n",
181 (rsp[2] << 8) + rsp[3]); 169 (rsp[2] << 8) + rsp[3]);
182 } 170 }
@@ -187,7 +175,7 @@ static int _modbus_tcp_pre_check_confirmation(modbus_t *ctx, const uint8_t *req, @@ -187,7 +175,7 @@ static int _modbus_tcp_pre_check_confirmation(modbus_t *ctx, const uint8_t *req,
187 return 0; 175 return 0;
188 } 176 }
189 177
190 -static int _modbus_tcp_set_ipv4_options(int s) 178 +static int _modbus_tcp_set_ipv4_options( int s )
191 { 179 {
192 int rc; 180 int rc;
193 int option; 181 int option;
@@ -195,9 +183,9 @@ static int _modbus_tcp_set_ipv4_options(int s) @@ -195,9 +183,9 @@ static int _modbus_tcp_set_ipv4_options(int s)
195 /* Set the TCP no delay flag */ 183 /* Set the TCP no delay flag */
196 /* SOL_TCP = IPPROTO_TCP */ 184 /* SOL_TCP = IPPROTO_TCP */
197 option = 1; 185 option = 1;
198 - rc = setsockopt(s, IPPROTO_TCP, TCP_NODELAY,  
199 - (const void *)&option, sizeof(int));  
200 - if (rc == -1) { 186 + rc = setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (const void *)&option, sizeof(int) );
  187 + if (rc == -1)
  188 + {
201 return -1; 189 return -1;
202 } 190 }
203 191
@@ -205,19 +193,10 @@ static int _modbus_tcp_set_ipv4_options(int s) @@ -205,19 +193,10 @@ static int _modbus_tcp_set_ipv4_options(int s)
205 * make sockets non-blocking */ 193 * make sockets non-blocking */
206 /* Do not care about the return value, this is optional */ 194 /* Do not care about the return value, this is optional */
207 #if !defined(SOCK_NONBLOCK) && defined(FIONBIO) 195 #if !defined(SOCK_NONBLOCK) && defined(FIONBIO)
208 -#ifdef OS_WIN32  
209 - {  
210 - /* Setting FIONBIO expects an unsigned long according to MSDN */  
211 - u_long loption = 1;  
212 - ioctlsocket(s, FIONBIO, &loption);  
213 - }  
214 -#else  
215 option = 1; 196 option = 1;
216 ioctl(s, FIONBIO, &option); 197 ioctl(s, FIONBIO, &option);
217 #endif 198 #endif
218 -#endif  
219 199
220 -#ifndef OS_WIN32  
221 /** 200 /**
222 * Cygwin defines IPTOS_LOWDELAY but can't handle that flag so it's 201 * Cygwin defines IPTOS_LOWDELAY but can't handle that flag so it's
223 * necessary to workaround that problem. 202 * necessary to workaround that problem.
@@ -229,26 +208,16 @@ static int _modbus_tcp_set_ipv4_options(int s) @@ -229,26 +208,16 @@ static int _modbus_tcp_set_ipv4_options(int s)
229 if (rc == -1) { 208 if (rc == -1) {
230 return -1; 209 return -1;
231 } 210 }
232 -#endif  
233 211
234 return 0; 212 return 0;
235 } 213 }
236 214
237 -static int _connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen,  
238 - const struct timeval *ro_tv) 215 +static int _connect( int sockfd, const struct sockaddr *addr, socklen_t addrlen, const struct timeval *ro_tv )
239 { 216 {
240 int rc = connect(sockfd, addr, addrlen); 217 int rc = connect(sockfd, addr, addrlen);
241 218
242 -#ifdef OS_WIN32  
243 - int wsaError = 0;  
244 - if (rc == -1) {  
245 - wsaError = WSAGetLastError();  
246 - }  
247 -  
248 - if (wsaError == WSAEWOULDBLOCK || wsaError == WSAEINPROGRESS) {  
249 -#else  
250 - if (rc == -1 && errno == EINPROGRESS) {  
251 -#endif 219 + if (rc == -1 && errno == EINPROGRESS)
  220 + {
252 fd_set wset; 221 fd_set wset;
253 int optval; 222 int optval;
254 socklen_t optlen = sizeof(optval); 223 socklen_t optlen = sizeof(optval);
@@ -258,16 +227,20 @@ static int _connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen, @@ -258,16 +227,20 @@ static int _connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen,
258 FD_ZERO(&wset); 227 FD_ZERO(&wset);
259 FD_SET(sockfd, &wset); 228 FD_SET(sockfd, &wset);
260 rc = select(sockfd + 1, NULL, &wset, NULL, &tv); 229 rc = select(sockfd + 1, NULL, &wset, NULL, &tv);
261 - if (rc <= 0) { 230 + if (rc <= 0)
  231 + {
262 /* Timeout or fail */ 232 /* Timeout or fail */
263 return -1; 233 return -1;
264 } 234 }
265 235
266 /* The connection is established if SO_ERROR and optval are set to 0 */ 236 /* The connection is established if SO_ERROR and optval are set to 0 */
267 rc = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&optval, &optlen); 237 rc = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&optval, &optlen);
268 - if (rc == 0 && optval == 0) { 238 + if ( rc == 0 && optval == 0 )
  239 + {
269 return 0; 240 return 0;
270 - } else { 241 + }
  242 + else
  243 + {
271 errno = ECONNREFUSED; 244 errno = ECONNREFUSED;
272 return -1; 245 return -1;
273 } 246 }
@@ -276,7 +249,7 @@ static int _connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen, @@ -276,7 +249,7 @@ static int _connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen,
276 } 249 }
277 250
278 /* Establishes a modbus TCP connection with a Modbus server. */ 251 /* Establishes a modbus TCP connection with a Modbus server. */
279 -static int _modbus_tcp_connect(modbus_t *ctx) 252 +static int _modbus_tcp_connect( modbus_t *ctx )
280 { 253 {
281 int rc; 254 int rc;
282 /* Specialized version of sockaddr for Internet socket address (same size) */ 255 /* Specialized version of sockaddr for Internet socket address (same size) */
@@ -284,12 +257,6 @@ static int _modbus_tcp_connect(modbus_t *ctx) @@ -284,12 +257,6 @@ static int _modbus_tcp_connect(modbus_t *ctx)
284 modbus_tcp_t *ctx_tcp = ctx->backend_data; 257 modbus_tcp_t *ctx_tcp = ctx->backend_data;
285 int flags = SOCK_STREAM; 258 int flags = SOCK_STREAM;
286 259
287 -#ifdef OS_WIN32  
288 - if (_modbus_tcp_init_win32() == -1) {  
289 - return -1;  
290 - }  
291 -#endif  
292 -  
293 #ifdef SOCK_CLOEXEC 260 #ifdef SOCK_CLOEXEC
294 flags |= SOCK_CLOEXEC; 261 flags |= SOCK_CLOEXEC;
295 #endif 262 #endif
@@ -299,18 +266,21 @@ static int _modbus_tcp_connect(modbus_t *ctx) @@ -299,18 +266,21 @@ static int _modbus_tcp_connect(modbus_t *ctx)
299 #endif 266 #endif
300 267
301 ctx->s = socket(PF_INET, flags, 0); 268 ctx->s = socket(PF_INET, flags, 0);
302 - if (ctx->s == -1) { 269 + if (ctx->s == -1)
  270 + {
303 return -1; 271 return -1;
304 } 272 }
305 273
306 rc = _modbus_tcp_set_ipv4_options(ctx->s); 274 rc = _modbus_tcp_set_ipv4_options(ctx->s);
307 - if (rc == -1) { 275 + if (rc == -1)
  276 + {
308 close(ctx->s); 277 close(ctx->s);
309 ctx->s = -1; 278 ctx->s = -1;
310 return -1; 279 return -1;
311 } 280 }
312 281
313 - if (ctx->debug) { 282 + if (ctx->debug)
  283 + {
314 printf("Connecting to %s:%d\n", ctx_tcp->ip, ctx_tcp->port); 284 printf("Connecting to %s:%d\n", ctx_tcp->ip, ctx_tcp->port);
315 } 285 }
316 286
@@ -318,8 +288,9 @@ static int _modbus_tcp_connect(modbus_t *ctx) @@ -318,8 +288,9 @@ static int _modbus_tcp_connect(modbus_t *ctx)
318 addr.sin_port = htons(ctx_tcp->port); 288 addr.sin_port = htons(ctx_tcp->port);
319 addr.sin_addr.s_addr = inet_addr(ctx_tcp->ip); 289 addr.sin_addr.s_addr = inet_addr(ctx_tcp->ip);
320 rc = _connect(ctx->s, (struct sockaddr *)&addr, sizeof(addr), &ctx->response_timeout); 290 rc = _connect(ctx->s, (struct sockaddr *)&addr, sizeof(addr), &ctx->response_timeout);
321 - if (rc == -1) {  
322 - close(ctx->s); 291 + if( rc == -1 )
  292 + {
  293 + close( ctx->s );
323 ctx->s = -1; 294 ctx->s = -1;
324 return -1; 295 return -1;
325 } 296 }
@@ -328,7 +299,7 @@ static int _modbus_tcp_connect(modbus_t *ctx) @@ -328,7 +299,7 @@ static int _modbus_tcp_connect(modbus_t *ctx)
328 } 299 }
329 300
330 /* Establishes a modbus TCP PI connection with a Modbus server. */ 301 /* Establishes a modbus TCP PI connection with a Modbus server. */
331 -static int _modbus_tcp_pi_connect(modbus_t *ctx) 302 +static int _modbus_tcp_pi_connect( modbus_t *ctx )
332 { 303 {
333 int rc; 304 int rc;
334 struct addrinfo *ai_list; 305 struct addrinfo *ai_list;
@@ -336,12 +307,6 @@ static int _modbus_tcp_pi_connect(modbus_t *ctx) @@ -336,12 +307,6 @@ static int _modbus_tcp_pi_connect(modbus_t *ctx)
336 struct addrinfo ai_hints; 307 struct addrinfo ai_hints;
337 modbus_tcp_pi_t *ctx_tcp_pi = ctx->backend_data; 308 modbus_tcp_pi_t *ctx_tcp_pi = ctx->backend_data;
338 309
339 -#ifdef OS_WIN32  
340 - if (_modbus_tcp_init_win32() == -1) {  
341 - return -1;  
342 - }  
343 -#endif  
344 -  
345 memset(&ai_hints, 0, sizeof(ai_hints)); 310 memset(&ai_hints, 0, sizeof(ai_hints));
346 #ifdef AI_ADDRCONFIG 311 #ifdef AI_ADDRCONFIG
347 ai_hints.ai_flags |= AI_ADDRCONFIG; 312 ai_hints.ai_flags |= AI_ADDRCONFIG;
@@ -353,17 +318,19 @@ static int _modbus_tcp_pi_connect(modbus_t *ctx) @@ -353,17 +318,19 @@ static int _modbus_tcp_pi_connect(modbus_t *ctx)
353 ai_hints.ai_next = NULL; 318 ai_hints.ai_next = NULL;
354 319
355 ai_list = NULL; 320 ai_list = NULL;
356 - rc = getaddrinfo(ctx_tcp_pi->node, ctx_tcp_pi->service,  
357 - &ai_hints, &ai_list);  
358 - if (rc != 0) {  
359 - if (ctx->debug) { 321 + rc = getaddrinfo(ctx_tcp_pi->node, ctx_tcp_pi->service, &ai_hints, &ai_list);
  322 + if (rc != 0)
  323 + {
  324 + if (ctx->debug)
  325 + {
360 fprintf(stderr, "Error returned by getaddrinfo: %s\n", gai_strerror(rc)); 326 fprintf(stderr, "Error returned by getaddrinfo: %s\n", gai_strerror(rc));
361 } 327 }
362 errno = ECONNREFUSED; 328 errno = ECONNREFUSED;
363 return -1; 329 return -1;
364 } 330 }
365 331
366 - for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) { 332 + for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
  333 + {
367 int flags = ai_ptr->ai_socktype; 334 int flags = ai_ptr->ai_socktype;
368 int s; 335 int s;
369 336
@@ -382,12 +349,14 @@ static int _modbus_tcp_pi_connect(modbus_t *ctx) @@ -382,12 +349,14 @@ static int _modbus_tcp_pi_connect(modbus_t *ctx)
382 if (ai_ptr->ai_family == AF_INET) 349 if (ai_ptr->ai_family == AF_INET)
383 _modbus_tcp_set_ipv4_options(s); 350 _modbus_tcp_set_ipv4_options(s);
384 351
385 - if (ctx->debug) { 352 + if (ctx->debug)
  353 + {
386 printf("Connecting to [%s]:%s\n", ctx_tcp_pi->node, ctx_tcp_pi->service); 354 printf("Connecting to [%s]:%s\n", ctx_tcp_pi->node, ctx_tcp_pi->service);
387 } 355 }
388 356
389 rc = _connect(s, ai_ptr->ai_addr, ai_ptr->ai_addrlen, &ctx->response_timeout); 357 rc = _connect(s, ai_ptr->ai_addr, ai_ptr->ai_addrlen, &ctx->response_timeout);
390 - if (rc == -1) { 358 + if (rc == -1)
  359 + {
391 close(s); 360 close(s);
392 continue; 361 continue;
393 } 362 }
@@ -398,7 +367,8 @@ static int _modbus_tcp_pi_connect(modbus_t *ctx) @@ -398,7 +367,8 @@ static int _modbus_tcp_pi_connect(modbus_t *ctx)
398 367
399 freeaddrinfo(ai_list); 368 freeaddrinfo(ai_list);
400 369
401 - if (ctx->s < 0) { 370 + if (ctx->s < 0)
  371 + {
402 return -1; 372 return -1;
403 } 373 }
404 374
@@ -406,102 +376,88 @@ static int _modbus_tcp_pi_connect(modbus_t *ctx) @@ -406,102 +376,88 @@ static int _modbus_tcp_pi_connect(modbus_t *ctx)
406 } 376 }
407 377
408 /* Closes the network connection and socket in TCP mode */ 378 /* Closes the network connection and socket in TCP mode */
409 -static void _modbus_tcp_close(modbus_t *ctx) 379 +static void _modbus_tcp_close( modbus_t *ctx )
410 { 380 {
411 - if (ctx->s != -1) { 381 + if (ctx->s != -1)
  382 + {
412 shutdown(ctx->s, SHUT_RDWR); 383 shutdown(ctx->s, SHUT_RDWR);
413 close(ctx->s); 384 close(ctx->s);
414 ctx->s = -1; 385 ctx->s = -1;
415 } 386 }
416 } 387 }
417 388
418 -static int _modbus_tcp_flush(modbus_t *ctx) 389 +static int _modbus_tcp_flush( modbus_t *ctx )
419 { 390 {
420 int rc; 391 int rc;
421 int rc_sum = 0; 392 int rc_sum = 0;
422 393
423 - do { 394 + do
  395 + {
424 /* Extract the garbage from the socket */ 396 /* Extract the garbage from the socket */
425 char devnull[MODBUS_TCP_MAX_ADU_LENGTH]; 397 char devnull[MODBUS_TCP_MAX_ADU_LENGTH];
426 -#ifndef OS_WIN32  
427 - rc = recv(ctx->s, devnull, MODBUS_TCP_MAX_ADU_LENGTH, MSG_DONTWAIT);  
428 -#else  
429 - /* On Win32, it's a bit more complicated to not wait */  
430 - fd_set rset;  
431 - struct timeval tv;  
432 -  
433 - tv.tv_sec = 0;  
434 - tv.tv_usec = 0;  
435 - FD_ZERO(&rset);  
436 - FD_SET(ctx->s, &rset);  
437 - rc = select(ctx->s+1, &rset, NULL, NULL, &tv);  
438 - if (rc == -1) {  
439 - return -1;  
440 - }  
441 398
442 - if (rc == 1) {  
443 - /* There is data to flush */  
444 - rc = recv(ctx->s, devnull, MODBUS_TCP_MAX_ADU_LENGTH, 0);  
445 - }  
446 -#endif  
447 - if (rc > 0) { 399 + rc = recv(ctx->s, devnull, MODBUS_TCP_MAX_ADU_LENGTH, MSG_DONTWAIT);
  400 + if ( rc > 0 )
  401 + {
448 rc_sum += rc; 402 rc_sum += rc;
449 } 403 }
450 - } while (rc == MODBUS_TCP_MAX_ADU_LENGTH); 404 + } while ( rc == MODBUS_TCP_MAX_ADU_LENGTH );
451 405
452 return rc_sum; 406 return rc_sum;
453 } 407 }
454 408
455 /* Listens for any request from one or many modbus masters in TCP */ 409 /* Listens for any request from one or many modbus masters in TCP */
456 -int modbus_tcp_listen(modbus_t *ctx, int nb_connection) 410 +int modbus_tcp_listen( modbus_t *ctx, int nb_connection )
457 { 411 {
458 int new_s; 412 int new_s;
459 int enable; 413 int enable;
460 struct sockaddr_in addr; 414 struct sockaddr_in addr;
461 modbus_tcp_t *ctx_tcp; 415 modbus_tcp_t *ctx_tcp;
462 416
463 - if (ctx == NULL) { 417 + if (ctx == NULL)
  418 + {
464 errno = EINVAL; 419 errno = EINVAL;
465 return -1; 420 return -1;
466 } 421 }
467 422
468 ctx_tcp = ctx->backend_data; 423 ctx_tcp = ctx->backend_data;
469 424
470 -#ifdef OS_WIN32  
471 - if (_modbus_tcp_init_win32() == -1) {  
472 - return -1;  
473 - }  
474 -#endif  
475 -  
476 new_s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 425 new_s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
477 - if (new_s == -1) { 426 + if ( new_s == -1 )
  427 + {
478 return -1; 428 return -1;
479 } 429 }
480 430
481 enable = 1; 431 enable = 1;
482 - if (setsockopt(new_s, SOL_SOCKET, SO_REUSEADDR,  
483 - (char *)&enable, sizeof(enable)) == -1) { 432 + if (setsockopt(new_s, SOL_SOCKET, SO_REUSEADDR, (char *)&enable, sizeof(enable)) == -1)
  433 + {
484 close(new_s); 434 close(new_s);
485 return -1; 435 return -1;
486 } 436 }
487 437
488 memset(&addr, 0, sizeof(addr)); 438 memset(&addr, 0, sizeof(addr));
489 addr.sin_family = AF_INET; 439 addr.sin_family = AF_INET;
  440 +
490 /* If the modbus port is < to 1024, we need the setuid root. */ 441 /* If the modbus port is < to 1024, we need the setuid root. */
491 addr.sin_port = htons(ctx_tcp->port); 442 addr.sin_port = htons(ctx_tcp->port);
492 - if (ctx_tcp->ip[0] == '0') { 443 + if (ctx_tcp->ip[0] == '0')
  444 + {
493 /* Listen any addresses */ 445 /* Listen any addresses */
494 addr.sin_addr.s_addr = htonl(INADDR_ANY); 446 addr.sin_addr.s_addr = htonl(INADDR_ANY);
495 - } else { 447 + }
  448 + else
  449 + {
496 /* Listen only specified IP address */ 450 /* Listen only specified IP address */
497 addr.sin_addr.s_addr = inet_addr(ctx_tcp->ip); 451 addr.sin_addr.s_addr = inet_addr(ctx_tcp->ip);
498 } 452 }
499 - if (bind(new_s, (struct sockaddr *)&addr, sizeof(addr)) == -1) { 453 + if (bind( new_s, (struct sockaddr *)&addr, sizeof(addr)) == -1)
  454 + {
500 close(new_s); 455 close(new_s);
501 return -1; 456 return -1;
502 } 457 }
503 458
504 - if (listen(new_s, nb_connection) == -1) { 459 + if (listen(new_s, nb_connection) == -1)
  460 + {
505 close(new_s); 461 close(new_s);
506 return -1; 462 return -1;
507 } 463 }
@@ -509,7 +465,7 @@ int modbus_tcp_listen(modbus_t *ctx, int nb_connection) @@ -509,7 +465,7 @@ int modbus_tcp_listen(modbus_t *ctx, int nb_connection)
509 return new_s; 465 return new_s;
510 } 466 }
511 467
512 -int modbus_tcp_pi_listen(modbus_t *ctx, int nb_connection) 468 +int modbus_tcp_pi_listen( modbus_t *ctx, int nb_connection )
513 { 469 {
514 int rc; 470 int rc;
515 struct addrinfo *ai_list; 471 struct addrinfo *ai_list;
@@ -520,32 +476,33 @@ int modbus_tcp_pi_listen(modbus_t *ctx, int nb_connection) @@ -520,32 +476,33 @@ int modbus_tcp_pi_listen(modbus_t *ctx, int nb_connection)
520 int new_s; 476 int new_s;
521 modbus_tcp_pi_t *ctx_tcp_pi; 477 modbus_tcp_pi_t *ctx_tcp_pi;
522 478
523 - if (ctx == NULL) { 479 + if (ctx == NULL)
  480 + {
524 errno = EINVAL; 481 errno = EINVAL;
525 return -1; 482 return -1;
526 } 483 }
527 484
528 ctx_tcp_pi = ctx->backend_data; 485 ctx_tcp_pi = ctx->backend_data;
529 486
530 -#ifdef OS_WIN32  
531 - if (_modbus_tcp_init_win32() == -1) {  
532 - return -1;  
533 - }  
534 -#endif  
535 -  
536 - if (ctx_tcp_pi->node[0] == 0) { 487 + if ( ctx_tcp_pi->node[0] == 0)
  488 + {
537 node = NULL; /* == any */ 489 node = NULL; /* == any */
538 - } else { 490 + }
  491 + else
  492 + {
539 node = ctx_tcp_pi->node; 493 node = ctx_tcp_pi->node;
540 } 494 }
541 495
542 - if (ctx_tcp_pi->service[0] == 0) { 496 + if ( ctx_tcp_pi->service[0] == 0 )
  497 + {
543 service = "502"; 498 service = "502";
544 - } else { 499 + }
  500 + else
  501 + {
545 service = ctx_tcp_pi->service; 502 service = ctx_tcp_pi->service;
546 } 503 }
547 504
548 - memset(&ai_hints, 0, sizeof (ai_hints)); 505 + memset( &ai_hints, 0, sizeof (ai_hints) );
549 /* If node is not NULL, than the AI_PASSIVE flag is ignored. */ 506 /* If node is not NULL, than the AI_PASSIVE flag is ignored. */
550 ai_hints.ai_flags |= AI_PASSIVE; 507 ai_hints.ai_flags |= AI_PASSIVE;
551 #ifdef AI_ADDRCONFIG 508 #ifdef AI_ADDRCONFIG
@@ -559,8 +516,10 @@ int modbus_tcp_pi_listen(modbus_t *ctx, int nb_connection) @@ -559,8 +516,10 @@ int modbus_tcp_pi_listen(modbus_t *ctx, int nb_connection)
559 516
560 ai_list = NULL; 517 ai_list = NULL;
561 rc = getaddrinfo(node, service, &ai_hints, &ai_list); 518 rc = getaddrinfo(node, service, &ai_hints, &ai_list);
562 - if (rc != 0) {  
563 - if (ctx->debug) { 519 + if (rc != 0)
  520 + {
  521 + if (ctx->debug)
  522 + {
564 fprintf(stderr, "Error returned by getaddrinfo: %s\n", gai_strerror(rc)); 523 fprintf(stderr, "Error returned by getaddrinfo: %s\n", gai_strerror(rc));
565 } 524 }
566 errno = ECONNREFUSED; 525 errno = ECONNREFUSED;
@@ -568,23 +527,28 @@ int modbus_tcp_pi_listen(modbus_t *ctx, int nb_connection) @@ -568,23 +527,28 @@ int modbus_tcp_pi_listen(modbus_t *ctx, int nb_connection)
568 } 527 }
569 528
570 new_s = -1; 529 new_s = -1;
571 - for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) { 530 + for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
  531 + {
572 int s; 532 int s;
573 533
574 - s = socket(ai_ptr->ai_family, ai_ptr->ai_socktype,  
575 - ai_ptr->ai_protocol);  
576 - if (s < 0) {  
577 - if (ctx->debug) { 534 + s = socket( ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol );
  535 + if (s < 0)
  536 + {
  537 + if (ctx->debug)
  538 + {
578 perror("socket"); 539 perror("socket");
579 } 540 }
580 continue; 541 continue;
581 - } else { 542 + }
  543 + else
  544 + {
582 int enable = 1; 545 int enable = 1;
583 - rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR,  
584 - (void *)&enable, sizeof (enable));  
585 - if (rc != 0) { 546 + rc = setsockopt( s, SOL_SOCKET, SO_REUSEADDR, (void *)&enable, sizeof (enable) );
  547 + if (rc != 0)
  548 + {
586 close(s); 549 close(s);
587 - if (ctx->debug) { 550 + if (ctx->debug)
  551 + {
588 perror("setsockopt"); 552 perror("setsockopt");
589 } 553 }
590 continue; 554 continue;
@@ -592,18 +556,22 @@ int modbus_tcp_pi_listen(modbus_t *ctx, int nb_connection) @@ -592,18 +556,22 @@ int modbus_tcp_pi_listen(modbus_t *ctx, int nb_connection)
592 } 556 }
593 557
594 rc = bind(s, ai_ptr->ai_addr, ai_ptr->ai_addrlen); 558 rc = bind(s, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
595 - if (rc != 0) { 559 + if (rc != 0)
  560 + {
596 close(s); 561 close(s);
597 - if (ctx->debug) { 562 + if (ctx->debug)
  563 + {
598 perror("bind"); 564 perror("bind");
599 } 565 }
600 continue; 566 continue;
601 } 567 }
602 568
603 rc = listen(s, nb_connection); 569 rc = listen(s, nb_connection);
604 - if (rc != 0) { 570 + if (rc != 0)
  571 + {
605 close(s); 572 close(s);
606 - if (ctx->debug) { 573 + if (ctx->debug)
  574 + {
607 perror("listen"); 575 perror("listen");
608 } 576 }
609 continue; 577 continue;
@@ -614,7 +582,8 @@ int modbus_tcp_pi_listen(modbus_t *ctx, int nb_connection) @@ -614,7 +582,8 @@ int modbus_tcp_pi_listen(modbus_t *ctx, int nb_connection)
614 } 582 }
615 freeaddrinfo(ai_list); 583 freeaddrinfo(ai_list);
616 584
617 - if (new_s < 0) { 585 + if (new_s < 0)
  586 + {
618 return -1; 587 return -1;
619 } 588 }
620 589
@@ -626,7 +595,8 @@ int modbus_tcp_accept(modbus_t *ctx, int *s) @@ -626,7 +595,8 @@ int modbus_tcp_accept(modbus_t *ctx, int *s)
626 struct sockaddr_in addr; 595 struct sockaddr_in addr;
627 socklen_t addrlen; 596 socklen_t addrlen;
628 597
629 - if (ctx == NULL) { 598 + if (ctx == NULL)
  599 + {
630 errno = EINVAL; 600 errno = EINVAL;
631 return -1; 601 return -1;
632 } 602 }
@@ -639,13 +609,15 @@ int modbus_tcp_accept(modbus_t *ctx, int *s) @@ -639,13 +609,15 @@ int modbus_tcp_accept(modbus_t *ctx, int *s)
639 ctx->s = accept(*s, (struct sockaddr *)&addr, &addrlen); 609 ctx->s = accept(*s, (struct sockaddr *)&addr, &addrlen);
640 #endif 610 #endif
641 611
642 - if (ctx->s == -1) { 612 + if (ctx->s == -1)
  613 + {
643 close(*s); 614 close(*s);
644 *s = -1; 615 *s = -1;
645 return -1; 616 return -1;
646 } 617 }
647 618
648 - if (ctx->debug) { 619 + if (ctx->debug)
  620 + {
649 printf("The client connection from %s is accepted\n", 621 printf("The client connection from %s is accepted\n",
650 inet_ntoa(addr.sin_addr)); 622 inet_ntoa(addr.sin_addr));
651 } 623 }
@@ -653,12 +625,13 @@ int modbus_tcp_accept(modbus_t *ctx, int *s) @@ -653,12 +625,13 @@ int modbus_tcp_accept(modbus_t *ctx, int *s)
653 return ctx->s; 625 return ctx->s;
654 } 626 }
655 627
656 -int modbus_tcp_pi_accept(modbus_t *ctx, int *s) 628 +int modbus_tcp_pi_accept( modbus_t *ctx, int *s )
657 { 629 {
658 struct sockaddr_storage addr; 630 struct sockaddr_storage addr;
659 socklen_t addrlen; 631 socklen_t addrlen;
660 632
661 - if (ctx == NULL) { 633 + if (ctx == NULL)
  634 + {
662 errno = EINVAL; 635 errno = EINVAL;
663 return -1; 636 return -1;
664 } 637 }
@@ -670,12 +643,14 @@ int modbus_tcp_pi_accept(modbus_t *ctx, int *s) @@ -670,12 +643,14 @@ int modbus_tcp_pi_accept(modbus_t *ctx, int *s)
670 #else 643 #else
671 ctx->s = accept(*s, (struct sockaddr *)&addr, &addrlen); 644 ctx->s = accept(*s, (struct sockaddr *)&addr, &addrlen);
672 #endif 645 #endif
673 - if (ctx->s == -1) { 646 + if (ctx->s == -1)
  647 + {
674 close(*s); 648 close(*s);
675 *s = -1; 649 *s = -1;
676 } 650 }
677 651
678 - if (ctx->debug) { 652 + if (ctx->debug)
  653 + {
679 printf("The client connection is accepted.\n"); 654 printf("The client connection is accepted.\n");
680 } 655 }
681 656
@@ -685,20 +660,26 @@ int modbus_tcp_pi_accept(modbus_t *ctx, int *s) @@ -685,20 +660,26 @@ int modbus_tcp_pi_accept(modbus_t *ctx, int *s)
685 static int _modbus_tcp_select(modbus_t *ctx, fd_set *rset, struct timeval *tv, int length_to_read) 660 static int _modbus_tcp_select(modbus_t *ctx, fd_set *rset, struct timeval *tv, int length_to_read)
686 { 661 {
687 int s_rc; 662 int s_rc;
688 - while ((s_rc = select(ctx->s+1, rset, NULL, NULL, tv)) == -1) {  
689 - if (errno == EINTR) {  
690 - if (ctx->debug) { 663 + while ((s_rc = select(ctx->s+1, rset, NULL, NULL, tv)) == -1)
  664 + {
  665 + if (errno == EINTR)
  666 + {
  667 + if (ctx->debug)
  668 + {
691 fprintf(stderr, "A non blocked signal was caught\n"); 669 fprintf(stderr, "A non blocked signal was caught\n");
692 } 670 }
693 /* Necessary after an error */ 671 /* Necessary after an error */
694 FD_ZERO(rset); 672 FD_ZERO(rset);
695 FD_SET(ctx->s, rset); 673 FD_SET(ctx->s, rset);
696 - } else { 674 + }
  675 + else
  676 + {
697 return -1; 677 return -1;
698 } 678 }
699 } 679 }
700 680
701 - if (s_rc == 0) { 681 + if ( s_rc == 0 )
  682 + {
702 errno = ETIMEDOUT; 683 errno = ETIMEDOUT;
703 return -1; 684 return -1;
704 } 685 }
@@ -706,12 +687,14 @@ static int _modbus_tcp_select(modbus_t *ctx, fd_set *rset, struct timeval *tv, i @@ -706,12 +687,14 @@ static int _modbus_tcp_select(modbus_t *ctx, fd_set *rset, struct timeval *tv, i
706 return s_rc; 687 return s_rc;
707 } 688 }
708 689
709 -static void _modbus_tcp_free(modbus_t *ctx) { 690 +static void _modbus_tcp_free( modbus_t *ctx )
  691 +{
710 free(ctx->backend_data); 692 free(ctx->backend_data);
711 free(ctx); 693 free(ctx);
712 } 694 }
713 695
714 -const modbus_backend_t _modbus_tcp_backend = { 696 +const modbus_backend_t _modbus_tcp_backend =
  697 +{
715 _MODBUS_BACKEND_TYPE_TCP, 698 _MODBUS_BACKEND_TYPE_TCP,
716 _MODBUS_TCP_HEADER_LENGTH, 699 _MODBUS_TCP_HEADER_LENGTH,
717 _MODBUS_TCP_CHECKSUM_LENGTH, 700 _MODBUS_TCP_CHECKSUM_LENGTH,
@@ -734,7 +717,8 @@ const modbus_backend_t _modbus_tcp_backend = { @@ -734,7 +717,8 @@ const modbus_backend_t _modbus_tcp_backend = {
734 }; 717 };
735 718
736 719
737 -const modbus_backend_t _modbus_tcp_pi_backend = { 720 +const modbus_backend_t _modbus_tcp_pi_backend =
  721 +{
738 _MODBUS_BACKEND_TYPE_TCP, 722 _MODBUS_BACKEND_TYPE_TCP,
739 _MODBUS_TCP_HEADER_LENGTH, 723 _MODBUS_TCP_HEADER_LENGTH,
740 _MODBUS_TCP_CHECKSUM_LENGTH, 724 _MODBUS_TCP_CHECKSUM_LENGTH,
@@ -756,27 +740,14 @@ const modbus_backend_t _modbus_tcp_pi_backend = { @@ -756,27 +740,14 @@ const modbus_backend_t _modbus_tcp_pi_backend = {
756 _modbus_tcp_free 740 _modbus_tcp_free
757 }; 741 };
758 742
759 -modbus_t* modbus_new_tcp(const char *ip, int port) 743 +modbus_t* modbus_new_tcp( const char *ip, int port )
760 { 744 {
761 modbus_t *ctx; 745 modbus_t *ctx;
762 modbus_tcp_t *ctx_tcp; 746 modbus_tcp_t *ctx_tcp;
763 size_t dest_size; 747 size_t dest_size;
764 size_t ret_size; 748 size_t ret_size;
765 749
766 -#if defined(OS_BSD)  
767 - /* MSG_NOSIGNAL is unsupported on *BSD so we install an ignore  
768 - handler for SIGPIPE. */  
769 - struct sigaction sa;  
770 -  
771 - sa.sa_handler = SIG_IGN;  
772 - if (sigaction(SIGPIPE, &sa, NULL) < 0) {  
773 - /* The debug flag can't be set here... */  
774 - fprintf(stderr, "Coud not install SIGPIPE handler.\n");  
775 - return NULL;  
776 - }  
777 -#endif  
778 -  
779 - ctx = (modbus_t *)malloc(sizeof(modbus_t)); 750 + ctx = (modbus_t *)malloc(sizeof(modbus_t) );
780 _modbus_init_common(ctx); 751 _modbus_init_common(ctx);
781 752
782 /* Could be changed after to reach a remote serial Modbus device */ 753 /* Could be changed after to reach a remote serial Modbus device */
@@ -784,26 +755,31 @@ modbus_t* modbus_new_tcp(const char *ip, int port) @@ -784,26 +755,31 @@ modbus_t* modbus_new_tcp(const char *ip, int port)
784 755
785 ctx->backend = &_modbus_tcp_backend; 756 ctx->backend = &_modbus_tcp_backend;
786 757
787 - ctx->backend_data = (modbus_tcp_t *)malloc(sizeof(modbus_tcp_t)); 758 + ctx->backend_data = ( modbus_tcp_t *)malloc(sizeof(modbus_tcp_t) );
788 ctx_tcp = (modbus_tcp_t *)ctx->backend_data; 759 ctx_tcp = (modbus_tcp_t *)ctx->backend_data;
789 760
790 - if (ip != NULL) { 761 + if (ip != NULL)
  762 + {
791 dest_size = sizeof(char) * 16; 763 dest_size = sizeof(char) * 16;
792 ret_size = strlcpy(ctx_tcp->ip, ip, dest_size); 764 ret_size = strlcpy(ctx_tcp->ip, ip, dest_size);
793 - if (ret_size == 0) { 765 + if (ret_size == 0)
  766 + {
794 fprintf(stderr, "The IP string is empty\n"); 767 fprintf(stderr, "The IP string is empty\n");
795 modbus_free(ctx); 768 modbus_free(ctx);
796 errno = EINVAL; 769 errno = EINVAL;
797 return NULL; 770 return NULL;
798 } 771 }
799 772
800 - if (ret_size >= dest_size) { 773 + if (ret_size >= dest_size)
  774 + {
801 fprintf(stderr, "The IP string has been truncated\n"); 775 fprintf(stderr, "The IP string has been truncated\n");
802 modbus_free(ctx); 776 modbus_free(ctx);
803 errno = EINVAL; 777 errno = EINVAL;
804 return NULL; 778 return NULL;
805 } 779 }
806 - } else { 780 + }
  781 + else
  782 + {
807 ctx_tcp->ip[0] = '0'; 783 ctx_tcp->ip[0] = '0';
808 } 784 }
809 ctx_tcp->port = port; 785 ctx_tcp->port = port;
@@ -813,12 +789,12 @@ modbus_t* modbus_new_tcp(const char *ip, int port) @@ -813,12 +789,12 @@ modbus_t* modbus_new_tcp(const char *ip, int port)
813 } 789 }
814 790
815 791
816 -modbus_t* modbus_new_tcp_pi(const char *node, const char *service) 792 +modbus_t* modbus_new_tcp_pi( const char *node, const char *service )
817 { 793 {
818 - modbus_t *ctx; 794 + modbus_t *ctx;
819 modbus_tcp_pi_t *ctx_tcp_pi; 795 modbus_tcp_pi_t *ctx_tcp_pi;
820 - size_t dest_size;  
821 - size_t ret_size; 796 + size_t dest_size;
  797 + size_t ret_size;
822 798
823 ctx = (modbus_t *)malloc(sizeof(modbus_t)); 799 ctx = (modbus_t *)malloc(sizeof(modbus_t));
824 _modbus_init_common(ctx); 800 _modbus_init_common(ctx);
@@ -831,20 +807,25 @@ modbus_t* modbus_new_tcp_pi(const char *node, const char *service) @@ -831,20 +807,25 @@ modbus_t* modbus_new_tcp_pi(const char *node, const char *service)
831 ctx->backend_data = (modbus_tcp_pi_t *)malloc(sizeof(modbus_tcp_pi_t)); 807 ctx->backend_data = (modbus_tcp_pi_t *)malloc(sizeof(modbus_tcp_pi_t));
832 ctx_tcp_pi = (modbus_tcp_pi_t *)ctx->backend_data; 808 ctx_tcp_pi = (modbus_tcp_pi_t *)ctx->backend_data;
833 809
834 - if (node == NULL) { 810 + if (node == NULL)
  811 + {
835 /* The node argument can be empty to indicate any hosts */ 812 /* The node argument can be empty to indicate any hosts */
836 ctx_tcp_pi->node[0] = 0; 813 ctx_tcp_pi->node[0] = 0;
837 - } else { 814 + }
  815 + else
  816 + {
838 dest_size = sizeof(char) * _MODBUS_TCP_PI_NODE_LENGTH; 817 dest_size = sizeof(char) * _MODBUS_TCP_PI_NODE_LENGTH;
839 ret_size = strlcpy(ctx_tcp_pi->node, node, dest_size); 818 ret_size = strlcpy(ctx_tcp_pi->node, node, dest_size);
840 - if (ret_size == 0) { 819 + if (ret_size == 0)
  820 + {
841 fprintf(stderr, "The node string is empty\n"); 821 fprintf(stderr, "The node string is empty\n");
842 modbus_free(ctx); 822 modbus_free(ctx);
843 errno = EINVAL; 823 errno = EINVAL;
844 return NULL; 824 return NULL;
845 } 825 }
846 826
847 - if (ret_size >= dest_size) { 827 + if (ret_size >= dest_size)
  828 + {
848 fprintf(stderr, "The node string has been truncated\n"); 829 fprintf(stderr, "The node string has been truncated\n");
849 modbus_free(ctx); 830 modbus_free(ctx);
850 errno = EINVAL; 831 errno = EINVAL;
@@ -852,22 +833,27 @@ modbus_t* modbus_new_tcp_pi(const char *node, const char *service) @@ -852,22 +833,27 @@ modbus_t* modbus_new_tcp_pi(const char *node, const char *service)
852 } 833 }
853 } 834 }
854 835
855 - if (service != NULL) { 836 + if (service != NULL)
  837 + {
856 dest_size = sizeof(char) * _MODBUS_TCP_PI_SERVICE_LENGTH; 838 dest_size = sizeof(char) * _MODBUS_TCP_PI_SERVICE_LENGTH;
857 ret_size = strlcpy(ctx_tcp_pi->service, service, dest_size); 839 ret_size = strlcpy(ctx_tcp_pi->service, service, dest_size);
858 - } else { 840 + }
  841 + else
  842 + {
859 /* Empty service is not allowed, error catched below. */ 843 /* Empty service is not allowed, error catched below. */
860 ret_size = 0; 844 ret_size = 0;
861 } 845 }
862 846
863 - if (ret_size == 0) { 847 + if (ret_size == 0)
  848 + {
864 fprintf(stderr, "The service string is empty\n"); 849 fprintf(stderr, "The service string is empty\n");
865 modbus_free(ctx); 850 modbus_free(ctx);
866 errno = EINVAL; 851 errno = EINVAL;
867 return NULL; 852 return NULL;
868 } 853 }
869 854
870 - if (ret_size >= dest_size) { 855 + if (ret_size >= dest_size)
  856 + {
871 fprintf(stderr, "The service string has been truncated\n"); 857 fprintf(stderr, "The service string has been truncated\n");
872 modbus_free(ctx); 858 modbus_free(ctx);
873 errno = EINVAL; 859 errno = EINVAL;
3rdparty/libmodbus/modbus-tcp.h
1 -/*  
2 - * Copyright © 2001-2010 Stéphane Raimbault <stephane.raimbault@gmail.com>  
3 - *  
4 - * SPDX-License-Identifier: LGPL-2.1+  
5 - */  
6 -  
7 -#ifndef MODBUS_TCP_H  
8 -#define MODBUS_TCP_H 1 +#pragma once
9 2
10 #include "modbus.h" 3 #include "modbus.h"
11 4
12 MODBUS_BEGIN_DECLS 5 MODBUS_BEGIN_DECLS
13 6
14 -#if defined(_WIN32) && !defined(__CYGWIN__)  
15 -/* Win32 with MinGW, supplement to <errno.h> */  
16 -#include <winsock2.h>  
17 -#if !defined(ECONNRESET)  
18 -#define ECONNRESET WSAECONNRESET  
19 -#endif  
20 -#if !defined(ECONNREFUSED)  
21 -#define ECONNREFUSED WSAECONNREFUSED  
22 -#endif  
23 -#if !defined(ETIMEDOUT)  
24 -#define ETIMEDOUT WSAETIMEDOUT  
25 -#endif  
26 -#if !defined(ENOPROTOOPT)  
27 -#define ENOPROTOOPT WSAENOPROTOOPT  
28 -#endif  
29 -#if !defined(EINPROGRESS)  
30 -#define EINPROGRESS WSAEINPROGRESS  
31 -#endif  
32 -#endif  
33 -  
34 #define MODBUS_TCP_DEFAULT_PORT 502 7 #define MODBUS_TCP_DEFAULT_PORT 502
35 #define MODBUS_TCP_SLAVE 0xFF 8 #define MODBUS_TCP_SLAVE 0xFF
36 9
@@ -49,4 +22,3 @@ MODBUS_API int modbus_tcp_pi_accept(modbus_t *ctx, int *s); @@ -49,4 +22,3 @@ MODBUS_API int modbus_tcp_pi_accept(modbus_t *ctx, int *s);
49 22
50 MODBUS_END_DECLS 23 MODBUS_END_DECLS
51 24
52 -#endif /* MODBUS_TCP_H */  
3rdparty/libmodbus/modbus-version.h
1 -/*  
2 - * Copyright © 2010-2014 Stéphane Raimbault <stephane.raimbault@gmail.com>  
3 - *  
4 - * This library is free software; you can redistribute it and/or  
5 - * modify it under the terms of the GNU Lesser General Public  
6 - * License as published by the Free Software Foundation; either  
7 - * version 2.1 of the License, or (at your option) any later version.  
8 - *  
9 - * This library is distributed in the hope that it will be useful,  
10 - * but WITHOUT ANY WARRANTY; without even the implied warranty of  
11 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  
12 - * Lesser General Public License for more details.  
13 - *  
14 - * You should have received a copy of the GNU Lesser General Public  
15 - * License along with this library; if not, write to the Free Software  
16 - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA  
17 - */  
18 -  
19 -#ifndef MODBUS_VERSION_H  
20 -#define MODBUS_VERSION_H 1 +#pragma once
21 2
22 /* The major version, (1, if %LIBMODBUS_VERSION is 1.2.3) */ 3 /* The major version, (1, if %LIBMODBUS_VERSION is 1.2.3) */
23 #define LIBMODBUS_VERSION_MAJOR (3) 4 #define LIBMODBUS_VERSION_MAJOR (3)
@@ -50,4 +31,4 @@ @@ -50,4 +31,4 @@
50 LIBMODBUS_VERSION_MINOR == (minor) && \ 31 LIBMODBUS_VERSION_MINOR == (minor) && \
51 LIBMODBUS_VERSION_MICRO >= (micro))) 32 LIBMODBUS_VERSION_MICRO >= (micro)))
52 33
53 -#endif /* MODBUS_VERSION_H */ 34 +
3rdparty/libmodbus/modbus.c
1 -/*  
2 - * Copyright © 2001-2011 Stéphane Raimbault <stephane.raimbault@gmail.com>  
3 - *  
4 - * SPDX-License-Identifier: LGPL-2.1+  
5 - *  
6 - * This library implements the Modbus protocol.  
7 - * http://libmodbus.org/  
8 - */  
9 - 1 +#include <config.h>
  2 +#include <errno.h>
  3 +#include <limits.h>
10 #include <stdio.h> 4 #include <stdio.h>
11 #include <string.h> 5 #include <string.h>
12 #include <stdlib.h> 6 #include <stdlib.h>
13 #include <stdarg.h> 7 #include <stdarg.h>
14 -#include <errno.h>  
15 -#include <limits.h>  
16 #include <time.h> 8 #include <time.h>
17 -#ifndef _MSC_VER  
18 #include <unistd.h> 9 #include <unistd.h>
19 -#endif  
20 -  
21 -#include <config.h>  
22 10
23 #include "modbus.h" 11 #include "modbus.h"
24 #include "modbus-private.h" 12 #include "modbus-private.h"
@@ -26,65 +14,67 @@ @@ -26,65 +14,67 @@
26 /* Internal use */ 14 /* Internal use */
27 #define MSG_LENGTH_UNDEFINED -1 15 #define MSG_LENGTH_UNDEFINED -1
28 16
29 -/* Exported version */  
30 -const unsigned int libmodbus_version_major = LIBMODBUS_VERSION_MAJOR;  
31 -const unsigned int libmodbus_version_minor = LIBMODBUS_VERSION_MINOR;  
32 -const unsigned int libmodbus_version_micro = LIBMODBUS_VERSION_MICRO;  
33 -  
34 /* Max between RTU and TCP max adu length (so TCP) */ 17 /* Max between RTU and TCP max adu length (so TCP) */
35 #define MAX_MESSAGE_LENGTH 260 18 #define MAX_MESSAGE_LENGTH 260
36 19
37 /* 3 steps are used to parse the query */ 20 /* 3 steps are used to parse the query */
38 -typedef enum { 21 +typedef enum
  22 +{
39 _STEP_FUNCTION, 23 _STEP_FUNCTION,
40 _STEP_META, 24 _STEP_META,
41 _STEP_DATA 25 _STEP_DATA
42 } _step_t; 26 } _step_t;
43 27
44 -const char *modbus_strerror(int errnum) {  
45 - switch (errnum) {  
46 - case EMBXILFUN:  
47 - return "Illegal function";  
48 - case EMBXILADD:  
49 - return "Illegal data address";  
50 - case EMBXILVAL:  
51 - return "Illegal data value";  
52 - case EMBXSFAIL:  
53 - return "Slave device or server failure";  
54 - case EMBXACK:  
55 - return "Acknowledge";  
56 - case EMBXSBUSY:  
57 - return "Slave device or server is busy";  
58 - case EMBXNACK:  
59 - return "Negative acknowledge";  
60 - case EMBXMEMPAR:  
61 - return "Memory parity error";  
62 - case EMBXGPATH:  
63 - return "Gateway path unavailable";  
64 - case EMBXGTAR:  
65 - return "Target device failed to respond";  
66 - case EMBBADCRC:  
67 - return "Invalid CRC";  
68 - case EMBBADDATA:  
69 - return "Invalid data";  
70 - case EMBBADEXC:  
71 - return "Invalid exception code";  
72 - case EMBMDATA:  
73 - return "Too many data";  
74 - case EMBBADSLAVE:  
75 - return "Response not from requested slave";  
76 - default:  
77 - return strerror(errnum); 28 +const char *modbus_strerror( int errnum )
  29 +{
  30 + switch (errnum)
  31 + {
  32 + case EMBXILFUN:
  33 + return "Illegal function";
  34 + case EMBXILADD:
  35 + return "Illegal data address";
  36 + case EMBXILVAL:
  37 + return "Illegal data value";
  38 + case EMBXSFAIL:
  39 + return "Slave device or server failure";
  40 + case EMBXACK:
  41 + return "Acknowledge";
  42 + case EMBXSBUSY:
  43 + return "Slave device or server is busy";
  44 + case EMBXNACK:
  45 + return "Negative acknowledge";
  46 + case EMBXMEMPAR:
  47 + return "Memory parity error";
  48 + case EMBXGPATH:
  49 + return "Gateway path unavailable";
  50 + case EMBXGTAR:
  51 + return "Target device failed to respond";
  52 + case EMBBADCRC:
  53 + return "Invalid CRC";
  54 + case EMBBADDATA:
  55 + return "Invalid data";
  56 + case EMBBADEXC:
  57 + return "Invalid exception code";
  58 + case EMBMDATA:
  59 + return "Too many data";
  60 + case EMBBADSLAVE:
  61 + return "Response not from requested slave";
  62 + default:
  63 + return strerror(errnum);
78 } 64 }
79 } 65 }
80 66
81 void _error_print(modbus_t *ctx, const char *context) 67 void _error_print(modbus_t *ctx, const char *context)
82 { 68 {
83 - if (ctx->debug) { 69 + if (ctx->debug)
  70 + {
84 fprintf(stderr, "ERROR %s", modbus_strerror(errno)); 71 fprintf(stderr, "ERROR %s", modbus_strerror(errno));
85 - if (context != NULL) { 72 + if (context != NULL)
  73 + {
86 fprintf(stderr, ": %s\n", context); 74 fprintf(stderr, ": %s\n", context);
87 - } else { 75 + }
  76 + else
  77 + {
88 fprintf(stderr, "\n"); 78 fprintf(stderr, "\n");
89 } 79 }
90 } 80 }
@@ -93,32 +83,29 @@ void _error_print(modbus_t *ctx, const char *context) @@ -93,32 +83,29 @@ void _error_print(modbus_t *ctx, const char *context)
93 static void _sleep_response_timeout(modbus_t *ctx) 83 static void _sleep_response_timeout(modbus_t *ctx)
94 { 84 {
95 /* Response timeout is always positive */ 85 /* Response timeout is always positive */
96 -#ifdef _WIN32  
97 - /* usleep doesn't exist on Windows */  
98 - Sleep((ctx->response_timeout.tv_sec * 1000) +  
99 - (ctx->response_timeout.tv_usec / 1000));  
100 -#else  
101 /* usleep source code */ 86 /* usleep source code */
102 struct timespec request, remaining; 87 struct timespec request, remaining;
103 request.tv_sec = ctx->response_timeout.tv_sec; 88 request.tv_sec = ctx->response_timeout.tv_sec;
104 request.tv_nsec = ((long int)ctx->response_timeout.tv_usec) * 1000; 89 request.tv_nsec = ((long int)ctx->response_timeout.tv_usec) * 1000;
105 - while (nanosleep(&request, &remaining) == -1 && errno == EINTR) { 90 + while ( nanosleep( &request, &remaining ) == -1 && errno == EINTR )
  91 + {
106 request = remaining; 92 request = remaining;
107 } 93 }
108 -#endif  
109 } 94 }
110 95
111 int modbus_flush(modbus_t *ctx) 96 int modbus_flush(modbus_t *ctx)
112 { 97 {
113 int rc; 98 int rc;
114 99
115 - if (ctx == NULL) { 100 + if (ctx == NULL)
  101 + {
116 errno = EINVAL; 102 errno = EINVAL;
117 return -1; 103 return -1;
118 } 104 }
119 105
120 - rc = ctx->backend->flush(ctx);  
121 - if (rc != -1 && ctx->debug) { 106 + rc = ctx->backend->flush( ctx );
  107 + if (rc != -1 && ctx->debug)
  108 + {
122 /* Not all backends are able to return the number of bytes flushed */ 109 /* Not all backends are able to return the number of bytes flushed */
123 printf("Bytes flushed (%d)\n", rc); 110 printf("Bytes flushed (%d)\n", rc);
124 } 111 }
@@ -131,32 +118,44 @@ static unsigned int compute_response_length_from_request(modbus_t *ctx, uint8_t @@ -131,32 +118,44 @@ static unsigned int compute_response_length_from_request(modbus_t *ctx, uint8_t
131 int length; 118 int length;
132 const int offset = ctx->backend->header_length; 119 const int offset = ctx->backend->header_length;
133 120
134 - switch (req[offset]) {  
135 - case MODBUS_FC_READ_COILS:  
136 - case MODBUS_FC_READ_DISCRETE_INPUTS: {  
137 - /* Header + nb values (code from write_bits) */  
138 - int nb = (req[offset + 3] << 8) | req[offset + 4];  
139 - length = 2 + (nb / 8) + ((nb % 8) ? 1 : 0);  
140 - }  
141 - break;  
142 - case MODBUS_FC_WRITE_AND_READ_REGISTERS:  
143 - case MODBUS_FC_READ_HOLDING_REGISTERS:  
144 - case MODBUS_FC_READ_INPUT_REGISTERS:  
145 - /* Header + 2 * nb values */  
146 - length = 2 + 2 * (req[offset + 3] << 8 | req[offset + 4]);  
147 - break;  
148 - case MODBUS_FC_READ_EXCEPTION_STATUS:  
149 - length = 3;  
150 - break;  
151 - case MODBUS_FC_REPORT_SLAVE_ID:  
152 - /* The response is device specific (the header provides the  
153 - length) */  
154 - return MSG_LENGTH_UNDEFINED;  
155 - case MODBUS_FC_MASK_WRITE_REGISTER:  
156 - length = 7;  
157 - break;  
158 - default:  
159 - length = 5; 121 + switch (req[offset])
  122 + {
  123 + case MODBUS_FC_READ_COILS:
  124 + case MODBUS_FC_READ_DISCRETE_INPUTS:
  125 + {
  126 + /* Header + nb values (code from write_bits) */
  127 + int nb = (req[offset + 3] << 8) | req[offset + 4];
  128 + length = 2 + (nb / 8) + ((nb % 8) ? 1 : 0);
  129 + break;
  130 + }
  131 + case MODBUS_FC_WRITE_AND_READ_REGISTERS:
  132 + case MODBUS_FC_READ_HOLDING_REGISTERS:
  133 + case MODBUS_FC_READ_INPUT_REGISTERS:
  134 + {
  135 + /* Header + 2 * nb values */
  136 + length = 2 + 2 * (req[offset + 3] << 8 | req[offset + 4]);
  137 + break;
  138 + }
  139 + case MODBUS_FC_READ_EXCEPTION_STATUS:
  140 + {
  141 + length = 3;
  142 + break;
  143 + }
  144 + case MODBUS_FC_REPORT_SLAVE_ID:
  145 + {
  146 + /* The response is device specific (the header provides the
  147 + length) */
  148 + return MSG_LENGTH_UNDEFINED;
  149 + }
  150 + case MODBUS_FC_MASK_WRITE_REGISTER:
  151 + {
  152 + length = 7;
  153 + break;
  154 + }
  155 + default:
  156 + {
  157 + length = 5;
  158 + }
160 } 159 }
161 160
162 return offset + length + ctx->backend->checksum_length; 161 return offset + length + ctx->backend->checksum_length;
@@ -170,34 +169,42 @@ static int send_msg(modbus_t *ctx, uint8_t *msg, int msg_length) @@ -170,34 +169,42 @@ static int send_msg(modbus_t *ctx, uint8_t *msg, int msg_length)
170 169
171 msg_length = ctx->backend->send_msg_pre(msg, msg_length); 170 msg_length = ctx->backend->send_msg_pre(msg, msg_length);
172 171
173 - if (ctx->debug) { 172 + if (ctx->debug)
  173 + {
174 for (i = 0; i < msg_length; i++) 174 for (i = 0; i < msg_length; i++)
  175 + {
175 printf("[%.2X]", msg[i]); 176 printf("[%.2X]", msg[i]);
  177 + }
176 printf("\n"); 178 printf("\n");
177 } 179 }
178 - 180 +
179 /* In recovery mode, the write command will be issued until to be 181 /* In recovery mode, the write command will be issued until to be
180 successful! Disabled by default. */ 182 successful! Disabled by default. */
181 - do { 183 + do
  184 + {
182 rc = ctx->backend->send(ctx, msg, msg_length); 185 rc = ctx->backend->send(ctx, msg, msg_length);
183 - if (rc == -1) { 186 + if (rc == -1)
  187 + {
184 _error_print(ctx, NULL); 188 _error_print(ctx, NULL);
185 - if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) { 189 + if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK)
  190 + {
186 int saved_errno = errno; 191 int saved_errno = errno;
187 192
188 - if ((errno == EBADF || errno == ECONNRESET || errno == EPIPE)) { 193 + if ( (errno == EBADF || errno == ECONNRESET || errno == EPIPE))
  194 + {
189 modbus_close(ctx); 195 modbus_close(ctx);
190 _sleep_response_timeout(ctx); 196 _sleep_response_timeout(ctx);
191 modbus_connect(ctx); 197 modbus_connect(ctx);
192 - } else { 198 + }
  199 + else
  200 + {
193 _sleep_response_timeout(ctx); 201 _sleep_response_timeout(ctx);
194 modbus_flush(ctx); 202 modbus_flush(ctx);
195 } 203 }
196 errno = saved_errno; 204 errno = saved_errno;
197 } 205 }
198 } 206 }
199 - } while ((ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) &&  
200 - rc == -1); 207 + } while ( (ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) && rc == -1);
201 208
202 if (rc > 0 && rc != msg_length) { 209 if (rc > 0 && rc != msg_length) {
203 errno = EMBBADDATA; 210 errno = EMBBADDATA;
@@ -207,18 +214,20 @@ static int send_msg(modbus_t *ctx, uint8_t *msg, int msg_length) @@ -207,18 +214,20 @@ static int send_msg(modbus_t *ctx, uint8_t *msg, int msg_length)
207 return rc; 214 return rc;
208 } 215 }
209 216
210 -int modbus_send_raw_request(modbus_t *ctx, uint8_t *raw_req, int raw_req_length) 217 +int modbus_send_raw_request( modbus_t *ctx, uint8_t *raw_req, int raw_req_length )
211 { 218 {
212 sft_t sft; 219 sft_t sft;
213 uint8_t req[MAX_MESSAGE_LENGTH]; 220 uint8_t req[MAX_MESSAGE_LENGTH];
214 int req_length; 221 int req_length;
215 222
216 - if (ctx == NULL) { 223 + if (ctx == NULL)
  224 + {
217 errno = EINVAL; 225 errno = EINVAL;
218 return -1; 226 return -1;
219 } 227 }
220 228
221 - if (raw_req_length < 2 || raw_req_length > (MODBUS_MAX_PDU_LENGTH + 1)) { 229 + if (raw_req_length < 2 || raw_req_length > (MODBUS_MAX_PDU_LENGTH + 1))
  230 + {
222 /* The raw request must contain function and slave at least and 231 /* The raw request must contain function and slave at least and
223 must not be longer than the maximum pdu length plus the slave 232 must not be longer than the maximum pdu length plus the slave
224 address. */ 233 address. */
@@ -233,7 +242,8 @@ int modbus_send_raw_request(modbus_t *ctx, uint8_t *raw_req, int raw_req_length) @@ -233,7 +242,8 @@ int modbus_send_raw_request(modbus_t *ctx, uint8_t *raw_req, int raw_req_length)
233 /* This response function only set the header so it's convenient here */ 242 /* This response function only set the header so it's convenient here */
234 req_length = ctx->backend->build_response_basis(&sft, req); 243 req_length = ctx->backend->build_response_basis(&sft, req);
235 244
236 - if (raw_req_length > 2) { 245 + if( raw_req_length > 2 )
  246 + {
237 /* Copy data after function code */ 247 /* Copy data after function code */
238 memcpy(req + req_length, raw_req + 2, raw_req_length - 2); 248 memcpy(req + req_length, raw_req + 2, raw_req_length - 2);
239 req_length += raw_req_length - 2; 249 req_length += raw_req_length - 2;
@@ -249,39 +259,50 @@ int modbus_send_raw_request(modbus_t *ctx, uint8_t *raw_req, int raw_req_length) @@ -249,39 +259,50 @@ int modbus_send_raw_request(modbus_t *ctx, uint8_t *raw_req, int raw_req_length)
249 */ 259 */
250 260
251 /* Computes the length to read after the function received */ 261 /* Computes the length to read after the function received */
252 -static uint8_t compute_meta_length_after_function(int function,  
253 - msg_type_t msg_type) 262 +static uint8_t compute_meta_length_after_function( int function, msg_type_t msg_type )
254 { 263 {
255 int length; 264 int length;
256 265
257 - if (msg_type == MSG_INDICATION) {  
258 - if (function <= MODBUS_FC_WRITE_SINGLE_REGISTER) { 266 + if (msg_type == MSG_INDICATION)
  267 + {
  268 + if (function <= MODBUS_FC_WRITE_SINGLE_REGISTER)
  269 + {
259 length = 4; 270 length = 4;
260 - } else if (function == MODBUS_FC_WRITE_MULTIPLE_COILS ||  
261 - function == MODBUS_FC_WRITE_MULTIPLE_REGISTERS) { 271 + }
  272 + else if (function == MODBUS_FC_WRITE_MULTIPLE_COILS || function == MODBUS_FC_WRITE_MULTIPLE_REGISTERS)
  273 + {
262 length = 5; 274 length = 5;
263 - } else if (function == MODBUS_FC_MASK_WRITE_REGISTER) { 275 + }
  276 + else if (function == MODBUS_FC_MASK_WRITE_REGISTER)
  277 + {
264 length = 6; 278 length = 6;
265 - } else if (function == MODBUS_FC_WRITE_AND_READ_REGISTERS) { 279 + }
  280 + else if (function == MODBUS_FC_WRITE_AND_READ_REGISTERS)
  281 + {
266 length = 9; 282 length = 9;
267 - } else { 283 + }
  284 + else
  285 + {
268 /* MODBUS_FC_READ_EXCEPTION_STATUS, MODBUS_FC_REPORT_SLAVE_ID */ 286 /* MODBUS_FC_READ_EXCEPTION_STATUS, MODBUS_FC_REPORT_SLAVE_ID */
269 length = 0; 287 length = 0;
270 } 288 }
271 - } else { 289 + }
  290 + else
  291 + {
272 /* MSG_CONFIRMATION */ 292 /* MSG_CONFIRMATION */
273 - switch (function) {  
274 - case MODBUS_FC_WRITE_SINGLE_COIL:  
275 - case MODBUS_FC_WRITE_SINGLE_REGISTER:  
276 - case MODBUS_FC_WRITE_MULTIPLE_COILS:  
277 - case MODBUS_FC_WRITE_MULTIPLE_REGISTERS:  
278 - length = 4;  
279 - break;  
280 - case MODBUS_FC_MASK_WRITE_REGISTER:  
281 - length = 6;  
282 - break;  
283 - default:  
284 - length = 1; 293 + switch (function)
  294 + {
  295 + case MODBUS_FC_WRITE_SINGLE_COIL:
  296 + case MODBUS_FC_WRITE_SINGLE_REGISTER:
  297 + case MODBUS_FC_WRITE_MULTIPLE_COILS:
  298 + case MODBUS_FC_WRITE_MULTIPLE_REGISTERS:
  299 + length = 4;
  300 + break;
  301 + case MODBUS_FC_MASK_WRITE_REGISTER:
  302 + length = 6;
  303 + break;
  304 + default:
  305 + length = 1;
285 } 306 }
286 } 307 }
287 308
@@ -289,31 +310,37 @@ static uint8_t compute_meta_length_after_function(int function, @@ -289,31 +310,37 @@ static uint8_t compute_meta_length_after_function(int function,
289 } 310 }
290 311
291 /* Computes the length to read after the meta information (address, count, etc) */ 312 /* Computes the length to read after the meta information (address, count, etc) */
292 -static int compute_data_length_after_meta(modbus_t *ctx, uint8_t *msg,  
293 - msg_type_t msg_type) 313 +static int compute_data_length_after_meta(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
294 { 314 {
295 int function = msg[ctx->backend->header_length]; 315 int function = msg[ctx->backend->header_length];
296 int length; 316 int length;
297 317
298 - if (msg_type == MSG_INDICATION) {  
299 - switch (function) {  
300 - case MODBUS_FC_WRITE_MULTIPLE_COILS:  
301 - case MODBUS_FC_WRITE_MULTIPLE_REGISTERS:  
302 - length = msg[ctx->backend->header_length + 5];  
303 - break;  
304 - case MODBUS_FC_WRITE_AND_READ_REGISTERS:  
305 - length = msg[ctx->backend->header_length + 9];  
306 - break;  
307 - default:  
308 - length = 0; 318 + if (msg_type == MSG_INDICATION)
  319 + {
  320 + switch (function)
  321 + {
  322 + case MODBUS_FC_WRITE_MULTIPLE_COILS:
  323 + case MODBUS_FC_WRITE_MULTIPLE_REGISTERS:
  324 + length = msg[ctx->backend->header_length + 5];
  325 + break;
  326 + case MODBUS_FC_WRITE_AND_READ_REGISTERS:
  327 + length = msg[ctx->backend->header_length + 9];
  328 + break;
  329 + default:
  330 + length = 0;
309 } 331 }
310 - } else { 332 + }
  333 + else
  334 + {
311 /* MSG_CONFIRMATION */ 335 /* MSG_CONFIRMATION */
312 if (function <= MODBUS_FC_READ_INPUT_REGISTERS || 336 if (function <= MODBUS_FC_READ_INPUT_REGISTERS ||
313 function == MODBUS_FC_REPORT_SLAVE_ID || 337 function == MODBUS_FC_REPORT_SLAVE_ID ||
314 - function == MODBUS_FC_WRITE_AND_READ_REGISTERS) { 338 + function == MODBUS_FC_WRITE_AND_READ_REGISTERS)
  339 + {
315 length = msg[ctx->backend->header_length + 1]; 340 length = msg[ctx->backend->header_length + 1];
316 - } else { 341 + }
  342 + else
  343 + {
317 length = 0; 344 length = 0;
318 } 345 }
319 } 346 }
@@ -337,7 +364,7 @@ static int compute_data_length_after_meta(modbus_t *ctx, uint8_t *msg, @@ -337,7 +364,7 @@ static int compute_data_length_after_meta(modbus_t *ctx, uint8_t *msg,
337 - read() or recv() error codes 364 - read() or recv() error codes
338 */ 365 */
339 366
340 -int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) 367 +int _modbus_receive_msg( modbus_t *ctx, uint8_t *msg, msg_type_t msg_type )
341 { 368 {
342 int rc; 369 int rc;
343 fd_set rset; 370 fd_set rset;
@@ -347,10 +374,14 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) @@ -347,10 +374,14 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
347 int msg_length = 0; 374 int msg_length = 0;
348 _step_t step; 375 _step_t step;
349 376
350 - if (ctx->debug) {  
351 - if (msg_type == MSG_INDICATION) { 377 + if (ctx->debug)
  378 + {
  379 + if (msg_type == MSG_INDICATION)
  380 + {
352 printf("Waiting for a indication...\n"); 381 printf("Waiting for a indication...\n");
353 - } else { 382 + }
  383 + else
  384 + {
354 printf("Waiting for a confirmation...\n"); 385 printf("Waiting for a confirmation...\n");
355 } 386 }
356 } 387 }
@@ -365,27 +396,36 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) @@ -365,27 +396,36 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
365 step = _STEP_FUNCTION; 396 step = _STEP_FUNCTION;
366 length_to_read = ctx->backend->header_length + 1; 397 length_to_read = ctx->backend->header_length + 1;
367 398
368 - if (msg_type == MSG_INDICATION) { 399 + if (msg_type == MSG_INDICATION)
  400 + {
369 /* Wait for a message, we don't know when the message will be 401 /* Wait for a message, we don't know when the message will be
370 * received */ 402 * received */
371 p_tv = NULL; 403 p_tv = NULL;
372 - } else { 404 + }
  405 + else
  406 + {
373 tv.tv_sec = ctx->response_timeout.tv_sec; 407 tv.tv_sec = ctx->response_timeout.tv_sec;
374 tv.tv_usec = ctx->response_timeout.tv_usec; 408 tv.tv_usec = ctx->response_timeout.tv_usec;
375 p_tv = &tv; 409 p_tv = &tv;
376 } 410 }
377 411
378 - while (length_to_read != 0) { 412 + while (length_to_read != 0)
  413 + {
379 rc = ctx->backend->select(ctx, &rset, p_tv, length_to_read); 414 rc = ctx->backend->select(ctx, &rset, p_tv, length_to_read);
380 - if (rc == -1) { 415 + if (rc == -1)
  416 + {
381 _error_print(ctx, "select"); 417 _error_print(ctx, "select");
382 - if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) { 418 + if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK)
  419 + {
383 int saved_errno = errno; 420 int saved_errno = errno;
384 421
385 - if (errno == ETIMEDOUT) { 422 + if (errno == ETIMEDOUT)
  423 + {
386 _sleep_response_timeout(ctx); 424 _sleep_response_timeout(ctx);
387 modbus_flush(ctx); 425 modbus_flush(ctx);
388 - } else if (errno == EBADF) { 426 + }
  427 + else if (errno == EBADF)
  428 + {
389 modbus_close(ctx); 429 modbus_close(ctx);
390 modbus_connect(ctx); 430 modbus_connect(ctx);
391 } 431 }
@@ -395,16 +435,19 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) @@ -395,16 +435,19 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
395 } 435 }
396 436
397 rc = ctx->backend->recv(ctx, msg + msg_length, length_to_read); 437 rc = ctx->backend->recv(ctx, msg + msg_length, length_to_read);
398 - if (rc == 0) { 438 + if (rc == 0)
  439 + {
399 errno = ECONNRESET; 440 errno = ECONNRESET;
400 rc = -1; 441 rc = -1;
401 } 442 }
402 443
403 - if (rc == -1) { 444 + if (rc == -1)
  445 + {
404 _error_print(ctx, "read"); 446 _error_print(ctx, "read");
405 if ((ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) && 447 if ((ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) &&
406 (errno == ECONNRESET || errno == ECONNREFUSED || 448 (errno == ECONNRESET || errno == ECONNREFUSED ||
407 - errno == EBADF)) { 449 + errno == EBADF))
  450 + {
408 int saved_errno = errno; 451 int saved_errno = errno;
409 modbus_close(ctx); 452 modbus_close(ctx);
410 modbus_connect(ctx); 453 modbus_connect(ctx);
@@ -415,7 +458,8 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) @@ -415,7 +458,8 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
415 } 458 }
416 459
417 /* Display the hex code of each character received */ 460 /* Display the hex code of each character received */
418 - if (ctx->debug) { 461 + if (ctx->debug)
  462 + {
419 int i; 463 int i;
420 for (i=0; i < rc; i++) 464 for (i=0; i < rc; i++)
421 printf("<%.2X>", msg[msg_length + i]); 465 printf("<%.2X>", msg[msg_length + i]);
@@ -426,34 +470,37 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) @@ -426,34 +470,37 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
426 /* Computes remaining bytes */ 470 /* Computes remaining bytes */
427 length_to_read -= rc; 471 length_to_read -= rc;
428 472
429 - if (length_to_read == 0) {  
430 - switch (step) {  
431 - case _STEP_FUNCTION:  
432 - /* Function code position */  
433 - length_to_read = compute_meta_length_after_function(  
434 - msg[ctx->backend->header_length],  
435 - msg_type);  
436 - if (length_to_read != 0) {  
437 - step = _STEP_META; 473 + if (length_to_read == 0)
  474 + {
  475 + switch( step )
  476 + {
  477 + case _STEP_FUNCTION:
  478 + /* Function code position */
  479 + length_to_read = compute_meta_length_after_function( msg[ctx->backend->header_length], msg_type);
  480 + if (length_to_read != 0)
  481 + {
  482 + step = _STEP_META;
  483 + break;
  484 + } /* else switches straight to the next step */
  485 + __attribute__((fallthrough)); ///< Let the compiler know we intentionallly created a fallthrough.
  486 + case _STEP_META:
  487 + length_to_read = compute_data_length_after_meta( ctx, msg, msg_type);
  488 + if ( (msg_length + length_to_read) > (int)ctx->backend->max_adu_length )
  489 + {
  490 + errno = EMBBADDATA;
  491 + _error_print(ctx, "too many data");
  492 + return -1;
  493 + }
  494 + step = _STEP_DATA;
  495 + break;
  496 + default:
438 break; 497 break;
439 - } /* else switches straight to the next step */  
440 - case _STEP_META:  
441 - length_to_read = compute_data_length_after_meta(  
442 - ctx, msg, msg_type);  
443 - if ((msg_length + length_to_read) > (int)ctx->backend->max_adu_length) {  
444 - errno = EMBBADDATA;  
445 - _error_print(ctx, "too many data");  
446 - return -1;  
447 - }  
448 - step = _STEP_DATA;  
449 - break;  
450 - default:  
451 - break;  
452 } 498 }
453 } 499 }
454 500
455 if (length_to_read > 0 && 501 if (length_to_read > 0 &&
456 - (ctx->byte_timeout.tv_sec > 0 || ctx->byte_timeout.tv_usec > 0)) { 502 + (ctx->byte_timeout.tv_sec > 0 || ctx->byte_timeout.tv_usec > 0))
  503 + {
457 /* If there is no character in the buffer, the allowed timeout 504 /* If there is no character in the buffer, the allowed timeout
458 interval between two consecutive bytes is defined by 505 interval between two consecutive bytes is defined by
459 byte_timeout */ 506 byte_timeout */
@@ -890,7 +937,8 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, @@ -890,7 +937,8 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req,
890 } 937 }
891 } 938 }
892 break; 939 break;
893 - case MODBUS_FC_REPORT_SLAVE_ID: { 940 + case MODBUS_FC_REPORT_SLAVE_ID:
  941 + {
894 int str_len; 942 int str_len;
895 int byte_count_pos; 943 int byte_count_pos;
896 944
@@ -900,9 +948,8 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, @@ -900,9 +948,8 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req,
900 rsp[rsp_length++] = _REPORT_SLAVE_ID; 948 rsp[rsp_length++] = _REPORT_SLAVE_ID;
901 /* Run indicator status to ON */ 949 /* Run indicator status to ON */
902 rsp[rsp_length++] = 0xFF; 950 rsp[rsp_length++] = 0xFF;
903 - /* LMB + length of LIBMODBUS_VERSION_STRING */  
904 - str_len = 3 + strlen(LIBMODBUS_VERSION_STRING);  
905 - memcpy(rsp + rsp_length, "LMB" LIBMODBUS_VERSION_STRING, str_len); 951 + str_len = 3 + strlen(MODBUS_VERSION_STRING);
  952 + memcpy(rsp + rsp_length, "LMB" MODBUS_VERSION_STRING, str_len);
906 rsp_length += str_len; 953 rsp_length += str_len;
907 rsp[byte_count_pos] = rsp_length - byte_count_pos - 1; 954 rsp[byte_count_pos] = rsp_length - byte_count_pos - 1;
908 } 955 }
@@ -1141,7 +1188,8 @@ static int read_registers(modbus_t *ctx, int function, int addr, int nb, uint16_ @@ -1141,7 +1188,8 @@ static int read_registers(modbus_t *ctx, int function, int addr, int nb, uint16_
1141 if (ctx->debug) 1188 if (ctx->debug)
1142 { 1189 {
1143 fprintf(stderr, 1190 fprintf(stderr,
1144 - "ERROR Too many registers requested (%d > %d)\n", nb, MODBUS_MAX_READ_REGISTERS); 1191 + "ERROR Too many registers requested (%d > %d)\n",
  1192 + nb, MODBUS_MAX_READ_REGISTERS);
1145 } 1193 }
1146 errno = EMBMDATA; 1194 errno = EMBMDATA;
1147 return -1; 1195 return -1;
@@ -1165,10 +1213,10 @@ static int read_registers(modbus_t *ctx, int function, int addr, int nb, uint16_ @@ -1165,10 +1213,10 @@ static int read_registers(modbus_t *ctx, int function, int addr, int nb, uint16_
1165 1213
1166 offset = ctx->backend->header_length; 1214 offset = ctx->backend->header_length;
1167 1215
1168 - for (i = 0; i < rc; i++)  
1169 - { 1216 + for (i = 0; i < rc; i++) {
1170 /* shift reg hi_byte to temp OR with lo_byte */ 1217 /* shift reg hi_byte to temp OR with lo_byte */
1171 - dest[i] = (rsp[offset + 2 + (i << 1)] << 8) | rsp[offset + 3 + (i << 1)]; 1218 + dest[i] = (rsp[offset + 2 + (i << 1)] << 8) |
  1219 + rsp[offset + 3 + (i << 1)];
1172 } 1220 }
1173 } 1221 }
1174 1222
@@ -1186,8 +1234,10 @@ int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest) @@ -1186,8 +1234,10 @@ int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest)
1186 return -1; 1234 return -1;
1187 } 1235 }
1188 1236
1189 - if (nb > MODBUS_MAX_READ_REGISTERS) {  
1190 - if (ctx->debug) { 1237 + if (nb > MODBUS_MAX_READ_REGISTERS)
  1238 + {
  1239 + if (ctx->debug)
  1240 + {
1191 fprintf(stderr, 1241 fprintf(stderr,
1192 "ERROR Too many registers requested (%d > %d)\n", 1242 "ERROR Too many registers requested (%d > %d)\n",
1193 nb, MODBUS_MAX_READ_REGISTERS); 1243 nb, MODBUS_MAX_READ_REGISTERS);
3rdparty/libmodbus/modbus.h
1 -/*  
2 - * Copyright © 2001-2013 Stéphane Raimbault <stephane.raimbault@gmail.com>  
3 - *  
4 - * SPDX-License-Identifier: LGPL-2.1+  
5 - */  
6 1
7 -#ifndef MODBUS_H  
8 -#define MODBUS_H 2 +#pragma once
9 3
10 /* Add this for macros that defined unix flavor */ 4 /* Add this for macros that defined unix flavor */
11 #if (defined(__unix__) || defined(unix)) && !defined(USG) 5 #if (defined(__unix__) || defined(unix)) && !defined(USG)
12 #include <sys/param.h> 6 #include <sys/param.h>
13 #endif 7 #endif
14 8
15 -#ifndef _MSC_VER  
16 #include <stdint.h> 9 #include <stdint.h>
17 -#else  
18 -#include "stdint.h"  
19 -#endif  
20 10
21 -#include "modbus-version.h" 11 +#define MODBUS_API
22 12
23 -#if defined(_MSC_VER)  
24 -# if defined(DLLBUILD)  
25 -/* define DLLBUILD when building the DLL */  
26 -# define MODBUS_API __declspec(dllexport)  
27 -# else  
28 -# define MODBUS_API __declspec(dllimport)  
29 -# endif  
30 -#else  
31 -# define MODBUS_API  
32 -#endif 13 +#define MODBUS_VERSION_STRING "1.0.0"
33 14
34 #ifdef __cplusplus 15 #ifdef __cplusplus
35 -# define MODBUS_BEGIN_DECLS extern "C" {  
36 -# define MODBUS_END_DECLS } 16 +#define MODBUS_BEGIN_DECLS extern "C" {
  17 +#define MODBUS_END_DECLS }
37 #else 18 #else
38 # define MODBUS_BEGIN_DECLS 19 # define MODBUS_BEGIN_DECLS
39 # define MODBUS_END_DECLS 20 # define MODBUS_END_DECLS
@@ -148,10 +129,6 @@ enum { @@ -148,10 +129,6 @@ enum {
148 #define EMBMDATA (EMBXGTAR + 5) 129 #define EMBMDATA (EMBXGTAR + 5)
149 #define EMBBADSLAVE (EMBXGTAR + 6) 130 #define EMBBADSLAVE (EMBXGTAR + 6)
150 131
151 -extern const unsigned int libmodbus_version_major;  
152 -extern const unsigned int libmodbus_version_minor;  
153 -extern const unsigned int libmodbus_version_micro;  
154 -  
155 typedef struct _modbus modbus_t; 132 typedef struct _modbus modbus_t;
156 133
157 typedef struct { 134 typedef struct {
@@ -208,19 +185,18 @@ MODBUS_API int modbus_write_register(modbus_t *ctx, int reg_addr, int value); @@ -208,19 +185,18 @@ MODBUS_API int modbus_write_register(modbus_t *ctx, int reg_addr, int value);
208 MODBUS_API int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *data); 185 MODBUS_API int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *data);
209 MODBUS_API int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *data); 186 MODBUS_API int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *data);
210 MODBUS_API int modbus_mask_write_register(modbus_t *ctx, int addr, uint16_t and_mask, uint16_t or_mask); 187 MODBUS_API int modbus_mask_write_register(modbus_t *ctx, int addr, uint16_t and_mask, uint16_t or_mask);
211 -MODBUS_API int modbus_write_and_read_registers(modbus_t *ctx, int write_addr, int write_nb,  
212 - const uint16_t *src, int read_addr, int read_nb,  
213 - uint16_t *dest); 188 +MODBUS_API int modbus_write_and_read_registers(modbus_t *ctx, int write_addr, int write_nb,const uint16_t *src, int read_addr, int read_nb,uint16_t *dest);
214 MODBUS_API int modbus_report_slave_id(modbus_t *ctx, int max_dest, uint8_t *dest); 189 MODBUS_API int modbus_report_slave_id(modbus_t *ctx, int max_dest, uint8_t *dest);
215 190
216 -MODBUS_API modbus_mapping_t* modbus_mapping_new_start_address( 191 +MODBUS_API modbus_mapping_t* modbus_mapping_new_start_address
  192 +(
217 unsigned int start_bits, unsigned int nb_bits, 193 unsigned int start_bits, unsigned int nb_bits,
218 unsigned int start_input_bits, unsigned int nb_input_bits, 194 unsigned int start_input_bits, unsigned int nb_input_bits,
219 unsigned int start_registers, unsigned int nb_registers, 195 unsigned int start_registers, unsigned int nb_registers,
220 - unsigned int start_input_registers, unsigned int nb_input_registers); 196 + unsigned int start_input_registers, unsigned int nb_input_registers
  197 +);
221 198
222 -MODBUS_API modbus_mapping_t* modbus_mapping_new(int nb_bits, int nb_input_bits,  
223 - int nb_registers, int nb_input_registers); 199 +MODBUS_API modbus_mapping_t* modbus_mapping_new(int nb_bits, int nb_input_bits, int nb_registers, int nb_input_registers);
224 MODBUS_API void modbus_mapping_free(modbus_mapping_t *mb_mapping); 200 MODBUS_API void modbus_mapping_free(modbus_mapping_t *mb_mapping);
225 201
226 MODBUS_API int modbus_send_raw_request(modbus_t *ctx, uint8_t *raw_req, int raw_req_length); 202 MODBUS_API int modbus_send_raw_request(modbus_t *ctx, uint8_t *raw_req, int raw_req_length);
@@ -229,10 +205,8 @@ MODBUS_API int modbus_receive(modbus_t *ctx, uint8_t *req); @@ -229,10 +205,8 @@ MODBUS_API int modbus_receive(modbus_t *ctx, uint8_t *req);
229 205
230 MODBUS_API int modbus_receive_confirmation(modbus_t *ctx, uint8_t *rsp); 206 MODBUS_API int modbus_receive_confirmation(modbus_t *ctx, uint8_t *rsp);
231 207
232 -MODBUS_API int modbus_reply(modbus_t *ctx, const uint8_t *req,  
233 - int req_length, modbus_mapping_t *mb_mapping);  
234 -MODBUS_API int modbus_reply_exception(modbus_t *ctx, const uint8_t *req,  
235 - unsigned int exception_code); 208 +MODBUS_API int modbus_reply(modbus_t *ctx, const uint8_t *req, int req_length, modbus_mapping_t *mb_mapping);
  209 +MODBUS_API int modbus_reply_exception(modbus_t *ctx, const uint8_t *req, unsigned int exception_code);
236 210
237 /** 211 /**
238 * UTILS FUNCTIONS 212 * UTILS FUNCTIONS
@@ -286,4 +260,3 @@ MODBUS_API void modbus_set_float_cdab(float f, uint16_t *dest); @@ -286,4 +260,3 @@ MODBUS_API void modbus_set_float_cdab(float f, uint16_t *dest);
286 260
287 MODBUS_END_DECLS 261 MODBUS_END_DECLS
288 262
289 -#endif /* MODBUS_H */  
src/ModbusAdapter.cpp
  1 +/*****************************************************************************
  2 + * Copyright (c) 2022 Priva b.v.
  3 + *****************************************************************************/
1 4
2 #include "ConnectionConfig.h" 5 #include "ConnectionConfig.h"
  6 +#include "modbus.h"
3 #include "ModbusAdapter.h" 7 #include "ModbusAdapter.h"
  8 +#include "privautils/PrivaLogger.h"
4 9
5 #include <cstring> /// Added for memset functionality 10 #include <cstring> /// Added for memset functionality
6 11
  12 +
  13 +
7 ModbusAdapter::ModbusAdapter() 14 ModbusAdapter::ModbusAdapter()
8 : m_modbus( nullptr ) 15 : m_modbus( nullptr )
9 { 16 {
10 - this->InitBuffers();  
11 } 17 }
12 18
13 ModbusAdapter::~ModbusAdapter() 19 ModbusAdapter::~ModbusAdapter()
@@ -15,23 +21,25 @@ ModbusAdapter::~ModbusAdapter() @@ -15,23 +21,25 @@ ModbusAdapter::~ModbusAdapter()
15 21
16 } 22 }
17 23
18 -bool ModbusAdapter::ModbusConnect( const ConnectionConfig &conncfg ) 24 +bool ModbusAdapter::ModbusConnect( const ConnectionConfig &config )
19 { 25 {
20 if( m_connected ) 26 if( m_connected )
21 { 27 {
22 this->ModbusDisconnect(); // Will already set m_connected 28 this->ModbusDisconnect(); // Will already set m_connected
23 } 29 }
24 30
25 - m_connType = conncfg.getType(); 31 + m_connType = config.getType();
26 32
27 switch( m_connType ) 33 switch( m_connType )
28 { 34 {
29 case ConnectionType::CT_SERIAL: 35 case ConnectionType::CT_SERIAL:
30 - m_connected = this->ModbusConnectRTU( conncfg.getPort(), conncfg.getBaudRate(), conncfg.getParity(), conncfg.getDataBits(), conncfg.getStopBits(), conncfg.getTimeOut(), MODBUS_RTU_RTS_NONE ); 36 + m_connected = this->ModbusConnectRTU( config.getPort(), config.getBaudRate(),
  37 + config.getParity(), config.getDataBits(),
  38 + config.getStopBits(), config.getTimeOut());
31 break; 39 break;
32 40
33 case ConnectionType::CT_TCP: 41 case ConnectionType::CT_TCP:
34 - m_connected = this->ModbusConnectTCP( conncfg.getIpAddress(), conncfg.getTcpPort(), 10 ); 42 + m_connected = this->ModbusConnectTCP( config.getIpAddress(), config.getTcpPort(), 10 );
35 break; 43 break;
36 44
37 default: 45 default:
@@ -138,7 +146,6 @@ modbusData ModbusAdapter::ModbusReadHoldReg( int slaveId, int startAddress, int @@ -138,7 +146,6 @@ modbusData ModbusAdapter::ModbusReadHoldReg( int slaveId, int startAddress, int
138 } 146 }
139 147
140 modbus_flush( m_modbus ); 148 modbus_flush( m_modbus );
141 - this->ClearBuffers();  
142 149
143 // -- End Critical Section --- ?? // 150 // -- End Critical Section --- ?? //
144 151
@@ -193,8 +200,6 @@ void ModbusAdapter::ModBusWriteData( int slaveId, int functionCode, int startAdd @@ -193,8 +200,6 @@ void ModbusAdapter::ModBusWriteData( int slaveId, int functionCode, int startAdd
193 break; 200 break;
194 } 201 }
195 202
196 - delete[] data8;  
197 - delete[] data16;  
198 modbus_flush(m_modbus); // Flush data. 203 modbus_flush(m_modbus); // Flush data.
199 204
200 if( resultValue != noOfItems ) 205 if( resultValue != noOfItems )
@@ -233,9 +238,18 @@ std::string ModbusAdapter::ErrorString( int errnum ) const @@ -233,9 +238,18 @@ std::string ModbusAdapter::ErrorString( int errnum ) const
233 } 238 }
234 239
235 /* ============= PRIVATE METHODS ============= */ 240 /* ============= PRIVATE METHODS ============= */
236 -bool ModbusAdapter::ModbusConnectRTU( const std::string &serialport, int baud, char parity, int dataBits, int stopBits, int RTS, int timeOut ) 241 +bool ModbusAdapter::ModbusConnectRTU( const std::string &serialport, int baud, char parity, int dataBits, int stopBits, int timeOut )
237 { 242 {
238 - m_modbus = modbus_new_rtu( serialport.c_str(), baud, parity, dataBits, stopBits, RTS ); 243 + { // Keep logging scope as short as possible
  244 + std::string logLine( "Connecting : " + serialport + " ( "
  245 + + std::to_string( baud ) + " : "
  246 + + std::to_string( dataBits ) + ","
  247 + + std::string( parity ) + " "
  248 + + std::to_string( stopBits ) + " ) with timeout : "
  249 + + std::to_string( timeout * 0.1 ) + " seconds." );
  250 + PRIVALOG_INFO(this->logZone, logLine );
  251 + }
  252 + m_modbus = modbus_new_rtu( serialport.c_str(), baud, parity, dataBits, stopBits );
239 253
240 #ifdef LIB_MODBUS_DEBUG_OUTPUT 254 #ifdef LIB_MODBUS_DEBUG_OUTPUT
241 // Do sensible logging through PRIVA_LOG 255 // Do sensible logging through PRIVA_LOG
@@ -260,7 +274,7 @@ bool ModbusAdapter::ModbusConnectRTU( const std::string &amp;serialport, int baud, c @@ -260,7 +274,7 @@ bool ModbusAdapter::ModbusConnectRTU( const std::string &amp;serialport, int baud, c
260 m_connected = true; 274 m_connected = true;
261 275
262 // Set recovery mode 276 // Set recovery mode
263 - modbus_set_error_recovery( m_modbus, MODBUS_ERROR_RECOVERY_PROTOCOL ); 277 + modbus_set_error_recovery( m_modbus, MODBUS_ERROR_RECOVERY_PROTOCOL | MODBUS_ERROR_RECOVERY_LINK );
264 278
265 // Set the response timeout 279 // Set the response timeout
266 modbus_set_response_timeout( m_modbus, timeOut, 0 ); 280 modbus_set_response_timeout( m_modbus, timeOut, 0 );
@@ -301,25 +315,10 @@ bool ModbusAdapter::ModbusConnectTCP( const std::string &amp;ip, int port, int timeO @@ -301,25 +315,10 @@ bool ModbusAdapter::ModbusConnectTCP( const std::string &amp;ip, int port, int timeO
301 m_connected = true; 315 m_connected = true;
302 316
303 // Set recovery mode 317 // Set recovery mode
304 - modbus_set_error_recovery( m_modbus, MODBUS_ERROR_RECOVERY_PROTOCOL ); 318 + modbus_set_error_recovery( m_modbus, MODBUS_ERROR_RECOVERY_PROTOCOL | MODBUS_ERROR_RECOVERY_LINK );
305 319
306 // Set the response timeout 320 // Set the response timeout
307 modbus_set_response_timeout( m_modbus, timeOut, 0 ); 321 modbus_set_response_timeout( m_modbus, timeOut, 0 );
308 322
309 return m_connected; 323 return m_connected;
310 } 324 }
311 -  
312 -void ModbusAdapter::InitBuffers()  
313 -{  
314 - // Setup memory for Data.  
315 - m_dest = (uint8_t *)malloc(2000 + sizeof(uint8_t));  
316 - m_dest16 = (uint16_t *)malloc(125 * sizeof(uint16_t));  
317 -  
318 - this->ClearBuffers();  
319 -}  
320 -  
321 -void ModbusAdapter::ClearBuffers()  
322 -{  
323 - memset(m_dest, 0, 2000 * sizeof(uint8_t));  
324 - memset(m_dest16, 0, 125 * sizeof(uint16_t));  
325 -}  
src/ModbusAdapter.h
@@ -6,13 +6,14 @@ @@ -6,13 +6,14 @@
6 6
7 #include "ConnectionConfig.h" 7 #include "ConnectionConfig.h"
8 #include "IModbusAdapter.h" 8 #include "IModbusAdapter.h"
9 -#include "modbus.h"  
10 9
11 // std 10 // std
12 #include <memory> 11 #include <memory>
13 #include <variant> 12 #include <variant>
14 #include <vector> 13 #include <vector>
15 14
  15 +typedef modbus_t;
  16 +
16 /// @brief The ModbusAdapter class represents a single modbus context. Each context will 17 /// @brief The ModbusAdapter class represents a single modbus context. Each context will
17 /// result in an instance of this class. It is not intended to be 18 /// result in an instance of this class. It is not intended to be
18 /// created directly but through a factory. The factory will create 19 /// created directly but through a factory. The factory will create
@@ -33,7 +34,7 @@ public: @@ -33,7 +34,7 @@ public:
33 /*! 34 /*!
34 * \brief /// Create a modbus connection, accepting a configuration object. 35 * \brief /// Create a modbus connection, accepting a configuration object.
35 */ 36 */
36 - bool ModbusConnect( const ConnectionConfig &conncfg ) override; 37 + bool ModbusConnect( const ConnectionConfig &config ) override;
37 38
38 /*! 39 /*!
39 * \brief ModbusDisconnect 40 * \brief ModbusDisconnect
@@ -86,21 +87,34 @@ public: @@ -86,21 +87,34 @@ public:
86 * \param errnum - error Number coming from the stack. 87 * \param errnum - error Number coming from the stack.
87 * \return The translated error as a string. Empty if not resolvable. 88 * \return The translated error as a string. Empty if not resolvable.
88 */ 89 */
89 - std::string ErrorString( int errnum ) const override; 90 + std::string ErrorString( int errorNumber ) const override;
90 91
91 private: // Methods 92 private: // Methods
92 - bool ModbusConnectRTU( const std::string &serialport, int baud, char parity, int dataBits, int stopBits, int RTS, int timeOut );  
93 - bool ModbusConnectTCP( const std::string &ip, int port, int timeOut = -1 ); 93 + /*!
  94 + * Create and connect to a serial port.
  95 + *
  96 + * @param serialport - The serial port by name ( i.e. /dev/ttyUSB0 )
  97 + * @param baud - The port speed in a serial port context ( default = 115200 )
  98 + * @param parity - The parity. ( Default : None, no parity )
  99 + * @param dataBits - The number of databits. RTU uses 8 (0 - 255), ASCII uses 7 (0 - 127). Default is RTU
  100 + * @param stopBits - The number of stopbits used to detect the end of the frame. ( Default = 1 )
  101 + * @param timeOut - Timeout in .1 secs. See the termios documentation for deviations on this.
  102 + */
  103 + bool ModbusConnectRTU( const std::string &serialport, int baud, char parity, int dataBits, int stopBits, int timeOut );
94 104
95 - void InitBuffers();  
96 - void ClearBuffers(); 105 + /*!
  106 + * ConnectionConfig Constructor. Used to create a new TCP connection.
  107 + *
  108 + * @param ip - The ip address of the ModBus device we want to connect to.
  109 + * @param portnum - The portnumber the ModBus device is using
  110 + * @param timeOut - Timeout in which a modbus device should respond.
  111 + */
  112 + bool ModbusConnectTCP( const std::string &ip, int port, int timeOut = -1 );
97 113
98 private: // Members 114 private: // Members
99 - ConnectionType m_connType { ConnectionType::CT_UNKNOWN }; ///> The type of connection this instance provides. Needed for administration  
100 - bool m_connected { false }; ///> Shows if the connection is still active.  
101 - modbus_t *m_modbus; ///> The actual low-level modbus instance as a raw-pointer. ( unique_pointer gives an error on this struct ) 115 + ConnectionType connectionType { ConnectionType::CT_UNKNOWN }; ///> The type of connection this instance provides. Needed for administration
  116 + bool connected { false }; ///> Shows if the connection is still active.
  117 + modbus_t *modbus; ///> The actual low-level modbus instance as a raw-pointer.
  118 + /// ( unique_pointer gives an error on this struct )
102 119
103 - // Return value Buffers ( Room for improvement )  
104 - uint8_t *m_dest;  
105 - uint16_t *m_dest16;  
106 }; 120 };
src/ModbusConnections.cpp deleted
1 -#include "ModbusConnections.h"  
2 -  
3 -ModbusConnections::ModbusConnections()  
4 -{  
5 -  
6 -}  
7 -  
8 -ModbusConnections::~ModbusConnections()  
9 -{  
10 - if( m_mapSerial.size() > 0 )  
11 - {  
12 - // Iterate, remove and destroy ( Searching, Seek & Destroy )  
13 - }  
14 -  
15 - if( m_mapTcp.size() > 0 )  
16 - {  
17 - // Iterate, remove and destroy ( Searching, Seek & Destroy )  
18 - }  
19 -}  
20 -  
21 -bool ModbusConnections::CreateConnection( const ConnectionConfig &config )  
22 -{  
23 - std::shared_ptr<IModbusAdapter> ptrNewAdapter = std::make_shared<ModbusAdapter>();  
24 - if( ptrNewAdapter == nullptr )  
25 - {  
26 - // Log a message and bail out  
27 - return false;  
28 - }  
29 -  
30 - // It looks like the pointer is valid. Time to connect.  
31 - ptrNewAdapter->ModbusConnect( config );  
32 - if( !ptrNewAdapter->isConnected() )  
33 - {  
34 - // Unsuccessful. Delete the object and return false  
35 - ptrNewAdapter.reset();  
36 - return false;  
37 - }  
38 -  
39 - std::shared_ptr<IModbusAdapter> ptr = connectionExist( config.getPortEnum(), createEndPoint( config ) );  
40 - if( ptr != nullptr )  
41 - {  
42 - if( !DeleteConnection( config.getPortEnum(), createEndPoint( config ) ) )  
43 - {  
44 - // Something went wrong here.. Our administration is "wonky" so report false and bail.  
45 - // New connection is not created.  
46 - ptrNewAdapter.reset();  
47 - return false;  
48 - }  
49 - }  
50 -  
51 - if( config.getType() == ConnectionType::CT_TCP )  
52 - {  
53 - // === Critical Section ===  
54 - std::lock_guard<std::mutex> guard( m_mapTcpMutex );  
55 - m_mapTcp.insert( { createEndPoint( config ), ptrNewAdapter } );  
56 - // === End Critical Section ===  
57 - }  
58 - else if( config.getType() == ConnectionType::CT_SERIAL )  
59 - {  
60 - // === Critical Section ===  
61 - std::lock_guard<std::mutex> guard( m_mapSerialMutex );  
62 - m_mapSerial.insert( { config.getPortEnum(), ptrNewAdapter } );  
63 - // === End Critical Section ===  
64 - }  
65 - else  
66 - {  
67 - // No idea what the type is but not something we recognize.  
68 - ptrNewAdapter.reset();  
69 - return false;  
70 - }  
71 - return true;  
72 -}  
73 -  
74 -bool ModbusConnections::DeleteConnection( const ConnectionPort portName, const std::string &endpoint )  
75 -{  
76 - std::shared_ptr<IModbusAdapter> ptr = this->connectionExist( portName, endpoint );  
77 - if( ptr == nullptr )  
78 - {  
79 - // Seems like it is already gone. Shouldn't happen, but ok.  
80 - return false;  
81 - }  
82 -  
83 - // First remove it from the map.  
84 - if( portName == ConnectionPort::CP_TCP )  
85 - {  
86 - // === Critical Section ===  
87 - std::lock_guard<std::mutex> guard( m_mapTcpMutex );  
88 - m_mapTcp.erase( endpoint );  
89 - // === End Critical Section ===  
90 - }  
91 - else  
92 - {  
93 - // === Critical Section ===  
94 - std::lock_guard<std::mutex> guard( m_mapSerialMutex );  
95 - m_mapSerial.erase( portName );  
96 - // === End Critical Section ===  
97 - }  
98 -  
99 - // Call the disconnect for a clean exit.  
100 - ptr->ModbusDisconnect();  
101 -  
102 - // Delete the pointer or decrease the ref-count  
103 - ptr.reset();  
104 -  
105 - return true;  
106 -}  
107 -  
108 -int ModbusConnections::ConnectionCount()  
109 -{  
110 - return ( m_mapSerial.size() + m_mapTcp.size() );  
111 -}  
112 -  
113 -std::shared_ptr<IModbusAdapter> ModbusConnections::getConnection( const ConnectionPort portName, const std::string &endpoint )  
114 -{  
115 - return this->connectionExist( portName, endpoint );  
116 -}  
117 -  
118 -std::shared_ptr<IModbusAdapter> ModbusConnections::getConnection( const ConnectionPort portName, const std::string &ipAddress, int tcpPortNumber )  
119 -{  
120 - return this->connectionExist( portName, this->createEndPoint( ipAddress, tcpPortNumber ) );  
121 -}  
122 -  
123 -AdapterList ModbusConnections::getConnections()  
124 -{  
125 - AdapterList lstResult;  
126 -  
127 - {  
128 - // === Critical Section ===  
129 - std::lock_guard<std::mutex> guard(m_mapSerialMutex);  
130 - // First we pick up the Serial Map  
131 - for( auto const& [key, value] : m_mapSerial )  
132 - {  
133 - lstResult.push_back( value );  
134 - }  
135 - // === End Critical Section ===  
136 - }  
137 -  
138 - {  
139 - // === Critical Section ===  
140 - std::lock_guard<std::mutex> guard(m_mapTcpMutex);  
141 - // Next we pick all the entries in the tcp-map  
142 - for( auto const& [key, value] : m_mapTcp )  
143 - {  
144 - lstResult.push_back( value );  
145 - }  
146 - // === End Critical Section ===  
147 - }  
148 -  
149 - return lstResult;  
150 -}  
151 -  
152 -std::shared_ptr<IModbusAdapter> ModbusConnections::connectionExist( const ConnectionPort portName, const std::string &endpoint )  
153 -{  
154 - if( portName == ConnectionPort::CP_TCP )  
155 - {  
156 - auto search = m_mapTcp.find( endpoint );  
157 - if( search != m_mapTcp.end() )  
158 - {  
159 - return search->second;  
160 - }  
161 - else  
162 - {  
163 - return nullptr;  
164 - }  
165 - }  
166 - else  
167 - {  
168 - auto search = m_mapSerial.find( portName );  
169 - if( search != m_mapSerial.end() )  
170 - {  
171 - return search->second;  
172 - }  
173 - else  
174 - {  
175 - return nullptr;  
176 - }  
177 - }  
178 -}  
179 -  
180 -std::string ModbusConnections::createEndPoint( const std::string &ipAddress, int portNumber )  
181 -{  
182 - if( portNumber > 0 && !ipAddress.empty() )  
183 - {  
184 - return std::string( "tcp://" + ipAddress + ":" + std::to_string( portNumber ) );  
185 - }  
186 -  
187 - return std::string();  
188 -}  
189 -  
190 -std::string ModbusConnections::createEndPoint( const ConnectionConfig &config )  
191 -{  
192 - if( config.getType() != ConnectionType::CT_TCP )  
193 - {  
194 - // Early opt-out  
195 - return std::string();  
196 - }  
197 -  
198 - return createEndPoint( config.getIpAddress(), config.getTcpPort() );  
199 -}  
src/ModbusConnections.h deleted
1 -/****************************************************************************  
2 - * Copyright (c) 2022 Priva B.V.  
3 - ****************************************************************************/  
4 -#pragma once  
5 -  
6 -// Flexblox  
7 -#include "IModbusAdapter.h"  
8 -#include "ModbusAdapter.h"  
9 -  
10 -// std  
11 -#include <memory>  
12 -#include <mutex>  
13 -#include <string>  
14 -#include <unordered_map>  
15 -  
16 -/// Easy replacement of template construction  
17 -using AdapterList = std::vector<std::shared_ptr<IModbusAdapter>>;  
18 -  
19 -/*!  
20 - * \brief The ModbusConnections class conatins a list of all modbus connections, Serial and TCP.  
21 - * To access a specific connection, use its portname and / or endpoint to return it's interface.  
22 - */  
23 -class ModbusConnections  
24 -{  
25 -public:  
26 - /*!  
27 - * \brief Default CTor  
28 - */  
29 - explicit ModbusConnections();  
30 -  
31 - /*!  
32 - * \brief Default DTor  
33 - */  
34 - virtual ~ModbusConnections();  
35 -  
36 - /*!  
37 - * \brief Create a modbus connection as described by the connection object.  
38 - * \param config - The connection object describing the connection in detail.  
39 - * \return The result of the creation.  
40 - * True = succesful.  
41 - * False = Failed.  
42 - */  
43 - bool CreateConnection( const ConnectionConfig &config );  
44 -  
45 - /*!  
46 - * \brief Remove the connection described by its portname and/or endpoint.  
47 - * \param portName - The portname as its enum  
48 - * \param endpoint - combination of ip-address and portname in endpoint-format  
49 - * ( tcp://<ip_address>:<portNumber> )  
50 - * ( i.e. tcp://127.0.0.1:501 )  
51 - * \return  
52 - */  
53 - bool DeleteConnection( const ConnectionPort portName, const std::string &endpoint = std::string() );  
54 -  
55 - /*!  
56 - * \brief Give the number of registered serial and tcp-connections combined.  
57 - */  
58 - int ConnectionCount();  
59 -  
60 - /*!  
61 - * \brief Get the connection give by its parameters.  
62 - * \param portName - The portname by its enum  
63 - * \param endpoint - combination of ip-address and portname in endpoint-format  
64 - * ( tcp://<ip_address>:<portNumber> )  
65 - * ( i.e. tcp://127.0.0.1:501 )  
66 - * \return Valid Pointer to the Modbus Connection Interface. nullptr if the connection wasn't found.  
67 - */  
68 - std::shared_ptr<IModbusAdapter> getConnection( const ConnectionPort portName, const std::string &endpoint = std::string() );  
69 -  
70 - // Convenient functions  
71 - /*!  
72 - * \brief Get the connection given by its parameters. If applicable, ipaddress and portnumber will be used to create the endpoint.  
73 - * \param portName - The portname by its enum  
74 - * \param ipAddress - The ipaddress of the TCP-connection  
75 - * \param tcpPortNumber - The portnumber of the TCP-connection  
76 - * \return Valid Pointer to the Modbus Connection Interface. nullptr if the connection wasn't found.  
77 - */  
78 - std::shared_ptr<IModbusAdapter> getConnection( const ConnectionPort portName, const std::string &ipAddress, int tcpPortNumber );  
79 -  
80 - /*!  
81 - * \brief Returns a list of all registered connections by their interfaces. This is a mix of Serial and TCP-connections.  
82 - */  
83 - AdapterList getConnections();  
84 -  
85 -private:  
86 - /*!  
87 - * \brief Check if a connection already exist.  
88 - * \param portName - The portName by its enum  
89 - * \param endpoint - The endpoint this connection was registered with.  
90 - * \return A valid pointer to the Interface if the connection exist. If the connection is unknown, it will return a nullptr.  
91 - * shared_ptr can manifest themselves as booleans, so "!ptr" is sufficient to check.  
92 - */  
93 - std::shared_ptr<IModbusAdapter> connectionExist( const ConnectionPort portName, const std::string &endpoint = std::string() );  
94 -  
95 - /*!  
96 - * \brief Create the TCP endpoint based on the connections IP-address and portnumber  
97 - * \param ipAddress - The ipAddress as string.  
98 - * \param portNumber - The portnumber as integer.  
99 - * \return The endpoint in format : tcp://<ip_address>:<portNumber> i.e. tcp://127.0.0.1:501  
100 - */  
101 - std::string createEndPoint( const std::string &ipAddress, int portNumber );  
102 -  
103 - /*!  
104 - * \brief Create the TCP endpoint based on the connections IP-address and portnumber extracted from the connection configuration.  
105 - * \param config - The configuration object used to create the connection.  
106 - * \return The endpoint in format : tcp://<ip_address>:<portNumber> i.e. tcp://127.0.0.1:501  
107 - */  
108 - std::string createEndPoint( const ConnectionConfig &config );  
109 -  
110 -private:  
111 - std::mutex m_mapSerialMutex; ///< Mutex protecting the serialmap  
112 - std::mutex m_mapTcpMutex; ///< Mutex protecting the TCPmap  
113 - std::unordered_map<ConnectionPort, std::shared_ptr<IModbusAdapter>> m_mapSerial; ///< Unordered map holding the Modbus connections By PortName  
114 - std::unordered_map<std::string, std::shared_ptr<IModbusAdapter>> m_mapTcp; ///< Unordered map holding the Modbus connections By tcp://endpoint:port  
115 -};  
src/main.cpp deleted
1 -#include <iostream>  
2 -  
3 -#include "ModbusAdapter.h"  
4 -  
5 -int main( int argc, char* argv[] )  
6 -{  
7 - ModbusAdapter oModbus;  
8 - ConnectionConfig oConfig( ConnectionPort::CP_EXTERNAL, 9600, Parity::PAR_NONE, 8, 1, 1 );  
9 -  
10 - std::cout << "========================= [START] Connection test ================================" << std::endl;  
11 - oModbus.ModbusConnect( oConfig );  
12 - if( oModbus.isConnected() )  
13 - {  
14 - std::cout << "Successful connected to : " << oConfig.getPort() << std::endl;  
15 - }  
16 - else  
17 - {  
18 - std::cout << "There was a problem connecting to : " << oConfig.getPort() << std::endl;  
19 - }  
20 -  
21 - oModbus.ModbusDisconnect();  
22 - if( !oModbus.isConnected() )  
23 - {  
24 - std::cout << "Successful disconnected from : " << oConfig.getPort() << std::endl;  
25 - }  
26 - else  
27 - {  
28 - std::cout << "There was a problem disconnecting from : " << oConfig.getPort() << std::endl;  
29 - }  
30 - std::cout << "========================= [END] Connection test ===============================" << std::endl;  
31 -  
32 - std::cout << "========================= [START] Reading test ================================" << std::endl;  
33 - std::cout << "== Reading the Hold Registers ==" << std::endl;  
34 - oModbus.ModbusConnect( oConfig );  
35 - if( oModbus.isConnected() )  
36 - {  
37 - std::cout << "Successful connected to : " << oConfig.getPort() << std::endl;  
38 - modbusData returnValues = oModbus.ModbusReadHoldReg( 1, MODBUS_FC_READ_HOLDING_REGISTERS, 2 );  
39 - if( returnValues.size() == 2 )  
40 - {  
41 - std::cout << "2 items returned from MODBUS_FC_READ_HOLDING_REGISTERS " << std::endl;  
42 - }  
43 - else  
44 - {  
45 - std::cout << "There was an error reading the Hold Registers " << std::endl;  
46 - std::cout << "Number of items returned : " << returnValues.size() << std::endl;  
47 - }  
48 -  
49 - std::cout << "== Reading the Temperature ==" << std::endl;  
50 - returnValues = oModbus.ModbusReadData( 0x01, MODBUS_FC_READ_INPUT_REGISTERS, 0x00, 0x02 );  
51 - if( returnValues.size() == 0 )  
52 - {  
53 - std::cout << "No values returned " << std::endl;  
54 - }  
55 - else  
56 - {  
57 - std::cout << "Number of items returned : " << returnValues.size() << std::endl;  
58 - }  
59 - }  
60 - else  
61 - {  
62 - std::cout << "There was a problem connecting to : " << oConfig.getPort() << std::endl;  
63 - return -1;  
64 - }  
65 - oModbus.ModbusDisconnect();  
66 - std::cout << "=========================== [END] Reading test ================================" << std::endl;  
67 -}  
stack/config.h deleted
1 -/* Define to 1 if you have the <arpa/inet.h> header file. */  
2 -#define HAVE_ARPA_INET_H 1  
3 -  
4 -/* Define to 1 if you have the declaration of `TIOCSRS485', and to 0 if you don't. */  
5 -#define HAVE_DECL_TIOCSRS485 0  
6 -  
7 -/* Define to 1 if you have the declaration of `TIOCM_RTS', and to 0 if you don't. */  
8 -#define HAVE_DECL_TIOCM_RTS 0  
9 -  
10 -/* Define to 1 if you have the declaration of `__CYGWIN__', and to 0 if you don't. */  
11 -#define HAVE_DECL___CYGWIN__ 0  
12 -  
13 -/* Define to 1 if you have the <dlfcn.h> header file. */  
14 -#define HAVE_DLFCN_H 1  
15 -  
16 -/* Define to 1 if you have the <errno.h> header file. */  
17 -#define HAVE_ERRNO_H 1  
18 -  
19 -/* Define to 1 if you have the <fcntl.h> header file. */  
20 -#define HAVE_FCNTL_H 1  
21 -  
22 -/* Define to 1 if you have the `fork' function. */  
23 -#define HAVE_FORK 1  
24 -  
25 -/* Define to 1 if you have the `getaddrinfo' function. */  
26 -#define HAVE_GETADDRINFO 1  
27 -  
28 -/* Define to 1 if you have the `gettimeofday' function. */  
29 -#define HAVE_GETTIMEOFDAY 1  
30 -  
31 -/* Define to 1 if you have the `inet_ntoa' function. */  
32 -#define HAVE_INET_NTOA 1  
33 -  
34 -/* Define to 1 if you have the <inttypes.h> header file. */  
35 -#define HAVE_INTTYPES_H 1  
36 -  
37 -/* Define to 1 if you have the <limits.h> header file. */  
38 -#define HAVE_LIMITS_H 1  
39 -  
40 -/* Define to 1 if you have the <linux/serial.h> header file. */  
41 -#define HAVE_LINUX_SERIAL_H 1  
42 -  
43 -/* Define to 1 if you have the <memory.h> header file. */  
44 -#define HAVE_MEMORY_H 1  
45 -  
46 -/* Define to 1 if you have the `memset' function. */  
47 -#define HAVE_MEMSET 1  
48 -  
49 -/* Define to 1 if you have the <netdb.h> header file. */  
50 -#define HAVE_NETDB_H 1  
51 -  
52 -/* Define to 1 if you have the <netinet/in.h> header file. */  
53 -#define HAVE_NETINET_IN_H 1  
54 -  
55 -/* Define to 1 if you have the <netinet/tcp.h> header file. */  
56 -#define HAVE_NETINET_TCP_H 1  
57 -  
58 -/* Define to 1 if you have the `select' function. */  
59 -#define HAVE_SELECT 1  
60 -  
61 -/* Define to 1 if you have the `socket' function. */  
62 -#define HAVE_SOCKET 1  
63 -  
64 -/* Define to 1 if you have the <stdint.h> header file. */  
65 -#define HAVE_STDINT_H 1  
66 -  
67 -/* Define to 1 if you have the <stdlib.h> header file. */  
68 -#define HAVE_STDLIB_H 1  
69 -  
70 -/* Define to 1 if you have the `strerror' function. */  
71 -#define HAVE_STRERROR 1  
72 -  
73 -/* Define to 1 if you have the <strings.h> header file. */  
74 -#define HAVE_STRINGS_H 1  
75 -  
76 -/* Define to 1 if you have the <string.h> header file. */  
77 -#define HAVE_STRING_H 1  
78 -  
79 -/* Define to 1 if you have the `strlcpy' function. */  
80 -/* #undef HAVE_STRLCPY */  
81 -  
82 -/* Define to 1 if you have the <sys/ioctl.h> header file. */  
83 -#define HAVE_SYS_IOCTL_H 1  
84 -  
85 -/* Define to 1 if you have the <sys/socket.h> header file. */  
86 -#define HAVE_SYS_SOCKET_H 1  
87 -  
88 -/* Define to 1 if you have the <sys/stat.h> header file. */  
89 -#define HAVE_SYS_STAT_H 1  
90 -  
91 -/* Define to 1 if you have the <sys/time.h> header file. */  
92 -#define HAVE_SYS_TIME_H 1  
93 -  
94 -/* Define to 1 if you have the <sys/types.h> header file. */  
95 -#define HAVE_SYS_TYPES_H 1  
96 -  
97 -/* Define to 1 if you have the <termios.h> header file. */  
98 -#define HAVE_TERMIOS_H 1  
99 -  
100 -/* Define to 1 if you have the <time.h> header file. */  
101 -#define HAVE_TIME_H 1  
102 -  
103 -/* Define to 1 if you have the <unistd.h> header file. */  
104 -#define HAVE_UNISTD_H 1  
105 -  
106 -/* Define to 1 if you have the `vfork' function. */  
107 -#define HAVE_VFORK 1  
108 -  
109 -/* Define to 1 if you have the <vfork.h> header file. */  
110 -/* #undef HAVE_VFORK_H */  
111 -  
112 -/* Define to 1 if you have the <winsock2.h> header file. */  
113 -/* #undef HAVE_WINSOCK2_H */  
114 -  
115 -/* Define to 1 if `fork' works. */  
116 -#define HAVE_WORKING_FORK 1  
117 -  
118 -/* Define to 1 if `vfork' works. */  
119 -#define HAVE_WORKING_VFORK 1  
120 -  
121 -/* Define to the sub-directory in which libtool stores uninstalled libraries.  
122 - */  
123 -#define LT_OBJDIR ".libs/"  
124 -  
125 -/* Name of package */  
126 -#define PACKAGE "libmodbus"  
127 -  
128 -/* Define to the address where bug reports for this package should be sent. */  
129 -#define PACKAGE_BUGREPORT "https://github.com/stephane/libmodbus/issues"  
130 -  
131 -/* Define to the full name of this package. */  
132 -#define PACKAGE_NAME "libmodbus"  
133 -  
134 -/* Define to the full name and version of this package. */  
135 -#define PACKAGE_STRING "libmodbus 3.1.0-1"  
136 -  
137 -/* Define to the one symbol short name of this package. */  
138 -#define PACKAGE_TARNAME "modbus"  
139 -  
140 -/* Define to the home page for this package. */  
141 -#define PACKAGE_URL ""  
142 -  
143 -/* Define to the version of this package. */  
144 -#define PACKAGE_VERSION "1.0.0"  
145 -  
146 -/* Define to 1 if you have the ANSI C header files. */  
147 -#define STDC_HEADERS 1  
148 -  
149 -/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */  
150 -#define TIME_WITH_SYS_TIME 1  
151 -  
152 -/* Version number of package */  
153 -#define VERSION "1.0.0"  
154 -  
155 -/* Define to empty if `const' does not conform to ANSI C. */  
156 -/* #undef const */  
157 -  
158 -/* Define to `int' if <sys/types.h> does not define. */  
159 -/* #undef pid_t */  
160 -  
161 -/* Define to `unsigned int' if <sys/types.h> does not define. */  
162 -/* #undef size_t */  
163 -  
164 -/* Define as `fork' if `vfork' does not work. */  
165 -/* #undef vfork */  
stack/modbus-data.c deleted
1 -  
2 -#include <stdlib.h>  
3 -  
4 -#include "stdint.h"  
5 -  
6 -#include <string.h>  
7 -#include <assert.h>  
8 -#include <arpa/inet.h>  
9 -#include <config.h>  
10 -  
11 -#include "modbus.h"  
12 -  
13 -#if defined(HAVE_BYTESWAP_H)  
14 -# include <byteswap.h>  
15 -#endif  
16 -  
17 -#if defined(__GNUC__)  
18 -# define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__ * 10)  
19 -# if GCC_VERSION >= 430  
20 -// Since GCC >= 4.30, GCC provides __builtin_bswapXX() alternatives so we switch to them  
21 -# undef bswap_32  
22 -# define bswap_32 __builtin_bswap32  
23 -# endif  
24 -#endif  
25 -  
26 -#if !defined(__CYGWIN__) && !defined(bswap_16)  
27 -#pragma message "Fallback on C functions for bswap_16"  
28 -static inline uint16_t bswap_16(uint16_t x)  
29 -{  
30 - return (x >> 8) | (x << 8);  
31 -}  
32 -#endif  
33 -  
34 -#if !defined(bswap_32)  
35 -#pragma message "Fallback on C functions for bswap_32"  
36 -static inline uint32_t bswap_32(uint32_t x)  
37 -{  
38 - return (bswap_16(x & 0xffff) << 16) | (bswap_16(x >> 16));  
39 -}  
40 -#endif  
41 -  
42 -/* Sets many bits from a single byte value (all 8 bits of the byte value are  
43 - set) */  
44 -void modbus_set_bits_from_byte( uint8_t *dest, int idx, const uint8_t value )  
45 -{  
46 - int i;  
47 -  
48 - for (i=0; i < 8; i++)  
49 - {  
50 - dest[idx+i] = (value & (1 << i)) ? 1 : 0;  
51 - }  
52 -}  
53 -  
54 -/* Sets many bits from a table of bytes (only the bits between idx and  
55 - idx + nb_bits are set) */  
56 -void modbus_set_bits_from_bytes( uint8_t *dest, int idx, unsigned int nb_bits, const uint8_t *tab_byte )  
57 -{  
58 - unsigned int i;  
59 - int shift = 0;  
60 -  
61 - for ( i = idx; i < idx + nb_bits; i++ )  
62 - {  
63 - dest[i] = tab_byte[(i - idx) / 8] & (1 << shift) ? 1 : 0;  
64 - /* gcc doesn't like: shift = (++shift) % 8; */  
65 - shift++;  
66 - shift %= 8;  
67 - }  
68 -}  
69 -  
70 -/* Gets the byte value from many bits.  
71 - To obtain a full byte, set nb_bits to 8. */  
72 -uint8_t modbus_get_byte_from_bits( const uint8_t *src, int idx, unsigned int nb_bits )  
73 -{  
74 - unsigned int i;  
75 - uint8_t value = 0;  
76 -  
77 - if (nb_bits > 8)  
78 - {  
79 - /* Assert is ignored if NDEBUG is set */  
80 - assert(nb_bits < 8);  
81 - nb_bits = 8;  
82 - }  
83 -  
84 - for (i=0; i < nb_bits; i++)  
85 - {  
86 - value |= (src[idx+i] << i);  
87 - }  
88 -  
89 - return value;  
90 -}  
91 -  
92 -/* Get a float from 4 bytes (Modbus) without any conversion (ABCD) */  
93 -float modbus_get_float_abcd(const uint16_t *src)  
94 -{  
95 - float f;  
96 - uint32_t i;  
97 -  
98 - i = ntohl(((uint32_t)src[0] << 16) + src[1]);  
99 - memcpy(&f, &i, sizeof(float));  
100 -  
101 - return f;  
102 -}  
103 -  
104 -/* Get a float from 4 bytes (Modbus) in inversed format (DCBA) */  
105 -float modbus_get_float_dcba(const uint16_t *src)  
106 -{  
107 - float f;  
108 - uint32_t i;  
109 -  
110 - i = ntohl(bswap_32((((uint32_t)src[0]) << 16) + src[1]));  
111 - memcpy(&f, &i, sizeof(float));  
112 -  
113 - return f;  
114 -}  
115 -  
116 -/* Get a float from 4 bytes (Modbus) with swapped bytes (BADC) */  
117 -float modbus_get_float_badc(const uint16_t *src)  
118 -{  
119 - float f;  
120 - uint32_t i;  
121 -  
122 - i = ntohl((uint32_t)(bswap_16(src[0]) << 16) + bswap_16(src[1]));  
123 - memcpy(&f, &i, sizeof(float));  
124 -  
125 - return f;  
126 -}  
127 -  
128 -/* Get a float from 4 bytes (Modbus) with swapped words (CDAB) */  
129 -float modbus_get_float_cdab(const uint16_t *src)  
130 -{  
131 - float f;  
132 - uint32_t i;  
133 -  
134 - i = ntohl((((uint32_t)src[1]) << 16) + src[0]);  
135 - memcpy(&f, &i, sizeof(float));  
136 -  
137 - return f;  
138 -}  
139 -  
140 -/* DEPRECATED - Get a float from 4 bytes in sort of Modbus format */  
141 -float modbus_get_float(const uint16_t *src)  
142 -{  
143 - float f;  
144 - uint32_t i;  
145 -  
146 - i = (((uint32_t)src[1]) << 16) + src[0];  
147 - memcpy(&f, &i, sizeof(float));  
148 -  
149 - return f;  
150 -}  
151 -  
152 -/* Set a float to 4 bytes for Modbus w/o any conversion (ABCD) */  
153 -void modbus_set_float_abcd(float f, uint16_t *dest)  
154 -{  
155 - uint32_t i;  
156 -  
157 - memcpy(&i, &f, sizeof(uint32_t));  
158 - i = htonl(i);  
159 - dest[0] = (uint16_t)(i >> 16);  
160 - dest[1] = (uint16_t)i;  
161 -}  
162 -  
163 -/* Set a float to 4 bytes for Modbus with byte and word swap conversion (DCBA) */  
164 -void modbus_set_float_dcba(float f, uint16_t *dest)  
165 -{  
166 - uint32_t i;  
167 -  
168 - memcpy(&i, &f, sizeof(uint32_t));  
169 - i = bswap_32(htonl(i));  
170 - dest[0] = (uint16_t)(i >> 16);  
171 - dest[1] = (uint16_t)i;  
172 -}  
173 -  
174 -/* Set a float to 4 bytes for Modbus with byte swap conversion (BADC) */  
175 -void modbus_set_float_badc(float f, uint16_t *dest)  
176 -{  
177 - uint32_t i;  
178 -  
179 - memcpy(&i, &f, sizeof(uint32_t));  
180 - i = htonl(i);  
181 - dest[0] = (uint16_t)bswap_16(i >> 16);  
182 - dest[1] = (uint16_t)bswap_16(i & 0xFFFF);  
183 -}  
184 -  
185 -/* Set a float to 4 bytes for Modbus with word swap conversion (CDAB) */  
186 -void modbus_set_float_cdab(float f, uint16_t *dest)  
187 -{  
188 - uint32_t i;  
189 -  
190 - memcpy(&i, &f, sizeof(uint32_t));  
191 - i = htonl(i);  
192 - dest[0] = (uint16_t)i;  
193 - dest[1] = (uint16_t)(i >> 16);  
194 -}  
195 -  
196 -/* DEPRECATED - Set a float to 4 bytes in a sort of Modbus format! */  
197 -void modbus_set_float(float f, uint16_t *dest)  
198 -{  
199 - uint32_t i;  
200 -  
201 - memcpy(&i, &f, sizeof(uint32_t));  
202 - dest[0] = (uint16_t)i;  
203 - dest[1] = (uint16_t)(i >> 16);  
204 -}  
stack/modbus-private.h deleted
1 -  
2 -#pragma once  
3 -  
4 -# include <stdint.h>  
5 -# include <sys/time.h>  
6 -#include <sys/types.h>  
7 -#include <config.h>  
8 -  
9 -#include "modbus.h"  
10 -  
11 -MODBUS_BEGIN_DECLS  
12 -  
13 -/* It's not really the minimal length (the real one is report slave ID  
14 - * in RTU (4 bytes)) but it's a convenient size to use in RTU or TCP  
15 - * communications to read many values or write a single one.  
16 - * Maximum between :  
17 - * - HEADER_LENGTH_TCP (7) + function (1) + address (2) + number (2)  
18 - * - HEADER_LENGTH_RTU (1) + function (1) + address (2) + number (2) + CRC (2)  
19 - */  
20 -#define _MIN_REQ_LENGTH 12  
21 -#define _REPORT_SLAVE_ID 180  
22 -#define _MODBUS_EXCEPTION_RSP_LENGTH 5  
23 -  
24 -/* Timeouts in microsecond (0.5 s) */  
25 -#define _RESPONSE_TIMEOUT 500000  
26 -#define _BYTE_TIMEOUT 500000  
27 -  
28 -typedef enum  
29 -{  
30 - _MODBUS_BACKEND_TYPE_RTU=0,  
31 - _MODBUS_BACKEND_TYPE_TCP  
32 -} modbus_backend_type_t;  
33 -  
34 -/*  
35 - * ---------- Request Indication ----------  
36 - * | Client | ---------------------->| Server |  
37 - * ---------- Confirmation Response ----------  
38 - */  
39 -typedef enum  
40 -{  
41 - /* Request message on the server side */  
42 - MSG_INDICATION,  
43 - /* Request message on the client side */  
44 - MSG_CONFIRMATION  
45 -} msg_type_t;  
46 -  
47 -/* This structure reduces the number of params in functions and so  
48 - * optimizes the speed of execution (~ 37%). */  
49 -typedef struct _sft  
50 -{  
51 - int slave;  
52 - int function;  
53 - int t_id;  
54 -} sft_t;  
55 -  
56 -typedef struct _modbus_backend  
57 -{  
58 - unsigned int backend_type;  
59 - unsigned int header_length;  
60 - unsigned int checksum_length;  
61 - unsigned int max_adu_length;  
62 - int (*set_slave) (modbus_t *ctx, int slave);  
63 - int (*build_request_basis) (modbus_t *ctx, int function, int addr, int nb, uint8_t *req);  
64 - int (*build_response_basis) (sft_t *sft, uint8_t *rsp);  
65 - int (*prepare_response_tid) (const uint8_t *req, int *req_length);  
66 - int (*send_msg_pre) (uint8_t *req, int req_length);  
67 - ssize_t (*send) (modbus_t *ctx, const uint8_t *req, int req_length);  
68 - int (*receive) (modbus_t *ctx, uint8_t *req);  
69 - ssize_t (*recv) (modbus_t *ctx, uint8_t *rsp, int rsp_length);  
70 - int (*check_integrity) (modbus_t *ctx, uint8_t *msg, const int msg_length);  
71 - int (*pre_check_confirmation) (modbus_t *ctx, const uint8_t *req, const uint8_t *rsp, int rsp_length);  
72 - int (*connect) (modbus_t *ctx);  
73 - void (*close) (modbus_t *ctx);  
74 - int (*flush) (modbus_t *ctx);  
75 - int (*select) (modbus_t *ctx, fd_set *rset, struct timeval *tv, int msg_length);  
76 - void (*free) (modbus_t *ctx);  
77 -} modbus_backend_t;  
78 -  
79 -struct _modbus  
80 -{  
81 - /* Slave address */  
82 - int slave;  
83 - /* Socket or file descriptor */  
84 - int s;  
85 - int debug;  
86 - int error_recovery;  
87 - struct timeval response_timeout;  
88 - struct timeval byte_timeout;  
89 - const modbus_backend_t *backend;  
90 - void *backend_data;  
91 -};  
92 -  
93 -void _modbus_init_common(modbus_t *ctx);  
94 -void _error_print(modbus_t *ctx, const char *context);  
95 -int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type);  
96 -  
97 -#ifndef HAVE_STRLCPY  
98 -size_t strlcpy(char *dest, const char *src, size_t dest_size);  
99 -#endif  
100 -  
101 -MODBUS_END_DECLS  
stack/modbus-rtu-private.h deleted
1 -  
2 -#pragma once  
3 -  
4 -#include <stdint.h>  
5 -#include <termios.h>  
6 -  
7 -#define _MODBUS_RTU_HEADER_LENGTH 1  
8 -#define _MODBUS_RTU_PRESET_REQ_LENGTH 6  
9 -#define _MODBUS_RTU_PRESET_RSP_LENGTH 2  
10 -  
11 -#define _MODBUS_RTU_CHECKSUM_LENGTH 2  
12 -  
13 -typedef struct _modbus_rtu  
14 -{  
15 - /* Device: "/dev/ttyS0", "/dev/ttyUSB0" or "/dev/tty.USA19*" on Mac OS X. */  
16 - char *device;  
17 - /* Bauds: 9600, 19200, 57600, 115200, etc */  
18 - int baud;  
19 - /* Data bit */  
20 - uint8_t data_bit;  
21 - /* Stop bit */  
22 - uint8_t stop_bit;  
23 - /* Parity: 'N', 'O', 'E' */  
24 - char parity;  
25 - /* Save old termios settings */  
26 - struct termios old_tios;  
27 -  
28 -#if HAVE_DECL_TIOCSRS485  
29 - int serial_mode;  
30 -#endif  
31 -  
32 - /* To handle many slaves on the same link */  
33 - int confirmation_to_ignore;  
34 -} modbus_rtu_t;  
stack/modbus-rtu.c deleted
1 -  
2 -#include <stdio.h>  
3 -#include <stdlib.h>  
4 -#include <errno.h>  
5 -#include <fcntl.h>  
6 -#include <string.h>  
7 -#include <unistd.h>  
8 -#include <assert.h>  
9 -  
10 -#include "modbus-private.h"  
11 -  
12 -#include "modbus-rtu.h"  
13 -#include "modbus-rtu-private.h"  
14 -  
15 -#if HAVE_DECL_TIOCSRS485 || HAVE_DECL_TIOCM_RTS  
16 -#include <sys/ioctl.h>  
17 -#endif  
18 -  
19 -#if HAVE_DECL_TIOCSRS485  
20 -#include <linux/serial.h>  
21 -#endif  
22 -  
23 -/* Table of CRC values for high-order byte */  
24 -static const uint8_t table_crc_hi[] = {  
25 - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,  
26 - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,  
27 - 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,  
28 - 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,  
29 - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,  
30 - 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,  
31 - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,  
32 - 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,  
33 - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,  
34 - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,  
35 - 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,  
36 - 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,  
37 - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,  
38 - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,  
39 - 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,  
40 - 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,  
41 - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,  
42 - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,  
43 - 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,  
44 - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,  
45 - 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,  
46 - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,  
47 - 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,  
48 - 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,  
49 - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,  
50 - 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40  
51 -};  
52 -  
53 -/* Table of CRC values for low-order byte */  
54 -static const uint8_t table_crc_lo[] = {  
55 - 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,  
56 - 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,  
57 - 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,  
58 - 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,  
59 - 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,  
60 - 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,  
61 - 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,  
62 - 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,  
63 - 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,  
64 - 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,  
65 - 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,  
66 - 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,  
67 - 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,  
68 - 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,  
69 - 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,  
70 - 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,  
71 - 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,  
72 - 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,  
73 - 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,  
74 - 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,  
75 - 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,  
76 - 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,  
77 - 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,  
78 - 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,  
79 - 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,  
80 - 0x43, 0x83, 0x41, 0x81, 0x80, 0x40  
81 -};  
82 -  
83 -/* Define the slave ID of the remote device to talk in master mode or set the  
84 - * internal slave ID in slave mode */  
85 -static int _modbus_set_slave( modbus_t *ctx, int slave )  
86 -{  
87 - /* Broadcast address is 0 (MODBUS_BROADCAST_ADDRESS) */  
88 - if (slave >= 0 && slave <= 247)  
89 - {  
90 - ctx->slave = slave;  
91 - }  
92 - else  
93 - {  
94 - errno = EINVAL;  
95 - return -1;  
96 - }  
97 -  
98 - return 0;  
99 -}  
100 -  
101 -/* Builds a RTU request header */  
102 -static int _modbus_rtu_build_request_basis( modbus_t *ctx, int function, int addr, int nb, uint8_t *req )  
103 -{  
104 - assert(ctx->slave != -1);  
105 - req[0] = ctx->slave;  
106 - req[1] = function;  
107 - req[2] = addr >> 8;  
108 - req[3] = addr & 0x00ff;  
109 - req[4] = nb >> 8;  
110 - req[5] = nb & 0x00ff;  
111 -  
112 - return _MODBUS_RTU_PRESET_REQ_LENGTH;  
113 -}  
114 -  
115 -/* Builds a RTU response header */  
116 -static int _modbus_rtu_build_response_basis( sft_t *sft, uint8_t *rsp )  
117 -{  
118 - /* In this case, the slave is certainly valid because a check is already  
119 - * done in _modbus_rtu_listen */  
120 - rsp[0] = sft->slave;  
121 - rsp[1] = sft->function;  
122 -  
123 - return _MODBUS_RTU_PRESET_RSP_LENGTH;  
124 -}  
125 -  
126 -static uint16_t crc16( uint8_t *buffer, uint16_t buffer_length )  
127 -{  
128 - uint8_t crc_hi = 0xFF; /* high CRC byte initialized */  
129 - uint8_t crc_lo = 0xFF; /* low CRC byte initialized */  
130 - unsigned int i; /* will index into CRC lookup */  
131 -  
132 - /* pass through message buffer */  
133 - while (buffer_length--) {  
134 - i = crc_hi ^ *buffer++; /* calculate the CRC */  
135 - crc_hi = crc_lo ^ table_crc_hi[i];  
136 - crc_lo = table_crc_lo[i];  
137 - }  
138 -  
139 - return (crc_hi << 8 | crc_lo);  
140 -}  
141 -  
142 -static int _modbus_rtu_prepare_response_tid( const uint8_t *req, int *req_length )  
143 -{  
144 - (*req_length) -= _MODBUS_RTU_CHECKSUM_LENGTH;  
145 - /* No TID */  
146 - return 0;  
147 -}  
148 -  
149 -static int _modbus_rtu_send_msg_pre( uint8_t *req, int req_length )  
150 -{  
151 - uint16_t crc = crc16( req, req_length );  
152 - req[req_length++] = crc >> 8;  
153 - req[req_length++] = crc & 0x00FF;  
154 -  
155 - return req_length;  
156 -}  
157 -  
158 -#if HAVE_DECL_TIOCM_RTS  
159 -static void _modbus_rtu_ioctl_rts( modbus_t *ctx, int on )  
160 -{  
161 - int fd = ctx->s;  
162 - int flags;  
163 -  
164 - ioctl(fd, TIOCMGET, &flags);  
165 - if (on)  
166 - {  
167 - flags |= TIOCM_RTS;  
168 - }  
169 - else  
170 - {  
171 - flags &= ~TIOCM_RTS;  
172 - }  
173 - ioctl(fd, TIOCMSET, &flags);  
174 -}  
175 -#endif  
176 -  
177 -static ssize_t _modbus_rtu_send( modbus_t *ctx, const uint8_t *req, int req_length )  
178 -{  
179 -#if HAVE_DECL_TIOCM_RTS  
180 - modbus_rtu_t *ctx_rtu = ctx->backend_data;  
181 - if (ctx_rtu->rts != MODBUS_RTU_RTS_NONE)  
182 - {  
183 - ssize_t size;  
184 -  
185 - if (ctx->debug) {  
186 - fprintf(stderr, "Sending request using RTS signal\n");  
187 - }  
188 -  
189 - ctx_rtu->set_rts(ctx, ctx_rtu->rts == MODBUS_RTU_RTS_UP);  
190 - usleep(ctx_rtu->rts_delay);  
191 -  
192 - size = write(ctx->s, req, req_length);  
193 -  
194 - usleep(ctx_rtu->onebyte_time * req_length + ctx_rtu->rts_delay);  
195 - ctx_rtu->set_rts(ctx, ctx_rtu->rts != MODBUS_RTU_RTS_UP);  
196 -  
197 - return size;  
198 - }  
199 - else  
200 - {  
201 -#endif  
202 - return write(ctx->s, req, req_length);  
203 -#if HAVE_DECL_TIOCM_RTS  
204 - }  
205 -#endif  
206 -}  
207 -  
208 -static int _modbus_rtu_receive( modbus_t *ctx, uint8_t *req )  
209 -{  
210 - int rc;  
211 - modbus_rtu_t *ctx_rtu = ctx->backend_data;  
212 -  
213 - if( ctx_rtu->confirmation_to_ignore )  
214 - {  
215 - _modbus_receive_msg(ctx, req, MSG_CONFIRMATION);  
216 - /* Ignore errors and reset the flag */  
217 - ctx_rtu->confirmation_to_ignore = FALSE;  
218 - rc = 0;  
219 - if( ctx->debug )  
220 - {  
221 - printf("Confirmation to ignore\n");  
222 - }  
223 - }  
224 - else  
225 - {  
226 - rc = _modbus_receive_msg( ctx, req, MSG_INDICATION );  
227 - if( rc == 0 )  
228 - {  
229 - /* The next expected message is a confirmation to ignore */  
230 - ctx_rtu->confirmation_to_ignore = TRUE;  
231 - }  
232 - }  
233 - return rc;  
234 -}  
235 -  
236 -static ssize_t _modbus_rtu_recv( modbus_t *ctx, uint8_t *rsp, int rsp_length )  
237 -{  
238 - return read(ctx->s, rsp, rsp_length);  
239 -}  
240 -  
241 -static int _modbus_rtu_flush(modbus_t *);  
242 -  
243 -static int _modbus_rtu_pre_check_confirmation(modbus_t *ctx, const uint8_t *req, const uint8_t *rsp, int rsp_length)  
244 -{  
245 - /* Check responding slave is the slave we requested (except for broacast request) */  
246 - if (req[0] != rsp[0] && req[0] != MODBUS_BROADCAST_ADDRESS)  
247 - {  
248 - if (ctx->debug)  
249 - {  
250 - fprintf(stderr, "The responding slave %d isn't the requested slave %d\n", rsp[0], req[0]);  
251 - }  
252 - errno = EMBBADSLAVE;  
253 - return -1;  
254 - }  
255 -  
256 - return 0;  
257 -}  
258 -  
259 -/* The check_crc16 function shall return 0 is the message is ignored and the  
260 - message length if the CRC is valid. Otherwise it shall return -1 and set  
261 - errno to EMBADCRC. */  
262 -static int _modbus_rtu_check_integrity(modbus_t *ctx, uint8_t *msg, const int msg_length)  
263 -{  
264 - uint16_t crc_calculated;  
265 - uint16_t crc_received;  
266 - int slave = msg[0];  
267 -  
268 - /* Filter on the Modbus unit identifier (slave) in RTU mode to avoid useless  
269 - * CRC computing. */  
270 - if (slave != ctx->slave && slave != MODBUS_BROADCAST_ADDRESS)  
271 - {  
272 - if (ctx->debug)  
273 - {  
274 - printf("Request for slave %d ignored (not %d)\n", slave, ctx->slave);  
275 - }  
276 - /* Following call to check_confirmation handles this error */  
277 - return 0;  
278 - }  
279 -  
280 - crc_calculated = crc16(msg, msg_length - 2);  
281 - crc_received = (msg[msg_length - 2] << 8) | msg[msg_length - 1];  
282 -  
283 - /* Check CRC of msg */  
284 - if (crc_calculated == crc_received)  
285 - {  
286 - return msg_length;  
287 - }  
288 - else  
289 - {  
290 - if (ctx->debug)  
291 - {  
292 - fprintf(stderr, "ERROR CRC received 0x%0X != CRC calculated 0x%0X\n",  
293 - crc_received, crc_calculated);  
294 - }  
295 -  
296 - if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_PROTOCOL)  
297 - {  
298 - _modbus_rtu_flush(ctx);  
299 - }  
300 - errno = EMBBADCRC;  
301 - return -1;  
302 - }  
303 -}  
304 -  
305 -/* Sets up a serial port for RTU communications */  
306 -static int _modbus_rtu_connect(modbus_t *ctx)  
307 -{  
308 - struct termios tios;  
309 - speed_t speed;  
310 - int flags;  
311 -  
312 - modbus_rtu_t *ctx_rtu = ctx->backend_data;  
313 -  
314 - if (ctx->debug)  
315 - {  
316 - printf("Opening %s at %d bauds (%c, %d, %d)\n",  
317 - ctx_rtu->device, ctx_rtu->baud, ctx_rtu->parity, ctx_rtu->data_bit, ctx_rtu->stop_bit);  
318 - }  
319 -  
320 - /* The O_NOCTTY flag tells UNIX that this program doesn't want  
321 - to be the "controlling terminal" for that port. If you  
322 - don't specify this then any input (such as keyboard abort  
323 - signals and so forth) will affect your process  
324 -  
325 - Timeouts are ignored in canonical input mode or when the  
326 - NDELAY option is set on the file via open or fcntl */  
327 - flags = O_RDWR | O_NOCTTY | O_NDELAY | O_EXCL;  
328 -#ifdef O_CLOEXEC  
329 - flags |= O_CLOEXEC;  
330 -#endif  
331 -  
332 - ctx->s = open(ctx_rtu->device, flags);  
333 - if (ctx->s == -1) {  
334 - if (ctx->debug) {  
335 - fprintf(stderr, "ERROR Can't open the device %s (%s)\n",  
336 - ctx_rtu->device, strerror(errno));  
337 - }  
338 - return -1;  
339 - }  
340 -  
341 - /* Save */  
342 - tcgetattr(ctx->s, &ctx_rtu->old_tios);  
343 -  
344 - memset(&tios, 0, sizeof(struct termios));  
345 -  
346 - /* C_ISPEED Input baud (new interface)  
347 - C_OSPEED Output baud (new interface)  
348 - */  
349 - switch (ctx_rtu->baud)  
350 - {  
351 - case 110:  
352 - speed = B110;  
353 - break;  
354 - case 300:  
355 - speed = B300;  
356 - break;  
357 - case 600:  
358 - speed = B600;  
359 - break;  
360 - case 1200:  
361 - speed = B1200;  
362 - break;  
363 - case 2400:  
364 - speed = B2400;  
365 - break;  
366 - case 4800:  
367 - speed = B4800;  
368 - break;  
369 - case 9600:  
370 - speed = B9600;  
371 - break;  
372 - case 19200:  
373 - speed = B19200;  
374 - break;  
375 - case 38400:  
376 - speed = B38400;  
377 - break;  
378 -#ifdef B57600  
379 - case 57600:  
380 - speed = B57600;  
381 - break;  
382 -#endif  
383 -#ifdef B115200  
384 - case 115200:  
385 - speed = B115200;  
386 - break;  
387 -#endif  
388 -#ifdef B230400  
389 - case 230400:  
390 - speed = B230400;  
391 - break;  
392 -#endif  
393 -#ifdef B460800  
394 - case 460800:  
395 - speed = B460800;  
396 - break;  
397 -#endif  
398 -#ifdef B500000  
399 - case 500000:  
400 - speed = B500000;  
401 - break;  
402 -#endif  
403 -#ifdef B576000  
404 - case 576000:  
405 - speed = B576000;  
406 - break;  
407 -#endif  
408 -#ifdef B921600  
409 - case 921600:  
410 - speed = B921600;  
411 - break;  
412 -#endif  
413 -#ifdef B1000000  
414 - case 1000000:  
415 - speed = B1000000;  
416 - break;  
417 -#endif  
418 -#ifdef B1152000  
419 - case 1152000:  
420 - speed = B1152000;  
421 - break;  
422 -#endif  
423 -#ifdef B1500000  
424 - case 1500000:  
425 - speed = B1500000;  
426 - break;  
427 -#endif  
428 -#ifdef B2500000  
429 - case 2500000:  
430 - speed = B2500000;  
431 - break;  
432 -#endif  
433 -#ifdef B3000000  
434 - case 3000000:  
435 - speed = B3000000;  
436 - break;  
437 -#endif  
438 -#ifdef B3500000  
439 - case 3500000:  
440 - speed = B3500000;  
441 - break;  
442 -#endif  
443 -#ifdef B4000000  
444 - case 4000000:  
445 - speed = B4000000;  
446 - break;  
447 -#endif  
448 - default:  
449 - speed = B9600;  
450 - if (ctx->debug) {  
451 - fprintf(stderr,  
452 - "WARNING Unknown baud rate %d for %s (B9600 used)\n",  
453 - ctx_rtu->baud, ctx_rtu->device);  
454 - }  
455 - }  
456 -  
457 - /* Set the baud rate */  
458 - if ((cfsetispeed(&tios, speed) < 0) ||  
459 - (cfsetospeed(&tios, speed) < 0)) {  
460 - close(ctx->s);  
461 - ctx->s = -1;  
462 - return -1;  
463 - }  
464 -  
465 - /* C_CFLAG Control options  
466 - CLOCAL Local line - do not change "owner" of port  
467 - CREAD Enable receiver  
468 - */  
469 - tios.c_cflag |= (CREAD | CLOCAL);  
470 - /* CSIZE, HUPCL, CRTSCTS (hardware flow control) */  
471 -  
472 - /* Set data bits (5, 6, 7, 8 bits)  
473 - CSIZE Bit mask for data bits  
474 - */  
475 - tios.c_cflag &= ~CSIZE;  
476 - switch (ctx_rtu->data_bit) {  
477 - case 5:  
478 - tios.c_cflag |= CS5;  
479 - break;  
480 - case 6:  
481 - tios.c_cflag |= CS6;  
482 - break;  
483 - case 7:  
484 - tios.c_cflag |= CS7;  
485 - break;  
486 - case 8:  
487 - default:  
488 - tios.c_cflag |= CS8;  
489 - break;  
490 - }  
491 -  
492 - /* Stop bit (1 or 2) */  
493 - if (ctx_rtu->stop_bit == 1)  
494 - tios.c_cflag &=~ CSTOPB;  
495 - else /* 2 */  
496 - tios.c_cflag |= CSTOPB;  
497 -  
498 - /* PARENB Enable parity bit  
499 - PARODD Use odd parity instead of even */  
500 - if (ctx_rtu->parity == 'N') {  
501 - /* None */  
502 - tios.c_cflag &=~ PARENB;  
503 - } else if (ctx_rtu->parity == 'E') {  
504 - /* Even */  
505 - tios.c_cflag |= PARENB;  
506 - tios.c_cflag &=~ PARODD;  
507 - } else {  
508 - /* Odd */  
509 - tios.c_cflag |= PARENB;  
510 - tios.c_cflag |= PARODD;  
511 - }  
512 -  
513 - /* Read the man page of termios if you need more information. */  
514 -  
515 - /* This field isn't used on POSIX systems  
516 - tios.c_line = 0;  
517 - */  
518 -  
519 - /* C_LFLAG Line options  
520 -  
521 - ISIG Enable SIGINTR, SIGSUSP, SIGDSUSP, and SIGQUIT signals  
522 - ICANON Enable canonical input (else raw)  
523 - XCASE Map uppercase \lowercase (obsolete)  
524 - ECHO Enable echoing of input characters  
525 - ECHOE Echo erase character as BS-SP-BS  
526 - ECHOK Echo NL after kill character  
527 - ECHONL Echo NL  
528 - NOFLSH Disable flushing of input buffers after  
529 - interrupt or quit characters  
530 - IEXTEN Enable extended functions  
531 - ECHOCTL Echo control characters as ^char and delete as ~?  
532 - ECHOPRT Echo erased character as character erased  
533 - ECHOKE BS-SP-BS entire line on line kill  
534 - FLUSHO Output being flushed  
535 - PENDIN Retype pending input at next read or input char  
536 - TOSTOP Send SIGTTOU for background output  
537 -  
538 - Canonical input is line-oriented. Input characters are put  
539 - into a buffer which can be edited interactively by the user  
540 - until a CR (carriage return) or LF (line feed) character is  
541 - received.  
542 -  
543 - Raw input is unprocessed. Input characters are passed  
544 - through exactly as they are received, when they are  
545 - received. Generally you'll deselect the ICANON, ECHO,  
546 - ECHOE, and ISIG options when using raw input  
547 - */  
548 -  
549 - /* Raw input */  
550 - tios.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);  
551 -  
552 - /* C_IFLAG Input options  
553 -  
554 - Constant Description  
555 - INPCK Enable parity check  
556 - IGNPAR Ignore parity errors  
557 - PARMRK Mark parity errors  
558 - ISTRIP Strip parity bits  
559 - IXON Enable software flow control (outgoing)  
560 - IXOFF Enable software flow control (incoming)  
561 - IXANY Allow any character to start flow again  
562 - IGNBRK Ignore break condition  
563 - BRKINT Send a SIGINT when a break condition is detected  
564 - INLCR Map NL to CR  
565 - IGNCR Ignore CR  
566 - ICRNL Map CR to NL  
567 - IUCLC Map uppercase to lowercase  
568 - IMAXBEL Echo BEL on input line too long  
569 - */  
570 - if (ctx_rtu->parity == 'N') {  
571 - /* None */  
572 - tios.c_iflag &= ~INPCK;  
573 - } else {  
574 - tios.c_iflag |= INPCK;  
575 - }  
576 -  
577 - /* Software flow control is disabled */  
578 - tios.c_iflag &= ~(IXON | IXOFF | IXANY);  
579 -  
580 - /* C_OFLAG Output options  
581 - OPOST Postprocess output (not set = raw output)  
582 - ONLCR Map NL to CR-NL  
583 -  
584 - ONCLR ant others needs OPOST to be enabled  
585 - */  
586 -  
587 - /* Raw ouput */  
588 - tios.c_oflag &=~ OPOST;  
589 -  
590 - /* C_CC Control characters  
591 - VMIN Minimum number of characters to read  
592 - VTIME Time to wait for data (tenths of seconds)  
593 -  
594 - UNIX serial interface drivers provide the ability to  
595 - specify character and packet timeouts. Two elements of the  
596 - c_cc array are used for timeouts: VMIN and VTIME. Timeouts  
597 - are ignored in canonical input mode or when the NDELAY  
598 - option is set on the file via open or fcntl.  
599 -  
600 - VMIN specifies the minimum number of characters to read. If  
601 - it is set to 0, then the VTIME value specifies the time to  
602 - wait for every character read. Note that this does not mean  
603 - that a read call for N bytes will wait for N characters to  
604 - come in. Rather, the timeout will apply to the first  
605 - character and the read call will return the number of  
606 - characters immediately available (up to the number you  
607 - request).  
608 -  
609 - If VMIN is non-zero, VTIME specifies the time to wait for  
610 - the first character read. If a character is read within the  
611 - time given, any read will block (wait) until all VMIN  
612 - characters are read. That is, once the first character is  
613 - read, the serial interface driver expects to receive an  
614 - entire packet of characters (VMIN bytes total). If no  
615 - character is read within the time allowed, then the call to  
616 - read returns 0. This method allows you to tell the serial  
617 - driver you need exactly N bytes and any read call will  
618 - return 0 or N bytes. However, the timeout only applies to  
619 - the first character read, so if for some reason the driver  
620 - misses one character inside the N byte packet then the read  
621 - call could block forever waiting for additional input  
622 - characters.  
623 -  
624 - VTIME specifies the amount of time to wait for incoming  
625 - characters in tenths of seconds. If VTIME is set to 0 (the  
626 - default), reads will block (wait) indefinitely unless the  
627 - NDELAY option is set on the port with open or fcntl.  
628 - */  
629 - /* Unused because we use open with the NDELAY option */  
630 - tios.c_cc[VMIN] = 0;  
631 - tios.c_cc[VTIME] = 10; // Set per default to 1 second  
632 -  
633 - if (tcsetattr(ctx->s, TCSANOW, &tios) < 0) {  
634 - close(ctx->s);  
635 - ctx->s = -1;  
636 - return -1;  
637 - }  
638 - return 0;  
639 -}  
640 -  
641 -int modbus_rtu_set_serial_mode(modbus_t *ctx, int mode)  
642 -{  
643 - if (ctx == NULL) {  
644 - errno = EINVAL;  
645 - return -1;  
646 - }  
647 -  
648 - if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) {  
649 -#if HAVE_DECL_TIOCSRS485  
650 - modbus_rtu_t *ctx_rtu = ctx->backend_data;  
651 - struct serial_rs485 rs485conf;  
652 - memset(&rs485conf, 0x0, sizeof(struct serial_rs485));  
653 -  
654 - if (mode == MODBUS_RTU_RS485) {  
655 - rs485conf.flags = SER_RS485_ENABLED;  
656 - if (ioctl(ctx->s, TIOCSRS485, &rs485conf) < 0) {  
657 - return -1;  
658 - }  
659 -  
660 - ctx_rtu->serial_mode = MODBUS_RTU_RS485;  
661 - return 0;  
662 - } else if (mode == MODBUS_RTU_RS232) {  
663 - /* Turn off RS485 mode only if required */  
664 - if (ctx_rtu->serial_mode == MODBUS_RTU_RS485) {  
665 - /* The ioctl call is avoided because it can fail on some RS232 ports */  
666 - if (ioctl(ctx->s, TIOCSRS485, &rs485conf) < 0) {  
667 - return -1;  
668 - }  
669 - }  
670 - ctx_rtu->serial_mode = MODBUS_RTU_RS232;  
671 - return 0;  
672 - }  
673 -#else  
674 - if (ctx->debug) {  
675 - fprintf(stderr, "This function isn't supported on your platform\n");  
676 - }  
677 - errno = ENOTSUP;  
678 - return -1;  
679 -#endif  
680 - }  
681 -  
682 - /* Wrong backend and invalid mode specified */  
683 - errno = EINVAL;  
684 - return -1;  
685 -}  
686 -  
687 -int modbus_rtu_get_serial_mode(modbus_t *ctx)  
688 -{  
689 - if (ctx == NULL) {  
690 - errno = EINVAL;  
691 - return -1;  
692 - }  
693 -  
694 - if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) {  
695 -#if HAVE_DECL_TIOCSRS485  
696 - modbus_rtu_t *ctx_rtu = ctx->backend_data;  
697 - return ctx_rtu->serial_mode;  
698 -#else  
699 - if (ctx->debug) {  
700 - fprintf(stderr, "This function isn't supported on your platform\n");  
701 - }  
702 - errno = ENOTSUP;  
703 - return -1;  
704 -#endif  
705 - } else {  
706 - errno = EINVAL;  
707 - return -1;  
708 - }  
709 -}  
710 -  
711 -int modbus_rtu_get_rts(modbus_t *ctx)  
712 -{  
713 - if (ctx == NULL) {  
714 - errno = EINVAL;  
715 - return -1;  
716 - }  
717 -  
718 - if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) {  
719 -#if HAVE_DECL_TIOCM_RTS  
720 - modbus_rtu_t *ctx_rtu = ctx->backend_data;  
721 - return ctx_rtu->rts;  
722 -#else  
723 - if (ctx->debug) {  
724 - fprintf(stderr, "This function isn't supported on your platform\n");  
725 - }  
726 - errno = ENOTSUP;  
727 - return -1;  
728 -#endif  
729 - } else {  
730 - errno = EINVAL;  
731 - return -1;  
732 - }  
733 -}  
734 -  
735 -int modbus_rtu_set_rts(modbus_t *ctx, int mode)  
736 -{  
737 - if (ctx == NULL) {  
738 - errno = EINVAL;  
739 - return -1;  
740 - }  
741 -  
742 - if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) {  
743 -#if HAVE_DECL_TIOCM_RTS  
744 - modbus_rtu_t *ctx_rtu = ctx->backend_data;  
745 -  
746 - if (mode == MODBUS_RTU_RTS_NONE || mode == MODBUS_RTU_RTS_UP ||  
747 - mode == MODBUS_RTU_RTS_DOWN) {  
748 - ctx_rtu->rts = mode;  
749 -  
750 - /* Set the RTS bit in order to not reserve the RS485 bus */  
751 - ctx_rtu->set_rts(ctx, ctx_rtu->rts != MODBUS_RTU_RTS_UP);  
752 -  
753 - return 0;  
754 - } else {  
755 - errno = EINVAL;  
756 - return -1;  
757 - }  
758 -#else  
759 - if (ctx->debug) {  
760 - fprintf(stderr, "This function isn't supported on your platform\n");  
761 - }  
762 - errno = ENOTSUP;  
763 - return -1;  
764 -#endif  
765 - }  
766 - /* Wrong backend or invalid mode specified */  
767 - errno = EINVAL;  
768 - return -1;  
769 -}  
770 -  
771 -int modbus_rtu_set_custom_rts(modbus_t *ctx, void (*set_rts) (modbus_t *ctx, int on))  
772 -{  
773 - if (ctx == NULL) {  
774 - errno = EINVAL;  
775 - return -1;  
776 - }  
777 -  
778 - if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) {  
779 -#if HAVE_DECL_TIOCM_RTS  
780 - modbus_rtu_t *ctx_rtu = ctx->backend_data;  
781 - ctx_rtu->set_rts = set_rts;  
782 - return 0;  
783 -#else  
784 - if (ctx->debug) {  
785 - fprintf(stderr, "This function isn't supported on your platform\n");  
786 - }  
787 - errno = ENOTSUP;  
788 - return -1;  
789 -#endif  
790 - } else {  
791 - errno = EINVAL;  
792 - return -1;  
793 - }  
794 -}  
795 -  
796 -int modbus_rtu_get_rts_delay(modbus_t *ctx)  
797 -{  
798 - if (ctx == NULL) {  
799 - errno = EINVAL;  
800 - return -1;  
801 - }  
802 -  
803 - if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) {  
804 -#if HAVE_DECL_TIOCM_RTS  
805 - modbus_rtu_t *ctx_rtu;  
806 - ctx_rtu = (modbus_rtu_t *)ctx->backend_data;  
807 - return ctx_rtu->rts_delay;  
808 -#else  
809 - if (ctx->debug) {  
810 - fprintf(stderr, "This function isn't supported on your platform\n");  
811 - }  
812 - errno = ENOTSUP;  
813 - return -1;  
814 -#endif  
815 - } else {  
816 - errno = EINVAL;  
817 - return -1;  
818 - }  
819 -}  
820 -  
821 -int modbus_rtu_set_rts_delay(modbus_t *ctx, int us)  
822 -{  
823 - if (ctx == NULL || us < 0) {  
824 - errno = EINVAL;  
825 - return -1;  
826 - }  
827 -  
828 - if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) {  
829 -#if HAVE_DECL_TIOCM_RTS  
830 - modbus_rtu_t *ctx_rtu;  
831 - ctx_rtu = (modbus_rtu_t *)ctx->backend_data;  
832 - ctx_rtu->rts_delay = us;  
833 - return 0;  
834 -#else  
835 - if (ctx->debug) {  
836 - fprintf(stderr, "This function isn't supported on your platform\n");  
837 - }  
838 - errno = ENOTSUP;  
839 - return -1;  
840 -#endif  
841 - } else {  
842 - errno = EINVAL;  
843 - return -1;  
844 - }  
845 -}  
846 -  
847 -static void _modbus_rtu_close(modbus_t *ctx)  
848 -{  
849 - /* Restore line settings and close file descriptor in RTU mode */  
850 - modbus_rtu_t *ctx_rtu = ctx->backend_data;  
851 -  
852 - if (ctx->s != -1) {  
853 - tcsetattr(ctx->s, TCSANOW, &ctx_rtu->old_tios);  
854 - close(ctx->s);  
855 - ctx->s = -1;  
856 - }  
857 -}  
858 -  
859 -static int _modbus_rtu_flush(modbus_t *ctx)  
860 -{  
861 - return tcflush(ctx->s, TCIOFLUSH);  
862 -}  
863 -  
864 -static int _modbus_rtu_select(modbus_t *ctx, fd_set *rset, struct timeval *tv, int length_to_read)  
865 -{  
866 - int s_rc;  
867 - while ((s_rc = select(ctx->s+1, rset, NULL, NULL, tv)) == -1)  
868 - {  
869 - if (errno == EINTR)  
870 - {  
871 - if (ctx->debug)  
872 - {  
873 - fprintf(stderr, "A non blocked signal was caught\n");  
874 - }  
875 - /* Necessary after an error */  
876 - FD_ZERO(rset);  
877 - FD_SET(ctx->s, rset);  
878 - }  
879 - else  
880 - {  
881 - return -1;  
882 - }  
883 - }  
884 -  
885 - if (s_rc == 0) {  
886 - /* Timeout */  
887 - errno = ETIMEDOUT;  
888 - return -1;  
889 - }  
890 -  
891 - return s_rc;  
892 -}  
893 -  
894 -static void _modbus_rtu_free(modbus_t *ctx) {  
895 - free(((modbus_rtu_t*)ctx->backend_data)->device);  
896 - free(ctx->backend_data);  
897 - free(ctx);  
898 -}  
899 -  
900 -const modbus_backend_t _modbus_rtu_backend = {  
901 - _MODBUS_BACKEND_TYPE_RTU,  
902 - _MODBUS_RTU_HEADER_LENGTH,  
903 - _MODBUS_RTU_CHECKSUM_LENGTH,  
904 - MODBUS_RTU_MAX_ADU_LENGTH,  
905 - _modbus_set_slave,  
906 - _modbus_rtu_build_request_basis,  
907 - _modbus_rtu_build_response_basis,  
908 - _modbus_rtu_prepare_response_tid,  
909 - _modbus_rtu_send_msg_pre,  
910 - _modbus_rtu_send,  
911 - _modbus_rtu_receive,  
912 - _modbus_rtu_recv,  
913 - _modbus_rtu_check_integrity,  
914 - _modbus_rtu_pre_check_confirmation,  
915 - _modbus_rtu_connect,  
916 - _modbus_rtu_close,  
917 - _modbus_rtu_flush,  
918 - _modbus_rtu_select,  
919 - _modbus_rtu_free  
920 -};  
921 -  
922 -modbus_t* modbus_new_rtu(const char *device,  
923 - int baud, char parity, int data_bit,  
924 - int stop_bit)  
925 -{  
926 - modbus_t *ctx;  
927 - modbus_rtu_t *ctx_rtu;  
928 -  
929 - /* Check device argument */  
930 - if (device == NULL || *device == 0) {  
931 - fprintf(stderr, "The device string is empty\n");  
932 - errno = EINVAL;  
933 - return NULL;  
934 - }  
935 -  
936 - /* Check baud argument */  
937 - if (baud == 0) {  
938 - fprintf(stderr, "The baud rate value must not be zero\n");  
939 - errno = EINVAL;  
940 - return NULL;  
941 - }  
942 -  
943 - ctx = (modbus_t *)malloc(sizeof(modbus_t));  
944 - _modbus_init_common(ctx);  
945 - ctx->backend = &_modbus_rtu_backend;  
946 - ctx->backend_data = (modbus_rtu_t *)malloc(sizeof(modbus_rtu_t));  
947 - ctx_rtu = (modbus_rtu_t *)ctx->backend_data;  
948 - ctx_rtu->device = NULL;  
949 -  
950 - /* Device name and \0 */  
951 - ctx_rtu->device = (char *)malloc((strlen(device) + 1) * sizeof(char));  
952 - strcpy(ctx_rtu->device, device);  
953 -  
954 - ctx_rtu->baud = baud;  
955 - if (parity == 'N' || parity == 'E' || parity == 'O') {  
956 - ctx_rtu->parity = parity;  
957 - } else {  
958 - modbus_free(ctx);  
959 - errno = EINVAL;  
960 - return NULL;  
961 - }  
962 - ctx_rtu->data_bit = data_bit;  
963 - ctx_rtu->stop_bit = stop_bit;  
964 -  
965 -#if HAVE_DECL_TIOCSRS485  
966 - /* The RS232 mode has been set by default */  
967 - ctx_rtu->serial_mode = MODBUS_RTU_RS232;  
968 -#endif  
969 -  
970 -#if HAVE_DECL_TIOCM_RTS  
971 - /* The RTS use has been set by default */  
972 - ctx_rtu->rts = MODBUS_RTU_RTS_NONE;  
973 -  
974 - /* Calculate estimated time in micro second to send one byte */  
975 - ctx_rtu->onebyte_time = 1000000 * (1 + data_bit + (parity == 'N' ? 0 : 1) + stop_bit) / baud;  
976 -  
977 - /* The internal function is used by default to set RTS */  
978 - ctx_rtu->set_rts = _modbus_rtu_ioctl_rts;  
979 -  
980 - /* The delay before and after transmission when toggling the RTS pin */  
981 - ctx_rtu->rts_delay = ctx_rtu->onebyte_time;  
982 -#endif  
983 -  
984 - ctx_rtu->confirmation_to_ignore = FALSE;  
985 -  
986 - return ctx;  
987 -}  
stack/modbus-rtu.h deleted
1 -  
2 -#pragma once  
3 -  
4 -#include "modbus.h"  
5 -  
6 -MODBUS_BEGIN_DECLS  
7 -  
8 -/* Modbus_Application_Protocol_V1_1b.pdf Chapter 4 Section 1 Page 5  
9 - * RS232 / RS485 ADU = 253 bytes + slave (1 byte) + CRC (2 bytes) = 256 bytes  
10 - */  
11 -#define MODBUS_RTU_MAX_ADU_LENGTH 256  
12 -  
13 -MODBUS_API modbus_t* modbus_new_rtu(const char *device, int baud, char parity, int data_bit, int stop_bit);  
14 -  
15 -#define MODBUS_RTU_RS232 0  
16 -#define MODBUS_RTU_RS485 1  
17 -  
18 -MODBUS_API int modbus_rtu_set_serial_mode( modbus_t *ctx, int mode );  
19 -MODBUS_API int modbus_rtu_get_serial_mode( modbus_t *ctx );  
20 -  
21 -#define MODBUS_RTU_RTS_NONE 0  
22 -#define MODBUS_RTU_RTS_UP 1  
23 -#define MODBUS_RTU_RTS_DOWN 2  
24 -  
25 -MODBUS_API int modbus_rtu_set_rts( modbus_t *ctx, int mode );  
26 -MODBUS_API int modbus_rtu_get_rts( modbus_t *ctx );  
27 -  
28 -MODBUS_API int modbus_rtu_set_custom_rts( modbus_t *ctx, void ( *set_rts ) ( modbus_t *ctx, int on ) );  
29 -  
30 -MODBUS_API int modbus_rtu_set_rts_delay( modbus_t *ctx, int us );  
31 -MODBUS_API int modbus_rtu_get_rts_delay( modbus_t *ctx );  
32 -  
33 -MODBUS_END_DECLS  
34 -  
stack/modbus-tcp-private.h deleted
1 -#pragma once  
2 -  
3 -#define _MODBUS_TCP_HEADER_LENGTH 7  
4 -#define _MODBUS_TCP_PRESET_REQ_LENGTH 12  
5 -#define _MODBUS_TCP_PRESET_RSP_LENGTH 8  
6 -  
7 -#define _MODBUS_TCP_CHECKSUM_LENGTH 0  
8 -  
9 -/* In both structures, the transaction ID must be placed on first position  
10 - to have a quick access not dependant of the TCP backend */  
11 -typedef struct _modbus_tcp  
12 -{  
13 - /* Extract from MODBUS Messaging on TCP/IP Implementation Guide V1.0b  
14 - (page 23/46):  
15 - The transaction identifier is used to associate the future response  
16 - with the request. This identifier is unique on each TCP connection. */  
17 - uint16_t t_id;  
18 - /* TCP port */  
19 - int port;  
20 - /* IP address */  
21 - char ip[16];  
22 -} modbus_tcp_t;  
23 -  
24 -#define _MODBUS_TCP_PI_NODE_LENGTH 1025  
25 -#define _MODBUS_TCP_PI_SERVICE_LENGTH 32  
26 -  
27 -typedef struct _modbus_tcp_pi  
28 -{  
29 - /* Transaction ID */  
30 - uint16_t t_id;  
31 - /* TCP port */  
32 - int port;  
33 - /* Node */  
34 - char node[_MODBUS_TCP_PI_NODE_LENGTH];  
35 - /* Service */  
36 - char service[_MODBUS_TCP_PI_SERVICE_LENGTH];  
37 -} modbus_tcp_pi_t;  
38 -  
39 -  
stack/modbus-tcp.c deleted
1 -  
2 -#include <stdio.h>  
3 -#include <stdlib.h>  
4 -#include <string.h>  
5 -#include <errno.h>  
6 -#include <unistd.h>  
7 -#include <signal.h>  
8 -#include <sys/types.h>  
9 -  
10 -# include <sys/socket.h>  
11 -# include <sys/ioctl.h>  
12 -  
13 -#if defined(__OpenBSD__) || (defined(__FreeBSD__) && __FreeBSD__ < 5)  
14 -# define OS_BSD  
15 -# include <netinet/in_systm.h>  
16 -#endif  
17 -  
18 -# include <netinet/in.h>  
19 -# include <netinet/ip.h>  
20 -# include <netinet/tcp.h>  
21 -# include <arpa/inet.h>  
22 -# include <netdb.h>  
23 -  
24 -#if !defined(MSG_NOSIGNAL)  
25 -#define MSG_NOSIGNAL 0  
26 -#endif  
27 -  
28 -#include "modbus-private.h"  
29 -  
30 -#include "modbus-tcp.h"  
31 -#include "modbus-tcp-private.h"  
32 -  
33 -static int _modbus_set_slave(modbus_t *ctx, int slave)  
34 -{  
35 - /* Broadcast address is 0 (MODBUS_BROADCAST_ADDRESS) */  
36 - if ( slave >= 0 && slave <= 247)  
37 - {  
38 - ctx->slave = slave;  
39 - }  
40 - else if ( slave == MODBUS_TCP_SLAVE )  
41 - {  
42 - /* The special value MODBUS_TCP_SLAVE (0xFF) can be used in TCP mode to  
43 - * restore the default value. */  
44 - ctx->slave = slave;  
45 - }  
46 - else  
47 - {  
48 - errno = EINVAL;  
49 - return -1;  
50 - }  
51 -  
52 - return 0;  
53 -}  
54 -  
55 -/* Builds a TCP request header */  
56 -static int _modbus_tcp_build_request_basis( modbus_t *ctx, int function, int addr, int nb, uint8_t *req )  
57 -{  
58 - modbus_tcp_t *ctx_tcp = ctx->backend_data;  
59 -  
60 - /* Increase transaction ID */  
61 - if (ctx_tcp->t_id < UINT16_MAX)  
62 - ctx_tcp->t_id++;  
63 - else  
64 - ctx_tcp->t_id = 0;  
65 -  
66 - req[0] = ctx_tcp->t_id >> 8;  
67 - req[1] = ctx_tcp->t_id & 0x00ff;  
68 -  
69 - /* Protocol Modbus */  
70 - req[2] = 0;  
71 - req[3] = 0;  
72 -  
73 - /* Length will be defined later by set_req_length_tcp at offsets 4  
74 - and 5 */  
75 -  
76 - req[6] = ctx->slave;  
77 - req[7] = function;  
78 - req[8] = addr >> 8;  
79 - req[9] = addr & 0x00ff;  
80 - req[10] = nb >> 8;  
81 - req[11] = nb & 0x00ff;  
82 -  
83 - return _MODBUS_TCP_PRESET_REQ_LENGTH;  
84 -}  
85 -  
86 -/* Builds a TCP response header */  
87 -static int _modbus_tcp_build_response_basis( sft_t *sft, uint8_t *rsp )  
88 -{  
89 - /* Extract from MODBUS Messaging on TCP/IP Implementation  
90 - Guide V1.0b (page 23/46):  
91 - The transaction identifier is used to associate the future  
92 - response with the request. */  
93 - rsp[0] = sft->t_id >> 8;  
94 - rsp[1] = sft->t_id & 0x00ff;  
95 -  
96 - /* Protocol Modbus */  
97 - rsp[2] = 0;  
98 - rsp[3] = 0;  
99 -  
100 - /* Length will be set later by send_msg (4 and 5) */  
101 -  
102 - /* The slave ID is copied from the indication */  
103 - rsp[6] = sft->slave;  
104 - rsp[7] = sft->function;  
105 -  
106 - return _MODBUS_TCP_PRESET_RSP_LENGTH;  
107 -}  
108 -  
109 -  
110 -static int _modbus_tcp_prepare_response_tid( const uint8_t *req, int *req_length )  
111 -{  
112 - return (req[0] << 8) + req[1];  
113 -}  
114 -  
115 -static int _modbus_tcp_send_msg_pre( uint8_t *req, int req_length )  
116 -{  
117 - /* Substract the header length to the message length */  
118 - int mbap_length = req_length - 6;  
119 -  
120 - req[4] = mbap_length >> 8;  
121 - req[5] = mbap_length & 0x00FF;  
122 -  
123 - return req_length;  
124 -}  
125 -  
126 -static ssize_t _modbus_tcp_send( modbus_t *ctx, const uint8_t *req, int req_length )  
127 -{  
128 - /* MSG_NOSIGNAL  
129 - Requests not to send SIGPIPE on errors on stream oriented  
130 - sockets when the other end breaks the connection. The EPIPE  
131 - error is still returned. */  
132 - return send(ctx->s, (const char *)req, req_length, MSG_NOSIGNAL);  
133 -}  
134 -  
135 -static int _modbus_tcp_receive(modbus_t *ctx, uint8_t *req)  
136 -{  
137 - return _modbus_receive_msg(ctx, req, MSG_INDICATION);  
138 -}  
139 -  
140 -static ssize_t _modbus_tcp_recv(modbus_t *ctx, uint8_t *rsp, int rsp_length)  
141 -{  
142 - return recv( ctx->s, (char *)rsp, rsp_length, 0 );  
143 -}  
144 -  
145 -static int _modbus_tcp_check_integrity( modbus_t *ctx, uint8_t *msg, const int msg_length )  
146 -{  
147 - return msg_length;  
148 -}  
149 -  
150 -static int _modbus_tcp_pre_check_confirmation( modbus_t *ctx, const uint8_t *req, const uint8_t *rsp, int rsp_length )  
151 -{  
152 - /* Check transaction ID */  
153 - if (req[0] != rsp[0] || req[1] != rsp[1]) {  
154 - if (ctx->debug)  
155 - {  
156 - fprintf(stderr, "Invalid transaction ID received 0x%X (not 0x%X)\n",  
157 - (rsp[0] << 8) + rsp[1], (req[0] << 8) + req[1]);  
158 - }  
159 - errno = EMBBADDATA;  
160 - return -1;  
161 - }  
162 -  
163 - /* Check protocol ID */  
164 - if (rsp[2] != 0x0 && rsp[3] != 0x0)  
165 - {  
166 - if (ctx->debug)  
167 - {  
168 - fprintf(stderr, "Invalid protocol ID received 0x%X (not 0x0)\n",  
169 - (rsp[2] << 8) + rsp[3]);  
170 - }  
171 - errno = EMBBADDATA;  
172 - return -1;  
173 - }  
174 -  
175 - return 0;  
176 -}  
177 -  
178 -static int _modbus_tcp_set_ipv4_options( int s )  
179 -{  
180 - int rc;  
181 - int option;  
182 -  
183 - /* Set the TCP no delay flag */  
184 - /* SOL_TCP = IPPROTO_TCP */  
185 - option = 1;  
186 - rc = setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (const void *)&option, sizeof(int) );  
187 - if (rc == -1)  
188 - {  
189 - return -1;  
190 - }  
191 -  
192 - /* If the OS does not offer SOCK_NONBLOCK, fall back to setting FIONBIO to  
193 - * make sockets non-blocking */  
194 - /* Do not care about the return value, this is optional */  
195 -#if !defined(SOCK_NONBLOCK) && defined(FIONBIO)  
196 - option = 1;  
197 - ioctl(s, FIONBIO, &option);  
198 -#endif  
199 -  
200 - /**  
201 - * Cygwin defines IPTOS_LOWDELAY but can't handle that flag so it's  
202 - * necessary to workaround that problem.  
203 - **/  
204 - /* Set the IP low delay option */  
205 - option = IPTOS_LOWDELAY;  
206 - rc = setsockopt(s, IPPROTO_IP, IP_TOS,  
207 - (const void *)&option, sizeof(int));  
208 - if (rc == -1) {  
209 - return -1;  
210 - }  
211 -  
212 - return 0;  
213 -}  
214 -  
215 -static int _connect( int sockfd, const struct sockaddr *addr, socklen_t addrlen, const struct timeval *ro_tv )  
216 -{  
217 - int rc = connect(sockfd, addr, addrlen);  
218 -  
219 - if (rc == -1 && errno == EINPROGRESS)  
220 - {  
221 - fd_set wset;  
222 - int optval;  
223 - socklen_t optlen = sizeof(optval);  
224 - struct timeval tv = *ro_tv;  
225 -  
226 - /* Wait to be available in writing */  
227 - FD_ZERO(&wset);  
228 - FD_SET(sockfd, &wset);  
229 - rc = select(sockfd + 1, NULL, &wset, NULL, &tv);  
230 - if (rc <= 0)  
231 - {  
232 - /* Timeout or fail */  
233 - return -1;  
234 - }  
235 -  
236 - /* The connection is established if SO_ERROR and optval are set to 0 */  
237 - rc = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&optval, &optlen);  
238 - if ( rc == 0 && optval == 0 )  
239 - {  
240 - return 0;  
241 - }  
242 - else  
243 - {  
244 - errno = ECONNREFUSED;  
245 - return -1;  
246 - }  
247 - }  
248 - return rc;  
249 -}  
250 -  
251 -/* Establishes a modbus TCP connection with a Modbus server. */  
252 -static int _modbus_tcp_connect( modbus_t *ctx )  
253 -{  
254 - int rc;  
255 - /* Specialized version of sockaddr for Internet socket address (same size) */  
256 - struct sockaddr_in addr;  
257 - modbus_tcp_t *ctx_tcp = ctx->backend_data;  
258 - int flags = SOCK_STREAM;  
259 -  
260 -#ifdef SOCK_CLOEXEC  
261 - flags |= SOCK_CLOEXEC;  
262 -#endif  
263 -  
264 -#ifdef SOCK_NONBLOCK  
265 - flags |= SOCK_NONBLOCK;  
266 -#endif  
267 -  
268 - ctx->s = socket(PF_INET, flags, 0);  
269 - if (ctx->s == -1)  
270 - {  
271 - return -1;  
272 - }  
273 -  
274 - rc = _modbus_tcp_set_ipv4_options(ctx->s);  
275 - if (rc == -1)  
276 - {  
277 - close(ctx->s);  
278 - ctx->s = -1;  
279 - return -1;  
280 - }  
281 -  
282 - if (ctx->debug)  
283 - {  
284 - printf("Connecting to %s:%d\n", ctx_tcp->ip, ctx_tcp->port);  
285 - }  
286 -  
287 - addr.sin_family = AF_INET;  
288 - addr.sin_port = htons(ctx_tcp->port);  
289 - addr.sin_addr.s_addr = inet_addr(ctx_tcp->ip);  
290 - rc = _connect(ctx->s, (struct sockaddr *)&addr, sizeof(addr), &ctx->response_timeout);  
291 - if( rc == -1 )  
292 - {  
293 - close( ctx->s );  
294 - ctx->s = -1;  
295 - return -1;  
296 - }  
297 -  
298 - return 0;  
299 -}  
300 -  
301 -/* Establishes a modbus TCP PI connection with a Modbus server. */  
302 -static int _modbus_tcp_pi_connect( modbus_t *ctx )  
303 -{  
304 - int rc;  
305 - struct addrinfo *ai_list;  
306 - struct addrinfo *ai_ptr;  
307 - struct addrinfo ai_hints;  
308 - modbus_tcp_pi_t *ctx_tcp_pi = ctx->backend_data;  
309 -  
310 - memset(&ai_hints, 0, sizeof(ai_hints));  
311 -#ifdef AI_ADDRCONFIG  
312 - ai_hints.ai_flags |= AI_ADDRCONFIG;  
313 -#endif  
314 - ai_hints.ai_family = AF_UNSPEC;  
315 - ai_hints.ai_socktype = SOCK_STREAM;  
316 - ai_hints.ai_addr = NULL;  
317 - ai_hints.ai_canonname = NULL;  
318 - ai_hints.ai_next = NULL;  
319 -  
320 - ai_list = NULL;  
321 - rc = getaddrinfo(ctx_tcp_pi->node, ctx_tcp_pi->service, &ai_hints, &ai_list);  
322 - if (rc != 0)  
323 - {  
324 - if (ctx->debug)  
325 - {  
326 - fprintf(stderr, "Error returned by getaddrinfo: %s\n", gai_strerror(rc));  
327 - }  
328 - errno = ECONNREFUSED;  
329 - return -1;  
330 - }  
331 -  
332 - for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)  
333 - {  
334 - int flags = ai_ptr->ai_socktype;  
335 - int s;  
336 -  
337 -#ifdef SOCK_CLOEXEC  
338 - flags |= SOCK_CLOEXEC;  
339 -#endif  
340 -  
341 -#ifdef SOCK_NONBLOCK  
342 - flags |= SOCK_NONBLOCK;  
343 -#endif  
344 -  
345 - s = socket(ai_ptr->ai_family, flags, ai_ptr->ai_protocol);  
346 - if (s < 0)  
347 - continue;  
348 -  
349 - if (ai_ptr->ai_family == AF_INET)  
350 - _modbus_tcp_set_ipv4_options(s);  
351 -  
352 - if (ctx->debug)  
353 - {  
354 - printf("Connecting to [%s]:%s\n", ctx_tcp_pi->node, ctx_tcp_pi->service);  
355 - }  
356 -  
357 - rc = _connect(s, ai_ptr->ai_addr, ai_ptr->ai_addrlen, &ctx->response_timeout);  
358 - if (rc == -1)  
359 - {  
360 - close(s);  
361 - continue;  
362 - }  
363 -  
364 - ctx->s = s;  
365 - break;  
366 - }  
367 -  
368 - freeaddrinfo(ai_list);  
369 -  
370 - if (ctx->s < 0)  
371 - {  
372 - return -1;  
373 - }  
374 -  
375 - return 0;  
376 -}  
377 -  
378 -/* Closes the network connection and socket in TCP mode */  
379 -static void _modbus_tcp_close( modbus_t *ctx )  
380 -{  
381 - if (ctx->s != -1)  
382 - {  
383 - shutdown(ctx->s, SHUT_RDWR);  
384 - close(ctx->s);  
385 - ctx->s = -1;  
386 - }  
387 -}  
388 -  
389 -static int _modbus_tcp_flush( modbus_t *ctx )  
390 -{  
391 - int rc;  
392 - int rc_sum = 0;  
393 -  
394 - do  
395 - {  
396 - /* Extract the garbage from the socket */  
397 - char devnull[MODBUS_TCP_MAX_ADU_LENGTH];  
398 -  
399 - rc = recv(ctx->s, devnull, MODBUS_TCP_MAX_ADU_LENGTH, MSG_DONTWAIT);  
400 - if ( rc > 0 )  
401 - {  
402 - rc_sum += rc;  
403 - }  
404 - } while ( rc == MODBUS_TCP_MAX_ADU_LENGTH );  
405 -  
406 - return rc_sum;  
407 -}  
408 -  
409 -/* Listens for any request from one or many modbus masters in TCP */  
410 -int modbus_tcp_listen( modbus_t *ctx, int nb_connection )  
411 -{  
412 - int new_s;  
413 - int enable;  
414 - struct sockaddr_in addr;  
415 - modbus_tcp_t *ctx_tcp;  
416 -  
417 - if (ctx == NULL)  
418 - {  
419 - errno = EINVAL;  
420 - return -1;  
421 - }  
422 -  
423 - ctx_tcp = ctx->backend_data;  
424 -  
425 - new_s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);  
426 - if ( new_s == -1 )  
427 - {  
428 - return -1;  
429 - }  
430 -  
431 - enable = 1;  
432 - if (setsockopt(new_s, SOL_SOCKET, SO_REUSEADDR, (char *)&enable, sizeof(enable)) == -1)  
433 - {  
434 - close(new_s);  
435 - return -1;  
436 - }  
437 -  
438 - memset(&addr, 0, sizeof(addr));  
439 - addr.sin_family = AF_INET;  
440 -  
441 - /* If the modbus port is < to 1024, we need the setuid root. */  
442 - addr.sin_port = htons(ctx_tcp->port);  
443 - if (ctx_tcp->ip[0] == '0')  
444 - {  
445 - /* Listen any addresses */  
446 - addr.sin_addr.s_addr = htonl(INADDR_ANY);  
447 - }  
448 - else  
449 - {  
450 - /* Listen only specified IP address */  
451 - addr.sin_addr.s_addr = inet_addr(ctx_tcp->ip);  
452 - }  
453 - if (bind( new_s, (struct sockaddr *)&addr, sizeof(addr)) == -1)  
454 - {  
455 - close(new_s);  
456 - return -1;  
457 - }  
458 -  
459 - if (listen(new_s, nb_connection) == -1)  
460 - {  
461 - close(new_s);  
462 - return -1;  
463 - }  
464 -  
465 - return new_s;  
466 -}  
467 -  
468 -int modbus_tcp_pi_listen( modbus_t *ctx, int nb_connection )  
469 -{  
470 - int rc;  
471 - struct addrinfo *ai_list;  
472 - struct addrinfo *ai_ptr;  
473 - struct addrinfo ai_hints;  
474 - const char *node;  
475 - const char *service;  
476 - int new_s;  
477 - modbus_tcp_pi_t *ctx_tcp_pi;  
478 -  
479 - if (ctx == NULL)  
480 - {  
481 - errno = EINVAL;  
482 - return -1;  
483 - }  
484 -  
485 - ctx_tcp_pi = ctx->backend_data;  
486 -  
487 - if ( ctx_tcp_pi->node[0] == 0)  
488 - {  
489 - node = NULL; /* == any */  
490 - }  
491 - else  
492 - {  
493 - node = ctx_tcp_pi->node;  
494 - }  
495 -  
496 - if ( ctx_tcp_pi->service[0] == 0 )  
497 - {  
498 - service = "502";  
499 - }  
500 - else  
501 - {  
502 - service = ctx_tcp_pi->service;  
503 - }  
504 -  
505 - memset( &ai_hints, 0, sizeof (ai_hints) );  
506 - /* If node is not NULL, than the AI_PASSIVE flag is ignored. */  
507 - ai_hints.ai_flags |= AI_PASSIVE;  
508 -#ifdef AI_ADDRCONFIG  
509 - ai_hints.ai_flags |= AI_ADDRCONFIG;  
510 -#endif  
511 - ai_hints.ai_family = AF_UNSPEC;  
512 - ai_hints.ai_socktype = SOCK_STREAM;  
513 - ai_hints.ai_addr = NULL;  
514 - ai_hints.ai_canonname = NULL;  
515 - ai_hints.ai_next = NULL;  
516 -  
517 - ai_list = NULL;  
518 - rc = getaddrinfo(node, service, &ai_hints, &ai_list);  
519 - if (rc != 0)  
520 - {  
521 - if (ctx->debug)  
522 - {  
523 - fprintf(stderr, "Error returned by getaddrinfo: %s\n", gai_strerror(rc));  
524 - }  
525 - errno = ECONNREFUSED;  
526 - return -1;  
527 - }  
528 -  
529 - new_s = -1;  
530 - for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)  
531 - {  
532 - int s;  
533 -  
534 - s = socket( ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol );  
535 - if (s < 0)  
536 - {  
537 - if (ctx->debug)  
538 - {  
539 - perror("socket");  
540 - }  
541 - continue;  
542 - }  
543 - else  
544 - {  
545 - int enable = 1;  
546 - rc = setsockopt( s, SOL_SOCKET, SO_REUSEADDR, (void *)&enable, sizeof (enable) );  
547 - if (rc != 0)  
548 - {  
549 - close(s);  
550 - if (ctx->debug)  
551 - {  
552 - perror("setsockopt");  
553 - }  
554 - continue;  
555 - }  
556 - }  
557 -  
558 - rc = bind(s, ai_ptr->ai_addr, ai_ptr->ai_addrlen);  
559 - if (rc != 0)  
560 - {  
561 - close(s);  
562 - if (ctx->debug)  
563 - {  
564 - perror("bind");  
565 - }  
566 - continue;  
567 - }  
568 -  
569 - rc = listen(s, nb_connection);  
570 - if (rc != 0)  
571 - {  
572 - close(s);  
573 - if (ctx->debug)  
574 - {  
575 - perror("listen");  
576 - }  
577 - continue;  
578 - }  
579 -  
580 - new_s = s;  
581 - break;  
582 - }  
583 - freeaddrinfo(ai_list);  
584 -  
585 - if (new_s < 0)  
586 - {  
587 - return -1;  
588 - }  
589 -  
590 - return new_s;  
591 -}  
592 -  
593 -int modbus_tcp_accept(modbus_t *ctx, int *s)  
594 -{  
595 - struct sockaddr_in addr;  
596 - socklen_t addrlen;  
597 -  
598 - if (ctx == NULL)  
599 - {  
600 - errno = EINVAL;  
601 - return -1;  
602 - }  
603 -  
604 - addrlen = sizeof(addr);  
605 -#ifdef HAVE_ACCEPT4  
606 - /* Inherit socket flags and use accept4 call */  
607 - ctx->s = accept4(*s, (struct sockaddr *)&addr, &addrlen, SOCK_CLOEXEC);  
608 -#else  
609 - ctx->s = accept(*s, (struct sockaddr *)&addr, &addrlen);  
610 -#endif  
611 -  
612 - if (ctx->s == -1)  
613 - {  
614 - close(*s);  
615 - *s = -1;  
616 - return -1;  
617 - }  
618 -  
619 - if (ctx->debug)  
620 - {  
621 - printf("The client connection from %s is accepted\n",  
622 - inet_ntoa(addr.sin_addr));  
623 - }  
624 -  
625 - return ctx->s;  
626 -}  
627 -  
628 -int modbus_tcp_pi_accept( modbus_t *ctx, int *s )  
629 -{  
630 - struct sockaddr_storage addr;  
631 - socklen_t addrlen;  
632 -  
633 - if (ctx == NULL)  
634 - {  
635 - errno = EINVAL;  
636 - return -1;  
637 - }  
638 -  
639 - addrlen = sizeof(addr);  
640 -#ifdef HAVE_ACCEPT4  
641 - /* Inherit socket flags and use accept4 call */  
642 - ctx->s = accept4(*s, (struct sockaddr *)&addr, &addrlen, SOCK_CLOEXEC);  
643 -#else  
644 - ctx->s = accept(*s, (struct sockaddr *)&addr, &addrlen);  
645 -#endif  
646 - if (ctx->s == -1)  
647 - {  
648 - close(*s);  
649 - *s = -1;  
650 - }  
651 -  
652 - if (ctx->debug)  
653 - {  
654 - printf("The client connection is accepted.\n");  
655 - }  
656 -  
657 - return ctx->s;  
658 -}  
659 -  
660 -static int _modbus_tcp_select(modbus_t *ctx, fd_set *rset, struct timeval *tv, int length_to_read)  
661 -{  
662 - int s_rc;  
663 - while ((s_rc = select(ctx->s+1, rset, NULL, NULL, tv)) == -1)  
664 - {  
665 - if (errno == EINTR)  
666 - {  
667 - if (ctx->debug)  
668 - {  
669 - fprintf(stderr, "A non blocked signal was caught\n");  
670 - }  
671 - /* Necessary after an error */  
672 - FD_ZERO(rset);  
673 - FD_SET(ctx->s, rset);  
674 - }  
675 - else  
676 - {  
677 - return -1;  
678 - }  
679 - }  
680 -  
681 - if ( s_rc == 0 )  
682 - {  
683 - errno = ETIMEDOUT;  
684 - return -1;  
685 - }  
686 -  
687 - return s_rc;  
688 -}  
689 -  
690 -static void _modbus_tcp_free( modbus_t *ctx )  
691 -{  
692 - free(ctx->backend_data);  
693 - free(ctx);  
694 -}  
695 -  
696 -const modbus_backend_t _modbus_tcp_backend =  
697 -{  
698 - _MODBUS_BACKEND_TYPE_TCP,  
699 - _MODBUS_TCP_HEADER_LENGTH,  
700 - _MODBUS_TCP_CHECKSUM_LENGTH,  
701 - MODBUS_TCP_MAX_ADU_LENGTH,  
702 - _modbus_set_slave,  
703 - _modbus_tcp_build_request_basis,  
704 - _modbus_tcp_build_response_basis,  
705 - _modbus_tcp_prepare_response_tid,  
706 - _modbus_tcp_send_msg_pre,  
707 - _modbus_tcp_send,  
708 - _modbus_tcp_receive,  
709 - _modbus_tcp_recv,  
710 - _modbus_tcp_check_integrity,  
711 - _modbus_tcp_pre_check_confirmation,  
712 - _modbus_tcp_connect,  
713 - _modbus_tcp_close,  
714 - _modbus_tcp_flush,  
715 - _modbus_tcp_select,  
716 - _modbus_tcp_free  
717 -};  
718 -  
719 -  
720 -const modbus_backend_t _modbus_tcp_pi_backend =  
721 -{  
722 - _MODBUS_BACKEND_TYPE_TCP,  
723 - _MODBUS_TCP_HEADER_LENGTH,  
724 - _MODBUS_TCP_CHECKSUM_LENGTH,  
725 - MODBUS_TCP_MAX_ADU_LENGTH,  
726 - _modbus_set_slave,  
727 - _modbus_tcp_build_request_basis,  
728 - _modbus_tcp_build_response_basis,  
729 - _modbus_tcp_prepare_response_tid,  
730 - _modbus_tcp_send_msg_pre,  
731 - _modbus_tcp_send,  
732 - _modbus_tcp_receive,  
733 - _modbus_tcp_recv,  
734 - _modbus_tcp_check_integrity,  
735 - _modbus_tcp_pre_check_confirmation,  
736 - _modbus_tcp_pi_connect,  
737 - _modbus_tcp_close,  
738 - _modbus_tcp_flush,  
739 - _modbus_tcp_select,  
740 - _modbus_tcp_free  
741 -};  
742 -  
743 -modbus_t* modbus_new_tcp( const char *ip, int port )  
744 -{  
745 - modbus_t *ctx;  
746 - modbus_tcp_t *ctx_tcp;  
747 - size_t dest_size;  
748 - size_t ret_size;  
749 -  
750 - ctx = (modbus_t *)malloc(sizeof(modbus_t) );  
751 - _modbus_init_common(ctx);  
752 -  
753 - /* Could be changed after to reach a remote serial Modbus device */  
754 - ctx->slave = MODBUS_TCP_SLAVE;  
755 -  
756 - ctx->backend = &_modbus_tcp_backend;  
757 -  
758 - ctx->backend_data = ( modbus_tcp_t *)malloc(sizeof(modbus_tcp_t) );  
759 - ctx_tcp = (modbus_tcp_t *)ctx->backend_data;  
760 -  
761 - if (ip != NULL)  
762 - {  
763 - dest_size = sizeof(char) * 16;  
764 - ret_size = strlcpy(ctx_tcp->ip, ip, dest_size);  
765 - if (ret_size == 0)  
766 - {  
767 - fprintf(stderr, "The IP string is empty\n");  
768 - modbus_free(ctx);  
769 - errno = EINVAL;  
770 - return NULL;  
771 - }  
772 -  
773 - if (ret_size >= dest_size)  
774 - {  
775 - fprintf(stderr, "The IP string has been truncated\n");  
776 - modbus_free(ctx);  
777 - errno = EINVAL;  
778 - return NULL;  
779 - }  
780 - }  
781 - else  
782 - {  
783 - ctx_tcp->ip[0] = '0';  
784 - }  
785 - ctx_tcp->port = port;  
786 - ctx_tcp->t_id = 0;  
787 -  
788 - return ctx;  
789 -}  
790 -  
791 -  
792 -modbus_t* modbus_new_tcp_pi( const char *node, const char *service )  
793 -{  
794 - modbus_t *ctx;  
795 - modbus_tcp_pi_t *ctx_tcp_pi;  
796 - size_t dest_size;  
797 - size_t ret_size;  
798 -  
799 - ctx = (modbus_t *)malloc(sizeof(modbus_t));  
800 - _modbus_init_common(ctx);  
801 -  
802 - /* Could be changed after to reach a remote serial Modbus device */  
803 - ctx->slave = MODBUS_TCP_SLAVE;  
804 -  
805 - ctx->backend = &_modbus_tcp_pi_backend;  
806 -  
807 - ctx->backend_data = (modbus_tcp_pi_t *)malloc(sizeof(modbus_tcp_pi_t));  
808 - ctx_tcp_pi = (modbus_tcp_pi_t *)ctx->backend_data;  
809 -  
810 - if (node == NULL)  
811 - {  
812 - /* The node argument can be empty to indicate any hosts */  
813 - ctx_tcp_pi->node[0] = 0;  
814 - }  
815 - else  
816 - {  
817 - dest_size = sizeof(char) * _MODBUS_TCP_PI_NODE_LENGTH;  
818 - ret_size = strlcpy(ctx_tcp_pi->node, node, dest_size);  
819 - if (ret_size == 0)  
820 - {  
821 - fprintf(stderr, "The node string is empty\n");  
822 - modbus_free(ctx);  
823 - errno = EINVAL;  
824 - return NULL;  
825 - }  
826 -  
827 - if (ret_size >= dest_size)  
828 - {  
829 - fprintf(stderr, "The node string has been truncated\n");  
830 - modbus_free(ctx);  
831 - errno = EINVAL;  
832 - return NULL;  
833 - }  
834 - }  
835 -  
836 - if (service != NULL)  
837 - {  
838 - dest_size = sizeof(char) * _MODBUS_TCP_PI_SERVICE_LENGTH;  
839 - ret_size = strlcpy(ctx_tcp_pi->service, service, dest_size);  
840 - }  
841 - else  
842 - {  
843 - /* Empty service is not allowed, error catched below. */  
844 - ret_size = 0;  
845 - }  
846 -  
847 - if (ret_size == 0)  
848 - {  
849 - fprintf(stderr, "The service string is empty\n");  
850 - modbus_free(ctx);  
851 - errno = EINVAL;  
852 - return NULL;  
853 - }  
854 -  
855 - if (ret_size >= dest_size)  
856 - {  
857 - fprintf(stderr, "The service string has been truncated\n");  
858 - modbus_free(ctx);  
859 - errno = EINVAL;  
860 - return NULL;  
861 - }  
862 -  
863 - ctx_tcp_pi->t_id = 0;  
864 -  
865 - return ctx;  
866 -}  
stack/modbus-tcp.h deleted
1 -#pragma once  
2 -  
3 -#include "modbus.h"  
4 -  
5 -MODBUS_BEGIN_DECLS  
6 -  
7 -#define MODBUS_TCP_DEFAULT_PORT 502  
8 -#define MODBUS_TCP_SLAVE 0xFF  
9 -  
10 -/* Modbus_Application_Protocol_V1_1b.pdf Chapter 4 Section 1 Page 5  
11 - * TCP MODBUS ADU = 253 bytes + MBAP (7 bytes) = 260 bytes  
12 - */  
13 -#define MODBUS_TCP_MAX_ADU_LENGTH 260  
14 -  
15 -MODBUS_API modbus_t* modbus_new_tcp(const char *ip_address, int port);  
16 -MODBUS_API int modbus_tcp_listen(modbus_t *ctx, int nb_connection);  
17 -MODBUS_API int modbus_tcp_accept(modbus_t *ctx, int *s);  
18 -  
19 -MODBUS_API modbus_t* modbus_new_tcp_pi(const char *node, const char *service);  
20 -MODBUS_API int modbus_tcp_pi_listen(modbus_t *ctx, int nb_connection);  
21 -MODBUS_API int modbus_tcp_pi_accept(modbus_t *ctx, int *s);  
22 -  
23 -MODBUS_END_DECLS  
24 -  
stack/modbus-version.h deleted
1 -#pragma once  
2 -  
3 -/* The major version, (1, if %LIBMODBUS_VERSION is 1.2.3) */  
4 -#define LIBMODBUS_VERSION_MAJOR (3)  
5 -  
6 -/* The minor version (2, if %LIBMODBUS_VERSION is 1.2.3) */  
7 -#define LIBMODBUS_VERSION_MINOR (1)  
8 -  
9 -/* The micro version (3, if %LIBMODBUS_VERSION is 1.2.3) */  
10 -#define LIBMODBUS_VERSION_MICRO (4)  
11 -  
12 -/* The full version, like 1.2.3 */  
13 -#define LIBMODBUS_VERSION 3.1.4  
14 -  
15 -/* The full version, in string form (suited for string concatenation)  
16 - */  
17 -#define LIBMODBUS_VERSION_STRING "3.1.4"  
18 -  
19 -/* Numerically encoded version, like 0x010203 */  
20 -#define LIBMODBUS_VERSION_HEX ((LIBMODBUS_VERSION_MAJOR << 24) | \  
21 - (LIBMODBUS_VERSION_MINOR << 16) | \  
22 - (LIBMODBUS_VERSION_MICRO << 8))  
23 -  
24 -/* Evaluates to True if the version is greater than @major, @minor and @micro  
25 - */  
26 -#define LIBMODBUS_VERSION_CHECK(major,minor,micro) \  
27 - (LIBMODBUS_VERSION_MAJOR > (major) || \  
28 - (LIBMODBUS_VERSION_MAJOR == (major) && \  
29 - LIBMODBUS_VERSION_MINOR > (minor)) || \  
30 - (LIBMODBUS_VERSION_MAJOR == (major) && \  
31 - LIBMODBUS_VERSION_MINOR == (minor) && \  
32 - LIBMODBUS_VERSION_MICRO >= (micro)))  
33 -  
34 -  
stack/modbus.c deleted
1 -#include <config.h>  
2 -#include <errno.h>  
3 -#include <limits.h>  
4 -#include <stdio.h>  
5 -#include <string.h>  
6 -#include <stdlib.h>  
7 -#include <stdarg.h>  
8 -#include <time.h>  
9 -#include <unistd.h>  
10 -  
11 -#include "modbus.h"  
12 -#include "modbus-private.h"  
13 -  
14 -/* Internal use */  
15 -#define MSG_LENGTH_UNDEFINED -1  
16 -  
17 -/* Max between RTU and TCP max adu length (so TCP) */  
18 -#define MAX_MESSAGE_LENGTH 260  
19 -  
20 -/* 3 steps are used to parse the query */  
21 -typedef enum  
22 -{  
23 - _STEP_FUNCTION,  
24 - _STEP_META,  
25 - _STEP_DATA  
26 -} _step_t;  
27 -  
28 -const char *modbus_strerror( int errnum )  
29 -{  
30 - switch (errnum)  
31 - {  
32 - case EMBXILFUN:  
33 - return "Illegal function";  
34 - case EMBXILADD:  
35 - return "Illegal data address";  
36 - case EMBXILVAL:  
37 - return "Illegal data value";  
38 - case EMBXSFAIL:  
39 - return "Slave device or server failure";  
40 - case EMBXACK:  
41 - return "Acknowledge";  
42 - case EMBXSBUSY:  
43 - return "Slave device or server is busy";  
44 - case EMBXNACK:  
45 - return "Negative acknowledge";  
46 - case EMBXMEMPAR:  
47 - return "Memory parity error";  
48 - case EMBXGPATH:  
49 - return "Gateway path unavailable";  
50 - case EMBXGTAR:  
51 - return "Target device failed to respond";  
52 - case EMBBADCRC:  
53 - return "Invalid CRC";  
54 - case EMBBADDATA:  
55 - return "Invalid data";  
56 - case EMBBADEXC:  
57 - return "Invalid exception code";  
58 - case EMBMDATA:  
59 - return "Too many data";  
60 - case EMBBADSLAVE:  
61 - return "Response not from requested slave";  
62 - default:  
63 - return strerror(errnum);  
64 - }  
65 -}  
66 -  
67 -void _error_print(modbus_t *ctx, const char *context)  
68 -{  
69 - if (ctx->debug)  
70 - {  
71 - fprintf(stderr, "ERROR %s", modbus_strerror(errno));  
72 - if (context != NULL)  
73 - {  
74 - fprintf(stderr, ": %s\n", context);  
75 - }  
76 - else  
77 - {  
78 - fprintf(stderr, "\n");  
79 - }  
80 - }  
81 -}  
82 -  
83 -static void _sleep_response_timeout(modbus_t *ctx)  
84 -{  
85 - /* Response timeout is always positive */  
86 - /* usleep source code */  
87 - struct timespec request, remaining;  
88 - request.tv_sec = ctx->response_timeout.tv_sec;  
89 - request.tv_nsec = ((long int)ctx->response_timeout.tv_usec) * 1000;  
90 - while ( nanosleep( &request, &remaining ) == -1 && errno == EINTR )  
91 - {  
92 - request = remaining;  
93 - }  
94 -}  
95 -  
96 -int modbus_flush(modbus_t *ctx)  
97 -{  
98 - int rc;  
99 -  
100 - if (ctx == NULL)  
101 - {  
102 - errno = EINVAL;  
103 - return -1;  
104 - }  
105 -  
106 - rc = ctx->backend->flush( ctx );  
107 - if (rc != -1 && ctx->debug)  
108 - {  
109 - /* Not all backends are able to return the number of bytes flushed */  
110 - printf("Bytes flushed (%d)\n", rc);  
111 - }  
112 - return rc;  
113 -}  
114 -  
115 -/* Computes the length of the expected response */  
116 -static unsigned int compute_response_length_from_request(modbus_t *ctx, uint8_t *req)  
117 -{  
118 - int length;  
119 - const int offset = ctx->backend->header_length;  
120 -  
121 - switch (req[offset])  
122 - {  
123 - case MODBUS_FC_READ_COILS:  
124 - case MODBUS_FC_READ_DISCRETE_INPUTS:  
125 - /* Header + nb values (code from write_bits) */  
126 - int nb = (req[offset + 3] << 8) | req[offset + 4];  
127 - length = 2 + (nb / 8) + ((nb % 8) ? 1 : 0);  
128 - break;  
129 - case MODBUS_FC_WRITE_AND_READ_REGISTERS:  
130 - case MODBUS_FC_READ_HOLDING_REGISTERS:  
131 - case MODBUS_FC_READ_INPUT_REGISTERS:  
132 - /* Header + 2 * nb values */  
133 - length = 2 + 2 * (req[offset + 3] << 8 | req[offset + 4]);  
134 - break;  
135 - case MODBUS_FC_READ_EXCEPTION_STATUS:  
136 - length = 3;  
137 - break;  
138 - case MODBUS_FC_REPORT_SLAVE_ID:  
139 - /* The response is device specific (the header provides the  
140 - length) */  
141 - return MSG_LENGTH_UNDEFINED;  
142 - case MODBUS_FC_MASK_WRITE_REGISTER:  
143 - length = 7;  
144 - break;  
145 - default:  
146 - length = 5;  
147 - }  
148 -  
149 - return offset + length + ctx->backend->checksum_length;  
150 -}  
151 -  
152 -/* Sends a request/response */  
153 -static int send_msg(modbus_t *ctx, uint8_t *msg, int msg_length)  
154 -{  
155 - int rc;  
156 - int i;  
157 -  
158 - msg_length = ctx->backend->send_msg_pre(msg, msg_length);  
159 -  
160 - if (ctx->debug)  
161 - {  
162 - for (i = 0; i < msg_length; i++)  
163 - {  
164 - printf("[%.2X]", msg[i]);  
165 - }  
166 - printf("\n");  
167 - }  
168 -  
169 - /* In recovery mode, the write command will be issued until to be  
170 - successful! Disabled by default. */  
171 - do  
172 - {  
173 - rc = ctx->backend->send(ctx, msg, msg_length);  
174 - if (rc == -1)  
175 - {  
176 - _error_print(ctx, NULL);  
177 - if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK)  
178 - {  
179 - int saved_errno = errno;  
180 -  
181 - if ( (errno == EBADF || errno == ECONNRESET || errno == EPIPE))  
182 - {  
183 - modbus_close(ctx);  
184 - _sleep_response_timeout(ctx);  
185 - modbus_connect(ctx);  
186 - }  
187 - else  
188 - {  
189 - _sleep_response_timeout(ctx);  
190 - modbus_flush(ctx);  
191 - }  
192 - errno = saved_errno;  
193 - }  
194 - }  
195 - } while ( (ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) && rc == -1);  
196 -  
197 - if (rc > 0 && rc != msg_length) {  
198 - errno = EMBBADDATA;  
199 - return -1;  
200 - }  
201 -  
202 - return rc;  
203 -}  
204 -  
205 -int modbus_send_raw_request( modbus_t *ctx, uint8_t *raw_req, int raw_req_length )  
206 -{  
207 - sft_t sft;  
208 - uint8_t req[MAX_MESSAGE_LENGTH];  
209 - int req_length;  
210 -  
211 - if (ctx == NULL)  
212 - {  
213 - errno = EINVAL;  
214 - return -1;  
215 - }  
216 -  
217 - if (raw_req_length < 2 || raw_req_length > (MODBUS_MAX_PDU_LENGTH + 1))  
218 - {  
219 - /* The raw request must contain function and slave at least and  
220 - must not be longer than the maximum pdu length plus the slave  
221 - address. */  
222 - errno = EINVAL;  
223 - return -1;  
224 - }  
225 -  
226 - sft.slave = raw_req[0];  
227 - sft.function = raw_req[1];  
228 - /* The t_id is left to zero */  
229 - sft.t_id = 0;  
230 - /* This response function only set the header so it's convenient here */  
231 - req_length = ctx->backend->build_response_basis(&sft, req);  
232 -  
233 - if( raw_req_length > 2 )  
234 - {  
235 - /* Copy data after function code */  
236 - memcpy(req + req_length, raw_req + 2, raw_req_length - 2);  
237 - req_length += raw_req_length - 2;  
238 - }  
239 -  
240 - return send_msg(ctx, req, req_length);  
241 -}  
242 -  
243 -/*  
244 - * ---------- Request Indication ----------  
245 - * | Client | ---------------------->| Server |  
246 - * ---------- Confirmation Response ----------  
247 - */  
248 -  
249 -/* Computes the length to read after the function received */  
250 -static uint8_t compute_meta_length_after_function( int function, msg_type_t msg_type )  
251 -{  
252 - int length;  
253 -  
254 - if (msg_type == MSG_INDICATION)  
255 - {  
256 - if (function <= MODBUS_FC_WRITE_SINGLE_REGISTER)  
257 - {  
258 - length = 4;  
259 - }  
260 - else if (function == MODBUS_FC_WRITE_MULTIPLE_COILS || function == MODBUS_FC_WRITE_MULTIPLE_REGISTERS)  
261 - {  
262 - length = 5;  
263 - }  
264 - else if (function == MODBUS_FC_MASK_WRITE_REGISTER)  
265 - {  
266 - length = 6;  
267 - }  
268 - else if (function == MODBUS_FC_WRITE_AND_READ_REGISTERS)  
269 - {  
270 - length = 9;  
271 - }  
272 - else  
273 - {  
274 - /* MODBUS_FC_READ_EXCEPTION_STATUS, MODBUS_FC_REPORT_SLAVE_ID */  
275 - length = 0;  
276 - }  
277 - }  
278 - else  
279 - {  
280 - /* MSG_CONFIRMATION */  
281 - switch (function)  
282 - {  
283 - case MODBUS_FC_WRITE_SINGLE_COIL:  
284 - case MODBUS_FC_WRITE_SINGLE_REGISTER:  
285 - case MODBUS_FC_WRITE_MULTIPLE_COILS:  
286 - case MODBUS_FC_WRITE_MULTIPLE_REGISTERS:  
287 - length = 4;  
288 - break;  
289 - case MODBUS_FC_MASK_WRITE_REGISTER:  
290 - length = 6;  
291 - break;  
292 - default:  
293 - length = 1;  
294 - }  
295 - }  
296 -  
297 - return length;  
298 -}  
299 -  
300 -/* Computes the length to read after the meta information (address, count, etc) */  
301 -static int compute_data_length_after_meta(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)  
302 -{  
303 - int function = msg[ctx->backend->header_length];  
304 - int length;  
305 -  
306 - if (msg_type == MSG_INDICATION)  
307 - {  
308 - switch (function)  
309 - {  
310 - case MODBUS_FC_WRITE_MULTIPLE_COILS:  
311 - case MODBUS_FC_WRITE_MULTIPLE_REGISTERS:  
312 - length = msg[ctx->backend->header_length + 5];  
313 - break;  
314 - case MODBUS_FC_WRITE_AND_READ_REGISTERS:  
315 - length = msg[ctx->backend->header_length + 9];  
316 - break;  
317 - default:  
318 - length = 0;  
319 - }  
320 - }  
321 - else  
322 - {  
323 - /* MSG_CONFIRMATION */  
324 - if (function <= MODBUS_FC_READ_INPUT_REGISTERS ||  
325 - function == MODBUS_FC_REPORT_SLAVE_ID ||  
326 - function == MODBUS_FC_WRITE_AND_READ_REGISTERS)  
327 - {  
328 - length = msg[ctx->backend->header_length + 1];  
329 - }  
330 - else  
331 - {  
332 - length = 0;  
333 - }  
334 - }  
335 -  
336 - length += ctx->backend->checksum_length;  
337 -  
338 - return length;  
339 -}  
340 -  
341 -  
342 -/* Waits a response from a modbus server or a request from a modbus client.  
343 - This function blocks if there is no replies (3 timeouts).  
344 -  
345 - The function shall return the number of received characters and the received  
346 - message in an array of uint8_t if successful. Otherwise it shall return -1  
347 - and errno is set to one of the values defined below:  
348 - - ECONNRESET  
349 - - EMBBADDATA  
350 - - EMBUNKEXC  
351 - - ETIMEDOUT  
352 - - read() or recv() error codes  
353 -*/  
354 -  
355 -int _modbus_receive_msg( modbus_t *ctx, uint8_t *msg, msg_type_t msg_type )  
356 -{  
357 - int rc;  
358 - fd_set rset;  
359 - struct timeval tv;  
360 - struct timeval *p_tv;  
361 - int length_to_read;  
362 - int msg_length = 0;  
363 - _step_t step;  
364 -  
365 - if (ctx->debug)  
366 - {  
367 - if (msg_type == MSG_INDICATION)  
368 - {  
369 - printf("Waiting for a indication...\n");  
370 - }  
371 - else  
372 - {  
373 - printf("Waiting for a confirmation...\n");  
374 - }  
375 - }  
376 -  
377 - /* Add a file descriptor to the set */  
378 - FD_ZERO(&rset);  
379 - FD_SET(ctx->s, &rset);  
380 -  
381 - /* We need to analyse the message step by step. At the first step, we want  
382 - * to reach the function code because all packets contain this  
383 - * information. */  
384 - step = _STEP_FUNCTION;  
385 - length_to_read = ctx->backend->header_length + 1;  
386 -  
387 - if (msg_type == MSG_INDICATION)  
388 - {  
389 - /* Wait for a message, we don't know when the message will be  
390 - * received */  
391 - p_tv = NULL;  
392 - }  
393 - else  
394 - {  
395 - tv.tv_sec = ctx->response_timeout.tv_sec;  
396 - tv.tv_usec = ctx->response_timeout.tv_usec;  
397 - p_tv = &tv;  
398 - }  
399 -  
400 - while (length_to_read != 0)  
401 - {  
402 - rc = ctx->backend->select(ctx, &rset, p_tv, length_to_read);  
403 - if (rc == -1)  
404 - {  
405 - _error_print(ctx, "select");  
406 - if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK)  
407 - {  
408 - int saved_errno = errno;  
409 -  
410 - if (errno == ETIMEDOUT)  
411 - {  
412 - _sleep_response_timeout(ctx);  
413 - modbus_flush(ctx);  
414 - }  
415 - else if (errno == EBADF)  
416 - {  
417 - modbus_close(ctx);  
418 - modbus_connect(ctx);  
419 - }  
420 - errno = saved_errno;  
421 - }  
422 - return -1;  
423 - }  
424 -  
425 - rc = ctx->backend->recv(ctx, msg + msg_length, length_to_read);  
426 - if (rc == 0)  
427 - {  
428 - errno = ECONNRESET;  
429 - rc = -1;  
430 - }  
431 -  
432 - if (rc == -1)  
433 - {  
434 - _error_print(ctx, "read");  
435 - if ((ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) &&  
436 - (errno == ECONNRESET || errno == ECONNREFUSED ||  
437 - errno == EBADF))  
438 - {  
439 - int saved_errno = errno;  
440 - modbus_close(ctx);  
441 - modbus_connect(ctx);  
442 - /* Could be removed by previous calls */  
443 - errno = saved_errno;  
444 - }  
445 - return -1;  
446 - }  
447 -  
448 - /* Display the hex code of each character received */  
449 - if (ctx->debug)  
450 - {  
451 - int i;  
452 - for (i=0; i < rc; i++)  
453 - printf("<%.2X>", msg[msg_length + i]);  
454 - }  
455 -  
456 - /* Sums bytes received */  
457 - msg_length += rc;  
458 - /* Computes remaining bytes */  
459 - length_to_read -= rc;  
460 -  
461 - if (length_to_read == 0)  
462 - {  
463 - switch (step)  
464 - {  
465 - case _STEP_FUNCTION:  
466 - /* Function code position */  
467 - length_to_read = compute_meta_length_after_function( msg[ctx->backend->header_length], msg_type);  
468 - if (length_to_read != 0)  
469 - {  
470 - step = _STEP_META;  
471 - break;  
472 - } /* else switches straight to the next step */  
473 - case _STEP_META:  
474 - length_to_read = compute_data_length_after_meta( ctx, msg, msg_type);  
475 - if ( (msg_length + length_to_read) > (int)ctx->backend->max_adu_length )  
476 - {  
477 - errno = EMBBADDATA;  
478 - _error_print(ctx, "too many data");  
479 - return -1;  
480 - }  
481 - step = _STEP_DATA;  
482 - break;  
483 - default:  
484 - break;  
485 - }  
486 - }  
487 -  
488 - if (length_to_read > 0 &&  
489 - (ctx->byte_timeout.tv_sec > 0 || ctx->byte_timeout.tv_usec > 0)) {  
490 - /* If there is no character in the buffer, the allowed timeout  
491 - interval between two consecutive bytes is defined by  
492 - byte_timeout */  
493 - tv.tv_sec = ctx->byte_timeout.tv_sec;  
494 - tv.tv_usec = ctx->byte_timeout.tv_usec;  
495 - p_tv = &tv;  
496 - }  
497 - /* else timeout isn't set again, the full response must be read before  
498 - expiration of response timeout (for CONFIRMATION only) */  
499 - }  
500 -  
501 - if (ctx->debug)  
502 - printf("\n");  
503 -  
504 - return ctx->backend->check_integrity(ctx, msg, msg_length);  
505 -}  
506 -  
507 -/* Receive the request from a modbus master */  
508 -int modbus_receive(modbus_t *ctx, uint8_t *req)  
509 -{  
510 - if (ctx == NULL) {  
511 - errno = EINVAL;  
512 - return -1;  
513 - }  
514 -  
515 - return ctx->backend->receive(ctx, req);  
516 -}  
517 -  
518 -/* Receives the confirmation.  
519 -  
520 - The function shall store the read response in rsp and return the number of  
521 - values (bits or words). Otherwise, its shall return -1 and errno is set.  
522 -  
523 - The function doesn't check the confirmation is the expected response to the  
524 - initial request.  
525 -*/  
526 -int modbus_receive_confirmation(modbus_t *ctx, uint8_t *rsp)  
527 -{  
528 - if (ctx == NULL) {  
529 - errno = EINVAL;  
530 - return -1;  
531 - }  
532 -  
533 - return _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION);  
534 -}  
535 -  
536 -static int check_confirmation(modbus_t *ctx, uint8_t *req,  
537 - uint8_t *rsp, int rsp_length)  
538 -{  
539 - int rc;  
540 - int rsp_length_computed;  
541 - const int offset = ctx->backend->header_length;  
542 - const int function = rsp[offset];  
543 -  
544 - if (ctx->backend->pre_check_confirmation) {  
545 - rc = ctx->backend->pre_check_confirmation(ctx, req, rsp, rsp_length);  
546 - if (rc == -1) {  
547 - if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_PROTOCOL) {  
548 - _sleep_response_timeout(ctx);  
549 - modbus_flush(ctx);  
550 - }  
551 - return -1;  
552 - }  
553 - }  
554 -  
555 - rsp_length_computed = compute_response_length_from_request(ctx, req);  
556 -  
557 - /* Exception code */  
558 - if (function >= 0x80) {  
559 - if (rsp_length == (offset + 2 + (int)ctx->backend->checksum_length) &&  
560 - req[offset] == (rsp[offset] - 0x80)) {  
561 - /* Valid exception code received */  
562 -  
563 - int exception_code = rsp[offset + 1];  
564 - if (exception_code < MODBUS_EXCEPTION_MAX) {  
565 - errno = MODBUS_ENOBASE + exception_code;  
566 - } else {  
567 - errno = EMBBADEXC;  
568 - }  
569 - _error_print(ctx, NULL);  
570 - return -1;  
571 - } else {  
572 - errno = EMBBADEXC;  
573 - _error_print(ctx, NULL);  
574 - return -1;  
575 - }  
576 - }  
577 -  
578 - /* Check length */  
579 - if ((rsp_length == rsp_length_computed ||  
580 - rsp_length_computed == MSG_LENGTH_UNDEFINED) &&  
581 - function < 0x80) {  
582 - int req_nb_value;  
583 - int rsp_nb_value;  
584 -  
585 - /* Check function code */  
586 - if (function != req[offset]) {  
587 - if (ctx->debug) {  
588 - fprintf(stderr,  
589 - "Received function not corresponding to the request (0x%X != 0x%X)\n",  
590 - function, req[offset]);  
591 - }  
592 - if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_PROTOCOL) {  
593 - _sleep_response_timeout(ctx);  
594 - modbus_flush(ctx);  
595 - }  
596 - errno = EMBBADDATA;  
597 - return -1;  
598 - }  
599 -  
600 - /* Check the number of values is corresponding to the request */  
601 - switch (function) {  
602 - case MODBUS_FC_READ_COILS:  
603 - case MODBUS_FC_READ_DISCRETE_INPUTS:  
604 - /* Read functions, 8 values in a byte (nb  
605 - * of values in the request and byte count in  
606 - * the response. */  
607 - req_nb_value = (req[offset + 3] << 8) + req[offset + 4];  
608 - req_nb_value = (req_nb_value / 8) + ((req_nb_value % 8) ? 1 : 0);  
609 - rsp_nb_value = rsp[offset + 1];  
610 - break;  
611 - case MODBUS_FC_WRITE_AND_READ_REGISTERS:  
612 - case MODBUS_FC_READ_HOLDING_REGISTERS:  
613 - case MODBUS_FC_READ_INPUT_REGISTERS:  
614 - /* Read functions 1 value = 2 bytes */  
615 - req_nb_value = (req[offset + 3] << 8) + req[offset + 4];  
616 - rsp_nb_value = (rsp[offset + 1] / 2);  
617 - break;  
618 - case MODBUS_FC_WRITE_MULTIPLE_COILS:  
619 - case MODBUS_FC_WRITE_MULTIPLE_REGISTERS:  
620 - /* N Write functions */  
621 - req_nb_value = (req[offset + 3] << 8) + req[offset + 4];  
622 - rsp_nb_value = (rsp[offset + 3] << 8) | rsp[offset + 4];  
623 - break;  
624 - case MODBUS_FC_REPORT_SLAVE_ID:  
625 - /* Report slave ID (bytes received) */  
626 - req_nb_value = rsp_nb_value = rsp[offset + 1];  
627 - break;  
628 - default:  
629 - /* 1 Write functions & others */  
630 - req_nb_value = rsp_nb_value = 1;  
631 - }  
632 -  
633 - if (req_nb_value == rsp_nb_value) {  
634 - rc = rsp_nb_value;  
635 - } else {  
636 - if (ctx->debug) {  
637 - fprintf(stderr,  
638 - "Quantity not corresponding to the request (%d != %d)\n",  
639 - rsp_nb_value, req_nb_value);  
640 - }  
641 -  
642 - if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_PROTOCOL) {  
643 - _sleep_response_timeout(ctx);  
644 - modbus_flush(ctx);  
645 - }  
646 -  
647 - errno = EMBBADDATA;  
648 - rc = -1;  
649 - }  
650 - } else {  
651 - if (ctx->debug) {  
652 - fprintf(stderr,  
653 - "Message length not corresponding to the computed length (%d != %d)\n",  
654 - rsp_length, rsp_length_computed);  
655 - }  
656 - if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_PROTOCOL) {  
657 - _sleep_response_timeout(ctx);  
658 - modbus_flush(ctx);  
659 - }  
660 - errno = EMBBADDATA;  
661 - rc = -1;  
662 - }  
663 -  
664 - return rc;  
665 -}  
666 -  
667 -static int response_io_status(uint8_t *tab_io_status,  
668 - int address, int nb,  
669 - uint8_t *rsp, int offset)  
670 -{  
671 - int shift = 0;  
672 - /* Instead of byte (not allowed in Win32) */  
673 - int one_byte = 0;  
674 - int i;  
675 -  
676 - for (i = address; i < address + nb; i++) {  
677 - one_byte |= tab_io_status[i] << shift;  
678 - if (shift == 7) {  
679 - /* Byte is full */  
680 - rsp[offset++] = one_byte;  
681 - one_byte = shift = 0;  
682 - } else {  
683 - shift++;  
684 - }  
685 - }  
686 -  
687 - if (shift != 0)  
688 - rsp[offset++] = one_byte;  
689 -  
690 - return offset;  
691 -}  
692 -  
693 -/* Build the exception response */  
694 -static int response_exception(modbus_t *ctx, sft_t *sft,  
695 - int exception_code, uint8_t *rsp,  
696 - unsigned int to_flush,  
697 - const char* template, ...)  
698 -{  
699 - int rsp_length;  
700 -  
701 - /* Print debug message */  
702 - if (ctx->debug) {  
703 - va_list ap;  
704 -  
705 - va_start(ap, template);  
706 - vfprintf(stderr, template, ap);  
707 - va_end(ap);  
708 - }  
709 -  
710 - /* Flush if required */  
711 - if (to_flush) {  
712 - _sleep_response_timeout(ctx);  
713 - modbus_flush(ctx);  
714 - }  
715 -  
716 - /* Build exception response */  
717 - sft->function = sft->function + 0x80;  
718 - rsp_length = ctx->backend->build_response_basis(sft, rsp);  
719 - rsp[rsp_length++] = exception_code;  
720 -  
721 - return rsp_length;  
722 -}  
723 -  
724 -/* Send a response to the received request.  
725 - Analyses the request and constructs a response.  
726 -  
727 - If an error occurs, this function construct the response  
728 - accordingly.  
729 -*/  
730 -int modbus_reply(modbus_t *ctx, const uint8_t *req,  
731 - int req_length, modbus_mapping_t *mb_mapping)  
732 -{  
733 - int offset;  
734 - int slave;  
735 - int function;  
736 - uint16_t address;  
737 - uint8_t rsp[MAX_MESSAGE_LENGTH];  
738 - int rsp_length = 0;  
739 - sft_t sft;  
740 -  
741 - if (ctx == NULL) {  
742 - errno = EINVAL;  
743 - return -1;  
744 - }  
745 -  
746 - offset = ctx->backend->header_length;  
747 - slave = req[offset - 1];  
748 - function = req[offset];  
749 - address = (req[offset + 1] << 8) + req[offset + 2];  
750 -  
751 - sft.slave = slave;  
752 - sft.function = function;  
753 - sft.t_id = ctx->backend->prepare_response_tid(req, &req_length);  
754 -  
755 - /* Data are flushed on illegal number of values errors. */  
756 - switch (function) {  
757 - case MODBUS_FC_READ_COILS:  
758 - case MODBUS_FC_READ_DISCRETE_INPUTS: {  
759 - unsigned int is_input = (function == MODBUS_FC_READ_DISCRETE_INPUTS);  
760 - int start_bits = is_input ? mb_mapping->start_input_bits : mb_mapping->start_bits;  
761 - int nb_bits = is_input ? mb_mapping->nb_input_bits : mb_mapping->nb_bits;  
762 - uint8_t *tab_bits = is_input ? mb_mapping->tab_input_bits : mb_mapping->tab_bits;  
763 - const char * const name = is_input ? "read_input_bits" : "read_bits";  
764 - int nb = (req[offset + 3] << 8) + req[offset + 4];  
765 - /* The mapping can be shifted to reduce memory consumption and it  
766 - doesn't always start at address zero. */  
767 - int mapping_address = address - start_bits;  
768 -  
769 - if (nb < 1 || MODBUS_MAX_READ_BITS < nb) {  
770 - rsp_length = response_exception(  
771 - ctx, &sft, MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp, TRUE,  
772 - "Illegal nb of values %d in %s (max %d)\n",  
773 - nb, name, MODBUS_MAX_READ_BITS);  
774 - } else if (mapping_address < 0 || (mapping_address + nb) > nb_bits) {  
775 - rsp_length = response_exception(  
776 - ctx, &sft,  
777 - MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp, FALSE,  
778 - "Illegal data address 0x%0X in %s\n",  
779 - mapping_address < 0 ? address : address + nb, name);  
780 - } else {  
781 - rsp_length = ctx->backend->build_response_basis(&sft, rsp);  
782 - rsp[rsp_length++] = (nb / 8) + ((nb % 8) ? 1 : 0);  
783 - rsp_length = response_io_status(tab_bits, mapping_address, nb,  
784 - rsp, rsp_length);  
785 - }  
786 - }  
787 - break;  
788 - case MODBUS_FC_READ_HOLDING_REGISTERS:  
789 - case MODBUS_FC_READ_INPUT_REGISTERS: {  
790 - unsigned int is_input = (function == MODBUS_FC_READ_INPUT_REGISTERS);  
791 - int start_registers = is_input ? mb_mapping->start_input_registers : mb_mapping->start_registers;  
792 - int nb_registers = is_input ? mb_mapping->nb_input_registers : mb_mapping->nb_registers;  
793 - uint16_t *tab_registers = is_input ? mb_mapping->tab_input_registers : mb_mapping->tab_registers;  
794 - const char * const name = is_input ? "read_input_registers" : "read_registers";  
795 - int nb = (req[offset + 3] << 8) + req[offset + 4];  
796 - /* The mapping can be shifted to reduce memory consumption and it  
797 - doesn't always start at address zero. */  
798 - int mapping_address = address - start_registers;  
799 -  
800 - if (nb < 1 || MODBUS_MAX_READ_REGISTERS < nb) {  
801 - rsp_length = response_exception(  
802 - ctx, &sft, MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp, TRUE,  
803 - "Illegal nb of values %d in %s (max %d)\n",  
804 - nb, name, MODBUS_MAX_READ_REGISTERS);  
805 - } else if (mapping_address < 0 || (mapping_address + nb) > nb_registers) {  
806 - rsp_length = response_exception(  
807 - ctx, &sft, MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp, FALSE,  
808 - "Illegal data address 0x%0X in %s\n",  
809 - mapping_address < 0 ? address : address + nb, name);  
810 - } else {  
811 - int i;  
812 -  
813 - rsp_length = ctx->backend->build_response_basis(&sft, rsp);  
814 - rsp[rsp_length++] = nb << 1;  
815 - for (i = mapping_address; i < mapping_address + nb; i++) {  
816 - rsp[rsp_length++] = tab_registers[i] >> 8;  
817 - rsp[rsp_length++] = tab_registers[i] & 0xFF;  
818 - }  
819 - }  
820 - }  
821 - break;  
822 - case MODBUS_FC_WRITE_SINGLE_COIL: {  
823 - int mapping_address = address - mb_mapping->start_bits;  
824 -  
825 - if (mapping_address < 0 || mapping_address >= mb_mapping->nb_bits) {  
826 - rsp_length = response_exception(  
827 - ctx, &sft, MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp, FALSE,  
828 - "Illegal data address 0x%0X in write_bit\n",  
829 - address);  
830 - } else {  
831 - int data = (req[offset + 3] << 8) + req[offset + 4];  
832 -  
833 - if (data == 0xFF00 || data == 0x0) {  
834 - mb_mapping->tab_bits[mapping_address] = data ? ON : OFF;  
835 - memcpy(rsp, req, req_length);  
836 - rsp_length = req_length;  
837 - } else {  
838 - rsp_length = response_exception(  
839 - ctx, &sft,  
840 - MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp, FALSE,  
841 - "Illegal data value 0x%0X in write_bit request at address %0X\n",  
842 - data, address);  
843 - }  
844 - }  
845 - }  
846 - break;  
847 - case MODBUS_FC_WRITE_SINGLE_REGISTER: {  
848 - int mapping_address = address - mb_mapping->start_registers;  
849 -  
850 - if (mapping_address < 0 || mapping_address >= mb_mapping->nb_registers) {  
851 - rsp_length = response_exception(  
852 - ctx, &sft,  
853 - MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp, FALSE,  
854 - "Illegal data address 0x%0X in write_register\n",  
855 - address);  
856 - } else {  
857 - int data = (req[offset + 3] << 8) + req[offset + 4];  
858 -  
859 - mb_mapping->tab_registers[mapping_address] = data;  
860 - memcpy(rsp, req, req_length);  
861 - rsp_length = req_length;  
862 - }  
863 - }  
864 - break;  
865 - case MODBUS_FC_WRITE_MULTIPLE_COILS: {  
866 - int nb = (req[offset + 3] << 8) + req[offset + 4];  
867 - int mapping_address = address - mb_mapping->start_bits;  
868 -  
869 - if (nb < 1 || MODBUS_MAX_WRITE_BITS < nb) {  
870 - /* May be the indication has been truncated on reading because of  
871 - * invalid address (eg. nb is 0 but the request contains values to  
872 - * write) so it's necessary to flush. */  
873 - rsp_length = response_exception(  
874 - ctx, &sft, MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp, TRUE,  
875 - "Illegal number of values %d in write_bits (max %d)\n",  
876 - nb, MODBUS_MAX_WRITE_BITS);  
877 - } else if (mapping_address < 0 ||  
878 - (mapping_address + nb) > mb_mapping->nb_bits) {  
879 - rsp_length = response_exception(  
880 - ctx, &sft,  
881 - MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp, FALSE,  
882 - "Illegal data address 0x%0X in write_bits\n",  
883 - mapping_address < 0 ? address : address + nb);  
884 - } else {  
885 - /* 6 = byte count */  
886 - modbus_set_bits_from_bytes(mb_mapping->tab_bits, mapping_address, nb,  
887 - &req[offset + 6]);  
888 -  
889 - rsp_length = ctx->backend->build_response_basis(&sft, rsp);  
890 - /* 4 to copy the bit address (2) and the quantity of bits */  
891 - memcpy(rsp + rsp_length, req + rsp_length, 4);  
892 - rsp_length += 4;  
893 - }  
894 - }  
895 - break;  
896 - case MODBUS_FC_WRITE_MULTIPLE_REGISTERS: {  
897 - int nb = (req[offset + 3] << 8) + req[offset + 4];  
898 - int mapping_address = address - mb_mapping->start_registers;  
899 -  
900 - if (nb < 1 || MODBUS_MAX_WRITE_REGISTERS < nb) {  
901 - rsp_length = response_exception(  
902 - ctx, &sft, MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp, TRUE,  
903 - "Illegal number of values %d in write_registers (max %d)\n",  
904 - nb, MODBUS_MAX_WRITE_REGISTERS);  
905 - } else if (mapping_address < 0 ||  
906 - (mapping_address + nb) > mb_mapping->nb_registers) {  
907 - rsp_length = response_exception(  
908 - ctx, &sft, MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp, FALSE,  
909 - "Illegal data address 0x%0X in write_registers\n",  
910 - mapping_address < 0 ? address : address + nb);  
911 - } else {  
912 - int i, j;  
913 - for (i = mapping_address, j = 6; i < mapping_address + nb; i++, j += 2) {  
914 - /* 6 and 7 = first value */  
915 - mb_mapping->tab_registers[i] =  
916 - (req[offset + j] << 8) + req[offset + j + 1];  
917 - }  
918 -  
919 - rsp_length = ctx->backend->build_response_basis(&sft, rsp);  
920 - /* 4 to copy the address (2) and the no. of registers */  
921 - memcpy(rsp + rsp_length, req + rsp_length, 4);  
922 - rsp_length += 4;  
923 - }  
924 - }  
925 - break;  
926 - case MODBUS_FC_REPORT_SLAVE_ID:  
927 - {  
928 - int str_len;  
929 - int byte_count_pos;  
930 -  
931 - rsp_length = ctx->backend->build_response_basis(&sft, rsp);  
932 - /* Skip byte count for now */  
933 - byte_count_pos = rsp_length++;  
934 - rsp[rsp_length++] = _REPORT_SLAVE_ID;  
935 - /* Run indicator status to ON */  
936 - rsp[rsp_length++] = 0xFF;  
937 - str_len = 3 + strlen(MODBUS_VERSION_STRING);  
938 - memcpy(rsp + rsp_length, "LMB" MODBUS_VERSION_STRING, str_len);  
939 - rsp_length += str_len;  
940 - rsp[byte_count_pos] = rsp_length - byte_count_pos - 1;  
941 - }  
942 - break;  
943 - case MODBUS_FC_READ_EXCEPTION_STATUS:  
944 - if (ctx->debug) {  
945 - fprintf(stderr, "FIXME Not implemented\n");  
946 - }  
947 - errno = ENOPROTOOPT;  
948 - return -1;  
949 - break;  
950 - case MODBUS_FC_MASK_WRITE_REGISTER: {  
951 - int mapping_address = address - mb_mapping->start_registers;  
952 -  
953 - if (mapping_address < 0 || mapping_address >= mb_mapping->nb_registers) {  
954 - rsp_length = response_exception(  
955 - ctx, &sft, MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp, FALSE,  
956 - "Illegal data address 0x%0X in write_register\n",  
957 - address);  
958 - } else {  
959 - uint16_t data = mb_mapping->tab_registers[mapping_address];  
960 - uint16_t and = (req[offset + 3] << 8) + req[offset + 4];  
961 - uint16_t or = (req[offset + 5] << 8) + req[offset + 6];  
962 -  
963 - data = (data & and) | (or & (~and));  
964 - mb_mapping->tab_registers[mapping_address] = data;  
965 - memcpy(rsp, req, req_length);  
966 - rsp_length = req_length;  
967 - }  
968 - }  
969 - break;  
970 - case MODBUS_FC_WRITE_AND_READ_REGISTERS: {  
971 - int nb = (req[offset + 3] << 8) + req[offset + 4];  
972 - uint16_t address_write = (req[offset + 5] << 8) + req[offset + 6];  
973 - int nb_write = (req[offset + 7] << 8) + req[offset + 8];  
974 - int nb_write_bytes = req[offset + 9];  
975 - int mapping_address = address - mb_mapping->start_registers;  
976 - int mapping_address_write = address_write - mb_mapping->start_registers;  
977 -  
978 - if (nb_write < 1 || MODBUS_MAX_WR_WRITE_REGISTERS < nb_write ||  
979 - nb < 1 || MODBUS_MAX_WR_READ_REGISTERS < nb ||  
980 - nb_write_bytes != nb_write * 2) {  
981 - rsp_length = response_exception(  
982 - ctx, &sft, MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp, TRUE,  
983 - "Illegal nb of values (W%d, R%d) in write_and_read_registers (max W%d, R%d)\n",  
984 - nb_write, nb, MODBUS_MAX_WR_WRITE_REGISTERS, MODBUS_MAX_WR_READ_REGISTERS);  
985 - } else if (mapping_address < 0 ||  
986 - (mapping_address + nb) > mb_mapping->nb_registers ||  
987 - mapping_address < 0 ||  
988 - (mapping_address_write + nb_write) > mb_mapping->nb_registers) {  
989 - rsp_length = response_exception(  
990 - ctx, &sft, MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp, FALSE,  
991 - "Illegal data read address 0x%0X or write address 0x%0X write_and_read_registers\n",  
992 - mapping_address < 0 ? address : address + nb,  
993 - mapping_address_write < 0 ? address_write : address_write + nb_write);  
994 - } else {  
995 - int i, j;  
996 - rsp_length = ctx->backend->build_response_basis(&sft, rsp);  
997 - rsp[rsp_length++] = nb << 1;  
998 -  
999 - /* Write first.  
1000 - 10 and 11 are the offset of the first values to write */  
1001 - for (i = mapping_address_write, j = 10;  
1002 - i < mapping_address_write + nb_write; i++, j += 2) {  
1003 - mb_mapping->tab_registers[i] =  
1004 - (req[offset + j] << 8) + req[offset + j + 1];  
1005 - }  
1006 -  
1007 - /* and read the data for the response */  
1008 - for (i = mapping_address; i < mapping_address + nb; i++) {  
1009 - rsp[rsp_length++] = mb_mapping->tab_registers[i] >> 8;  
1010 - rsp[rsp_length++] = mb_mapping->tab_registers[i] & 0xFF;  
1011 - }  
1012 - }  
1013 - }  
1014 - break;  
1015 -  
1016 - default:  
1017 - rsp_length = response_exception(  
1018 - ctx, &sft, MODBUS_EXCEPTION_ILLEGAL_FUNCTION, rsp, TRUE,  
1019 - "Unknown Modbus function code: 0x%0X\n", function);  
1020 - break;  
1021 - }  
1022 -  
1023 - /* Suppress any responses when the request was a broadcast */  
1024 - return (slave == MODBUS_BROADCAST_ADDRESS) ? 0 : send_msg(ctx, rsp, rsp_length);  
1025 -}  
1026 -  
1027 -int modbus_reply_exception(modbus_t *ctx, const uint8_t *req,  
1028 - unsigned int exception_code)  
1029 -{  
1030 - int offset;  
1031 - int slave;  
1032 - int function;  
1033 - uint8_t rsp[MAX_MESSAGE_LENGTH];  
1034 - int rsp_length;  
1035 - int dummy_length = 99;  
1036 - sft_t sft;  
1037 -  
1038 - if (ctx == NULL) {  
1039 - errno = EINVAL;  
1040 - return -1;  
1041 - }  
1042 -  
1043 - offset = ctx->backend->header_length;  
1044 - slave = req[offset - 1];  
1045 - function = req[offset];  
1046 -  
1047 - sft.slave = slave;  
1048 - sft.function = function + 0x80;;  
1049 - sft.t_id = ctx->backend->prepare_response_tid(req, &dummy_length);  
1050 - rsp_length = ctx->backend->build_response_basis(&sft, rsp);  
1051 -  
1052 - /* Positive exception code */  
1053 - if (exception_code < MODBUS_EXCEPTION_MAX) {  
1054 - rsp[rsp_length++] = exception_code;  
1055 - return send_msg(ctx, rsp, rsp_length);  
1056 - } else {  
1057 - errno = EINVAL;  
1058 - return -1;  
1059 - }  
1060 -}  
1061 -  
1062 -/* Reads IO status */  
1063 -static int read_io_status(modbus_t *ctx, int function,  
1064 - int addr, int nb, uint8_t *dest)  
1065 -{  
1066 - int rc;  
1067 - int req_length;  
1068 -  
1069 - uint8_t req[_MIN_REQ_LENGTH];  
1070 - uint8_t rsp[MAX_MESSAGE_LENGTH];  
1071 -  
1072 - req_length = ctx->backend->build_request_basis(ctx, function, addr, nb, req);  
1073 -  
1074 - rc = send_msg(ctx, req, req_length);  
1075 - if (rc > 0) {  
1076 - int i, temp, bit;  
1077 - int pos = 0;  
1078 - int offset;  
1079 - int offset_end;  
1080 -  
1081 - rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION);  
1082 - if (rc == -1)  
1083 - return -1;  
1084 -  
1085 - rc = check_confirmation(ctx, req, rsp, rc);  
1086 - if (rc == -1)  
1087 - return -1;  
1088 -  
1089 - offset = ctx->backend->header_length + 2;  
1090 - offset_end = offset + rc;  
1091 - for (i = offset; i < offset_end; i++) {  
1092 - /* Shift reg hi_byte to temp */  
1093 - temp = rsp[i];  
1094 -  
1095 - for (bit = 0x01; (bit & 0xff) && (pos < nb);) {  
1096 - dest[pos++] = (temp & bit) ? TRUE : FALSE;  
1097 - bit = bit << 1;  
1098 - }  
1099 -  
1100 - }  
1101 - }  
1102 -  
1103 - return rc;  
1104 -}  
1105 -  
1106 -/* Reads the boolean status of bits and sets the array elements  
1107 - in the destination to TRUE or FALSE (single bits). */  
1108 -int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest)  
1109 -{  
1110 - int rc;  
1111 -  
1112 - if (ctx == NULL) {  
1113 - errno = EINVAL;  
1114 - return -1;  
1115 - }  
1116 -  
1117 - if (nb > MODBUS_MAX_READ_BITS) {  
1118 - if (ctx->debug) {  
1119 - fprintf(stderr,  
1120 - "ERROR Too many bits requested (%d > %d)\n",  
1121 - nb, MODBUS_MAX_READ_BITS);  
1122 - }  
1123 - errno = EMBMDATA;  
1124 - return -1;  
1125 - }  
1126 -  
1127 - rc = read_io_status(ctx, MODBUS_FC_READ_COILS, addr, nb, dest);  
1128 -  
1129 - if (rc == -1)  
1130 - return -1;  
1131 - else  
1132 - return nb;  
1133 -}  
1134 -  
1135 -  
1136 -/* Same as modbus_read_bits but reads the remote device input table */  
1137 -int modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest)  
1138 -{  
1139 - int rc;  
1140 -  
1141 - if (ctx == NULL) {  
1142 - errno = EINVAL;  
1143 - return -1;  
1144 - }  
1145 -  
1146 - if (nb > MODBUS_MAX_READ_BITS) {  
1147 - if (ctx->debug) {  
1148 - fprintf(stderr,  
1149 - "ERROR Too many discrete inputs requested (%d > %d)\n",  
1150 - nb, MODBUS_MAX_READ_BITS);  
1151 - }  
1152 - errno = EMBMDATA;  
1153 - return -1;  
1154 - }  
1155 -  
1156 - rc = read_io_status(ctx, MODBUS_FC_READ_DISCRETE_INPUTS, addr, nb, dest);  
1157 -  
1158 - if (rc == -1)  
1159 - return -1;  
1160 - else  
1161 - return nb;  
1162 -}  
1163 -  
1164 -/* Reads the data from a remove device and put that data into an array */  
1165 -static int read_registers(modbus_t *ctx, int function, int addr, int nb, uint16_t *dest)  
1166 -{  
1167 - int rc;  
1168 - int req_length;  
1169 - uint8_t req[_MIN_REQ_LENGTH];  
1170 - uint8_t rsp[MAX_MESSAGE_LENGTH];  
1171 -  
1172 - if (nb > MODBUS_MAX_READ_REGISTERS)  
1173 - {  
1174 - if (ctx->debug)  
1175 - {  
1176 - fprintf(stderr,  
1177 - "ERROR Too many registers requested (%d > %d)\n",  
1178 - nb, MODBUS_MAX_READ_REGISTERS);  
1179 - }  
1180 - errno = EMBMDATA;  
1181 - return -1;  
1182 - }  
1183 -  
1184 - req_length = ctx->backend->build_request_basis(ctx, function, addr, nb, req);  
1185 -  
1186 - rc = send_msg(ctx, req, req_length);  
1187 - if (rc > 0)  
1188 - {  
1189 - int offset;  
1190 - int i;  
1191 -  
1192 - rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION);  
1193 - if (rc == -1)  
1194 - return -1;  
1195 -  
1196 - rc = check_confirmation(ctx, req, rsp, rc);  
1197 - if (rc == -1)  
1198 - return -1;  
1199 -  
1200 - offset = ctx->backend->header_length;  
1201 -  
1202 - for (i = 0; i < rc; i++) {  
1203 - /* shift reg hi_byte to temp OR with lo_byte */  
1204 - dest[i] = (rsp[offset + 2 + (i << 1)] << 8) |  
1205 - rsp[offset + 3 + (i << 1)];  
1206 - }  
1207 - }  
1208 -  
1209 - return rc;  
1210 -}  
1211 -  
1212 -/* Reads the holding registers of remote device and put the data into an  
1213 - array */  
1214 -int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest)  
1215 -{  
1216 - int status;  
1217 -  
1218 - if (ctx == NULL) {  
1219 - errno = EINVAL;  
1220 - return -1;  
1221 - }  
1222 -  
1223 - if (nb > MODBUS_MAX_READ_REGISTERS)  
1224 - {  
1225 - if (ctx->debug)  
1226 - {  
1227 - fprintf(stderr,  
1228 - "ERROR Too many registers requested (%d > %d)\n",  
1229 - nb, MODBUS_MAX_READ_REGISTERS);  
1230 - }  
1231 - errno = EMBMDATA;  
1232 - return -1;  
1233 - }  
1234 -  
1235 - status = read_registers(ctx, MODBUS_FC_READ_HOLDING_REGISTERS,  
1236 - addr, nb, dest);  
1237 - return status;  
1238 -}  
1239 -  
1240 -/* Reads the input registers of remote device and put the data into an array */  
1241 -int modbus_read_input_registers(modbus_t *ctx, int addr, int nb,  
1242 - uint16_t *dest)  
1243 -{  
1244 - int status;  
1245 -  
1246 - if (ctx == NULL) {  
1247 - errno = EINVAL;  
1248 - return -1;  
1249 - }  
1250 -  
1251 - if (nb > MODBUS_MAX_READ_REGISTERS) {  
1252 - fprintf(stderr,  
1253 - "ERROR Too many input registers requested (%d > %d)\n",  
1254 - nb, MODBUS_MAX_READ_REGISTERS);  
1255 - errno = EMBMDATA;  
1256 - return -1;  
1257 - }  
1258 -  
1259 - status = read_registers(ctx, MODBUS_FC_READ_INPUT_REGISTERS,  
1260 - addr, nb, dest);  
1261 -  
1262 - return status;  
1263 -}  
1264 -  
1265 -/* Write a value to the specified register of the remote device.  
1266 - Used by write_bit and write_register */  
1267 -static int write_single(modbus_t *ctx, int function, int addr, int value)  
1268 -{  
1269 - int rc;  
1270 - int req_length;  
1271 - uint8_t req[_MIN_REQ_LENGTH];  
1272 -  
1273 - if (ctx == NULL) {  
1274 - errno = EINVAL;  
1275 - return -1;  
1276 - }  
1277 -  
1278 - req_length = ctx->backend->build_request_basis(ctx, function, addr, value, req);  
1279 -  
1280 - rc = send_msg(ctx, req, req_length);  
1281 - if (rc > 0) {  
1282 - /* Used by write_bit and write_register */  
1283 - uint8_t rsp[MAX_MESSAGE_LENGTH];  
1284 -  
1285 - rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION);  
1286 - if (rc == -1)  
1287 - return -1;  
1288 -  
1289 - rc = check_confirmation(ctx, req, rsp, rc);  
1290 - }  
1291 -  
1292 - return rc;  
1293 -}  
1294 -  
1295 -/* Turns ON or OFF a single bit of the remote device */  
1296 -int modbus_write_bit(modbus_t *ctx, int addr, int status)  
1297 -{  
1298 - if (ctx == NULL) {  
1299 - errno = EINVAL;  
1300 - return -1;  
1301 - }  
1302 -  
1303 - return write_single(ctx, MODBUS_FC_WRITE_SINGLE_COIL, addr,  
1304 - status ? 0xFF00 : 0);  
1305 -}  
1306 -  
1307 -/* Writes a value in one register of the remote device */  
1308 -int modbus_write_register(modbus_t *ctx, int addr, int value)  
1309 -{  
1310 - if (ctx == NULL) {  
1311 - errno = EINVAL;  
1312 - return -1;  
1313 - }  
1314 -  
1315 - return write_single(ctx, MODBUS_FC_WRITE_SINGLE_REGISTER, addr, value);  
1316 -}  
1317 -  
1318 -/* Write the bits of the array in the remote device */  
1319 -int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *src)  
1320 -{  
1321 - int rc;  
1322 - int i;  
1323 - int byte_count;  
1324 - int req_length;  
1325 - int bit_check = 0;  
1326 - int pos = 0;  
1327 - uint8_t req[MAX_MESSAGE_LENGTH];  
1328 -  
1329 - if (ctx == NULL) {  
1330 - errno = EINVAL;  
1331 - return -1;  
1332 - }  
1333 -  
1334 - if (nb > MODBUS_MAX_WRITE_BITS) {  
1335 - if (ctx->debug) {  
1336 - fprintf(stderr, "ERROR Writing too many bits (%d > %d)\n",  
1337 - nb, MODBUS_MAX_WRITE_BITS);  
1338 - }  
1339 - errno = EMBMDATA;  
1340 - return -1;  
1341 - }  
1342 -  
1343 - req_length = ctx->backend->build_request_basis(ctx,  
1344 - MODBUS_FC_WRITE_MULTIPLE_COILS,  
1345 - addr, nb, req);  
1346 - byte_count = (nb / 8) + ((nb % 8) ? 1 : 0);  
1347 - req[req_length++] = byte_count;  
1348 -  
1349 - for (i = 0; i < byte_count; i++) {  
1350 - int bit;  
1351 -  
1352 - bit = 0x01;  
1353 - req[req_length] = 0;  
1354 -  
1355 - while ((bit & 0xFF) && (bit_check++ < nb)) {  
1356 - if (src[pos++])  
1357 - req[req_length] |= bit;  
1358 - else  
1359 - req[req_length] &=~ bit;  
1360 -  
1361 - bit = bit << 1;  
1362 - }  
1363 - req_length++;  
1364 - }  
1365 -  
1366 - rc = send_msg(ctx, req, req_length);  
1367 - if (rc > 0) {  
1368 - uint8_t rsp[MAX_MESSAGE_LENGTH];  
1369 -  
1370 - rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION);  
1371 - if (rc == -1)  
1372 - return -1;  
1373 -  
1374 - rc = check_confirmation(ctx, req, rsp, rc);  
1375 - }  
1376 -  
1377 -  
1378 - return rc;  
1379 -}  
1380 -  
1381 -/* Write the values from the array to the registers of the remote device */  
1382 -int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *src)  
1383 -{  
1384 - int rc;  
1385 - int i;  
1386 - int req_length;  
1387 - int byte_count;  
1388 - uint8_t req[MAX_MESSAGE_LENGTH];  
1389 -  
1390 - if (ctx == NULL) {  
1391 - errno = EINVAL;  
1392 - return -1;  
1393 - }  
1394 -  
1395 - if (nb > MODBUS_MAX_WRITE_REGISTERS) {  
1396 - if (ctx->debug) {  
1397 - fprintf(stderr,  
1398 - "ERROR Trying to write to too many registers (%d > %d)\n",  
1399 - nb, MODBUS_MAX_WRITE_REGISTERS);  
1400 - }  
1401 - errno = EMBMDATA;  
1402 - return -1;  
1403 - }  
1404 -  
1405 - req_length = ctx->backend->build_request_basis(ctx,  
1406 - MODBUS_FC_WRITE_MULTIPLE_REGISTERS,  
1407 - addr, nb, req);  
1408 - byte_count = nb * 2;  
1409 - req[req_length++] = byte_count;  
1410 -  
1411 - for (i = 0; i < nb; i++) {  
1412 - req[req_length++] = src[i] >> 8;  
1413 - req[req_length++] = src[i] & 0x00FF;  
1414 - }  
1415 -  
1416 - rc = send_msg(ctx, req, req_length);  
1417 - if (rc > 0) {  
1418 - uint8_t rsp[MAX_MESSAGE_LENGTH];  
1419 -  
1420 - rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION);  
1421 - if (rc == -1)  
1422 - return -1;  
1423 -  
1424 - rc = check_confirmation(ctx, req, rsp, rc);  
1425 - }  
1426 -  
1427 - return rc;  
1428 -}  
1429 -  
1430 -int modbus_mask_write_register(modbus_t *ctx, int addr, uint16_t and_mask, uint16_t or_mask)  
1431 -{  
1432 - int rc;  
1433 - int req_length;  
1434 - /* The request length can not exceed _MIN_REQ_LENGTH - 2 and 4 bytes to  
1435 - * store the masks. The ugly substraction is there to remove the 'nb' value  
1436 - * (2 bytes) which is not used. */  
1437 - uint8_t req[_MIN_REQ_LENGTH + 2];  
1438 -  
1439 - req_length = ctx->backend->build_request_basis(ctx,  
1440 - MODBUS_FC_MASK_WRITE_REGISTER,  
1441 - addr, 0, req);  
1442 -  
1443 - /* HACKISH, count is not used */  
1444 - req_length -= 2;  
1445 -  
1446 - req[req_length++] = and_mask >> 8;  
1447 - req[req_length++] = and_mask & 0x00ff;  
1448 - req[req_length++] = or_mask >> 8;  
1449 - req[req_length++] = or_mask & 0x00ff;  
1450 -  
1451 - rc = send_msg(ctx, req, req_length);  
1452 - if (rc > 0) {  
1453 - /* Used by write_bit and write_register */  
1454 - uint8_t rsp[MAX_MESSAGE_LENGTH];  
1455 -  
1456 - rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION);  
1457 - if (rc == -1)  
1458 - return -1;  
1459 -  
1460 - rc = check_confirmation(ctx, req, rsp, rc);  
1461 - }  
1462 -  
1463 - return rc;  
1464 -}  
1465 -  
1466 -/* Write multiple registers from src array to remote device and read multiple  
1467 - registers from remote device to dest array. */  
1468 -int modbus_write_and_read_registers(modbus_t *ctx,  
1469 - int write_addr, int write_nb,  
1470 - const uint16_t *src,  
1471 - int read_addr, int read_nb,  
1472 - uint16_t *dest)  
1473 -  
1474 -{  
1475 - int rc;  
1476 - int req_length;  
1477 - int i;  
1478 - int byte_count;  
1479 - uint8_t req[MAX_MESSAGE_LENGTH];  
1480 - uint8_t rsp[MAX_MESSAGE_LENGTH];  
1481 -  
1482 - if (ctx == NULL) {  
1483 - errno = EINVAL;  
1484 - return -1;  
1485 - }  
1486 -  
1487 - if (write_nb > MODBUS_MAX_WR_WRITE_REGISTERS) {  
1488 - if (ctx->debug) {  
1489 - fprintf(stderr,  
1490 - "ERROR Too many registers to write (%d > %d)\n",  
1491 - write_nb, MODBUS_MAX_WR_WRITE_REGISTERS);  
1492 - }  
1493 - errno = EMBMDATA;  
1494 - return -1;  
1495 - }  
1496 -  
1497 - if (read_nb > MODBUS_MAX_WR_READ_REGISTERS) {  
1498 - if (ctx->debug) {  
1499 - fprintf(stderr,  
1500 - "ERROR Too many registers requested (%d > %d)\n",  
1501 - read_nb, MODBUS_MAX_WR_READ_REGISTERS);  
1502 - }  
1503 - errno = EMBMDATA;  
1504 - return -1;  
1505 - }  
1506 - req_length = ctx->backend->build_request_basis(ctx,  
1507 - MODBUS_FC_WRITE_AND_READ_REGISTERS,  
1508 - read_addr, read_nb, req);  
1509 -  
1510 - req[req_length++] = write_addr >> 8;  
1511 - req[req_length++] = write_addr & 0x00ff;  
1512 - req[req_length++] = write_nb >> 8;  
1513 - req[req_length++] = write_nb & 0x00ff;  
1514 - byte_count = write_nb * 2;  
1515 - req[req_length++] = byte_count;  
1516 -  
1517 - for (i = 0; i < write_nb; i++) {  
1518 - req[req_length++] = src[i] >> 8;  
1519 - req[req_length++] = src[i] & 0x00FF;  
1520 - }  
1521 -  
1522 - rc = send_msg(ctx, req, req_length);  
1523 - if (rc > 0) {  
1524 - int offset;  
1525 -  
1526 - rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION);  
1527 - if (rc == -1)  
1528 - return -1;  
1529 -  
1530 - rc = check_confirmation(ctx, req, rsp, rc);  
1531 - if (rc == -1)  
1532 - return -1;  
1533 -  
1534 - offset = ctx->backend->header_length;  
1535 - for (i = 0; i < rc; i++) {  
1536 - /* shift reg hi_byte to temp OR with lo_byte */  
1537 - dest[i] = (rsp[offset + 2 + (i << 1)] << 8) |  
1538 - rsp[offset + 3 + (i << 1)];  
1539 - }  
1540 - }  
1541 -  
1542 - return rc;  
1543 -}  
1544 -  
1545 -/* Send a request to get the slave ID of the device (only available in serial  
1546 - communication). */  
1547 -int modbus_report_slave_id(modbus_t *ctx, int max_dest, uint8_t *dest)  
1548 -{  
1549 - int rc;  
1550 - int req_length;  
1551 - uint8_t req[_MIN_REQ_LENGTH];  
1552 -  
1553 - if (ctx == NULL || max_dest <= 0) {  
1554 - errno = EINVAL;  
1555 - return -1;  
1556 - }  
1557 -  
1558 - req_length = ctx->backend->build_request_basis(ctx, MODBUS_FC_REPORT_SLAVE_ID,  
1559 - 0, 0, req);  
1560 -  
1561 - /* HACKISH, addr and count are not used */  
1562 - req_length -= 4;  
1563 -  
1564 - rc = send_msg(ctx, req, req_length);  
1565 - if (rc > 0) {  
1566 - int i;  
1567 - int offset;  
1568 - uint8_t rsp[MAX_MESSAGE_LENGTH];  
1569 -  
1570 - rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION);  
1571 - if (rc == -1)  
1572 - return -1;  
1573 -  
1574 - rc = check_confirmation(ctx, req, rsp, rc);  
1575 - if (rc == -1)  
1576 - return -1;  
1577 -  
1578 - offset = ctx->backend->header_length + 2;  
1579 -  
1580 - /* Byte count, slave id, run indicator status and  
1581 - additional data. Truncate copy to max_dest. */  
1582 - for (i=0; i < rc && i < max_dest; i++) {  
1583 - dest[i] = rsp[offset + i];  
1584 - }  
1585 - }  
1586 -  
1587 - return rc;  
1588 -}  
1589 -  
1590 -void _modbus_init_common(modbus_t *ctx)  
1591 -{  
1592 - /* Slave and socket are initialized to -1 */  
1593 - ctx->slave = -1;  
1594 - ctx->s = -1;  
1595 -  
1596 - ctx->debug = FALSE;  
1597 - ctx->error_recovery = MODBUS_ERROR_RECOVERY_NONE;  
1598 -  
1599 - ctx->response_timeout.tv_sec = 0;  
1600 - ctx->response_timeout.tv_usec = _RESPONSE_TIMEOUT;  
1601 -  
1602 - ctx->byte_timeout.tv_sec = 0;  
1603 - ctx->byte_timeout.tv_usec = _BYTE_TIMEOUT;  
1604 -}  
1605 -  
1606 -/* Define the slave number */  
1607 -int modbus_set_slave(modbus_t *ctx, int slave)  
1608 -{  
1609 - if (ctx == NULL) {  
1610 - errno = EINVAL;  
1611 - return -1;  
1612 - }  
1613 -  
1614 - return ctx->backend->set_slave(ctx, slave);  
1615 -}  
1616 -  
1617 -int modbus_set_error_recovery(modbus_t *ctx,  
1618 - modbus_error_recovery_mode error_recovery)  
1619 -{  
1620 - if (ctx == NULL) {  
1621 - errno = EINVAL;  
1622 - return -1;  
1623 - }  
1624 -  
1625 - /* The type of modbus_error_recovery_mode is unsigned enum */  
1626 - ctx->error_recovery = (uint8_t) error_recovery;  
1627 - return 0;  
1628 -}  
1629 -  
1630 -int modbus_set_socket(modbus_t *ctx, int s)  
1631 -{  
1632 - if (ctx == NULL) {  
1633 - errno = EINVAL;  
1634 - return -1;  
1635 - }  
1636 -  
1637 - ctx->s = s;  
1638 - return 0;  
1639 -}  
1640 -  
1641 -int modbus_get_socket(modbus_t *ctx)  
1642 -{  
1643 - if (ctx == NULL) {  
1644 - errno = EINVAL;  
1645 - return -1;  
1646 - }  
1647 -  
1648 - return ctx->s;  
1649 -}  
1650 -  
1651 -/* Get the timeout interval used to wait for a response */  
1652 -int modbus_get_response_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec)  
1653 -{  
1654 - if (ctx == NULL) {  
1655 - errno = EINVAL;  
1656 - return -1;  
1657 - }  
1658 -  
1659 - *to_sec = ctx->response_timeout.tv_sec;  
1660 - *to_usec = ctx->response_timeout.tv_usec;  
1661 - return 0;  
1662 -}  
1663 -  
1664 -int modbus_set_response_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec)  
1665 -{  
1666 - if (ctx == NULL ||  
1667 - (to_sec == 0 && to_usec == 0) || to_usec > 999999) {  
1668 - errno = EINVAL;  
1669 - return -1;  
1670 - }  
1671 -  
1672 - ctx->response_timeout.tv_sec = to_sec;  
1673 - ctx->response_timeout.tv_usec = to_usec;  
1674 - return 0;  
1675 -}  
1676 -  
1677 -/* Get the timeout interval between two consecutive bytes of a message */  
1678 -int modbus_get_byte_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec)  
1679 -{  
1680 - if (ctx == NULL) {  
1681 - errno = EINVAL;  
1682 - return -1;  
1683 - }  
1684 -  
1685 - *to_sec = ctx->byte_timeout.tv_sec;  
1686 - *to_usec = ctx->byte_timeout.tv_usec;  
1687 - return 0;  
1688 -}  
1689 -  
1690 -int modbus_set_byte_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec)  
1691 -{  
1692 - /* Byte timeout can be disabled when both values are zero */  
1693 - if (ctx == NULL || to_usec > 999999) {  
1694 - errno = EINVAL;  
1695 - return -1;  
1696 - }  
1697 -  
1698 - ctx->byte_timeout.tv_sec = to_sec;  
1699 - ctx->byte_timeout.tv_usec = to_usec;  
1700 - return 0;  
1701 -}  
1702 -  
1703 -int modbus_get_header_length(modbus_t *ctx)  
1704 -{  
1705 - if (ctx == NULL) {  
1706 - errno = EINVAL;  
1707 - return -1;  
1708 - }  
1709 -  
1710 - return ctx->backend->header_length;  
1711 -}  
1712 -  
1713 -int modbus_connect(modbus_t *ctx)  
1714 -{  
1715 - if (ctx == NULL) {  
1716 - errno = EINVAL;  
1717 - return -1;  
1718 - }  
1719 -  
1720 - return ctx->backend->connect(ctx);  
1721 -}  
1722 -  
1723 -void modbus_close(modbus_t *ctx)  
1724 -{  
1725 - if (ctx == NULL)  
1726 - return;  
1727 -  
1728 - ctx->backend->close(ctx);  
1729 -}  
1730 -  
1731 -void modbus_free(modbus_t *ctx)  
1732 -{  
1733 - if (ctx == NULL)  
1734 - return;  
1735 -  
1736 - ctx->backend->free(ctx);  
1737 -}  
1738 -  
1739 -int modbus_set_debug(modbus_t *ctx, int flag)  
1740 -{  
1741 - if (ctx == NULL) {  
1742 - errno = EINVAL;  
1743 - return -1;  
1744 - }  
1745 -  
1746 - ctx->debug = flag;  
1747 - return 0;  
1748 -}  
1749 -  
1750 -/* Allocates 4 arrays to store bits, input bits, registers and inputs  
1751 - registers. The pointers are stored in modbus_mapping structure.  
1752 -  
1753 - The modbus_mapping_new_ranges() function shall return the new allocated  
1754 - structure if successful. Otherwise it shall return NULL and set errno to  
1755 - ENOMEM. */  
1756 -modbus_mapping_t* modbus_mapping_new_start_address(  
1757 - unsigned int start_bits, unsigned int nb_bits,  
1758 - unsigned int start_input_bits, unsigned int nb_input_bits,  
1759 - unsigned int start_registers, unsigned int nb_registers,  
1760 - unsigned int start_input_registers, unsigned int nb_input_registers)  
1761 -{  
1762 - modbus_mapping_t *mb_mapping;  
1763 -  
1764 - mb_mapping = (modbus_mapping_t *)malloc(sizeof(modbus_mapping_t));  
1765 - if (mb_mapping == NULL) {  
1766 - return NULL;  
1767 - }  
1768 -  
1769 - /* 0X */  
1770 - mb_mapping->nb_bits = nb_bits;  
1771 - mb_mapping->start_bits = start_bits;  
1772 - if (nb_bits == 0) {  
1773 - mb_mapping->tab_bits = NULL;  
1774 - } else {  
1775 - /* Negative number raises a POSIX error */  
1776 - mb_mapping->tab_bits =  
1777 - (uint8_t *) malloc(nb_bits * sizeof(uint8_t));  
1778 - if (mb_mapping->tab_bits == NULL) {  
1779 - free(mb_mapping);  
1780 - return NULL;  
1781 - }  
1782 - memset(mb_mapping->tab_bits, 0, nb_bits * sizeof(uint8_t));  
1783 - }  
1784 -  
1785 - /* 1X */  
1786 - mb_mapping->nb_input_bits = nb_input_bits;  
1787 - mb_mapping->start_input_bits = start_input_bits;  
1788 - if (nb_input_bits == 0) {  
1789 - mb_mapping->tab_input_bits = NULL;  
1790 - } else {  
1791 - mb_mapping->tab_input_bits =  
1792 - (uint8_t *) malloc(nb_input_bits * sizeof(uint8_t));  
1793 - if (mb_mapping->tab_input_bits == NULL) {  
1794 - free(mb_mapping->tab_bits);  
1795 - free(mb_mapping);  
1796 - return NULL;  
1797 - }  
1798 - memset(mb_mapping->tab_input_bits, 0, nb_input_bits * sizeof(uint8_t));  
1799 - }  
1800 -  
1801 - /* 4X */  
1802 - mb_mapping->nb_registers = nb_registers;  
1803 - mb_mapping->start_registers = start_registers;  
1804 - if (nb_registers == 0) {  
1805 - mb_mapping->tab_registers = NULL;  
1806 - } else {  
1807 - mb_mapping->tab_registers =  
1808 - (uint16_t *) malloc(nb_registers * sizeof(uint16_t));  
1809 - if (mb_mapping->tab_registers == NULL) {  
1810 - free(mb_mapping->tab_input_bits);  
1811 - free(mb_mapping->tab_bits);  
1812 - free(mb_mapping);  
1813 - return NULL;  
1814 - }  
1815 - memset(mb_mapping->tab_registers, 0, nb_registers * sizeof(uint16_t));  
1816 - }  
1817 -  
1818 - /* 3X */  
1819 - mb_mapping->nb_input_registers = nb_input_registers;  
1820 - mb_mapping->start_input_registers = start_input_registers;  
1821 - if (nb_input_registers == 0) {  
1822 - mb_mapping->tab_input_registers = NULL;  
1823 - } else {  
1824 - mb_mapping->tab_input_registers =  
1825 - (uint16_t *) malloc(nb_input_registers * sizeof(uint16_t));  
1826 - if (mb_mapping->tab_input_registers == NULL) {  
1827 - free(mb_mapping->tab_registers);  
1828 - free(mb_mapping->tab_input_bits);  
1829 - free(mb_mapping->tab_bits);  
1830 - free(mb_mapping);  
1831 - return NULL;  
1832 - }  
1833 - memset(mb_mapping->tab_input_registers, 0,  
1834 - nb_input_registers * sizeof(uint16_t));  
1835 - }  
1836 -  
1837 - return mb_mapping;  
1838 -}  
1839 -  
1840 -modbus_mapping_t* modbus_mapping_new(int nb_bits, int nb_input_bits,  
1841 - int nb_registers, int nb_input_registers)  
1842 -{  
1843 - return modbus_mapping_new_start_address(  
1844 - 0, nb_bits, 0, nb_input_bits, 0, nb_registers, 0, nb_input_registers);  
1845 -}  
1846 -  
1847 -/* Frees the 4 arrays */  
1848 -void modbus_mapping_free(modbus_mapping_t *mb_mapping)  
1849 -{  
1850 - if (mb_mapping == NULL) {  
1851 - return;  
1852 - }  
1853 -  
1854 - free(mb_mapping->tab_input_registers);  
1855 - free(mb_mapping->tab_registers);  
1856 - free(mb_mapping->tab_input_bits);  
1857 - free(mb_mapping->tab_bits);  
1858 - free(mb_mapping);  
1859 -}  
1860 -  
1861 -#ifndef HAVE_STRLCPY  
1862 -/*  
1863 - * Function strlcpy was originally developed by  
1864 - * Todd C. Miller <Todd.Miller@courtesan.com> to simplify writing secure code.  
1865 - * See ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/strlcpy.3  
1866 - * for more information.  
1867 - *  
1868 - * Thank you Ulrich Drepper... not!  
1869 - *  
1870 - * Copy src to string dest of size dest_size. At most dest_size-1 characters  
1871 - * will be copied. Always NUL terminates (unless dest_size == 0). Returns  
1872 - * strlen(src); if retval >= dest_size, truncation occurred.  
1873 - */  
1874 -size_t strlcpy(char *dest, const char *src, size_t dest_size)  
1875 -{  
1876 - register char *d = dest;  
1877 - register const char *s = src;  
1878 - register size_t n = dest_size;  
1879 -  
1880 - /* Copy as many bytes as will fit */  
1881 - if (n != 0 && --n != 0) {  
1882 - do {  
1883 - if ((*d++ = *s++) == 0)  
1884 - break;  
1885 - } while (--n != 0);  
1886 - }  
1887 -  
1888 - /* Not enough room in dest, add NUL and traverse rest of src */  
1889 - if (n == 0) {  
1890 - if (dest_size != 0)  
1891 - *d = '\0'; /* NUL-terminate dest */  
1892 - while (*s++)  
1893 - ;  
1894 - }  
1895 -  
1896 - return (s - src - 1); /* count does not include NUL */  
1897 -}  
1898 -#endif  
stack/modbus.h deleted
1 -  
2 -#pragma once  
3 -  
4 -/* Add this for macros that defined unix flavor */  
5 -#if (defined(__unix__) || defined(unix)) && !defined(USG)  
6 -#include <sys/param.h>  
7 -#endif  
8 -  
9 -#include <stdint.h>  
10 -  
11 -#define MODBUS_API  
12 -  
13 -#define MODBUS_VERSION_STRING "1.0.0"  
14 -  
15 -#ifdef __cplusplus  
16 -#define MODBUS_BEGIN_DECLS extern "C" {  
17 -#define MODBUS_END_DECLS }  
18 -#else  
19 -# define MODBUS_BEGIN_DECLS  
20 -# define MODBUS_END_DECLS  
21 -#endif  
22 -  
23 -MODBUS_BEGIN_DECLS  
24 -  
25 -#ifndef FALSE  
26 -#define FALSE 0  
27 -#endif  
28 -  
29 -#ifndef TRUE  
30 -#define TRUE 1  
31 -#endif  
32 -  
33 -#ifndef OFF  
34 -#define OFF 0  
35 -#endif  
36 -  
37 -#ifndef ON  
38 -#define ON 1  
39 -#endif  
40 -  
41 -/* Modbus function codes */  
42 -#define MODBUS_FC_READ_COILS 0x01  
43 -#define MODBUS_FC_READ_DISCRETE_INPUTS 0x02  
44 -#define MODBUS_FC_READ_HOLDING_REGISTERS 0x03  
45 -#define MODBUS_FC_READ_INPUT_REGISTERS 0x04  
46 -#define MODBUS_FC_WRITE_SINGLE_COIL 0x05  
47 -#define MODBUS_FC_WRITE_SINGLE_REGISTER 0x06  
48 -#define MODBUS_FC_READ_EXCEPTION_STATUS 0x07  
49 -#define MODBUS_FC_WRITE_MULTIPLE_COILS 0x0F  
50 -#define MODBUS_FC_WRITE_MULTIPLE_REGISTERS 0x10  
51 -#define MODBUS_FC_REPORT_SLAVE_ID 0x11  
52 -#define MODBUS_FC_MASK_WRITE_REGISTER 0x16  
53 -#define MODBUS_FC_WRITE_AND_READ_REGISTERS 0x17  
54 -  
55 -#define MODBUS_BROADCAST_ADDRESS 0  
56 -  
57 -/* Modbus_Application_Protocol_V1_1b.pdf (chapter 6 section 1 page 12)  
58 - * Quantity of Coils to read (2 bytes): 1 to 2000 (0x7D0)  
59 - * (chapter 6 section 11 page 29)  
60 - * Quantity of Coils to write (2 bytes): 1 to 1968 (0x7B0)  
61 - */  
62 -#define MODBUS_MAX_READ_BITS 2000  
63 -#define MODBUS_MAX_WRITE_BITS 1968  
64 -  
65 -/* Modbus_Application_Protocol_V1_1b.pdf (chapter 6 section 3 page 15)  
66 - * Quantity of Registers to read (2 bytes): 1 to 125 (0x7D)  
67 - * (chapter 6 section 12 page 31)  
68 - * Quantity of Registers to write (2 bytes) 1 to 123 (0x7B)  
69 - * (chapter 6 section 17 page 38)  
70 - * Quantity of Registers to write in R/W registers (2 bytes) 1 to 121 (0x79)  
71 - */  
72 -#define MODBUS_MAX_READ_REGISTERS 125  
73 -#define MODBUS_MAX_WRITE_REGISTERS 123  
74 -#define MODBUS_MAX_WR_WRITE_REGISTERS 121  
75 -#define MODBUS_MAX_WR_READ_REGISTERS 125  
76 -  
77 -/* The size of the MODBUS PDU is limited by the size constraint inherited from  
78 - * the first MODBUS implementation on Serial Line network (max. RS485 ADU = 256  
79 - * bytes). Therefore, MODBUS PDU for serial line communication = 256 - Server  
80 - * address (1 byte) - CRC (2 bytes) = 253 bytes.  
81 - */  
82 -#define MODBUS_MAX_PDU_LENGTH 253  
83 -  
84 -/* Consequently:  
85 - * - RTU MODBUS ADU = 253 bytes + Server address (1 byte) + CRC (2 bytes) = 256  
86 - * bytes.  
87 - * - TCP MODBUS ADU = 253 bytes + MBAP (7 bytes) = 260 bytes.  
88 - * so the maximum of both backend in 260 bytes. This size can used to allocate  
89 - * an array of bytes to store responses and it will be compatible with the two  
90 - * backends.  
91 - */  
92 -#define MODBUS_MAX_ADU_LENGTH 260  
93 -  
94 -/* Random number to avoid errno conflicts */  
95 -#define MODBUS_ENOBASE 112345678  
96 -  
97 -/* Protocol exceptions */  
98 -enum {  
99 - MODBUS_EXCEPTION_ILLEGAL_FUNCTION = 0x01,  
100 - MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS,  
101 - MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,  
102 - MODBUS_EXCEPTION_SLAVE_OR_SERVER_FAILURE,  
103 - MODBUS_EXCEPTION_ACKNOWLEDGE,  
104 - MODBUS_EXCEPTION_SLAVE_OR_SERVER_BUSY,  
105 - MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE,  
106 - MODBUS_EXCEPTION_MEMORY_PARITY,  
107 - MODBUS_EXCEPTION_NOT_DEFINED,  
108 - MODBUS_EXCEPTION_GATEWAY_PATH,  
109 - MODBUS_EXCEPTION_GATEWAY_TARGET,  
110 - MODBUS_EXCEPTION_MAX  
111 -};  
112 -  
113 -#define EMBXILFUN (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_FUNCTION)  
114 -#define EMBXILADD (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS)  
115 -#define EMBXILVAL (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE)  
116 -#define EMBXSFAIL (MODBUS_ENOBASE + MODBUS_EXCEPTION_SLAVE_OR_SERVER_FAILURE)  
117 -#define EMBXACK (MODBUS_ENOBASE + MODBUS_EXCEPTION_ACKNOWLEDGE)  
118 -#define EMBXSBUSY (MODBUS_ENOBASE + MODBUS_EXCEPTION_SLAVE_OR_SERVER_BUSY)  
119 -#define EMBXNACK (MODBUS_ENOBASE + MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE)  
120 -#define EMBXMEMPAR (MODBUS_ENOBASE + MODBUS_EXCEPTION_MEMORY_PARITY)  
121 -#define EMBXGPATH (MODBUS_ENOBASE + MODBUS_EXCEPTION_GATEWAY_PATH)  
122 -#define EMBXGTAR (MODBUS_ENOBASE + MODBUS_EXCEPTION_GATEWAY_TARGET)  
123 -  
124 -/* Native libmodbus error codes */  
125 -#define EMBBADCRC (EMBXGTAR + 1)  
126 -#define EMBBADDATA (EMBXGTAR + 2)  
127 -#define EMBBADEXC (EMBXGTAR + 3)  
128 -#define EMBUNKEXC (EMBXGTAR + 4)  
129 -#define EMBMDATA (EMBXGTAR + 5)  
130 -#define EMBBADSLAVE (EMBXGTAR + 6)  
131 -  
132 -typedef struct _modbus modbus_t;  
133 -  
134 -typedef struct {  
135 - int nb_bits;  
136 - int start_bits;  
137 - int nb_input_bits;  
138 - int start_input_bits;  
139 - int nb_input_registers;  
140 - int start_input_registers;  
141 - int nb_registers;  
142 - int start_registers;  
143 - uint8_t *tab_bits;  
144 - uint8_t *tab_input_bits;  
145 - uint16_t *tab_input_registers;  
146 - uint16_t *tab_registers;  
147 -} modbus_mapping_t;  
148 -  
149 -typedef enum  
150 -{  
151 - MODBUS_ERROR_RECOVERY_NONE = 0,  
152 - MODBUS_ERROR_RECOVERY_LINK = (1<<1),  
153 - MODBUS_ERROR_RECOVERY_PROTOCOL = (1<<2)  
154 -} modbus_error_recovery_mode;  
155 -  
156 -MODBUS_API int modbus_set_slave(modbus_t* ctx, int slave);  
157 -MODBUS_API int modbus_set_error_recovery(modbus_t *ctx, modbus_error_recovery_mode error_recovery);  
158 -MODBUS_API int modbus_set_socket(modbus_t *ctx, int s);  
159 -MODBUS_API int modbus_get_socket(modbus_t *ctx);  
160 -  
161 -MODBUS_API int modbus_get_response_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec);  
162 -MODBUS_API int modbus_set_response_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec);  
163 -  
164 -MODBUS_API int modbus_get_byte_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec);  
165 -MODBUS_API int modbus_set_byte_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec);  
166 -  
167 -MODBUS_API int modbus_get_header_length(modbus_t *ctx);  
168 -  
169 -MODBUS_API int modbus_connect(modbus_t *ctx);  
170 -MODBUS_API void modbus_close(modbus_t *ctx);  
171 -  
172 -MODBUS_API void modbus_free(modbus_t *ctx);  
173 -  
174 -MODBUS_API int modbus_flush(modbus_t *ctx);  
175 -MODBUS_API int modbus_set_debug(modbus_t *ctx, int flag);  
176 -  
177 -MODBUS_API const char *modbus_strerror(int errnum);  
178 -  
179 -MODBUS_API int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest);  
180 -MODBUS_API int modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest);  
181 -MODBUS_API int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest);  
182 -MODBUS_API int modbus_read_input_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest);  
183 -MODBUS_API int modbus_write_bit(modbus_t *ctx, int coil_addr, int status);  
184 -MODBUS_API int modbus_write_register(modbus_t *ctx, int reg_addr, int value);  
185 -MODBUS_API int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *data);  
186 -MODBUS_API int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *data);  
187 -MODBUS_API int modbus_mask_write_register(modbus_t *ctx, int addr, uint16_t and_mask, uint16_t or_mask);  
188 -MODBUS_API int modbus_write_and_read_registers(modbus_t *ctx, int write_addr, int write_nb,const uint16_t *src, int read_addr, int read_nb,uint16_t *dest);  
189 -MODBUS_API int modbus_report_slave_id(modbus_t *ctx, int max_dest, uint8_t *dest);  
190 -  
191 -MODBUS_API modbus_mapping_t* modbus_mapping_new_start_address  
192 -(  
193 - unsigned int start_bits, unsigned int nb_bits,  
194 - unsigned int start_input_bits, unsigned int nb_input_bits,  
195 - unsigned int start_registers, unsigned int nb_registers,  
196 - unsigned int start_input_registers, unsigned int nb_input_registers  
197 -);  
198 -  
199 -MODBUS_API modbus_mapping_t* modbus_mapping_new(int nb_bits, int nb_input_bits, int nb_registers, int nb_input_registers);  
200 -MODBUS_API void modbus_mapping_free(modbus_mapping_t *mb_mapping);  
201 -  
202 -MODBUS_API int modbus_send_raw_request(modbus_t *ctx, uint8_t *raw_req, int raw_req_length);  
203 -  
204 -MODBUS_API int modbus_receive(modbus_t *ctx, uint8_t *req);  
205 -  
206 -MODBUS_API int modbus_receive_confirmation(modbus_t *ctx, uint8_t *rsp);  
207 -  
208 -MODBUS_API int modbus_reply(modbus_t *ctx, const uint8_t *req, int req_length, modbus_mapping_t *mb_mapping);  
209 -MODBUS_API int modbus_reply_exception(modbus_t *ctx, const uint8_t *req, unsigned int exception_code);  
210 -  
211 -/**  
212 - * UTILS FUNCTIONS  
213 - **/  
214 -  
215 -#define MODBUS_GET_HIGH_BYTE(data) (((data) >> 8) & 0xFF)  
216 -#define MODBUS_GET_LOW_BYTE(data) ((data) & 0xFF)  
217 -#define MODBUS_GET_INT64_FROM_INT16(tab_int16, index) \  
218 - (((int64_t)tab_int16[(index) ] << 48) + \  
219 - ((int64_t)tab_int16[(index) + 1] << 32) + \  
220 - ((int64_t)tab_int16[(index) + 2] << 16) + \  
221 - (int64_t)tab_int16[(index) + 3])  
222 -#define MODBUS_GET_INT32_FROM_INT16(tab_int16, index) ((tab_int16[(index)] << 16) + tab_int16[(index) + 1])  
223 -#define MODBUS_GET_INT16_FROM_INT8(tab_int8, index) ((tab_int8[(index)] << 8) + tab_int8[(index) + 1])  
224 -#define MODBUS_SET_INT16_TO_INT8(tab_int8, index, value) \  
225 - do { \  
226 - tab_int8[(index)] = (value) >> 8; \  
227 - tab_int8[(index) + 1] = (value) & 0xFF; \  
228 - } while (0)  
229 -#define MODBUS_SET_INT32_TO_INT16(tab_int16, index, value) \  
230 - do { \  
231 - tab_int16[(index) ] = (value) >> 16; \  
232 - tab_int16[(index) + 1] = (value); \  
233 - } while (0)  
234 -#define MODBUS_SET_INT64_TO_INT16(tab_int16, index, value) \  
235 - do { \  
236 - tab_int16[(index) ] = (value) >> 48; \  
237 - tab_int16[(index) + 1] = (value) >> 32; \  
238 - tab_int16[(index) + 2] = (value) >> 16; \  
239 - tab_int16[(index) + 3] = (value); \  
240 - } while (0)  
241 -  
242 -MODBUS_API void modbus_set_bits_from_byte(uint8_t *dest, int idx, const uint8_t value);  
243 -MODBUS_API void modbus_set_bits_from_bytes(uint8_t *dest, int idx, unsigned int nb_bits,  
244 - const uint8_t *tab_byte);  
245 -MODBUS_API uint8_t modbus_get_byte_from_bits(const uint8_t *src, int idx, unsigned int nb_bits);  
246 -MODBUS_API float modbus_get_float(const uint16_t *src);  
247 -MODBUS_API float modbus_get_float_abcd(const uint16_t *src);  
248 -MODBUS_API float modbus_get_float_dcba(const uint16_t *src);  
249 -MODBUS_API float modbus_get_float_badc(const uint16_t *src);  
250 -MODBUS_API float modbus_get_float_cdab(const uint16_t *src);  
251 -  
252 -MODBUS_API void modbus_set_float(float f, uint16_t *dest);  
253 -MODBUS_API void modbus_set_float_abcd(float f, uint16_t *dest);  
254 -MODBUS_API void modbus_set_float_dcba(float f, uint16_t *dest);  
255 -MODBUS_API void modbus_set_float_badc(float f, uint16_t *dest);  
256 -MODBUS_API void modbus_set_float_cdab(float f, uint16_t *dest);  
257 -  
258 -#include "modbus-tcp.h"  
259 -#include "modbus-rtu.h"  
260 -  
261 -MODBUS_END_DECLS  
262 -