Skip to content

Commit 3622de0

Browse files
committed
Import libmodbus v3.1.4
1 parent 50a7dad commit 3622de0

11 files changed

+4937
-0
lines changed

src/libmodbus/modbus-data.c

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
/*
2+
* Copyright © 2010-2014 Stéphane Raimbault <stephane.raimbault@gmail.com>
3+
*
4+
* SPDX-License-Identifier: LGPL-2.1+
5+
*/
6+
7+
#include <stdlib.h>
8+
9+
#ifndef _MSC_VER
10+
# include <stdint.h>
11+
#else
12+
# include "stdint.h"
13+
#endif
14+
15+
#include <string.h>
16+
#include <assert.h>
17+
18+
#if defined(_WIN32)
19+
# include <winsock2.h>
20+
#else
21+
# include <arpa/inet.h>
22+
#endif
23+
24+
#include <config.h>
25+
26+
#include "modbus.h"
27+
28+
#if defined(HAVE_BYTESWAP_H)
29+
# include <byteswap.h>
30+
#endif
31+
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__)
40+
# define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__ * 10)
41+
# if GCC_VERSION >= 430
42+
// Since GCC >= 4.30, GCC provides __builtin_bswapXX() alternatives so we switch to them
43+
# undef bswap_32
44+
# define bswap_32 __builtin_bswap32
45+
# endif
46+
#endif
47+
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)
54+
# warning "Fallback on C functions for bswap_16"
55+
static inline uint16_t bswap_16(uint16_t x)
56+
{
57+
return (x >> 8) | (x << 8);
58+
}
59+
#endif
60+
61+
#if !defined(bswap_32)
62+
# warning "Fallback on C functions for bswap_32"
63+
static inline uint32_t bswap_32(uint32_t x)
64+
{
65+
return (bswap_16(x & 0xffff) << 16) | (bswap_16(x >> 16));
66+
}
67+
#endif
68+
69+
/* Sets many bits from a single byte value (all 8 bits of the byte value are
70+
set) */
71+
void modbus_set_bits_from_byte(uint8_t *dest, int idx, const uint8_t value)
72+
{
73+
int i;
74+
75+
for (i=0; i < 8; i++) {
76+
dest[idx+i] = (value & (1 << i)) ? 1 : 0;
77+
}
78+
}
79+
80+
/* Sets many bits from a table of bytes (only the bits between idx and
81+
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)
84+
{
85+
unsigned int i;
86+
int shift = 0;
87+
88+
for (i = idx; i < idx + nb_bits; i++) {
89+
dest[i] = tab_byte[(i - idx) / 8] & (1 << shift) ? 1 : 0;
90+
/* gcc doesn't like: shift = (++shift) % 8; */
91+
shift++;
92+
shift %= 8;
93+
}
94+
}
95+
96+
/* Gets the byte value from many bits.
97+
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)
100+
{
101+
unsigned int i;
102+
uint8_t value = 0;
103+
104+
if (nb_bits > 8) {
105+
/* Assert is ignored if NDEBUG is set */
106+
assert(nb_bits < 8);
107+
nb_bits = 8;
108+
}
109+
110+
for (i=0; i < nb_bits; i++) {
111+
value |= (src[idx+i] << i);
112+
}
113+
114+
return value;
115+
}
116+
117+
/* Get a float from 4 bytes (Modbus) without any conversion (ABCD) */
118+
float modbus_get_float_abcd(const uint16_t *src)
119+
{
120+
float f;
121+
uint32_t i;
122+
123+
i = ntohl(((uint32_t)src[0] << 16) + src[1]);
124+
memcpy(&f, &i, sizeof(float));
125+
126+
return f;
127+
}
128+
129+
/* Get a float from 4 bytes (Modbus) in inversed format (DCBA) */
130+
float modbus_get_float_dcba(const uint16_t *src)
131+
{
132+
float f;
133+
uint32_t i;
134+
135+
i = ntohl(bswap_32((((uint32_t)src[0]) << 16) + src[1]));
136+
memcpy(&f, &i, sizeof(float));
137+
138+
return f;
139+
}
140+
141+
/* Get a float from 4 bytes (Modbus) with swapped bytes (BADC) */
142+
float modbus_get_float_badc(const uint16_t *src)
143+
{
144+
float f;
145+
uint32_t i;
146+
147+
i = ntohl((uint32_t)(bswap_16(src[0]) << 16) + bswap_16(src[1]));
148+
memcpy(&f, &i, sizeof(float));
149+
150+
return f;
151+
}
152+
153+
/* Get a float from 4 bytes (Modbus) with swapped words (CDAB) */
154+
float modbus_get_float_cdab(const uint16_t *src)
155+
{
156+
float f;
157+
uint32_t i;
158+
159+
i = ntohl((((uint32_t)src[1]) << 16) + src[0]);
160+
memcpy(&f, &i, sizeof(float));
161+
162+
return f;
163+
}
164+
165+
/* DEPRECATED - Get a float from 4 bytes in sort of Modbus format */
166+
float modbus_get_float(const uint16_t *src)
167+
{
168+
float f;
169+
uint32_t i;
170+
171+
i = (((uint32_t)src[1]) << 16) + src[0];
172+
memcpy(&f, &i, sizeof(float));
173+
174+
return f;
175+
}
176+
177+
/* Set a float to 4 bytes for Modbus w/o any conversion (ABCD) */
178+
void modbus_set_float_abcd(float f, uint16_t *dest)
179+
{
180+
uint32_t i;
181+
182+
memcpy(&i, &f, sizeof(uint32_t));
183+
i = htonl(i);
184+
dest[0] = (uint16_t)(i >> 16);
185+
dest[1] = (uint16_t)i;
186+
}
187+
188+
/* Set a float to 4 bytes for Modbus with byte and word swap conversion (DCBA) */
189+
void modbus_set_float_dcba(float f, uint16_t *dest)
190+
{
191+
uint32_t i;
192+
193+
memcpy(&i, &f, sizeof(uint32_t));
194+
i = bswap_32(htonl(i));
195+
dest[0] = (uint16_t)(i >> 16);
196+
dest[1] = (uint16_t)i;
197+
}
198+
199+
/* Set a float to 4 bytes for Modbus with byte swap conversion (BADC) */
200+
void modbus_set_float_badc(float f, uint16_t *dest)
201+
{
202+
uint32_t i;
203+
204+
memcpy(&i, &f, sizeof(uint32_t));
205+
i = htonl(i);
206+
dest[0] = (uint16_t)bswap_16(i >> 16);
207+
dest[1] = (uint16_t)bswap_16(i & 0xFFFF);
208+
}
209+
210+
/* Set a float to 4 bytes for Modbus with word swap conversion (CDAB) */
211+
void modbus_set_float_cdab(float f, uint16_t *dest)
212+
{
213+
uint32_t i;
214+
215+
memcpy(&i, &f, sizeof(uint32_t));
216+
i = htonl(i);
217+
dest[0] = (uint16_t)i;
218+
dest[1] = (uint16_t)(i >> 16);
219+
}
220+
221+
/* DEPRECATED - Set a float to 4 bytes in a sort of Modbus format! */
222+
void modbus_set_float(float f, uint16_t *dest)
223+
{
224+
uint32_t i;
225+
226+
memcpy(&i, &f, sizeof(uint32_t));
227+
dest[0] = (uint16_t)i;
228+
dest[1] = (uint16_t)(i >> 16);
229+
}

