Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ libmodbus_la_SOURCES = \
modbus-tcp.c \
modbus-tcp.h \
modbus-tcp-private.h \
modbus-version.h
modbus-version.h \
modbus-enc.c \
modbus-enc.h

libmodbus_la_LDFLAGS = -no-undefined \
-version-info $(LIBMODBUS_LT_VERSION_INFO)
Expand All @@ -35,7 +37,7 @@ endif

# Header files to install
libmodbusincludedir = $(includedir)/modbus
libmodbusinclude_HEADERS = modbus.h modbus-version.h modbus-rtu.h modbus-tcp.h
libmodbusinclude_HEADERS = modbus.h modbus-version.h modbus-rtu.h modbus-tcp.h modbus-enc.h

DISTCLEANFILES = modbus-version.h
EXTRA_DIST += modbus-version.h.in
Expand Down
265 changes: 265 additions & 0 deletions src/modbus-enc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
#include "modbus-enc.h"

#include "modbus.h"
#include "modbus-private.h"
#include "modbus-tcp.h"
#include "modbus-rtu.h"
#include "modbus-rtu-private.h"
#include "modbus-tcp-private.h"

#include <stdlib.h>
#include <string.h>

/* Table of CRC values for high-order byte */
static const uint8_t table_crc_hi[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
};

/* Table of CRC values for low-order byte */
static const uint8_t table_crc_lo[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
0x43, 0x83, 0x41, 0x81, 0x80, 0x40
};


static modbus_t* get_rtu_ctx(modbus_t* ctx)
{
return ((modbus_t**)(ctx->backend_data))[0];
}

static modbus_t* get_tcp_ctx(modbus_t* ctx)
{
return ((modbus_t**)(ctx->backend_data))[1];
}

static int _modbus_enc_set_slave(modbus_t *ctx, int slave)
{
modbus_t* ctx_rtu = get_rtu_ctx(ctx);

return ctx_rtu->backend->set_slave(ctx_rtu, slave);
}

static int _modbus_enc_build_request_basis(modbus_t *ctx, int function,
int addr, int nb,
uint8_t *req)
{
modbus_t* ctx_rtu = get_rtu_ctx(ctx);

return ctx_rtu->backend->build_request_basis(ctx_rtu, function, addr, nb, req);
}

static int _modbus_enc_build_response_basis(sft_t *sft, uint8_t *rsp)
{
/* In this case, the slave is certainly valid because a check is already
* done in _modbus_rtu_listen */
rsp[0] = sft->slave;
rsp[1] = sft->function;

return _MODBUS_RTU_PRESET_RSP_LENGTH;
}

static int _modbus_enc_prepare_response_tid(const uint8_t *req, int *req_length)
{
(*req_length) -= _MODBUS_RTU_CHECKSUM_LENGTH;
/* No TID */
return 0;
}

static uint16_t crc16(uint8_t *buffer, uint16_t buffer_length)
{
uint8_t crc_hi = 0xFF; /* high CRC byte initialized */
uint8_t crc_lo = 0xFF; /* low CRC byte initialized */
unsigned int i; /* will index into CRC lookup */

/* pass through message buffer */
while (buffer_length--) {
i = crc_hi ^ *buffer++; /* calculate the CRC */
crc_hi = crc_lo ^ table_crc_hi[i];
crc_lo = table_crc_lo[i];
}

return (crc_hi << 8 | crc_lo);
}

static int _modbus_enc_send_msg_pre(uint8_t *req, int req_length)
{
uint16_t crc = crc16(req, req_length);
req[req_length++] = crc >> 8;
req[req_length++] = crc & 0x00FF;

return req_length;
}

static int _modbus_enc_check_integrity(modbus_t *ctx, uint8_t *msg,
const int msg_length)
{
modbus_t* ctx_rtu = get_rtu_ctx(ctx);

return ctx_rtu->backend->check_integrity(ctx_rtu, msg, msg_length);
}

static int _modbus_enc_pre_check_confirmation(modbus_t *ctx, const uint8_t *req,
const uint8_t *rsp, int rsp_length)
{
modbus_t* ctx_rtu = get_rtu_ctx(ctx);

return ctx_rtu->backend->pre_check_confirmation(ctx_rtu, req, rsp, rsp_length);
}

