248 lines
4.0 KiB
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;
|
|
}
|
|
|
|
|
|
|
|
|