src/libmodbus/modbus-private.h

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/*
2+
* Copyright © 2010-2012 Stéphane Raimbault <stephane.raimbault@gmail.com>
3+
*
4+
* SPDX-License-Identifier: LGPL-2.1+
5+
*/
6+
7+
#ifndef MODBUS_PRIVATE_H
8+
#define MODBUS_PRIVATE_H
9+
10+
#ifndef _MSC_VER
11+
# include <stdint.h>
12+
# 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>
19+
#include <config.h>
20+
21+
#include "modbus.h"
22+
23+
MODBUS_BEGIN_DECLS
24+
25+
/* It's not really the minimal length (the real one is report slave ID
26+
* in RTU (4 bytes)) but it's a convenient size to use in RTU or TCP
27+
* communications to read many values or write a single one.
28+
* Maximum between :
29+
* - HEADER_LENGTH_TCP (7) + function (1) + address (2) + number (2)
30+
* - HEADER_LENGTH_RTU (1) + function (1) + address (2) + number (2) + CRC (2)
31+
*/
32+
#define _MIN_REQ_LENGTH 12
33+
34+
#define _REPORT_SLAVE_ID 180
35+
36+
#define _MODBUS_EXCEPTION_RSP_LENGTH 5
37+
38+
/* Timeouts in microsecond (0.5 s) */
39+
#define _RESPONSE_TIMEOUT 500000
40+
#define _BYTE_TIMEOUT 500000
41+
42+
typedef enum {
43+
_MODBUS_BACKEND_TYPE_RTU=0,
44+
_MODBUS_BACKEND_TYPE_TCP
45+
} modbus_backend_type_t;
46+
47+
/*
48+
* ---------- Request Indication ----------
49+
* | Client | ---------------------->| Server |
50+
* ---------- Confirmation Response ----------
51+
*/
52+
typedef enum {
53+
/* Request message on the server side */
54+
MSG_INDICATION,
55+
/* Request message on the client side */
56+
MSG_CONFIRMATION
57+
} msg_type_t;
58+
59+
/* This structure reduces the number of params in functions and so
60+
* optimizes the speed of execution (~ 37%). */
61+
typedef struct _sft {
62+
int slave;
63+
int function;
64+
int t_id;
65+
} sft_t;
66+
67+
typedef struct _modbus_backend {
68+
unsigned int backend_type;
69+
unsigned int header_length;
70+
unsigned int checksum_length;
71+
unsigned int max_adu_length;
72+
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);
75+
int (*build_response_basis) (sft_t *sft, uint8_t *rsp);
76+
int (*prepare_response_tid) (const uint8_t *req, int *req_length);
77+
int (*send_msg_pre) (uint8_t *req, int req_length);
78+
ssize_t (*send) (modbus_t *ctx, const uint8_t *req, int req_length);
79+
int (*receive) (modbus_t *ctx, uint8_t *req);
80+
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);
85+
int (*connect) (modbus_t *ctx);
86+
void (*close) (modbus_t *ctx);
87+
int (*flush) (modbus_t *ctx);
88+
int (*select) (modbus_t *ctx, fd_set *rset, struct timeval *tv, int msg_length);
89+
void (*free) (modbus_t *ctx);
90+
} modbus_backend_t;
91+
92+
struct _modbus {
93+
/* Slave address */
94+
int slave;
95+
/* Socket or file descriptor */
96+
int s;
97+
int debug;
98+
int error_recovery;
99+
struct timeval response_timeout;
100+
struct timeval byte_timeout;
101+
const modbus_backend_t *backend;
102+
void *backend_data;
103+
};
104+
105+
void _modbus_init_common(modbus_t *ctx);
106+
void _error_print(modbus_t *ctx, const char *context);
107+
int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type);
108+
109+
#ifndef HAVE_STRLCPY
110+
size_t strlcpy(char *dest, const char *src, size_t dest_size);
111+
#endif
112+
113+
MODBUS_END_DECLS
114+
115+
#endif /* MODBUS_PRIVATE_H */

0 commit comments

Comments
 (0)