static int _modbus_enc_connect(modbus_t *ctx)
{
int ret;
modbus_t* ctx_tcp = get_tcp_ctx(ctx);

ret = ctx_tcp->backend->connect(ctx_tcp);
ctx->s = ctx_tcp->s;
return ret;
}

static void _modbus_enc_close(modbus_t *ctx)
{
modbus_t* ctx_tcp = get_tcp_ctx(ctx);

return ctx_tcp->backend->close(ctx_tcp);
}

static int _modbus_enc_flush(modbus_t *ctx)
{
modbus_t* ctx_tcp = get_tcp_ctx(ctx);

return ctx_tcp->backend->flush(ctx_tcp);
}

static void _modbus_enc_free(modbus_t *ctx)
{
modbus_t* ctx_tcp = get_tcp_ctx(ctx);
modbus_t* ctx_rtu = get_rtu_ctx(ctx);

modbus_free(ctx_tcp);
modbus_free(ctx_rtu);

free(ctx->backend_data);
free(ctx);
}

static ssize_t _modbus_enc_send(modbus_t *ctx, const uint8_t *req, int req_length)
{
modbus_t* ctx_tcp = get_tcp_ctx(ctx);

return ctx_tcp->backend->send(ctx_tcp, req, req_length);
}

static int _modbus_enc_receive(modbus_t *ctx, uint8_t *req)
{
modbus_t* ctx_tcp = get_tcp_ctx(ctx);

return ctx_tcp->backend->receive(ctx_tcp, req);
}

static ssize_t _modbus_enc_recv(modbus_t *ctx, uint8_t *rsp, int rsp_length)
{
modbus_t* ctx_tcp = get_tcp_ctx(ctx);

return ctx_tcp->backend->recv(ctx_tcp, rsp, rsp_length);
}

static int _modbus_enc_select(modbus_t *ctx, fd_set *rset, struct timeval *tv, int length_to_read) {
modbus_t* ctx_tcp = get_tcp_ctx(ctx);

return ctx_tcp->backend->select(ctx_tcp, rset, tv, length_to_read);
}


extern const modbus_backend_t _modbus_rtu_backend;
extern const modbus_backend_t _modbus_tcp_backend;

modbus_backend_t _modbus_enc_backend = {
_MODBUS_BACKEND_TYPE_RTU,
_MODBUS_RTU_HEADER_LENGTH,
_MODBUS_RTU_CHECKSUM_LENGTH,
MODBUS_RTU_MAX_ADU_LENGTH,
_modbus_enc_set_slave,
_modbus_enc_build_request_basis,
_modbus_enc_build_response_basis,
_modbus_enc_prepare_response_tid,
_modbus_enc_send_msg_pre,
_modbus_enc_send,
_modbus_enc_receive,
_modbus_enc_recv,
_modbus_enc_check_integrity,
_modbus_enc_pre_check_confirmation,
_modbus_enc_connect,
_modbus_enc_close,
_modbus_enc_flush,
_modbus_enc_select,
_modbus_enc_free
};


modbus_t* modbus_new_enc(const char *ip_address, int port)
{
modbus_t* ctx;
modbus_t* ctx_rtu = modbus_new_rtu("/tmp", 115200, 'N', 8, 1);
modbus_t* ctx_tcp = modbus_new_tcp(ip_address, port);
modbus_t** data;

ctx = (modbus_t *)malloc(sizeof(modbus_t));
data = malloc(2*sizeof(modbus_t*));

data[0] = ctx_rtu;
data[1] = ctx_tcp;

ctx->backend = &_modbus_enc_backend;
ctx->backend_data = data;

return ctx;
}
12 changes: 12 additions & 0 deletions src/modbus-enc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#ifndef MODBUS_ENC_H
#define MODBUS_ENC_H

#include "modbus.h"

MODBUS_BEGIN_DECLS

MODBUS_API modbus_t* modbus_new_enc(const char *ip_address, int port);

MODBUS_END_DECLS

#endif /* MODBUS_ENC_H */
1 change: 1 addition & 0 deletions src/modbus.h
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ MODBUS_API void modbus_set_float_cdab(float f, uint16_t *dest);

#include "modbus-tcp.h"
#include "modbus-rtu.h"
#include "modbus-enc.h"

MODBUS_END_DECLS

Expand Down