You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

163 lines
3.7 KiB

/////////////////////////////////////////////////////////////////////////////////
//
// modbus.cc is part of TestModbus-Client.
//
/////////////////////////////////////////////////////////////////////////////////
#include "tcp.h"
#include "modbus.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
#else
#include <unistd.h> /* close() */
#endif
#define PACK_INT8(__dstptr, __srci8) \
memcpy(__dstptr, &__srci8, 1); \
__dstptr += 1
#define UNPACK_INT8(__dsti8, __srcptr) \
memcpy(&__dsti8, __srcptr, 1); \
__srcptr += 1
#define PACK_INT16(__tmpi16, __dstptr, __srci16) \
__tmpi16 = htons((uint16_t)__srci16); \
memcpy(__dstptr, &__tmpi16, 2); \
__dstptr += 2
#define UNPACK_INT16(__tmpi16, __dsti16, __srcptr) \
memcpy(&__tmpi16, __srcptr, 2); \
__srcptr += 2; \
__dsti16 = ntohs((uint16_t)__tmpi16)
/*
* packs the request header into the buffer data and returns the lenght of the header
* returns NULL on error or points to end of data
*/
char * modbustcp_pkt_headerrq (char *destbuffer, int bufsize, modbustcp_rq_header *srcmbh) {
uint16_t tmp;
// destination memory valid
if (destbuffer == NULL) {
errno = EFAULT;
return NULL;
}
if (bufsize < 12) {
errno = EOVERFLOW;
return NULL;
}
char *pos = destbuffer;
PACK_INT16(tmp, pos, srcmbh->transid);
PACK_INT16(tmp, pos, srcmbh->protid);
PACK_INT16(tmp, pos, srcmbh->length);
PACK_INT8(pos, srcmbh->uid);
PACK_INT8(pos, srcmbh->fc);
PACK_INT16(tmp, pos, srcmbh->offset);
PACK_INT16(tmp, pos, srcmbh->number);
return pos;
}
/*
* unpacks the buffer into the header request
* returns NULL on error or points to end of data
*/
char * modbustcp_unpkt_headerrq (modbustcp_rq_header *destmbh, char *srcbuffer, int bufsize) {
uint16_t tmp;
printf ("%s:%d %s bufsize:%d\n", __FILE__, __LINE__, __FUNCTION__, bufsize);
// source memory valid
if (srcbuffer == NULL) {
errno = EFAULT;
return NULL;
}
if (bufsize < 12) {
errno = EOVERFLOW;
return NULL;
}
char *src = srcbuffer;
UNPACK_INT16(tmp, destmbh->transid, src);
UNPACK_INT16(tmp, destmbh->protid, src);
UNPACK_INT16(tmp, destmbh->length, src);
UNPACK_INT8(destmbh->uid, src);
UNPACK_INT8(destmbh->fc, src);
UNPACK_INT16(tmp, destmbh->offset, src);
UNPACK_INT16(tmp, destmbh->number, src);
return src;
}
/*
* packs the resonse header into the buffer data and returns the lenght of the header
* returns NULL on error or points to end of data
*/
char * modbustcp_pkt_headerres (char *destbuffer, int bufsize, modbustcp_res_header *srcmbh) {
uint16_t tmp;
// destination memory valid
if (destbuffer == NULL) {
errno = EFAULT;
return NULL;
}
if (bufsize < 9) {
errno = EOVERFLOW;
return NULL;
}
char *pos = destbuffer;
PACK_INT16(tmp, pos, srcmbh->transid);
PACK_INT16(tmp, pos, srcmbh->protid);
PACK_INT16(tmp, pos, srcmbh->length);
PACK_INT8(pos, srcmbh->uid);
PACK_INT8(pos, srcmbh->fc);
PACK_INT8(pos, srcmbh->number);
return pos;
}
/*
* unpacks the buffer into the header modbustcp response
* returns NULL on error or points to end of data
*/
char * modbustcp_unpkt_headerres (modbustcp_res_header *destmbh, char *srcbuffer, int bufsize) {
uint16_t tmp;
printf ("%s:%d %s bufsize:%d\n", __FILE__, __LINE__, __FUNCTION__, bufsize);
// source memory valid
if (srcbuffer == NULL) {
errno = EFAULT;
return NULL;
}
if (bufsize < 10) {
errno = EOVERFLOW;
return NULL;
}
char *src = srcbuffer;
UNPACK_INT16(tmp, destmbh->transid, src);
UNPACK_INT16(tmp, destmbh->protid, src);
UNPACK_INT16(tmp, destmbh->length, src);
UNPACK_INT8(destmbh->uid, src);
UNPACK_INT8(destmbh->fc, src);
UNPACK_INT8(destmbh->number, src);
return src;
}