Files
aqhomecontrol/aqhome/msg.c

248 lines
4.0 KiB
C

/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "aqhome/msg_p.h"
#include <gwenhywfar/misc.h>
#include <gwenhywfar/list.h>
#include <gwenhywfar/error.h>
#include <gwenhywfar/debug.h>
GWEN_LIST_FUNCTIONS(AQH_MSG, AQH_Msg)
static uint8_t _calcChecksum(const uint8_t *ptr, uint8_t len);
AQH_MSG *AQH_Msg_new()
{
AQH_MSG *msg;
GWEN_NEW_OBJECT(AQH_MSG, msg);
GWEN_LIST_INIT(AQH_MSG, msg);
return msg;
}
void AQH_Msg_free(AQH_MSG *msg)
{
if (msg) {
GWEN_LIST_FINI(AQH_MSG, msg);
GWEN_FREE_OBJECT(msg);
}
}
uint8_t *AQH_Msg_GetBuffer(AQH_MSG *msg)
{
if (msg)
return msg->buffer;
return NULL;
}
const uint8_t *AQH_Msg_GetConstBuffer(const AQH_MSG *msg)
{
if (msg)
return msg->buffer;
return NULL;
}
uint8_t AQH_Msg_GetBytesInBuffer(const AQH_MSG *msg)
{
if (msg)
return msg->bytesInBuffer;
else
return 0;
}
uint8_t AQH_Msg_GetCurrentPos(const AQH_MSG *msg)
{
if (msg)
return msg->currentPos;
else
return 0;
}
int AQH_Msg_AddByte(AQH_MSG *msg, uint8_t b)
{
if (msg) {
if ((msg->bytesInBuffer<AQH_MAXMSGSIZE) &&
(msg->currentPos<AQH_MAXMSGSIZE)) {
msg->buffer[(msg->currentPos)++]=b;
msg->bytesInBuffer++;
return 0;
}
}
return GWEN_ERROR_MEMORY_FULL;
}
int AQH_Msg_ReadNextByte(AQH_MSG *msg)
{
if (msg) {
if ((msg->currentPos<AQH_MAXMSGSIZE) &&
(msg->currentPos<msg->bytesInBuffer)) {
return ((int)(msg->buffer[(msg->currentPos)++])) & 0xff;
}
}
return GWEN_ERROR_EOF;
}
int AQH_Msg_IncCurrentPos(AQH_MSG *msg, uint8_t i)
{
if (msg) {
if (((msg->currentPos+i)<AQH_MAXMSGSIZE) &&
((msg->currentPos+i)<msg->bytesInBuffer)) {
msg->currentPos+=i;
return 0;
}
}
return GWEN_ERROR_EOF;
}
int AQH_Msg_RewindCurrentPos(AQH_MSG *msg)
{
if (msg) {
msg->currentPos=0;
return 0;
}
return GWEN_ERROR_EOF;
}
int AQH_Msg_GetRemainingBytes(const AQH_MSG *msg)
{
if (msg)
return msg->bytesInBuffer-msg->currentPos;
return 0;
}
uint8_t AQH_Msg_GetDestAddress(const AQH_MSG *msg)
{
if (msg && msg->bytesInBuffer>AQH_MSG_OFFS_ALL_DEST_ADDRESS)
return msg->buffer[AQH_MSG_OFFS_ALL_DEST_ADDRESS];
return 0;
}
uint8_t AQH_Msg_GetMsgType(const AQH_MSG *msg)
{
if (msg && msg->bytesInBuffer>AQH_MSG_OFFS_ALL_MSG_TYPE)
return msg->buffer[AQH_MSG_OFFS_ALL_MSG_TYPE];
return 0;
}
uint8_t AQH_Msg_GetSourceAddress(const AQH_MSG *msg)
{
if (msg && msg->bytesInBuffer>AQH_MSG_OFFS_ALL_SRC_ADDRESS)
return msg->buffer[AQH_MSG_OFFS_ALL_SRC_ADDRESS];
return 0;
}
uint8_t AQH_Msg_GetMsgPayloadLen(const AQH_MSG *msg)
{
if (msg && msg->bytesInBuffer>AQH_MSG_OFFS_ALL_PAYLOAD_LEN)
return msg->buffer[AQH_MSG_OFFS_ALL_PAYLOAD_LEN];
return 0;
}
int AQH_Msg_IsMsgComplete(const AQH_MSG *msg)
{
if (msg && msg->bytesInBuffer>AQH_MSG_OFFS_ALL_PAYLOAD_LEN) {
uint8_t len;
len=msg->buffer[AQH_MSG_OFFS_ALL_PAYLOAD_LEN]+AQH_MSG_OFFS_ALL_PAYLOAD_BEGIN+1;
if (len>AQH_MAXMSGSIZE)
return -1;
else if (msg->bytesInBuffer>=len)
return 1;
}
return 0;
}
int AQH_Msg_IsChecksumValid(const AQH_MSG *msg)
{
if (msg && AQH_Msg_IsMsgComplete(msg))
return (_calcChecksum(msg->buffer, msg->bytesInBuffer)==0)?1:0;
return 0;
}
int AQH_Msg_AddChecksum(AQH_MSG *msg)
{
if (msg) {
int rv;
rv=AQH_Msg_AddByte(msg, _calcChecksum(msg->buffer, msg->bytesInBuffer));
if (rv<0) {
DBG_INFO(NULL, "here (%d)", rv);
return rv;
}
return 0;
}
return GWEN_ERROR_GENERIC;
}
uint8_t _calcChecksum(const uint8_t *ptr, uint8_t len)
{
int i;
uint8_t x=0;
for (i=0; i<len; i++, ptr++) {
x^=*ptr;
}
return x;
}