///////////////////////////////////////////////////////////////////////////////// // // modbus.cc is part of TestModbus-Client. // ///////////////////////////////////////////////////////////////////////////////// #include "tcp.h" #include "modbus.h" #include #include #include #include #if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__) #else #include /* 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; }